Primo Committ

This commit is contained in:
paoloar77
2024-05-07 12:17:25 +02:00
commit e73d0e5113
7204 changed files with 884387 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
* - (c) Atlassian Pty Ltd
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\Node\Node;
/**
* @internal
*/
final class AdjacentTextMerger
{
public static function mergeChildNodes(Node $node): void
{
// No children or just one child node, no need for merging
if ($node->firstChild() === $node->lastChild() || $node->firstChild() === null || $node->lastChild() === null) {
return;
}
self::mergeTextNodesInclusive($node->firstChild(), $node->lastChild());
}
public static function mergeTextNodesBetweenExclusive(Node $fromNode, Node $toNode): void
{
// No nodes between them
if ($fromNode === $toNode || $fromNode->next() === $toNode || $fromNode->next() === null || $toNode->previous() === null) {
return;
}
self::mergeTextNodesInclusive($fromNode->next(), $toNode->previous());
}
private static function mergeTextNodesInclusive(Node $fromNode, Node $toNode): void
{
$first = null;
$last = null;
$node = $fromNode;
while ($node !== null) {
if ($node instanceof Text) {
if ($first === null) {
$first = $node;
}
$last = $node;
} else {
self::mergeIfNeeded($first, $last);
$first = null;
$last = null;
}
if ($node === $toNode) {
break;
}
$node = $node->next();
}
self::mergeIfNeeded($first, $last);
}
private static function mergeIfNeeded(?Text $first, ?Text $last): void
{
if ($first === null || $last === null || $first === $last) {
// No merging needed
return;
}
$s = $first->getContent();
$node = $first->next();
$stop = $last->next();
while ($node !== $stop && $node instanceof Text) {
$s .= $node->getContent();
$unlink = $node;
$node = $node->next();
$unlink->detach();
}
$first->setContent($s);
}
}

View File

