1,
'underline' => 2,
'em' => 3,
'code' => 4,
'subscript' => 5,
'superscript' => 6,
'deleted' => 7,
'unformatted' => 99,
];
protected $type;
protected $attrs;
protected $tailLength = 0;
/** @var Mark */
protected $previousMark = null;
/** @var Mark */
protected $nextMark = null;
/** @var TextNode */
protected $parent;
public function __construct($data, &$parent)
{
$this->type = $data['type'];
if (isset($data['attrs'])) {
$this->attrs = $data['attrs'];
}
$this->parent = &$parent;
}
public function setPrevious($previousMark)
{
$this->previousMark = &$previousMark;
}
public function setNext($nextMark)
{
$this->nextMark = &$nextMark;
}
public function isOpeningMark()
{
return $this->parent->getStartingNodeMarkScore($this->type) === $this->getTailLength();
}
public function isClosingMark()
{
return $this->tailLength === 0;
}
public function incrementTail()
{
$this->tailLength += 1;
}
public function getTailLength()
{
return $this->tailLength;
}
public function getType()
{
return $this->type;
}
/**
* @param Mark $newPrevious
* @param null|Mark $newNext
*
* @return Mark
*/
public function switchPlaces(Mark $newPrevious, $newNext)
{
$oldPrevious = $this->previousMark;
$this->previousMark = &$newPrevious;
$this->nextMark = &$newNext;
if (null !== $newNext) {
$newNext->setPrevious($this);
}
return $oldPrevious;
}
public function sort()
{
if ($this->previousMark === null) {
return true;
}
if ($this->previousMark->getTailLength() > $this->tailLength) {
// the marks that ends later must be printed in front of those that end earlier
return true;
}
if ($this->previousMark->getTailLength() === $this->tailLength) {
if (self::$markOrder[$this->previousMark->getType()] < self::$markOrder[$this->type]) {
return true;
}
}
$newPrevious = $this->previousMark->switchPlaces($this, $this->nextMark);
$this->nextMark = &$this->previousMark;
$this->previousMark = &$newPrevious;
if (null !== $newPrevious) {
$newPrevious->setNext($this);
}
return false;
}
public function getFirst()
{
if (!$this->previousMark) {
return $this;
}
return $this->previousMark->getFirst();
}
public function getLast()
{
if (!$this->nextMark) {
return $this;
}
return $this->nextMark->getLast();
}
public function getPrevious()
{
return $this->previousMark;
}
public function getNext()
{
return $this->nextMark;
}
protected static $openingMarks = [
'strong' => '**',
'em' => '//',
'underline' => '__',
'code' => '\'\'',
'subscript' => '',
'superscript' => '',
'deleted' => '',
];
protected static $closingMarks = [
'strong' => '**',
'em' => '//',
'underline' => '__',
'code' => '\'\'',
'subscript' => '',
'superscript' => '',
'deleted' => '',
];
public function getOpeningSyntax()
{
if ($this->type !== 'unformatted') {
return self::$openingMarks[$this->type];
}
return $this->getUnformattedSyntax('opening');
}
public function getClosingSyntax()
{
if ($this->type !== 'unformatted') {
return self::$closingMarks[$this->type];
}
return $this->getUnformattedSyntax('closing');
}
/**
* Handle the edge case that %% is wrapped in nowiki syntax
*
* @param string $type 'opening' or 'closing'
*
* @return string
*/
protected function getUnformattedSyntax($type)
{
if (strpos($this->parent->getInnerSyntax(), '%%') === false) {
return '%%';
}
if ($type === 'opening') {
return '';
}
return '';
}
}