@@ -0,0 +1,46 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
use League\CommonMark\Node\Node;
/**
* @method children() AbstractInline[]
*/
abstract class AbstractInline extends Node
{
/**
* @var array<string, mixed>
*
* Used for storage of arbitrary data
*/
public $data = [];
public function isContainer(): bool
{
return false;
}
/**
* @param string $key
* @param mixed $default
*
* @return mixed
*/
public function getData(string $key, $default = null)
{
return isset($this->data[$key]) ? $this->data[$key] : $default;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class AbstractStringContainer extends AbstractInline
{
/**
* @var string
*/
protected $content = '';
/**
* @param string $contents
* @param array<string, mixed> $data
*/
public function __construct(string $contents = '', array $data = [])
{
$this->content = $contents;
$this->data = $data;
}
/**
* @return string
*/
public function getContent(): string
{
return $this->content;
}
/**
* @param string $contents
*
* @return $this
*/
public function setContent(string $contents)
{
$this->content = $contents;
return $this;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
abstract class AbstractWebResource extends AbstractInline
{
/**
* @var string
*/
protected $url;
public function __construct(string $url)
{
$this->url = $url;
}
/**
* @return string
*/
public function getUrl(): string
{
return $this->url;
}
/**
* @param string $url
*
* @return $this
*/
public function setUrl(string $url)
{
$this->url = $url;
return $this;
}
public function isContainer(): bool
{
return true;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Code extends AbstractStringContainer
{
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Emphasis extends AbstractInline
{
public function isContainer(): bool
{
return true;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class HtmlInline extends AbstractStringContainer
{
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Image extends AbstractWebResource
{
public function __construct(string $url, ?string $label = null, ?string $title = null)
{
parent::__construct($url);
if (!empty($label)) {
$this->appendChild(new Text($label));
}
if (!empty($title)) {
$this->data['title'] = $title;
}
}
}

View File

@@ -0,0 +1,31 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Link extends AbstractWebResource
{
public function __construct(string $url, ?string $label = null, ?string $title = null)
{
parent::__construct($url);
if (!empty($label)) {
$this->appendChild(new Text($label));
}
if (!empty($title)) {
$this->data['title'] = $title;
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Newline extends AbstractInline
{
// Any changes to these constants should be reflected in .phpstorm.meta.php
const HARDBREAK = 0;
const SOFTBREAK = 1;
/** @var int */
protected $type;
public function __construct(int $breakType = self::HARDBREAK)
{
$this->type = $breakType;
}
public function getType(): int
{
return $this->type;
}
}

View File

@@ -0,0 +1,23 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Strong extends AbstractInline
{
public function isContainer(): bool
{
return true;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Element;
class Text extends AbstractStringContainer
{
/**
* @param string $character
*
* @return void
*/
public function append(string $character)
{
$this->content .= $character;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\InlineParserContext;
use League\CommonMark\Util\UrlEncoder;
final class AutolinkParser implements InlineParserInterface
{
const EMAIL_REGEX = '/^<([a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/';
const OTHER_LINK_REGEX = '/^<[A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]*>/i';
public function getCharacters(): array
{
return ['<'];
}
public function parse(InlineParserContext $inlineContext): bool
{
$cursor = $inlineContext->getCursor();
if ($m = $cursor->match(self::EMAIL_REGEX)) {
$email = \substr($m, 1, -1);
$inlineContext->getContainer()->appendChild(new Link('mailto:' . UrlEncoder::unescapeAndEncode($email), $email));
return true;
} elseif ($m = $cursor->match(self::OTHER_LINK_REGEX)) {
$dest = \substr($m, 1, -1);
$inlineContext->getContainer()->appendChild(new Link(UrlEncoder::unescapeAndEncode($dest), $dest));
return true;
}
return false;
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Inline\Element\Code;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
final class BacktickParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ['`'];
}
public function parse(InlineParserContext $inlineContext): bool
{
$cursor = $inlineContext->getCursor();
$ticks = $cursor->match('/^`+/');
$currentPosition = $cursor->getPosition();
$previousState = $cursor->saveState();
while ($matchingTicks = $cursor->match('/`+/m')) {
if ($matchingTicks === $ticks) {
$code = $cursor->getSubstring($currentPosition, $cursor->getPosition() - $currentPosition - \strlen($ticks));
$c = \preg_replace('/\n/m', ' ', $code);
if (
!empty($c) &&
$c[0] === ' ' &&
\substr($c, -1, 1) === ' ' &&
\preg_match('/[^ ]/', $c)
) {
$c = \substr($c, 1, -1);
}
$inlineContext->getContainer()->appendChild(new Code($c));
return true;
}
}
// If we got here, we didn't match a closing backtick sequence
$cursor->restoreState($previousState);
$inlineContext->getContainer()->appendChild(new Text($ticks));
return true;
}
}

View File

@@ -0,0 +1,45 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Delimiter\Delimiter;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
final class BangParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ['!'];
}
public function parse(InlineParserContext $inlineContext): bool
{
$cursor = $inlineContext->getCursor();
if ($cursor->peek() === '[') {
$cursor->advanceBy(2);
$node = new Text('![', ['delim' => true]);
$inlineContext->getContainer()->appendChild($node);
// Add entry to stack for this opener
$delimiter = new Delimiter('!', 1, $node, true, false, $cursor->getPosition());
$inlineContext->getDelimiterStack()->push($delimiter);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,214 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Cursor;
use League\CommonMark\Delimiter\DelimiterInterface;
use League\CommonMark\EnvironmentAwareInterface;
use League\CommonMark\EnvironmentInterface;
use League\CommonMark\Extension\Mention\Mention;
use League\CommonMark\Inline\AdjacentTextMerger;
use League\CommonMark\Inline\Element\AbstractWebResource;
use League\CommonMark\Inline\Element\Image;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
use League\CommonMark\Reference\ReferenceInterface;
use League\CommonMark\Reference\ReferenceMapInterface;
use League\CommonMark\Util\LinkParserHelper;
use League\CommonMark\Util\RegexHelper;
final class CloseBracketParser implements InlineParserInterface, EnvironmentAwareInterface
{
/**
* @var EnvironmentInterface
*/
private $environment;
public function getCharacters(): array
{
return [']'];
}
public function parse(InlineParserContext $inlineContext): bool
{
// Look through stack of delimiters for a [ or !
$opener = $inlineContext->getDelimiterStack()->searchByCharacter(['[', '!']);
if ($opener === null) {
return false;
}
if (!$opener->isActive()) {
// no matched opener; remove from emphasis stack
$inlineContext->getDelimiterStack()->removeDelimiter($opener);
return false;
}
$cursor = $inlineContext->getCursor();
$startPos = $cursor->getPosition();
$previousState = $cursor->saveState();
$cursor->advanceBy(1);
// Check to see if we have a link/image
if (!($link = $this->tryParseLink($cursor, $inlineContext->getReferenceMap(), $opener, $startPos))) {
// No match
$inlineContext->getDelimiterStack()->removeDelimiter($opener); // Remove this opener from stack
$cursor->restoreState($previousState);
return false;
}
$isImage = $opener->getChar() === '!';
$inline = $this->createInline($link['url'], $link['title'], $isImage);
$opener->getInlineNode()->replaceWith($inline);
while (($label = $inline->next()) !== null) {
// Is there a Mention contained within this link?
// CommonMark does not allow nested links, so we'll restore the original text.
if ($label instanceof Mention) {
$label->replaceWith($replacement = new Text($label->getSymbol() . $label->getIdentifier()));
$label = $replacement;
}
$inline->appendChild($label);
}
// Process delimiters such as emphasis inside link/image
$delimiterStack = $inlineContext->getDelimiterStack();
$stackBottom = $opener->getPrevious();
$delimiterStack->processDelimiters($stackBottom, $this->environment->getDelimiterProcessors());
$delimiterStack->removeAll($stackBottom);
// Merge any adjacent Text nodes together
AdjacentTextMerger::mergeChildNodes($inline);
// processEmphasis will remove this and later delimiters.
// Now, for a link, we also remove earlier link openers (no links in links)
if (!$isImage) {
$inlineContext->getDelimiterStack()->removeEarlierMatches('[');
}
return true;
}
public function setEnvironment(EnvironmentInterface $environment)
{
$this->environment = $environment;
}
/**
* @param Cursor $cursor
* @param ReferenceMapInterface $referenceMap
* @param DelimiterInterface $opener
* @param int $startPos
*
* @return array<string, string>|false
*/
private function tryParseLink(Cursor $cursor, ReferenceMapInterface $referenceMap, DelimiterInterface $opener, int $startPos)
{
// Check to see if we have a link/image
// Inline link?
if ($result = $this->tryParseInlineLinkAndTitle($cursor)) {
return $result;
}
if ($link = $this->tryParseReference($cursor, $referenceMap, $opener, $startPos)) {
return ['url' => $link->getDestination(), 'title' => $link->getTitle()];
}
return false;
}
/**
* @param Cursor $cursor
*
* @return array<string, string>|false
*/
private function tryParseInlineLinkAndTitle(Cursor $cursor)
{
if ($cursor->getCharacter() !== '(') {
return false;
}
$previousState = $cursor->saveState();
$cursor->advanceBy(1);
$cursor->advanceToNextNonSpaceOrNewline();
if (($dest = LinkParserHelper::parseLinkDestination($cursor)) === null) {
$cursor->restoreState($previousState);
return false;
}
$cursor->advanceToNextNonSpaceOrNewline();
$title = '';
// make sure there's a space before the title:
if (\preg_match(RegexHelper::REGEX_WHITESPACE_CHAR, $cursor->peek(-1))) {
$title = LinkParserHelper::parseLinkTitle($cursor) ?? '';
}
$cursor->advanceToNextNonSpaceOrNewline();
if ($cursor->getCharacter() !== ')') {
$cursor->restoreState($previousState);
return false;
}
$cursor->advanceBy(1);
return ['url' => $dest, 'title' => $title];
}
private function tryParseReference(Cursor $cursor, ReferenceMapInterface $referenceMap, DelimiterInterface $opener, int $startPos): ?ReferenceInterface
{
if ($opener->getIndex() === null) {
return null;
}
$savePos = $cursor->saveState();
$beforeLabel = $cursor->getPosition();
$n = LinkParserHelper::parseLinkLabel($cursor);
if ($n === 0 || $n === 2) {
$start = $opener->getIndex();
$length = $startPos - $opener->getIndex();
} else {
$start = $beforeLabel + 1;
$length = $n - 2;
}
$referenceLabel = $cursor->getSubstring($start, $length);
if ($n === 0) {
// If shortcut reference link, rewind before spaces we skipped
$cursor->restoreState($savePos);
}
return $referenceMap->getReference($referenceLabel);
}
private function createInline(string $url, string $title, bool $isImage): AbstractWebResource
{
if ($isImage) {
return new Image($url, null, $title);
}
return new Link($url, null, $title);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
use League\CommonMark\Util\Html5EntityDecoder;
use League\CommonMark\Util\RegexHelper;
final class EntityParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ['&'];
}
public function parse(InlineParserContext $inlineContext): bool
{
if ($m = $inlineContext->getCursor()->match('/^' . RegexHelper::PARTIAL_ENTITY . '/i')) {
$inlineContext->getContainer()->appendChild(new Text(Html5EntityDecoder::decode($m)));
return true;
}
return false;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Inline\Element\Newline;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
use League\CommonMark\Util\RegexHelper;
final class EscapableParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ['\\'];
}
public function parse(InlineParserContext $inlineContext): bool
{
$cursor = $inlineContext->getCursor();
$nextChar = $cursor->peek();
if ($nextChar === "\n") {
$cursor->advanceBy(2);
$inlineContext->getContainer()->appendChild(new Newline(Newline::HARDBREAK));
return true;
} elseif ($nextChar !== null && RegexHelper::isEscapable($nextChar)) {
$cursor->advanceBy(2);
$inlineContext->getContainer()->appendChild(new Text($nextChar));
return true;
}
$cursor->advanceBy(1);
$inlineContext->getContainer()->appendChild(new Text('\\'));
return true;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Inline\Element\HtmlInline;
use League\CommonMark\InlineParserContext;
use League\CommonMark\Util\RegexHelper;
final class HtmlInlineParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ['<'];
}
public function parse(InlineParserContext $inlineContext): bool
{
if ($m = $inlineContext->getCursor()->match('/^' . RegexHelper::PARTIAL_HTMLTAG . '/i')) {
$inlineContext->getContainer()->appendChild(new HtmlInline($m));
return true;
}
return false;
}
}

View File

@@ -0,0 +1,29 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\InlineParserContext;
interface InlineParserInterface
{
/**
* @return string[]
*/
public function getCharacters(): array;
/**
* @param InlineParserContext $inlineContext
*
* @return bool
*/
public function parse(InlineParserContext $inlineContext): bool;
}

View File

@@ -0,0 +1,51 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Inline\Element\Newline;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
final class NewlineParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ["\n"];
}
public function parse(InlineParserContext $inlineContext): bool
{
$inlineContext->getCursor()->advanceBy(1);
// Check previous inline for trailing spaces
$spaces = 0;
$lastInline = $inlineContext->getContainer()->lastChild();
if ($lastInline instanceof Text) {
$trimmed = \rtrim($lastInline->getContent(), ' ');
$spaces = \strlen($lastInline->getContent()) - \strlen($trimmed);
if ($spaces) {
$lastInline->setContent($trimmed);
}
}
if ($spaces >= 2) {
$inlineContext->getContainer()->appendChild(new Newline(Newline::HARDBREAK));
} else {
$inlineContext->getContainer()->appendChild(new Newline(Newline::SOFTBREAK));
}
return true;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Parser;
use League\CommonMark\Delimiter\Delimiter;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\InlineParserContext;
final class OpenBracketParser implements InlineParserInterface
{
public function getCharacters(): array
{
return ['['];
}
public function parse(InlineParserContext $inlineContext): bool
{
$inlineContext->getCursor()->advanceBy(1);
$node = new Text('[', ['delim' => true]);
$inlineContext->getContainer()->appendChild($node);
// Add entry to stack for this opener
$delimiter = new Delimiter('[', 1, $node, true, false, $inlineContext->getCursor()->getPosition());
$inlineContext->getDelimiterStack()->push($delimiter);
return true;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Code;
use League\CommonMark\Util\Xml;
final class CodeRenderer implements InlineRendererInterface
{
/**
* @param Code $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Code)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$attrs = $inline->getData('attributes', []);
return new HtmlElement('code', $attrs, Xml::escape($inline->getContent()));
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Emphasis;
final class EmphasisRenderer implements InlineRendererInterface
{
/**
* @param Emphasis $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Emphasis)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$attrs = $inline->getData('attributes', []);
return new HtmlElement('em', $attrs, $htmlRenderer->renderInlines($inline->children()));
}
}

View File

@@ -0,0 +1,58 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\EnvironmentInterface;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\HtmlInline;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Util\ConfigurationInterface;
final class HtmlInlineRenderer implements InlineRendererInterface, ConfigurationAwareInterface
{
/**
* @var ConfigurationInterface
*/
protected $config;
/**
* @param HtmlInline $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return string
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof HtmlInline)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
if ($this->config->get('html_input') === EnvironmentInterface::HTML_INPUT_STRIP) {
return '';
}
if ($this->config->get('html_input') === EnvironmentInterface::HTML_INPUT_ESCAPE) {
return \htmlspecialchars($inline->getContent(), \ENT_NOQUOTES);
}
return $inline->getContent();
}
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->config = $configuration;
}
}

View File

@@ -0,0 +1,68 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Image;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Util\ConfigurationInterface;
use League\CommonMark\Util\RegexHelper;
final class ImageRenderer implements InlineRendererInterface, ConfigurationAwareInterface
{
/**
* @var ConfigurationInterface
*/
protected $config;
/**
* @param Image $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Image)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$attrs = $inline->getData('attributes', []);
$forbidUnsafeLinks = !$this->config->get('allow_unsafe_links');
if ($forbidUnsafeLinks && RegexHelper::isLinkPotentiallyUnsafe($inline->getUrl())) {
$attrs['src'] = '';
} else {
$attrs['src'] = $inline->getUrl();
}
$alt = $htmlRenderer->renderInlines($inline->children());
$alt = \preg_replace('/\<[^>]*alt="([^"]*)"[^>]*\>/', '$1', $alt);
$attrs['alt'] = \preg_replace('/\<[^>]*\>/', '', $alt);
if (isset($inline->data['title'])) {
$attrs['title'] = $inline->data['title'];
}
return new HtmlElement('img', $attrs, '', true);
}
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->config = $configuration;
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
interface InlineRendererInterface
{
/**
* @param AbstractInline $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement|string|null
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer);
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Util\ConfigurationInterface;
use League\CommonMark\Util\RegexHelper;
final class LinkRenderer implements InlineRendererInterface, ConfigurationAwareInterface
{
/**
* @var ConfigurationInterface
*/
protected $config;
/**
* @param Link $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Link)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$attrs = $inline->getData('attributes', []);
$forbidUnsafeLinks = !$this->config->get('allow_unsafe_links');
if (!($forbidUnsafeLinks && RegexHelper::isLinkPotentiallyUnsafe($inline->getUrl()))) {
$attrs['href'] = $inline->getUrl();
}
if (isset($inline->data['title'])) {
$attrs['title'] = $inline->data['title'];
}
if (isset($attrs['target']) && $attrs['target'] === '_blank' && !isset($attrs['rel'])) {
$attrs['rel'] = 'noopener noreferrer';
}
return new HtmlElement('a', $attrs, $htmlRenderer->renderInlines($inline->children()));
}
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->config = $configuration;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Newline;
final class NewlineRenderer implements InlineRendererInterface
{
/**
* @param Newline $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement|string
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Newline)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
if ($inline->getType() === Newline::HARDBREAK) {
return new HtmlElement('br', [], '', true) . "\n";
}
return $htmlRenderer->getOption('soft_break', "\n");
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Strong;
final class StrongRenderer implements InlineRendererInterface
{
/**
* @param Strong $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Strong)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$attrs = $inline->getData('attributes', []);
return new HtmlElement('strong', $attrs, $htmlRenderer->renderInlines($inline->children()));
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the league/commonmark package.
*
* (c) Colin O'Dell <colinodell@gmail.com>
*
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
* - (c) John MacFarlane
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\CommonMark\Inline\Renderer;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\Util\Xml;
final class TextRenderer implements InlineRendererInterface
{
/**
* @param Text $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return string
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Text)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
return Xml::escape($inline->getContent());
}
}