Primo Committ
This commit is contained in:
32
vendor/league/commonmark/src/Extension/Attributes/AttributesExtension.php
vendored
Normal file
32
vendor/league/commonmark/src/Extension/Attributes/AttributesExtension.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Attributes\Event\AttributesListener;
|
||||
use League\CommonMark\Extension\Attributes\Parser\AttributesBlockParser;
|
||||
use League\CommonMark\Extension\Attributes\Parser\AttributesInlineParser;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
final class AttributesExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addBlockParser(new AttributesBlockParser());
|
||||
$environment->addInlineParser(new AttributesInlineParser());
|
||||
$environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener(), 'processDocument']);
|
||||
}
|
||||
}
|
||||
141
vendor/league/commonmark/src/Extension/Attributes/Event/AttributesListener.php
vendored
Normal file
141
vendor/league/commonmark/src/Extension/Attributes/Event/AttributesListener.php
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Event;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Element\FencedCode;
|
||||
use League\CommonMark\Block\Element\ListBlock;
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Attributes\Node\Attributes;
|
||||
use League\CommonMark\Extension\Attributes\Node\AttributesInline;
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Node\Node;
|
||||
|
||||
final class AttributesListener
|
||||
{
|
||||
private const DIRECTION_PREFIX = 'prefix';
|
||||
private const DIRECTION_SUFFIX = 'suffix';
|
||||
|
||||
public function processDocument(DocumentParsedEvent $event): void
|
||||
{
|
||||
$walker = $event->getDocument()->walker();
|
||||
while ($event = $walker->next()) {
|
||||
$node = $event->getNode();
|
||||
if (!$node instanceof AttributesInline && ($event->isEntering() || !$node instanceof Attributes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[$target, $direction] = self::findTargetAndDirection($node);
|
||||
|
||||
if ($target instanceof AbstractBlock || $target instanceof AbstractInline) {
|
||||
$parent = $target->parent();
|
||||
if ($parent instanceof ListItem && $parent->parent() instanceof ListBlock && $parent->parent()->isTight()) {
|
||||
$target = $parent;
|
||||
}
|
||||
|
||||
if ($direction === self::DIRECTION_SUFFIX) {
|
||||
$attributes = AttributesHelper::mergeAttributes($target, $node->getAttributes());
|
||||
} else {
|
||||
$attributes = AttributesHelper::mergeAttributes($node->getAttributes(), $target);
|
||||
}
|
||||
|
||||
$target->data['attributes'] = $attributes;
|
||||
}
|
||||
|
||||
if ($node instanceof AbstractBlock && $node->endsWithBlankLine() && $node->next() && $node->previous()) {
|
||||
$previous = $node->previous();
|
||||
if ($previous instanceof AbstractBlock) {
|
||||
$previous->setLastLineBlank(true);
|
||||
}
|
||||
}
|
||||
|
||||
$node->detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
*
|
||||
* @return array<Node|string|null>
|
||||
*/
|
||||
private static function findTargetAndDirection(Node $node): array
|
||||
{
|
||||
$target = null;
|
||||
$direction = null;
|
||||
$previous = $next = $node;
|
||||
while (true) {
|
||||
$previous = self::getPrevious($previous);
|
||||
$next = self::getNext($next);
|
||||
|
||||
if ($previous === null && $next === null) {
|
||||
if (!$node->parent() instanceof FencedCode) {
|
||||
$target = $node->parent();
|
||||
$direction = self::DIRECTION_SUFFIX;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($node instanceof AttributesInline && ($previous === null || ($previous instanceof AbstractInline && $node->isBlock()))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($previous !== null && !self::isAttributesNode($previous)) {
|
||||
$target = $previous;
|
||||
$direction = self::DIRECTION_SUFFIX;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($next !== null && !self::isAttributesNode($next)) {
|
||||
$target = $next;
|
||||
$direction = self::DIRECTION_PREFIX;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [$target, $direction];
|
||||
}
|
||||
|
||||
private static function getPrevious(?Node $node = null): ?Node
|
||||
{
|
||||
$previous = $node instanceof Node ? $node->previous() : null;
|
||||
|
||||
if ($previous instanceof AbstractBlock && $previous->endsWithBlankLine()) {
|
||||
$previous = null;
|
||||
}
|
||||
|
||||
return $previous;
|
||||
}
|
||||
|
||||
private static function getNext(?Node $node = null): ?Node
|
||||
{
|
||||
$next = $node instanceof Node ? $node->next() : null;
|
||||
|
||||
if ($node instanceof AbstractBlock && $node->endsWithBlankLine()) {
|
||||
$next = null;
|
||||
}
|
||||
|
||||
return $next;
|
||||
}
|
||||
|
||||
private static function isAttributesNode(Node $node): bool
|
||||
{
|
||||
return $node instanceof Attributes || $node instanceof AttributesInline;
|
||||
}
|
||||
}
|
||||
62
vendor/league/commonmark/src/Extension/Attributes/Node/Attributes.php
vendored
Normal file
62
vendor/league/commonmark/src/Extension/Attributes/Node/Attributes.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Node;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Cursor;
|
||||
|
||||
final class Attributes extends AbstractBlock
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
private $attributes;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function __construct(array $attributes)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
$this->setLastLineBlank($cursor->isBlank());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function shouldLastLineBeBlank(Cursor $cursor, int $currentLineNumber): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
50
vendor/league/commonmark/src/Extension/Attributes/Node/AttributesInline.php
vendored
Normal file
50
vendor/league/commonmark/src/Extension/Attributes/Node/AttributesInline.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Node;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
final class AttributesInline extends AbstractInline
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
public $attributes;
|
||||
|
||||
/** @var bool */
|
||||
public $block;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
* @param bool $block
|
||||
*/
|
||||
public function __construct(array $attributes, bool $block)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
$this->block = $block;
|
||||
$this->data = ['delim' => true]; // TODO: Re-implement as a delimiter?
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
public function isBlock(): bool
|
||||
{
|
||||
return $this->block;
|
||||
}
|
||||
}
|
||||
44
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesBlockParser.php
vendored
Normal file
44
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesBlockParser.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Parser;
|
||||
|
||||
use League\CommonMark\Block\Parser\BlockParserInterface;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\Extension\Attributes\Node\Attributes;
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
|
||||
final class AttributesBlockParser implements BlockParserInterface
|
||||
{
|
||||
public function parse(ContextInterface $context, Cursor $cursor): bool
|
||||
{
|
||||
$state = $cursor->saveState();
|
||||
$attributes = AttributesHelper::parseAttributes($cursor);
|
||||
if ($attributes === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cursor->getNextNonSpaceCharacter() !== null) {
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$context->addBlock(new Attributes($attributes));
|
||||
$context->setBlocksParsed(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesInlineParser.php
vendored
Normal file
57
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesInlineParser.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Parser;
|
||||
|
||||
use League\CommonMark\Extension\Attributes\Node\AttributesInline;
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
|
||||
final class AttributesInlineParser implements InlineParserInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return ['{'];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
|
||||
$char = (string) $cursor->peek(-1);
|
||||
|
||||
$attributes = AttributesHelper::parseAttributes($cursor);
|
||||
if ($attributes === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($char === ' ' && ($previousInline = $inlineContext->getContainer()->lastChild()) instanceof Text) {
|
||||
$previousInline->setContent(\rtrim($previousInline->getContent(), ' '));
|
||||
}
|
||||
|
||||
if ($char === '') {
|
||||
$cursor->advanceToNextNonSpaceOrNewline();
|
||||
}
|
||||
|
||||
$node = new AttributesInline($attributes, $char === ' ' || $char === '');
|
||||
$inlineContext->getContainer()->appendChild($node);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
130
vendor/league/commonmark/src/Extension/Attributes/Util/AttributesHelper.php
vendored
Normal file
130
vendor/league/commonmark/src/Extension/Attributes/Util/AttributesHelper.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Util;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Util\RegexHelper;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class AttributesHelper
|
||||
{
|
||||
/**
|
||||
* @param Cursor $cursor
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function parseAttributes(Cursor $cursor): array
|
||||
{
|
||||
$state = $cursor->saveState();
|
||||
$cursor->advanceToNextNonSpaceOrNewline();
|
||||
if ($cursor->getCharacter() !== '{') {
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$cursor->advanceBy(1);
|
||||
if ($cursor->getCharacter() === ':') {
|
||||
$cursor->advanceBy(1);
|
||||
}
|
||||
|
||||
$attributes = [];
|
||||
$regex = '/^\s*([.#][_a-z0-9-]+|' . RegexHelper::PARTIAL_ATTRIBUTENAME . RegexHelper::PARTIAL_ATTRIBUTEVALUESPEC . ')(?<!})\s*/i';
|
||||
while ($attribute = \trim((string) $cursor->match($regex))) {
|
||||
if ($attribute[0] === '#') {
|
||||
$attributes['id'] = \substr($attribute, 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($attribute[0] === '.') {
|
||||
$attributes['class'][] = \substr($attribute, 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
[$name, $value] = \explode('=', $attribute, 2);
|
||||
$first = $value[0];
|
||||
$last = \substr($value, -1);
|
||||
if ((($first === '"' && $last === '"') || ($first === "'" && $last === "'")) && \strlen($value) > 1) {
|
||||
$value = \substr($value, 1, -1);
|
||||
}
|
||||
|
||||
if (\strtolower(\trim($name)) === 'class') {
|
||||
foreach (\array_filter(\explode(' ', \trim($value))) as $class) {
|
||||
$attributes['class'][] = $class;
|
||||
}
|
||||
} else {
|
||||
$attributes[trim($name)] = trim($value);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cursor->match('/}/') === null) {
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($attributes === []) {
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if (isset($attributes['class'])) {
|
||||
$attributes['class'] = \implode(' ', (array) $attributes['class']);
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AbstractBlock|AbstractInline|array<string, mixed> $attributes1
|
||||
* @param AbstractBlock|AbstractInline|array<string, mixed> $attributes2
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function mergeAttributes($attributes1, $attributes2): array
|
||||
{
|
||||
$attributes = [];
|
||||
foreach ([$attributes1, $attributes2] as $arg) {
|
||||
if ($arg instanceof AbstractBlock || $arg instanceof AbstractInline) {
|
||||
$arg = $arg->data['attributes'] ?? [];
|
||||
}
|
||||
|
||||
/** @var array<string, mixed> $arg */
|
||||
$arg = (array) $arg;
|
||||
if (isset($arg['class'])) {
|
||||
foreach (\array_filter(\explode(' ', \trim($arg['class']))) as $class) {
|
||||
$attributes['class'][] = $class;
|
||||
}
|
||||
|
||||
unset($arg['class']);
|
||||
}
|
||||
|
||||
$attributes = \array_merge($attributes, $arg);
|
||||
}
|
||||
|
||||
if (isset($attributes['class'])) {
|
||||
$attributes['class'] = \implode(' ', $attributes['class']);
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
25
vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php
vendored
Normal file
25
vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
final class AutolinkExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addEventListener(DocumentParsedEvent::class, new EmailAutolinkProcessor());
|
||||
$environment->addEventListener(DocumentParsedEvent::class, new UrlAutolinkProcessor());
|
||||
}
|
||||
}
|
||||
78
vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkProcessor.php
vendored
Normal file
78
vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkProcessor.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?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\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Inline\Element\Link;
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
|
||||
final class EmailAutolinkProcessor
|
||||
{
|
||||
const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/';
|
||||
|
||||
/**
|
||||
* @param DocumentParsedEvent $e
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __invoke(DocumentParsedEvent $e)
|
||||
{
|
||||
$walker = $e->getDocument()->walker();
|
||||
|
||||
while ($event = $walker->next()) {
|
||||
$node = $event->getNode();
|
||||
if ($node instanceof Text && !($node->parent() instanceof Link)) {
|
||||
self::processAutolinks($node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function processAutolinks(Text $node): void
|
||||
{
|
||||
$contents = \preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
if ($contents === false || \count($contents) === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$leftovers = '';
|
||||
foreach ($contents as $i => $content) {
|
||||
if ($i % 2 === 0) {
|
||||
$text = $leftovers . $content;
|
||||
if ($text !== '') {
|
||||
$node->insertBefore(new Text($leftovers . $content));
|
||||
}
|
||||
|
||||
$leftovers = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Does the URL end with punctuation that should be stripped?
|
||||
if (\substr($content, -1) === '.') {
|
||||
// Add the punctuation later
|
||||
$content = \substr($content, 0, -1);
|
||||
$leftovers = '.';
|
||||
}
|
||||
|
||||
// The last character cannot be - or _
|
||||
if (\in_array(\substr($content, -1), ['-', '_'])) {
|
||||
$node->insertBefore(new Text($content . $leftovers));
|
||||
$leftovers = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
$node->insertBefore(new Link('mailto:' . $content, $content));
|
||||
}
|
||||
|
||||
$node->detach();
|
||||
}
|
||||
}
|
||||
96
vendor/league/commonmark/src/Extension/Autolink/InlineMentionParser.php
vendored
Normal file
96
vendor/league/commonmark/src/Extension/Autolink/InlineMentionParser.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?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\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\Extension\Mention\MentionParser;
|
||||
use League\CommonMark\Inline\Element\Link;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
|
||||
@trigger_error(sprintf('%s is deprecated; use %s instead', InlineMentionParser::class, MentionParser::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* @deprecated Use MentionParser instead
|
||||
*/
|
||||
final class InlineMentionParser implements InlineParserInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $linkPattern;
|
||||
|
||||
/** @var string */
|
||||
private $handleRegex;
|
||||
|
||||
/**
|
||||
* @param string $linkPattern
|
||||
* @param string $handleRegex
|
||||
*/
|
||||
public function __construct($linkPattern, $handleRegex = '/^[A-Za-z0-9_]+(?!\w)/')
|
||||
{
|
||||
$this->linkPattern = $linkPattern;
|
||||
$this->handleRegex = $handleRegex;
|
||||
}
|
||||
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return ['@'];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
|
||||
// The @ symbol must not have any other characters immediately prior
|
||||
$previousChar = $cursor->peek(-1);
|
||||
if ($previousChar !== null && $previousChar !== ' ') {
|
||||
// peek() doesn't modify the cursor, so no need to restore state first
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the cursor state in case we need to rewind and bail
|
||||
$previousState = $cursor->saveState();
|
||||
|
||||
// Advance past the @ symbol to keep parsing simpler
|
||||
$cursor->advance();
|
||||
|
||||
// Parse the handle
|
||||
$handle = $cursor->match($this->handleRegex);
|
||||
if (empty($handle)) {
|
||||
// Regex failed to match; this isn't a valid Twitter handle
|
||||
$cursor->restoreState($previousState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = \sprintf($this->linkPattern, $handle);
|
||||
|
||||
$inlineContext->getContainer()->appendChild(new Link($url, '@' . $handle));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InlineMentionParser
|
||||
*/
|
||||
public static function createTwitterHandleParser()
|
||||
{
|
||||
return new self('https://twitter.com/%s', '/^[A-Za-z0-9_]{1,15}(?!\w)/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InlineMentionParser
|
||||
*/
|
||||
public static function createGithubHandleParser()
|
||||
{
|
||||
// RegEx adapted from https://github.com/shinnn/github-username-regex/blob/master/index.js
|
||||
return new self('https://www.github.com/%s', '/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)/');
|
||||
}
|
||||
}
|
||||
153
vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkProcessor.php
vendored
Normal file
153
vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkProcessor.php
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
<?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\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Inline\Element\Link;
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
|
||||
final class UrlAutolinkProcessor
|
||||
{
|
||||
// RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php
|
||||
const REGEX = '~
|
||||
(?<=^|[ \\t\\n\\x0b\\x0c\\x0d*_\\~\\(]) # Can only come at the beginning of a line, after whitespace, or certain delimiting characters
|
||||
(
|
||||
# Must start with a supported scheme + auth, or "www"
|
||||
(?:
|
||||
(?:%s):// # protocol
|
||||
(?:([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth
|
||||
|www\.)
|
||||
(?:
|
||||
(?:[\pL\pN\pS\-\.])+(?:\.?(?:[\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
|
||||
| # or
|
||||
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address
|
||||
| # or
|
||||
\[
|
||||
(?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
|
||||
\] # an IPv6 address
|
||||
)
|
||||
(?::[0-9]+)? # a port (optional)
|
||||
(?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path
|
||||
(?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional)
|
||||
(?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
|
||||
)~ixu';
|
||||
|
||||
/** @var string */
|
||||
private $finalRegex;
|
||||
|
||||
/**
|
||||
* @param array<int, string> $allowedProtocols
|
||||
*/
|
||||
public function __construct(array $allowedProtocols = ['http', 'https', 'ftp'])
|
||||
{
|
||||
$this->finalRegex = \sprintf(self::REGEX, \implode('|', $allowedProtocols));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DocumentParsedEvent $e
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __invoke(DocumentParsedEvent $e)
|
||||
{
|
||||
$walker = $e->getDocument()->walker();
|
||||
|
||||
while ($event = $walker->next()) {
|
||||
$node = $event->getNode();
|
||||
if ($node instanceof Text && !($node->parent() instanceof Link)) {
|
||||
self::processAutolinks($node, $this->finalRegex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function processAutolinks(Text $node, string $regex): void
|
||||
{
|
||||
$contents = \preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
if ($contents === false || \count($contents) === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$leftovers = '';
|
||||
foreach ($contents as $i => $content) {
|
||||
// Even-indexed elements are things before/after the URLs
|
||||
if ($i % 2 === 0) {
|
||||
// Insert any left-over characters here as well
|
||||
$text = $leftovers . $content;
|
||||
if ($text !== '') {
|
||||
$node->insertBefore(new Text($leftovers . $content));
|
||||
}
|
||||
|
||||
$leftovers = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
$leftovers = '';
|
||||
|
||||
// Does the URL end with punctuation that should be stripped?
|
||||
if (\preg_match('/(.+)([?!.,:*_~]+)$/', $content, $matches)) {
|
||||
// Add the punctuation later
|
||||
$content = $matches[1];
|
||||
$leftovers = $matches[2];
|
||||
}
|
||||
|
||||
// Does the URL end with something that looks like an entity reference?
|
||||
if (\preg_match('/(.+)(&[A-Za-z0-9]+;)$/', $content, $matches)) {
|
||||
$content = $matches[1];
|
||||
$leftovers = $matches[2] . $leftovers;
|
||||
}
|
||||
|
||||
// Does the URL need its closing paren chopped off?
|
||||
if (\substr($content, -1) === ')' && ($diff = self::diffParens($content)) > 0) {
|
||||
$content = \substr($content, 0, -$diff);
|
||||
$leftovers = str_repeat(')', $diff) . $leftovers;
|
||||
}
|
||||
|
||||
self::addLink($node, $content);
|
||||
}
|
||||
|
||||
$node->detach();
|
||||
}
|
||||
|
||||
private static function addLink(Text $node, string $url): void
|
||||
{
|
||||
// Auto-prefix 'http://' onto 'www' URLs
|
||||
if (\substr($url, 0, 4) === 'www.') {
|
||||
$node->insertBefore(new Link('http://' . $url, $url));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$node->insertBefore(new Link($url, $url));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function diffParens(string $content): int
|
||||
{
|
||||
// Scan the entire autolink for the total number of parentheses.
|
||||
// If there is a greater number of closing parentheses than opening ones,
|
||||
// we don’t consider ANY of the last characters as part of the autolink,
|
||||
// in order to facilitate including an autolink inside a parenthesis.
|
||||
\preg_match_all('/[()]/', $content, $matches);
|
||||
|
||||
$charCount = ['(' => 0, ')' => 0];
|
||||
foreach ($matches[0] as $char) {
|
||||
$charCount[$char]++;
|
||||
}
|
||||
|
||||
return $charCount[')'] - $charCount['('];
|
||||
}
|
||||
}
|
||||
95
vendor/league/commonmark/src/Extension/CommonMarkCoreExtension.php
vendored
Normal file
95
vendor/league/commonmark/src/Extension/CommonMarkCoreExtension.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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\Extension;
|
||||
|
||||
use League\CommonMark\Block\Element as BlockElement;
|
||||
use League\CommonMark\Block\Parser as BlockParser;
|
||||
use League\CommonMark\Block\Renderer as BlockRenderer;
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor;
|
||||
use League\CommonMark\Inline\Element as InlineElement;
|
||||
use League\CommonMark\Inline\Parser as InlineParser;
|
||||
use League\CommonMark\Inline\Renderer as InlineRenderer;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class CommonMarkCoreExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment
|
||||
->addBlockParser(new BlockParser\BlockQuoteParser(), 70)
|
||||
->addBlockParser(new BlockParser\ATXHeadingParser(), 60)
|
||||
->addBlockParser(new BlockParser\FencedCodeParser(), 50)
|
||||
->addBlockParser(new BlockParser\HtmlBlockParser(), 40)
|
||||
->addBlockParser(new BlockParser\SetExtHeadingParser(), 30)
|
||||
->addBlockParser(new BlockParser\ThematicBreakParser(), 20)
|
||||
->addBlockParser(new BlockParser\ListParser(), 10)
|
||||
->addBlockParser(new BlockParser\IndentedCodeParser(), -100)
|
||||
->addBlockParser(new BlockParser\LazyParagraphParser(), -200)
|
||||
|
||||
->addInlineParser(new InlineParser\NewlineParser(), 200)
|
||||
->addInlineParser(new InlineParser\BacktickParser(), 150)
|
||||
->addInlineParser(new InlineParser\EscapableParser(), 80)
|
||||
->addInlineParser(new InlineParser\EntityParser(), 70)
|
||||
->addInlineParser(new InlineParser\AutolinkParser(), 50)
|
||||
->addInlineParser(new InlineParser\HtmlInlineParser(), 40)
|
||||
->addInlineParser(new InlineParser\CloseBracketParser(), 30)
|
||||
->addInlineParser(new InlineParser\OpenBracketParser(), 20)
|
||||
->addInlineParser(new InlineParser\BangParser(), 10)
|
||||
|
||||
->addBlockRenderer(BlockElement\BlockQuote::class, new BlockRenderer\BlockQuoteRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\Document::class, new BlockRenderer\DocumentRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\FencedCode::class, new BlockRenderer\FencedCodeRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\Heading::class, new BlockRenderer\HeadingRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\HtmlBlock::class, new BlockRenderer\HtmlBlockRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\IndentedCode::class, new BlockRenderer\IndentedCodeRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\ListBlock::class, new BlockRenderer\ListBlockRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\ListItem::class, new BlockRenderer\ListItemRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\Paragraph::class, new BlockRenderer\ParagraphRenderer(), 0)
|
||||
->addBlockRenderer(BlockElement\ThematicBreak::class, new BlockRenderer\ThematicBreakRenderer(), 0)
|
||||
|
||||
->addInlineRenderer(InlineElement\Code::class, new InlineRenderer\CodeRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Emphasis::class, new InlineRenderer\EmphasisRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\HtmlInline::class, new InlineRenderer\HtmlInlineRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Image::class, new InlineRenderer\ImageRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Link::class, new InlineRenderer\LinkRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Newline::class, new InlineRenderer\NewlineRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Strong::class, new InlineRenderer\StrongRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Text::class, new InlineRenderer\TextRenderer(), 0)
|
||||
;
|
||||
|
||||
$deprecatedUseAsterisk = $environment->getConfig('use_asterisk', ConfigurationInterface::MISSING);
|
||||
if ($deprecatedUseAsterisk !== ConfigurationInterface::MISSING) {
|
||||
@\trigger_error('The "use_asterisk" configuration option is deprecated in league/commonmark 1.6 and will be replaced with "commonmark > use_asterisk" in 2.0', \E_USER_DEPRECATED);
|
||||
} else {
|
||||
$deprecatedUseAsterisk = true;
|
||||
}
|
||||
|
||||
if ($environment->getConfig('commonmark/use_asterisk', $deprecatedUseAsterisk)) {
|
||||
$environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*'));
|
||||
}
|
||||
|
||||
$deprecatedUseUnderscore = $environment->getConfig('use_underscore', ConfigurationInterface::MISSING);
|
||||
if ($deprecatedUseUnderscore !== ConfigurationInterface::MISSING) {
|
||||
@\trigger_error('The "use_underscore" configuration option is deprecated in league/commonmark 1.6 and will be replaced with "commonmark > use_underscore" in 2.0', \E_USER_DEPRECATED);
|
||||
} else {
|
||||
$deprecatedUseUnderscore = true;
|
||||
}
|
||||
|
||||
if ($environment->getConfig('commonmark/use_underscore', $deprecatedUseUnderscore)) {
|
||||
$environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
48
vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php
vendored
Normal file
48
vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Extension\DisallowedRawHtml;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class DisallowedRawHtmlBlockRenderer implements BlockRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var BlockRendererInterface */
|
||||
private $htmlBlockRenderer;
|
||||
|
||||
public function __construct(BlockRendererInterface $htmlBlockRenderer)
|
||||
{
|
||||
$this->htmlBlockRenderer = $htmlBlockRenderer;
|
||||
}
|
||||
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
$rendered = $this->htmlBlockRenderer->render($block, $htmlRenderer, $inTightList);
|
||||
|
||||
if ($rendered === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Match these types of tags: <title> </title> <title x="sdf"> <title/> <title />
|
||||
return preg_replace('/<(\/?(?:title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext)[ \/>])/i', '<$1', $rendered);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
if ($this->htmlBlockRenderer instanceof ConfigurationAwareInterface) {
|
||||
$this->htmlBlockRenderer->setConfiguration($configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php
vendored
Normal file
28
vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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\Extension\DisallowedRawHtml;
|
||||
|
||||
use League\CommonMark\Block\Element\HtmlBlock;
|
||||
use League\CommonMark\Block\Renderer\HtmlBlockRenderer;
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Inline\Element\HtmlInline;
|
||||
use League\CommonMark\Inline\Renderer\HtmlInlineRenderer;
|
||||
|
||||
final class DisallowedRawHtmlExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addBlockRenderer(HtmlBlock::class, new DisallowedRawHtmlBlockRenderer(new HtmlBlockRenderer()), 50);
|
||||
$environment->addInlineRenderer(HtmlInline::class, new DisallowedRawHtmlInlineRenderer(new HtmlInlineRenderer()), 50);
|
||||
}
|
||||
}
|
||||
48
vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php
vendored
Normal file
48
vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Extension\DisallowedRawHtml;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class DisallowedRawHtmlInlineRenderer implements InlineRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var InlineRendererInterface */
|
||||
private $htmlInlineRenderer;
|
||||
|
||||
public function __construct(InlineRendererInterface $htmlBlockRenderer)
|
||||
{
|
||||
$this->htmlInlineRenderer = $htmlBlockRenderer;
|
||||
}
|
||||
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
$rendered = $this->htmlInlineRenderer->render($inline, $htmlRenderer);
|
||||
|
||||
if ($rendered === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Match these types of tags: <title> </title> <title x="sdf"> <title/> <title />
|
||||
return preg_replace('/<(\/?(?:title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext)[ \/>])/i', '<$1', $rendered);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
if ($this->htmlInlineRenderer instanceof ConfigurationAwareInterface) {
|
||||
$this->htmlInlineRenderer->setConfiguration($configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
vendor/league/commonmark/src/Extension/ExtensionInterface.php
vendored
Normal file
27
vendor/league/commonmark/src/Extension/ExtensionInterface.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?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\Extension;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
|
||||
interface ExtensionInterface
|
||||
{
|
||||
/**
|
||||
* @param ConfigurableEnvironmentInterface $environment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register(ConfigurableEnvironmentInterface $environment);
|
||||
}
|
||||
24
vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkExtension.php
vendored
Normal file
24
vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkExtension.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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\Extension\ExternalLink;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
final class ExternalLinkExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment), -50);
|
||||
}
|
||||
}
|
||||
131
vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkProcessor.php
vendored
Normal file
131
vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkProcessor.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?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\Extension\ExternalLink;
|
||||
|
||||
use League\CommonMark\EnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Inline\Element\Link;
|
||||
|
||||
final class ExternalLinkProcessor
|
||||
{
|
||||
public const APPLY_NONE = '';
|
||||
public const APPLY_ALL = 'all';
|
||||
public const APPLY_EXTERNAL = 'external';
|
||||
public const APPLY_INTERNAL = 'internal';
|
||||
|
||||
/** @var EnvironmentInterface */
|
||||
private $environment;
|
||||
|
||||
public function __construct(EnvironmentInterface $environment)
|
||||
{
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DocumentParsedEvent $e
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __invoke(DocumentParsedEvent $e)
|
||||
{
|
||||
$internalHosts = $this->environment->getConfig('external_link/internal_hosts', []);
|
||||
$openInNewWindow = $this->environment->getConfig('external_link/open_in_new_window', false);
|
||||
$classes = $this->environment->getConfig('external_link/html_class', '');
|
||||
|
||||
$walker = $e->getDocument()->walker();
|
||||
while ($event = $walker->next()) {
|
||||
if ($event->isEntering() && $event->getNode() instanceof Link) {
|
||||
/** @var Link $link */
|
||||
$link = $event->getNode();
|
||||
|
||||
$host = parse_url($link->getUrl(), PHP_URL_HOST);
|
||||
if (empty($host)) {
|
||||
// Something is terribly wrong with this URL
|
||||
continue;
|
||||
}
|
||||
|
||||
if (self::hostMatches($host, $internalHosts)) {
|
||||
$link->data['external'] = false;
|
||||
$this->applyRelAttribute($link, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Host does not match our list
|
||||
$this->markLinkAsExternal($link, $openInNewWindow, $classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function markLinkAsExternal(Link $link, bool $openInNewWindow, string $classes): void
|
||||
{
|
||||
$link->data['external'] = true;
|
||||
$link->data['attributes'] = $link->getData('attributes', []);
|
||||
$this->applyRelAttribute($link, true);
|
||||
|
||||
if ($openInNewWindow) {
|
||||
$link->data['attributes']['target'] = '_blank';
|
||||
}
|
||||
|
||||
if (!empty($classes)) {
|
||||
$link->data['attributes']['class'] = trim(($link->data['attributes']['class'] ?? '') . ' ' . $classes);
|
||||
}
|
||||
}
|
||||
|
||||
private function applyRelAttribute(Link $link, bool $isExternal): void
|
||||
{
|
||||
$rel = [];
|
||||
|
||||
$options = [
|
||||
'nofollow' => $this->environment->getConfig('external_link/nofollow', self::APPLY_NONE),
|
||||
'noopener' => $this->environment->getConfig('external_link/noopener', self::APPLY_EXTERNAL),
|
||||
'noreferrer' => $this->environment->getConfig('external_link/noreferrer', self::APPLY_EXTERNAL),
|
||||
];
|
||||
|
||||
foreach ($options as $type => $option) {
|
||||
switch (true) {
|
||||
case $option === self::APPLY_ALL:
|
||||
case $isExternal && $option === self::APPLY_EXTERNAL:
|
||||
case !$isExternal && $option === self::APPLY_INTERNAL:
|
||||
$rel[] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
if ($rel === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$link->data['attributes']['rel'] = \implode(' ', $rel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param mixed $compareTo
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal This method is only public so we can easily test it. DO NOT USE THIS OUTSIDE OF THIS EXTENSION!
|
||||
*/
|
||||
public static function hostMatches(string $host, $compareTo)
|
||||
{
|
||||
foreach ((array) $compareTo as $c) {
|
||||
if (strpos($c, '/') === 0) {
|
||||
if (preg_match($c, $host)) {
|
||||
return true;
|
||||
}
|
||||
} elseif ($c === $host) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
61
vendor/league/commonmark/src/Extension/Footnote/Event/AnonymousFootnotesListener.php
vendored
Normal file
61
vendor/league/commonmark/src/Extension/Footnote/Event/AnonymousFootnotesListener.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Event;
|
||||
|
||||
use League\CommonMark\Block\Element\Paragraph;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Footnote\Node\Footnote;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteBackref;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
use League\CommonMark\Reference\Reference;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class AnonymousFootnotesListener implements ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function onDocumentParsed(DocumentParsedEvent $event): void
|
||||
{
|
||||
$document = $event->getDocument();
|
||||
$walker = $document->walker();
|
||||
|
||||
while ($event = $walker->next()) {
|
||||
$node = $event->getNode();
|
||||
if ($node instanceof FootnoteRef && $event->isEntering() && null !== $text = $node->getContent()) {
|
||||
// Anonymous footnote needs to create a footnote from its content
|
||||
$existingReference = $node->getReference();
|
||||
$reference = new Reference(
|
||||
$existingReference->getLabel(),
|
||||
'#' . $this->config->get('footnote/ref_id_prefix', 'fnref:') . $existingReference->getLabel(),
|
||||
$existingReference->getTitle()
|
||||
);
|
||||
$footnote = new Footnote($reference);
|
||||
$footnote->addBackref(new FootnoteBackref($reference));
|
||||
$paragraph = new Paragraph();
|
||||
$paragraph->appendChild(new Text($text));
|
||||
$footnote->appendChild($paragraph);
|
||||
$document->appendChild($footnote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $config): void
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
||||
100
vendor/league/commonmark/src/Extension/Footnote/Event/GatherFootnotesListener.php
vendored
Normal file
100
vendor/league/commonmark/src/Extension/Footnote/Event/GatherFootnotesListener.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Event;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Footnote\Node\Footnote;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteBackref;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteContainer;
|
||||
use League\CommonMark\Reference\Reference;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class GatherFootnotesListener implements ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function onDocumentParsed(DocumentParsedEvent $event): void
|
||||
{
|
||||
$document = $event->getDocument();
|
||||
$walker = $document->walker();
|
||||
|
||||
$footnotes = [];
|
||||
while ($event = $walker->next()) {
|
||||
if (!$event->isEntering()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$node = $event->getNode();
|
||||
if (!$node instanceof Footnote) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for existing reference with footnote label
|
||||
$ref = $document->getReferenceMap()->getReference($node->getReference()->getLabel());
|
||||
if ($ref !== null) {
|
||||
// Use numeric title to get footnotes order
|
||||
$footnotes[\intval($ref->getTitle())] = $node;
|
||||
} else {
|
||||
// Footnote call is missing, append footnote at the end
|
||||
$footnotes[INF] = $node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for all footnote refs pointing to this footnote
|
||||
* and create each footnote backrefs.
|
||||
*/
|
||||
$backrefs = $document->getData(
|
||||
'#' . $this->config->get('footnote/footnote_id_prefix', 'fn:') . $node->getReference()->getDestination(),
|
||||
[]
|
||||
);
|
||||
/** @var Reference $backref */
|
||||
foreach ($backrefs as $backref) {
|
||||
$node->addBackref(new FootnoteBackref(new Reference(
|
||||
$backref->getLabel(),
|
||||
'#' . $this->config->get('footnote/ref_id_prefix', 'fnref:') . $backref->getLabel(),
|
||||
$backref->getTitle()
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Only add a footnote container if there are any
|
||||
if (\count($footnotes) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$container = $this->getFootnotesContainer($document);
|
||||
|
||||
\ksort($footnotes);
|
||||
foreach ($footnotes as $footnote) {
|
||||
$container->appendChild($footnote);
|
||||
}
|
||||
}
|
||||
|
||||
private function getFootnotesContainer(Document $document): FootnoteContainer
|
||||
{
|
||||
$footnoteContainer = new FootnoteContainer();
|
||||
$document->appendChild($footnoteContainer);
|
||||
|
||||
return $footnoteContainer;
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $config): void
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
||||
86
vendor/league/commonmark/src/Extension/Footnote/Event/NumberFootnotesListener.php
vendored
Normal file
86
vendor/league/commonmark/src/Extension/Footnote/Event/NumberFootnotesListener.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Event;
|
||||
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
|
||||
use League\CommonMark\Reference\Reference;
|
||||
|
||||
final class NumberFootnotesListener
|
||||
{
|
||||
public function onDocumentParsed(DocumentParsedEvent $event): void
|
||||
{
|
||||
$document = $event->getDocument();
|
||||
$walker = $document->walker();
|
||||
$nextCounter = 1;
|
||||
$usedLabels = [];
|
||||
$usedCounters = [];
|
||||
|
||||
while ($event = $walker->next()) {
|
||||
if (!$event->isEntering()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$node = $event->getNode();
|
||||
|
||||
if (!$node instanceof FootnoteRef) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existingReference = $node->getReference();
|
||||
$label = $existingReference->getLabel();
|
||||
$counter = $nextCounter;
|
||||
$canIncrementCounter = true;
|
||||
|
||||
if (\array_key_exists($label, $usedLabels)) {
|
||||
/*
|
||||
* Reference is used again, we need to point
|
||||
* to the same footnote. But with a different ID
|
||||
*/
|
||||
$counter = $usedCounters[$label];
|
||||
$label = $label . '__' . ++$usedLabels[$label];
|
||||
$canIncrementCounter = false;
|
||||
}
|
||||
|
||||
// rewrite reference title to use a numeric link
|
||||
$newReference = new Reference(
|
||||
$label,
|
||||
$existingReference->getDestination(),
|
||||
(string) $counter
|
||||
);
|
||||
|
||||
// Override reference with numeric link
|
||||
$node->setReference($newReference);
|
||||
$document->getReferenceMap()->addReference($newReference);
|
||||
|
||||
/*
|
||||
* Store created references in document for
|
||||
* creating FootnoteBackrefs
|
||||
*/
|
||||
if (false === $document->getData($existingReference->getDestination(), false)) {
|
||||
$document->data[$existingReference->getDestination()] = [];
|
||||
}
|
||||
|
||||
$document->data[$existingReference->getDestination()][] = $newReference;
|
||||
|
||||
$usedLabels[$label] = 1;
|
||||
$usedCounters[$label] = $nextCounter;
|
||||
|
||||
if ($canIncrementCounter) {
|
||||
$nextCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
53
vendor/league/commonmark/src/Extension/Footnote/FootnoteExtension.php
vendored
Normal file
53
vendor/league/commonmark/src/Extension/Footnote/FootnoteExtension.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Extension\Footnote\Event\AnonymousFootnotesListener;
|
||||
use League\CommonMark\Extension\Footnote\Event\GatherFootnotesListener;
|
||||
use League\CommonMark\Extension\Footnote\Event\NumberFootnotesListener;
|
||||
use League\CommonMark\Extension\Footnote\Node\Footnote;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteBackref;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteContainer;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
|
||||
use League\CommonMark\Extension\Footnote\Parser\AnonymousFootnoteRefParser;
|
||||
use League\CommonMark\Extension\Footnote\Parser\FootnoteParser;
|
||||
use League\CommonMark\Extension\Footnote\Parser\FootnoteRefParser;
|
||||
use League\CommonMark\Extension\Footnote\Renderer\FootnoteBackrefRenderer;
|
||||
use League\CommonMark\Extension\Footnote\Renderer\FootnoteContainerRenderer;
|
||||
use League\CommonMark\Extension\Footnote\Renderer\FootnoteRefRenderer;
|
||||
use League\CommonMark\Extension\Footnote\Renderer\FootnoteRenderer;
|
||||
|
||||
final class FootnoteExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addBlockParser(new FootnoteParser(), 51);
|
||||
$environment->addInlineParser(new AnonymousFootnoteRefParser(), 35);
|
||||
$environment->addInlineParser(new FootnoteRefParser(), 51);
|
||||
|
||||
$environment->addBlockRenderer(FootnoteContainer::class, new FootnoteContainerRenderer());
|
||||
$environment->addBlockRenderer(Footnote::class, new FootnoteRenderer());
|
||||
|
||||
$environment->addInlineRenderer(FootnoteRef::class, new FootnoteRefRenderer());
|
||||
$environment->addInlineRenderer(FootnoteBackref::class, new FootnoteBackrefRenderer());
|
||||
|
||||
$environment->addEventListener(DocumentParsedEvent::class, [new AnonymousFootnotesListener(), 'onDocumentParsed']);
|
||||
$environment->addEventListener(DocumentParsedEvent::class, [new NumberFootnotesListener(), 'onDocumentParsed']);
|
||||
$environment->addEventListener(DocumentParsedEvent::class, [new GatherFootnotesListener(), 'onDocumentParsed']);
|
||||
}
|
||||
}
|
||||
75
vendor/league/commonmark/src/Extension/Footnote/Node/Footnote.php
vendored
Normal file
75
vendor/league/commonmark/src/Extension/Footnote/Node/Footnote.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Node;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\Reference\ReferenceInterface;
|
||||
|
||||
/**
|
||||
* @method children() AbstractBlock[]
|
||||
*/
|
||||
final class Footnote extends AbstractBlock
|
||||
{
|
||||
/**
|
||||
* @var FootnoteBackref[]
|
||||
*/
|
||||
private $backrefs = [];
|
||||
|
||||
/**
|
||||
* @var ReferenceInterface
|
||||
*/
|
||||
private $reference;
|
||||
|
||||
public function __construct(ReferenceInterface $reference)
|
||||
{
|
||||
$this->reference = $reference;
|
||||
}
|
||||
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getReference(): ReferenceInterface
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function addBackref(FootnoteBackref $backref): self
|
||||
{
|
||||
$this->backrefs[] = $backref;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FootnoteBackref[]
|
||||
*/
|
||||
public function getBackrefs(): array
|
||||
{
|
||||
return $this->backrefs;
|
||||
}
|
||||
}
|
||||
37
vendor/league/commonmark/src/Extension/Footnote/Node/FootnoteBackref.php
vendored
Normal file
37
vendor/league/commonmark/src/Extension/Footnote/Node/FootnoteBackref.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Node;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Reference\ReferenceInterface;
|
||||
|
||||
/**
|
||||
* Link from the footnote on the bottom of the document back to the reference
|
||||
*/
|
||||
final class FootnoteBackref extends AbstractInline
|
||||
{
|
||||
/** @var ReferenceInterface */
|
||||
private $reference;
|
||||
|
||||
public function __construct(ReferenceInterface $reference)
|
||||
{
|
||||
$this->reference = $reference;
|
||||
}
|
||||
|
||||
public function getReference(): ReferenceInterface
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
}
|
||||
39
vendor/league/commonmark/src/Extension/Footnote/Node/FootnoteContainer.php
vendored
Normal file
39
vendor/league/commonmark/src/Extension/Footnote/Node/FootnoteContainer.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Node;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Cursor;
|
||||
|
||||
/**
|
||||
* @method children() AbstractBlock[]
|
||||
*/
|
||||
final class FootnoteContainer extends AbstractBlock
|
||||
{
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return $block instanceof Footnote;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
56
vendor/league/commonmark/src/Extension/Footnote/Node/FootnoteRef.php
vendored
Normal file
56
vendor/league/commonmark/src/Extension/Footnote/Node/FootnoteRef.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Node;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Reference\ReferenceInterface;
|
||||
|
||||
final class FootnoteRef extends AbstractInline
|
||||
{
|
||||
/** @var ReferenceInterface */
|
||||
private $reference;
|
||||
|
||||
/** @var string|null */
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @param ReferenceInterface $reference
|
||||
* @param string|null $content
|
||||
* @param array<mixed> $data
|
||||
*/
|
||||
public function __construct(ReferenceInterface $reference, ?string $content = null, array $data = [])
|
||||
{
|
||||
$this->reference = $reference;
|
||||
$this->content = $content;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getReference(): ReferenceInterface
|
||||
{
|
||||
return $this->reference;
|
||||
}
|
||||
|
||||
public function setReference(ReferenceInterface $reference): FootnoteRef
|
||||
{
|
||||
$this->reference = $reference;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContent(): ?string
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
}
|
||||
85
vendor/league/commonmark/src/Extension/Footnote/Parser/AnonymousFootnoteRefParser.php
vendored
Normal file
85
vendor/league/commonmark/src/Extension/Footnote/Parser/AnonymousFootnoteRefParser.php
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Parser;
|
||||
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
use League\CommonMark\Normalizer\SlugNormalizer;
|
||||
use League\CommonMark\Normalizer\TextNormalizerInterface;
|
||||
use League\CommonMark\Reference\Reference;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class AnonymousFootnoteRefParser implements InlineParserInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
/** @var TextNormalizerInterface */
|
||||
private $slugNormalizer;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->slugNormalizer = new SlugNormalizer();
|
||||
}
|
||||
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return ['^'];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$container = $inlineContext->getContainer();
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$nextChar = $cursor->peek();
|
||||
if ($nextChar !== '[') {
|
||||
return false;
|
||||
}
|
||||
$state = $cursor->saveState();
|
||||
|
||||
$m = $cursor->match('/\^\[[^\n^\]]+\]/');
|
||||
if ($m !== null) {
|
||||
if (\preg_match('#\^\[([^\]]+)\]#', $m, $matches) > 0) {
|
||||
$reference = $this->createReference($matches[1]);
|
||||
$container->appendChild(new FootnoteRef($reference, $matches[1]));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function createReference(string $label): Reference
|
||||
{
|
||||
$refLabel = $this->slugNormalizer->normalize($label);
|
||||
$refLabel = \mb_substr($refLabel, 0, 20);
|
||||
|
||||
return new Reference(
|
||||
$refLabel,
|
||||
'#' . $this->config->get('footnote/footnote_id_prefix', 'fn:') . $refLabel,
|
||||
$label
|
||||
);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $config): void
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
||||
63
vendor/league/commonmark/src/Extension/Footnote/Parser/FootnoteParser.php
vendored
Normal file
63
vendor/league/commonmark/src/Extension/Footnote/Parser/FootnoteParser.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Parser;
|
||||
|
||||
use League\CommonMark\Block\Parser\BlockParserInterface;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\Extension\Footnote\Node\Footnote;
|
||||
use League\CommonMark\Reference\Reference;
|
||||
use League\CommonMark\Util\RegexHelper;
|
||||
|
||||
final class FootnoteParser implements BlockParserInterface
|
||||
{
|
||||
public function parse(ContextInterface $context, Cursor $cursor): bool
|
||||
{
|
||||
if ($cursor->isIndented()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$match = RegexHelper::matchFirst(
|
||||
'/^\[\^([^\n^\]]+)\]\:\s/',
|
||||
$cursor->getLine(),
|
||||
$cursor->getNextNonSpacePosition()
|
||||
);
|
||||
|
||||
if (!$match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cursor->advanceToNextNonSpaceOrTab();
|
||||
$cursor->advanceBy(\strlen($match[0]));
|
||||
$str = $cursor->getRemainder();
|
||||
\preg_replace('/^\[\^([^\n^\]]+)\]\:\s/', '', $str);
|
||||
|
||||
if (\preg_match('/^\[\^([^\n^\]]+)\]\:\s/', $match[0], $matches) > 0) {
|
||||
$context->addBlock($this->createFootnote($matches[1]));
|
||||
$context->setBlocksParsed(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function createFootnote(string $label): Footnote
|
||||
{
|
||||
return new Footnote(
|
||||
new Reference($label, $label, $label)
|
||||
);
|
||||
}
|
||||
}
|
||||
72
vendor/league/commonmark/src/Extension/Footnote/Parser/FootnoteRefParser.php
vendored
Normal file
72
vendor/league/commonmark/src/Extension/Footnote/Parser/FootnoteRefParser.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Parser;
|
||||
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
use League\CommonMark\Reference\Reference;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class FootnoteRefParser implements InlineParserInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return ['['];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$container = $inlineContext->getContainer();
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$nextChar = $cursor->peek();
|
||||
if ($nextChar !== '^') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$state = $cursor->saveState();
|
||||
|
||||
$m = $cursor->match('#\[\^([^\]]+)\]#');
|
||||
if ($m !== null) {
|
||||
if (\preg_match('#\[\^([^\]]+)\]#', $m, $matches) > 0) {
|
||||
$container->appendChild(new FootnoteRef($this->createReference($matches[1])));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function createReference(string $label): Reference
|
||||
{
|
||||
return new Reference(
|
||||
$label,
|
||||
'#' . $this->config->get('footnote/footnote_id_prefix', 'fn:') . $label,
|
||||
$label
|
||||
);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $config): void
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
||||
49
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteBackrefRenderer.php
vendored
Normal file
49
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteBackrefRenderer.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Renderer;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteBackref;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class FootnoteBackrefRenderer implements InlineRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
if (!($inline instanceof FootnoteBackref)) {
|
||||
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
|
||||
}
|
||||
|
||||
$attrs = $inline->getData('attributes', []);
|
||||
$attrs['class'] = $attrs['class'] ?? $this->config->get('footnote/backref_class', 'footnote-backref');
|
||||
$attrs['rev'] = 'footnote';
|
||||
$attrs['href'] = \mb_strtolower($inline->getReference()->getDestination());
|
||||
$attrs['role'] = 'doc-backlink';
|
||||
|
||||
return ' ' . new HtmlElement('a', $attrs, '↩', true);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
}
|
||||
52
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteContainerRenderer.php
vendored
Normal file
52
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteContainerRenderer.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Renderer;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteContainer;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class FootnoteContainerRenderer implements BlockRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
if (!($block instanceof FootnoteContainer)) {
|
||||
throw new \InvalidArgumentException('Incompatible block type: ' . \get_class($block));
|
||||
}
|
||||
|
||||
$attrs = $block->getData('attributes', []);
|
||||
$attrs['class'] = $attrs['class'] ?? $this->config->get('footnote/container_class', 'footnotes');
|
||||
$attrs['role'] = 'doc-endnotes';
|
||||
|
||||
$contents = new HtmlElement('ol', [], $htmlRenderer->renderBlocks($block->children()));
|
||||
if ($this->config->get('footnote/container_add_hr', true)) {
|
||||
$contents = [new HtmlElement('hr', [], null, true), $contents];
|
||||
}
|
||||
|
||||
return new HtmlElement('div', $attrs, $contents);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
}
|
||||
62
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteRefRenderer.php
vendored
Normal file
62
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteRefRenderer.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Renderer;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class FootnoteRefRenderer implements InlineRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
if (!($inline instanceof FootnoteRef)) {
|
||||
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
|
||||
}
|
||||
|
||||
$attrs = $inline->getData('attributes', []);
|
||||
$class = $attrs['class'] ?? $this->config->get('footnote/ref_class', 'footnote-ref');
|
||||
$idPrefix = $this->config->get('footnote/ref_id_prefix', 'fnref:');
|
||||
|
||||
return new HtmlElement(
|
||||
'sup',
|
||||
[
|
||||
'id' => $idPrefix . \mb_strtolower($inline->getReference()->getLabel()),
|
||||
],
|
||||
new HTMLElement(
|
||||
'a',
|
||||
[
|
||||
'class' => $class,
|
||||
'href' => \mb_strtolower($inline->getReference()->getDestination()),
|
||||
'role' => 'doc-noteref',
|
||||
],
|
||||
$inline->getReference()->getTitle()
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
}
|
||||
64
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteRenderer.php
vendored
Normal file
64
vendor/league/commonmark/src/Extension/Footnote/Renderer/FootnoteRenderer.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) Rezo Zero / Ambroise Maupate
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Footnote\Renderer;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Extension\Footnote\Node\Footnote;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class FootnoteRenderer implements BlockRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param Footnote $block
|
||||
* @param ElementRendererInterface $htmlRenderer
|
||||
* @param bool $inTightList
|
||||
*
|
||||
* @return HtmlElement
|
||||
*/
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
if (!($block instanceof Footnote)) {
|
||||
throw new \InvalidArgumentException('Incompatible block type: ' . \get_class($block));
|
||||
}
|
||||
|
||||
$attrs = $block->getData('attributes', []);
|
||||
$attrs['class'] = $attrs['class'] ?? $this->config->get('footnote/footnote_class', 'footnote');
|
||||
$attrs['id'] = $this->config->get('footnote/footnote_id_prefix', 'fn:') . \mb_strtolower($block->getReference()->getLabel());
|
||||
$attrs['role'] = 'doc-endnote';
|
||||
|
||||
foreach ($block->getBackrefs() as $backref) {
|
||||
$block->lastChild()->appendChild($backref);
|
||||
}
|
||||
|
||||
return new HtmlElement(
|
||||
'li',
|
||||
$attrs,
|
||||
$htmlRenderer->renderBlocks($block->children()),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
}
|
||||
31
vendor/league/commonmark/src/Extension/GithubFlavoredMarkdownExtension.php
vendored
Normal file
31
vendor/league/commonmark/src/Extension/GithubFlavoredMarkdownExtension.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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\Extension;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Extension\Autolink\AutolinkExtension;
|
||||
use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension;
|
||||
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
|
||||
use League\CommonMark\Extension\Table\TableExtension;
|
||||
use League\CommonMark\Extension\TaskList\TaskListExtension;
|
||||
|
||||
final class GithubFlavoredMarkdownExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addExtension(new AutolinkExtension());
|
||||
$environment->addExtension(new DisallowedRawHtmlExtension());
|
||||
$environment->addExtension(new StrikethroughExtension());
|
||||
$environment->addExtension(new TableExtension());
|
||||
$environment->addExtension(new TaskListExtension());
|
||||
}
|
||||
}
|
||||
33
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalink.php
vendored
Normal file
33
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalink.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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\Extension\HeadingPermalink;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
/**
|
||||
* Represents an anchor link within a heading
|
||||
*/
|
||||
final class HeadingPermalink extends AbstractInline
|
||||
{
|
||||
/** @var string */
|
||||
private $slug;
|
||||
|
||||
public function __construct(string $slug)
|
||||
{
|
||||
$this->slug = $slug;
|
||||
}
|
||||
|
||||
public function getSlug(): string
|
||||
{
|
||||
return $this->slug;
|
||||
}
|
||||
}
|
||||
28
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkExtension.php
vendored
Normal file
28
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkExtension.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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\Extension\HeadingPermalink;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
/**
|
||||
* Extension which automatically anchor links to heading elements
|
||||
*/
|
||||
final class HeadingPermalinkExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addEventListener(DocumentParsedEvent::class, new HeadingPermalinkProcessor(), -100);
|
||||
$environment->addInlineRenderer(HeadingPermalink::class, new HeadingPermalinkRenderer());
|
||||
}
|
||||
}
|
||||
147
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkProcessor.php
vendored
Normal file
147
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkProcessor.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?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\Extension\HeadingPermalink;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\Heading;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Exception\InvalidOptionException;
|
||||
use League\CommonMark\Extension\HeadingPermalink\Slug\SlugGeneratorInterface as DeprecatedSlugGeneratorInterface;
|
||||
use League\CommonMark\Inline\Element\AbstractStringContainer;
|
||||
use League\CommonMark\Node\Node;
|
||||
use League\CommonMark\Normalizer\SlugNormalizer;
|
||||
use League\CommonMark\Normalizer\TextNormalizerInterface;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* Searches the Document for Heading elements and adds HeadingPermalinks to each one
|
||||
*/
|
||||
final class HeadingPermalinkProcessor implements ConfigurationAwareInterface
|
||||
{
|
||||
const INSERT_BEFORE = 'before';
|
||||
const INSERT_AFTER = 'after';
|
||||
|
||||
/** @var TextNormalizerInterface|DeprecatedSlugGeneratorInterface */
|
||||
private $slugNormalizer;
|
||||
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param TextNormalizerInterface|DeprecatedSlugGeneratorInterface|null $slugNormalizer
|
||||
*/
|
||||
public function __construct($slugNormalizer = null)
|
||||
{
|
||||
if ($slugNormalizer instanceof DeprecatedSlugGeneratorInterface) {
|
||||
@trigger_error(sprintf('Passing a %s into the %s constructor is deprecated; use a %s instead', DeprecatedSlugGeneratorInterface::class, self::class, TextNormalizerInterface::class), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->slugNormalizer = $slugNormalizer ?? new SlugNormalizer();
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
|
||||
public function __invoke(DocumentParsedEvent $e): void
|
||||
{
|
||||
$this->useNormalizerFromConfigurationIfProvided();
|
||||
|
||||
$walker = $e->getDocument()->walker();
|
||||
|
||||
while ($event = $walker->next()) {
|
||||
$node = $event->getNode();
|
||||
if ($node instanceof Heading && $event->isEntering()) {
|
||||
$this->addHeadingLink($node, $e->getDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function useNormalizerFromConfigurationIfProvided(): void
|
||||
{
|
||||
$generator = $this->config->get('heading_permalink/slug_normalizer');
|
||||
if ($generator === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!($generator instanceof DeprecatedSlugGeneratorInterface || $generator instanceof TextNormalizerInterface)) {
|
||||
throw new InvalidOptionException('The heading_permalink/slug_normalizer option must be an instance of ' . TextNormalizerInterface::class);
|
||||
}
|
||||
|
||||
$this->slugNormalizer = $generator;
|
||||
}
|
||||
|
||||
private function addHeadingLink(Heading $heading, Document $document): void
|
||||
{
|
||||
$text = $this->getChildText($heading);
|
||||
if ($this->slugNormalizer instanceof DeprecatedSlugGeneratorInterface) {
|
||||
$slug = $this->slugNormalizer->createSlug($text);
|
||||
} else {
|
||||
$slug = $this->slugNormalizer->normalize($text, $heading);
|
||||
}
|
||||
|
||||
$slug = $this->ensureUnique($slug, $document);
|
||||
|
||||
$headingLinkAnchor = new HeadingPermalink($slug);
|
||||
|
||||
switch ($this->config->get('heading_permalink/insert', 'before')) {
|
||||
case self::INSERT_BEFORE:
|
||||
$heading->prependChild($headingLinkAnchor);
|
||||
|
||||
return;
|
||||
case self::INSERT_AFTER:
|
||||
$heading->appendChild($headingLinkAnchor);
|
||||
|
||||
return;
|
||||
default:
|
||||
throw new \RuntimeException("Invalid configuration value for heading_permalink/insert; expected 'before' or 'after'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Not needed in 2.0
|
||||
*/
|
||||
private function getChildText(Node $node): string
|
||||
{
|
||||
$text = '';
|
||||
|
||||
$walker = $node->walker();
|
||||
while ($event = $walker->next()) {
|
||||
if ($event->isEntering() && (($child = $event->getNode()) instanceof AbstractStringContainer)) {
|
||||
$text .= $child->getContent();
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
private function ensureUnique(string $proposed, Document $document): string
|
||||
{
|
||||
// Quick path, it's a unique ID
|
||||
if (!isset($document->data['heading_ids'][$proposed])) {
|
||||
$document->data['heading_ids'][$proposed] = true;
|
||||
|
||||
return $proposed;
|
||||
}
|
||||
|
||||
$extension = 0;
|
||||
do {
|
||||
++$extension;
|
||||
} while (isset($document->data['heading_ids']["$proposed-$extension"]));
|
||||
|
||||
$document->data['heading_ids']["$proposed-$extension"] = true;
|
||||
|
||||
return "$proposed-$extension";
|
||||
}
|
||||
}
|
||||
72
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkRenderer.php
vendored
Normal file
72
vendor/league/commonmark/src/Extension/HeadingPermalink/HeadingPermalinkRenderer.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?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\Extension\HeadingPermalink;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* Renders the HeadingPermalink elements
|
||||
*/
|
||||
final class HeadingPermalinkRenderer implements InlineRendererInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @deprecated */
|
||||
const DEFAULT_INNER_CONTENTS = '<svg class="heading-permalink-icon" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>';
|
||||
|
||||
const DEFAULT_SYMBOL = '¶';
|
||||
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
if (!$inline instanceof HeadingPermalink) {
|
||||
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
|
||||
}
|
||||
|
||||
$slug = $inline->getSlug();
|
||||
|
||||
$idPrefix = (string) $this->config->get('heading_permalink/id_prefix', 'user-content');
|
||||
if ($idPrefix !== '') {
|
||||
$idPrefix .= '-';
|
||||
}
|
||||
|
||||
$attrs = [
|
||||
'id' => $idPrefix . $slug,
|
||||
'href' => '#' . $slug,
|
||||
'name' => $slug,
|
||||
'class' => $this->config->get('heading_permalink/html_class', 'heading-permalink'),
|
||||
'aria-hidden' => 'true',
|
||||
'title' => $this->config->get('heading_permalink/title', 'Permalink'),
|
||||
];
|
||||
|
||||
$innerContents = $this->config->get('heading_permalink/inner_contents');
|
||||
if ($innerContents !== null) {
|
||||
@trigger_error(sprintf('The %s config option is deprecated; use %s instead', 'inner_contents', 'symbol'), E_USER_DEPRECATED);
|
||||
|
||||
return new HtmlElement('a', $attrs, $innerContents, false);
|
||||
}
|
||||
|
||||
$symbol = $this->config->get('heading_permalink/symbol', self::DEFAULT_SYMBOL);
|
||||
|
||||
return new HtmlElement('a', $attrs, \htmlspecialchars($symbol), false);
|
||||
}
|
||||
}
|
||||
38
vendor/league/commonmark/src/Extension/HeadingPermalink/Slug/DefaultSlugGenerator.php
vendored
Normal file
38
vendor/league/commonmark/src/Extension/HeadingPermalink/Slug/DefaultSlugGenerator.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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\Extension\HeadingPermalink\Slug;
|
||||
|
||||
use League\CommonMark\Normalizer\SlugNormalizer;
|
||||
|
||||
@trigger_error(sprintf('%s is deprecated; use %s instead', DefaultSlugGenerator::class, SlugNormalizer::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Creates URL-friendly strings
|
||||
*
|
||||
* @deprecated Use League\CommonMark\Normalizer\SlugNormalizer instead
|
||||
*/
|
||||
final class DefaultSlugGenerator implements SlugGeneratorInterface
|
||||
{
|
||||
public function createSlug(string $input): string
|
||||
{
|
||||
// Trim whitespace
|
||||
$slug = \trim($input);
|
||||
// Convert to lowercase
|
||||
$slug = \mb_strtolower($slug);
|
||||
// Try replacing whitespace with a dash
|
||||
$slug = \preg_replace('/\s+/u', '-', $slug) ?? $slug;
|
||||
// Try removing characters other than letters, numbers, and marks.
|
||||
$slug = \preg_replace('/[^\p{L}\p{Nd}\p{Nl}\p{M}-]+/u', '', $slug) ?? $slug;
|
||||
|
||||
return $slug;
|
||||
}
|
||||
}
|
||||
31
vendor/league/commonmark/src/Extension/HeadingPermalink/Slug/SlugGeneratorInterface.php
vendored
Normal file
31
vendor/league/commonmark/src/Extension/HeadingPermalink/Slug/SlugGeneratorInterface.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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\Extension\HeadingPermalink\Slug;
|
||||
|
||||
use League\CommonMark\Normalizer\TextNormalizerInterface;
|
||||
|
||||
@trigger_error(sprintf('%s is deprecated; use %s instead', SlugGeneratorInterface::class, TextNormalizerInterface::class), E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* @deprecated Use League\CommonMark\Normalizer\TextNormalizerInterface instead
|
||||
*/
|
||||
interface SlugGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* Create a URL-friendly slug based on the given input string
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createSlug(string $input): string;
|
||||
}
|
||||
46
vendor/league/commonmark/src/Extension/InlinesOnly/ChildRenderer.php
vendored
Normal file
46
vendor/league/commonmark/src/Extension/InlinesOnly/ChildRenderer.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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\Extension\InlinesOnly;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\InlineContainerInterface;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
/**
|
||||
* Simply renders child elements as-is, adding newlines as needed.
|
||||
*/
|
||||
final class ChildRenderer implements BlockRendererInterface
|
||||
{
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
$out = '';
|
||||
|
||||
if ($block instanceof InlineContainerInterface) {
|
||||
/** @var iterable<AbstractInline> $children */
|
||||
$children = $block->children();
|
||||
$out .= $htmlRenderer->renderInlines($children);
|
||||
} else {
|
||||
/** @var iterable<AbstractBlock> $children */
|
||||
$children = $block->children();
|
||||
$out .= $htmlRenderer->renderBlocks($children);
|
||||
}
|
||||
|
||||
if (!($block instanceof Document)) {
|
||||
$out .= "\n";
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
63
vendor/league/commonmark/src/Extension/InlinesOnly/InlinesOnlyExtension.php
vendored
Normal file
63
vendor/league/commonmark/src/Extension/InlinesOnly/InlinesOnlyExtension.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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\Extension\InlinesOnly;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\Paragraph;
|
||||
use League\CommonMark\Block\Parser as BlockParser;
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Inline\Element as InlineElement;
|
||||
use League\CommonMark\Inline\Parser as InlineParser;
|
||||
use League\CommonMark\Inline\Renderer as InlineRenderer;
|
||||
|
||||
final class InlinesOnlyExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$childRenderer = new ChildRenderer();
|
||||
|
||||
$environment
|
||||
->addBlockParser(new BlockParser\LazyParagraphParser(), -200)
|
||||
|
||||
->addInlineParser(new InlineParser\NewlineParser(), 200)
|
||||
->addInlineParser(new InlineParser\BacktickParser(), 150)
|
||||
->addInlineParser(new InlineParser\EscapableParser(), 80)
|
||||
->addInlineParser(new InlineParser\EntityParser(), 70)
|
||||
->addInlineParser(new InlineParser\AutolinkParser(), 50)
|
||||
->addInlineParser(new InlineParser\HtmlInlineParser(), 40)
|
||||
->addInlineParser(new InlineParser\CloseBracketParser(), 30)
|
||||
->addInlineParser(new InlineParser\OpenBracketParser(), 20)
|
||||
->addInlineParser(new InlineParser\BangParser(), 10)
|
||||
|
||||
->addBlockRenderer(Document::class, $childRenderer, 0)
|
||||
->addBlockRenderer(Paragraph::class, $childRenderer, 0)
|
||||
|
||||
->addInlineRenderer(InlineElement\Code::class, new InlineRenderer\CodeRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Emphasis::class, new InlineRenderer\EmphasisRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\HtmlInline::class, new InlineRenderer\HtmlInlineRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Image::class, new InlineRenderer\ImageRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Link::class, new InlineRenderer\LinkRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Newline::class, new InlineRenderer\NewlineRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Strong::class, new InlineRenderer\StrongRenderer(), 0)
|
||||
->addInlineRenderer(InlineElement\Text::class, new InlineRenderer\TextRenderer(), 0)
|
||||
;
|
||||
|
||||
if ($environment->getConfig('use_asterisk', true)) {
|
||||
$environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*'));
|
||||
}
|
||||
if ($environment->getConfig('use_underscore', true)) {
|
||||
$environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
48
vendor/league/commonmark/src/Extension/Mention/Generator/CallbackGenerator.php
vendored
Normal file
48
vendor/league/commonmark/src/Extension/Mention/Generator/CallbackGenerator.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Extension\Mention\Generator;
|
||||
|
||||
use League\CommonMark\Extension\Mention\Mention;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
final class CallbackGenerator implements MentionGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* A callback function which sets the URL on the passed mention and returns the mention, return a new AbstractInline based object or null if the mention is not a match
|
||||
*
|
||||
* @var callable(Mention): ?AbstractInline
|
||||
*/
|
||||
private $callback;
|
||||
|
||||
public function __construct(callable $callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
public function generateMention(Mention $mention): ?AbstractInline
|
||||
{
|
||||
$result = \call_user_func_array($this->callback, [$mention]);
|
||||
if ($result === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($result instanceof AbstractInline && !($result instanceof Mention)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if ($result instanceof Mention && $result->hasUrl()) {
|
||||
return $mention;
|
||||
}
|
||||
|
||||
throw new \RuntimeException('CallbackGenerator callable must set the URL on the passed mention and return the mention, return a new AbstractInline based object or null if the mention is not a match');
|
||||
}
|
||||
}
|
||||
25
vendor/league/commonmark/src/Extension/Mention/Generator/MentionGeneratorInterface.php
vendored
Normal file
25
vendor/league/commonmark/src/Extension/Mention/Generator/MentionGeneratorInterface.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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\Extension\Mention\Generator;
|
||||
|
||||
use League\CommonMark\Extension\Mention\Mention;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
interface MentionGeneratorInterface
|
||||
{
|
||||
/**
|
||||
* @param Mention $mention
|
||||
*
|
||||
* @return AbstractInline|null
|
||||
*/
|
||||
public function generateMention(Mention $mention): ?AbstractInline;
|
||||
}
|
||||
31
vendor/league/commonmark/src/Extension/Mention/Generator/StringTemplateLinkGenerator.php
vendored
Normal file
31
vendor/league/commonmark/src/Extension/Mention/Generator/StringTemplateLinkGenerator.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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\Extension\Mention\Generator;
|
||||
|
||||
use League\CommonMark\Extension\Mention\Mention;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
final class StringTemplateLinkGenerator implements MentionGeneratorInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $urlTemplate;
|
||||
|
||||
public function __construct(string $urlTemplate)
|
||||
{
|
||||
$this->urlTemplate = $urlTemplate;
|
||||
}
|
||||
|
||||
public function generateMention(Mention $mention): ?AbstractInline
|
||||
{
|
||||
return $mention->setUrl(\sprintf($this->urlTemplate, $mention->getIdentifier()));
|
||||
}
|
||||
}
|
||||
104
vendor/league/commonmark/src/Extension/Mention/Mention.php
vendored
Normal file
104
vendor/league/commonmark/src/Extension/Mention/Mention.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?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\Extension\Mention;
|
||||
|
||||
use League\CommonMark\Inline\Element\Link;
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
|
||||
class Mention extends Link
|
||||
{
|
||||
/** @var string */
|
||||
private $symbol;
|
||||
|
||||
/** @var string */
|
||||
private $identifier;
|
||||
|
||||
/**
|
||||
* @param string $symbol
|
||||
* @param string $identifier
|
||||
* @param string $label
|
||||
*/
|
||||
public function __construct(string $symbol, string $identifier, string $label = null)
|
||||
{
|
||||
$this->symbol = $symbol;
|
||||
$this->identifier = $identifier;
|
||||
|
||||
parent::__construct('', $label ?? \sprintf('%s%s', $symbol, $identifier));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getLabel(): ?string
|
||||
{
|
||||
if (($labelNode = $this->findLabelNode()) === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $labelNode->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier(): string
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSymbol(): string
|
||||
{
|
||||
return $this->symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUrl(): bool
|
||||
{
|
||||
return !empty($this->url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $label
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLabel(string $label): self
|
||||
{
|
||||
if (($labelNode = $this->findLabelNode()) === null) {
|
||||
$labelNode = new Text();
|
||||
$this->prependChild($labelNode);
|
||||
}
|
||||
|
||||
$labelNode->setContent($label);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function findLabelNode(): ?Text
|
||||
{
|
||||
foreach ($this->children() as $child) {
|
||||
if ($child instanceof Text) {
|
||||
return $child;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
65
vendor/league/commonmark/src/Extension/Mention/MentionExtension.php
vendored
Normal file
65
vendor/league/commonmark/src/Extension/Mention/MentionExtension.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?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\Extension\Mention;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Exception\InvalidOptionException;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Extension\Mention\Generator\MentionGeneratorInterface;
|
||||
|
||||
final class MentionExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$mentions = $environment->getConfig('mentions', []);
|
||||
foreach ($mentions as $name => $mention) {
|
||||
if (\array_key_exists('symbol', $mention)) {
|
||||
@\trigger_error('The "mentions/*/symbol" configuration option is deprecated in league/commonmark 1.6; rename "symbol" to "prefix" for compatibility with 2.0', \E_USER_DEPRECATED);
|
||||
$mention['prefix'] = $mention['symbol'];
|
||||
}
|
||||
|
||||
if (\array_key_exists('pattern', $mention)) {
|
||||
// v2.0 does not allow full regex patterns passed into the configuration
|
||||
if (!self::isAValidPartialRegex($mention['pattern'])) {
|
||||
throw new InvalidOptionException(\sprintf('Option "mentions/%s/pattern" must not include starting/ending delimiters (like "/")', $name));
|
||||
}
|
||||
|
||||
$mention['pattern'] = '/' . $mention['pattern'] . '/i';
|
||||
} elseif (\array_key_exists('regex', $mention)) {
|
||||
@\trigger_error('The "mentions/*/regex" configuration option is deprecated in league/commonmark 1.6; rename "regex" to "pattern" for compatibility with 2.0', \E_USER_DEPRECATED);
|
||||
$mention['pattern'] = $mention['regex'];
|
||||
}
|
||||
|
||||
foreach (['prefix', 'pattern', 'generator'] as $key) {
|
||||
if (empty($mention[$key])) {
|
||||
throw new \RuntimeException("Missing \"$key\" from MentionParser configuration");
|
||||
}
|
||||
}
|
||||
if ($mention['generator'] instanceof MentionGeneratorInterface) {
|
||||
$environment->addInlineParser(new MentionParser($mention['prefix'], $mention['pattern'], $mention['generator']));
|
||||
} elseif (is_string($mention['generator'])) {
|
||||
$environment->addInlineParser(MentionParser::createWithStringTemplate($mention['prefix'], $mention['pattern'], $mention['generator']));
|
||||
} elseif (is_callable($mention['generator'])) {
|
||||
$environment->addInlineParser(MentionParser::createWithCallback($mention['prefix'], $mention['pattern'], $mention['generator']));
|
||||
} else {
|
||||
throw new \RuntimeException(sprintf('The "generator" provided for the MentionParser configuration must be a string template, callable, or an object that implements %s.', MentionGeneratorInterface::class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function isAValidPartialRegex(string $regex): bool
|
||||
{
|
||||
$regex = '/' . $regex . '/i';
|
||||
|
||||
return @\preg_match($regex, '') !== false;
|
||||
}
|
||||
}
|
||||
91
vendor/league/commonmark/src/Extension/Mention/MentionParser.php
vendored
Normal file
91
vendor/league/commonmark/src/Extension/Mention/MentionParser.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?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\Extension\Mention;
|
||||
|
||||
use League\CommonMark\Extension\Mention\Generator\CallbackGenerator;
|
||||
use League\CommonMark\Extension\Mention\Generator\MentionGeneratorInterface;
|
||||
use League\CommonMark\Extension\Mention\Generator\StringTemplateLinkGenerator;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
|
||||
final class MentionParser implements InlineParserInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $symbol;
|
||||
|
||||
/** @var string */
|
||||
private $mentionRegex;
|
||||
|
||||
/** @var MentionGeneratorInterface */
|
||||
private $mentionGenerator;
|
||||
|
||||
public function __construct(string $symbol, string $mentionRegex, MentionGeneratorInterface $mentionGenerator)
|
||||
{
|
||||
$this->symbol = $symbol;
|
||||
$this->mentionRegex = $mentionRegex;
|
||||
$this->mentionGenerator = $mentionGenerator;
|
||||
}
|
||||
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return [$this->symbol];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
|
||||
// The symbol must not have any other characters immediately prior
|
||||
$previousChar = $cursor->peek(-1);
|
||||
if ($previousChar !== null && \preg_match('/\w/', $previousChar)) {
|
||||
// peek() doesn't modify the cursor, so no need to restore state first
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the cursor state in case we need to rewind and bail
|
||||
$previousState = $cursor->saveState();
|
||||
|
||||
// Advance past the symbol to keep parsing simpler
|
||||
$cursor->advance();
|
||||
|
||||
// Parse the mention match value
|
||||
$identifier = $cursor->match($this->mentionRegex);
|
||||
if ($identifier === null) {
|
||||
// Regex failed to match; this isn't a valid mention
|
||||
$cursor->restoreState($previousState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$mention = $this->mentionGenerator->generateMention(new Mention($this->symbol, $identifier));
|
||||
|
||||
if ($mention === null) {
|
||||
$cursor->restoreState($previousState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$inlineContext->getContainer()->appendChild($mention);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function createWithStringTemplate(string $symbol, string $mentionRegex, string $urlTemplate): MentionParser
|
||||
{
|
||||
return new self($symbol, $mentionRegex, new StringTemplateLinkGenerator($urlTemplate));
|
||||
}
|
||||
|
||||
public static function createWithCallback(string $symbol, string $mentionRegex, callable $callback): MentionParser
|
||||
{
|
||||
return new self($symbol, $mentionRegex, new CallbackGenerator($callback));
|
||||
}
|
||||
}
|
||||
70
vendor/league/commonmark/src/Extension/SmartPunct/PunctuationParser.php
vendored
Normal file
70
vendor/league/commonmark/src/Extension/SmartPunct/PunctuationParser.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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 (http://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\Extension\SmartPunct;
|
||||
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
|
||||
final class PunctuationParser implements InlineParserInterface
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return ['-', '.'];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$ch = $cursor->getCharacter();
|
||||
|
||||
// Ellipses
|
||||
if ($ch === '.' && $matched = $cursor->match('/^\\.( ?\\.)\\1/')) {
|
||||
$inlineContext->getContainer()->appendChild(new Text('…'));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Em/En-dashes
|
||||
elseif ($ch === '-' && $matched = $cursor->match('/^(?<!-)(-{2,})/')) {
|
||||
$count = strlen($matched);
|
||||
$en_dash = '–';
|
||||
$en_count = 0;
|
||||
$em_dash = '—';
|
||||
$em_count = 0;
|
||||
if ($count % 3 === 0) { // If divisible by 3, use all em dashes
|
||||
$em_count = $count / 3;
|
||||
} elseif ($count % 2 === 0) { // If divisible by 2, use all en dashes
|
||||
$en_count = $count / 2;
|
||||
} elseif ($count % 3 === 2) { // If 2 extra dashes, use en dash for last 2; em dashes for rest
|
||||
$em_count = ($count - 2) / 3;
|
||||
$en_count = 1;
|
||||
} else { // Use en dashes for last 4 hyphens; em dashes for rest
|
||||
$em_count = ($count - 4) / 3;
|
||||
$en_count = 2;
|
||||
}
|
||||
$inlineContext->getContainer()->appendChild(new Text(
|
||||
str_repeat($em_dash, (int) $em_count) . str_repeat($en_dash, (int) $en_count)
|
||||
));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
28
vendor/league/commonmark/src/Extension/SmartPunct/Quote.php
vendored
Normal file
28
vendor/league/commonmark/src/Extension/SmartPunct/Quote.php
vendored
Normal 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 (http://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\Extension\SmartPunct;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractStringContainer;
|
||||
|
||||
final class Quote extends AbstractStringContainer
|
||||
{
|
||||
public const DOUBLE_QUOTE = '"';
|
||||
public const DOUBLE_QUOTE_OPENER = '“';
|
||||
public const DOUBLE_QUOTE_CLOSER = '”';
|
||||
|
||||
public const SINGLE_QUOTE = "'";
|
||||
public const SINGLE_QUOTE_OPENER = '‘';
|
||||
public const SINGLE_QUOTE_CLOSER = '’';
|
||||
}
|
||||
104
vendor/league/commonmark/src/Extension/SmartPunct/QuoteParser.php
vendored
Normal file
104
vendor/league/commonmark/src/Extension/SmartPunct/QuoteParser.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?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 (http://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\Extension\SmartPunct;
|
||||
|
||||
use League\CommonMark\Delimiter\Delimiter;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
use League\CommonMark\Util\RegexHelper;
|
||||
|
||||
final class QuoteParser implements InlineParserInterface
|
||||
{
|
||||
public const DOUBLE_QUOTES = [Quote::DOUBLE_QUOTE, Quote::DOUBLE_QUOTE_OPENER, Quote::DOUBLE_QUOTE_CLOSER];
|
||||
public const SINGLE_QUOTES = [Quote::SINGLE_QUOTE, Quote::SINGLE_QUOTE_OPENER, Quote::SINGLE_QUOTE_CLOSER];
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return array_merge(self::DOUBLE_QUOTES, self::SINGLE_QUOTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes any quote characters found and manually adds them to the delimiter stack
|
||||
*/
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$normalizedCharacter = $this->getNormalizedQuoteCharacter($cursor->getCharacter());
|
||||
|
||||
$charBefore = $cursor->peek(-1);
|
||||
if ($charBefore === null) {
|
||||
$charBefore = "\n";
|
||||
}
|
||||
|
||||
$cursor->advance();
|
||||
|
||||
$charAfter = $cursor->getCharacter();
|
||||
if ($charAfter === null) {
|
||||
$charAfter = "\n";
|
||||
}
|
||||
|
||||
[$leftFlanking, $rightFlanking] = $this->determineFlanking($charBefore, $charAfter);
|
||||
$canOpen = $leftFlanking && !$rightFlanking;
|
||||
$canClose = $rightFlanking;
|
||||
|
||||
$node = new Quote($normalizedCharacter, ['delim' => true]);
|
||||
$inlineContext->getContainer()->appendChild($node);
|
||||
|
||||
// Add entry to stack to this opener
|
||||
$inlineContext->getDelimiterStack()->push(new Delimiter($normalizedCharacter, 1, $node, $canOpen, $canClose));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getNormalizedQuoteCharacter(string $character): string
|
||||
{
|
||||
if (in_array($character, self::DOUBLE_QUOTES)) {
|
||||
return Quote::DOUBLE_QUOTE;
|
||||
} elseif (in_array($character, self::SINGLE_QUOTES)) {
|
||||
return Quote::SINGLE_QUOTE;
|
||||
}
|
||||
|
||||
return $character;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $charBefore
|
||||
* @param string $charAfter
|
||||
*
|
||||
* @return bool[]
|
||||
*/
|
||||
private function determineFlanking(string $charBefore, string $charAfter)
|
||||
{
|
||||
$afterIsWhitespace = preg_match('/\pZ|\s/u', $charAfter);
|
||||
$afterIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charAfter);
|
||||
$beforeIsWhitespace = preg_match('/\pZ|\s/u', $charBefore);
|
||||
$beforeIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charBefore);
|
||||
|
||||
$leftFlanking = !$afterIsWhitespace &&
|
||||
!($afterIsPunctuation &&
|
||||
!$beforeIsWhitespace &&
|
||||
!$beforeIsPunctuation);
|
||||
|
||||
$rightFlanking = !$beforeIsWhitespace &&
|
||||
!($beforeIsPunctuation &&
|
||||
!$afterIsWhitespace &&
|
||||
!$afterIsPunctuation);
|
||||
|
||||
return [$leftFlanking, $rightFlanking];
|
||||
}
|
||||
}
|
||||
90
vendor/league/commonmark/src/Extension/SmartPunct/QuoteProcessor.php
vendored
Normal file
90
vendor/league/commonmark/src/Extension/SmartPunct/QuoteProcessor.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?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 (http://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\Extension\SmartPunct;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterInterface;
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface;
|
||||
use League\CommonMark\Inline\Element\AbstractStringContainer;
|
||||
|
||||
final class QuoteProcessor implements DelimiterProcessorInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $normalizedCharacter;
|
||||
|
||||
/** @var string */
|
||||
private $openerCharacter;
|
||||
|
||||
/** @var string */
|
||||
private $closerCharacter;
|
||||
|
||||
private function __construct(string $char, string $opener, string $closer)
|
||||
{
|
||||
$this->normalizedCharacter = $char;
|
||||
$this->openerCharacter = $opener;
|
||||
$this->closerCharacter = $closer;
|
||||
}
|
||||
|
||||
public function getOpeningCharacter(): string
|
||||
{
|
||||
return $this->normalizedCharacter;
|
||||
}
|
||||
|
||||
public function getClosingCharacter(): string
|
||||
{
|
||||
return $this->normalizedCharacter;
|
||||
}
|
||||
|
||||
public function getMinLength(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse)
|
||||
{
|
||||
$opener->insertAfter(new Quote($this->openerCharacter));
|
||||
$closer->insertBefore(new Quote($this->closerCharacter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a double-quote processor
|
||||
*
|
||||
* @param string $opener
|
||||
* @param string $closer
|
||||
*
|
||||
* @return QuoteProcessor
|
||||
*/
|
||||
public static function createDoubleQuoteProcessor(string $opener = Quote::DOUBLE_QUOTE_OPENER, string $closer = Quote::DOUBLE_QUOTE_CLOSER): self
|
||||
{
|
||||
return new self(Quote::DOUBLE_QUOTE, $opener, $closer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single-quote processor
|
||||
*
|
||||
* @param string $opener
|
||||
* @param string $closer
|
||||
*
|
||||
* @return QuoteProcessor
|
||||
*/
|
||||
public static function createSingleQuoteProcessor(string $opener = Quote::SINGLE_QUOTE_OPENER, string $closer = Quote::SINGLE_QUOTE_CLOSER): self
|
||||
{
|
||||
return new self(Quote::SINGLE_QUOTE, $opener, $closer);
|
||||
}
|
||||
}
|
||||
47
vendor/league/commonmark/src/Extension/SmartPunct/QuoteRenderer.php
vendored
Normal file
47
vendor/league/commonmark/src/Extension/SmartPunct/QuoteRenderer.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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 (http://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\Extension\SmartPunct;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
|
||||
final class QuoteRenderer implements InlineRendererInterface
|
||||
{
|
||||
/**
|
||||
* @param Quote $inline
|
||||
* @param ElementRendererInterface $htmlRenderer
|
||||
*
|
||||
* @return HtmlElement|string|null
|
||||
*/
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
if (!$inline instanceof Quote) {
|
||||
throw new \InvalidArgumentException(sprintf('Expected an instance of "%s", got "%s" instead', Quote::class, get_class($inline)));
|
||||
}
|
||||
|
||||
// Handles unpaired quotes which remain after processing delimiters
|
||||
if ($inline->getContent() === Quote::SINGLE_QUOTE) {
|
||||
// Render as an apostrophe
|
||||
return Quote::SINGLE_QUOTE_CLOSER;
|
||||
} elseif ($inline->getContent() === Quote::DOUBLE_QUOTE) {
|
||||
// Render as an opening quote
|
||||
return Quote::DOUBLE_QUOTE_OPENER;
|
||||
}
|
||||
|
||||
return $inline->getContent();
|
||||
}
|
||||
}
|
||||
49
vendor/league/commonmark/src/Extension/SmartPunct/SmartPunctExtension.php
vendored
Normal file
49
vendor/league/commonmark/src/Extension/SmartPunct/SmartPunctExtension.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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 (http://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\Extension\SmartPunct;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\Paragraph;
|
||||
use League\CommonMark\Block\Renderer as CoreBlockRenderer;
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Inline\Element\Text;
|
||||
use League\CommonMark\Inline\Renderer as CoreInlineRenderer;
|
||||
|
||||
final class SmartPunctExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment
|
||||
->addInlineParser(new QuoteParser(), 10)
|
||||
->addInlineParser(new PunctuationParser(), 0)
|
||||
|
||||
->addDelimiterProcessor(QuoteProcessor::createDoubleQuoteProcessor(
|
||||
$environment->getConfig('smartpunct/double_quote_opener', Quote::DOUBLE_QUOTE_OPENER),
|
||||
$environment->getConfig('smartpunct/double_quote_closer', Quote::DOUBLE_QUOTE_CLOSER)
|
||||
))
|
||||
->addDelimiterProcessor(QuoteProcessor::createSingleQuoteProcessor(
|
||||
$environment->getConfig('smartpunct/single_quote_opener', Quote::SINGLE_QUOTE_OPENER),
|
||||
$environment->getConfig('smartpunct/single_quote_closer', Quote::SINGLE_QUOTE_CLOSER)
|
||||
))
|
||||
|
||||
->addBlockRenderer(Document::class, new CoreBlockRenderer\DocumentRenderer(), 0)
|
||||
->addBlockRenderer(Paragraph::class, new CoreBlockRenderer\ParagraphRenderer(), 0)
|
||||
|
||||
->addInlineRenderer(Quote::class, new QuoteRenderer(), 100)
|
||||
->addInlineRenderer(Text::class, new CoreInlineRenderer\TextRenderer(), 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
22
vendor/league/commonmark/src/Extension/Strikethrough/Strikethrough.php
vendored
Normal file
22
vendor/league/commonmark/src/Extension/Strikethrough/Strikethrough.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com)
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Strikethrough;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
final class Strikethrough extends AbstractInline
|
||||
{
|
||||
public function isContainer(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
55
vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughDelimiterProcessor.php
vendored
Normal file
55
vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughDelimiterProcessor.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com)
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Strikethrough;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterInterface;
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface;
|
||||
use League\CommonMark\Inline\Element\AbstractStringContainer;
|
||||
|
||||
final class StrikethroughDelimiterProcessor implements DelimiterProcessorInterface
|
||||
{
|
||||
public function getOpeningCharacter(): string
|
||||
{
|
||||
return '~';
|
||||
}
|
||||
|
||||
public function getClosingCharacter(): string
|
||||
{
|
||||
return '~';
|
||||
}
|
||||
|
||||
public function getMinLength(): int
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int
|
||||
{
|
||||
$min = \min($opener->getLength(), $closer->getLength());
|
||||
|
||||
return $min >= 2 ? $min : 0;
|
||||
}
|
||||
|
||||
public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse)
|
||||
{
|
||||
$strikethrough = new Strikethrough();
|
||||
|
||||
$tmp = $opener->next();
|
||||
while ($tmp !== null && $tmp !== $closer) {
|
||||
$next = $tmp->next();
|
||||
$strikethrough->appendChild($tmp);
|
||||
$tmp = $next;
|
||||
}
|
||||
|
||||
$opener->insertAfter($strikethrough);
|
||||
}
|
||||
}
|
||||
24
vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughExtension.php
vendored
Normal file
24
vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughExtension.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com)
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Strikethrough;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
final class StrikethroughExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor());
|
||||
$environment->addInlineRenderer(Strikethrough::class, new StrikethroughRenderer());
|
||||
}
|
||||
}
|
||||
29
vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughRenderer.php
vendored
Normal file
29
vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughRenderer.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com)
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Strikethrough;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
|
||||
final class StrikethroughRenderer implements InlineRendererInterface
|
||||
{
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
if (!($inline instanceof Strikethrough)) {
|
||||
throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
|
||||
}
|
||||
|
||||
return new HtmlElement('del', $inline->getData('attributes', []), $htmlRenderer->renderInlines($inline->children()));
|
||||
}
|
||||
}
|
||||
69
vendor/league/commonmark/src/Extension/Table/Table.php
vendored
Normal file
69
vendor/league/commonmark/src/Extension/Table/Table.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Element\AbstractStringContainerBlock;
|
||||
use League\CommonMark\Block\Element\InlineContainerInterface;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
|
||||
final class Table extends AbstractStringContainerBlock implements InlineContainerInterface
|
||||
{
|
||||
/** @var TableSection */
|
||||
private $head;
|
||||
/** @var TableSection */
|
||||
private $body;
|
||||
/** @var \Closure */
|
||||
private $parser;
|
||||
|
||||
public function __construct(\Closure $parser)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->appendChild($this->head = new TableSection(TableSection::TYPE_HEAD));
|
||||
$this->appendChild($this->body = new TableSection(TableSection::TYPE_BODY));
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return $block instanceof TableSection;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getHead(): TableSection
|
||||
{
|
||||
return $this->head;
|
||||
}
|
||||
|
||||
public function getBody(): TableSection
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return call_user_func($this->parser, $cursor, $this);
|
||||
}
|
||||
|
||||
public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void
|
||||
{
|
||||
}
|
||||
}
|
||||
66
vendor/league/commonmark/src/Extension/Table/TableCell.php
vendored
Normal file
66
vendor/league/commonmark/src/Extension/Table/TableCell.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Element\AbstractStringContainerBlock;
|
||||
use League\CommonMark\Block\Element\InlineContainerInterface;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
|
||||
final class TableCell extends AbstractStringContainerBlock implements InlineContainerInterface
|
||||
{
|
||||
const TYPE_HEAD = 'th';
|
||||
const TYPE_BODY = 'td';
|
||||
|
||||
const ALIGN_LEFT = 'left';
|
||||
const ALIGN_RIGHT = 'right';
|
||||
const ALIGN_CENTER = 'center';
|
||||
|
||||
/** @var string */
|
||||
public $type = self::TYPE_BODY;
|
||||
|
||||
/** @var string|null */
|
||||
public $align;
|
||||
|
||||
public function __construct(string $string = '', string $type = self::TYPE_BODY, string $align = null)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->finalStringContents = $string;
|
||||
$this->addLine($string);
|
||||
$this->type = $type;
|
||||
$this->align = $align;
|
||||
}
|
||||
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void
|
||||
{
|
||||
}
|
||||
}
|
||||
39
vendor/league/commonmark/src/Extension/Table/TableCellRenderer.php
vendored
Normal file
39
vendor/league/commonmark/src/Extension/Table/TableCellRenderer.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
|
||||
final class TableCellRenderer implements BlockRendererInterface
|
||||
{
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
if (!$block instanceof TableCell) {
|
||||
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
|
||||
}
|
||||
|
||||
$attrs = $block->getData('attributes', []);
|
||||
|
||||
if ($block->align !== null) {
|
||||
$attrs['align'] = $block->align;
|
||||
}
|
||||
|
||||
return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children()));
|
||||
}
|
||||
}
|
||||
34
vendor/league/commonmark/src/Extension/Table/TableExtension.php
vendored
Normal file
34
vendor/league/commonmark/src/Extension/Table/TableExtension.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
final class TableExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment): void
|
||||
{
|
||||
$environment
|
||||
->addBlockParser(new TableParser())
|
||||
|
||||
->addBlockRenderer(Table::class, new TableRenderer())
|
||||
->addBlockRenderer(TableSection::class, new TableSectionRenderer())
|
||||
->addBlockRenderer(TableRow::class, new TableRowRenderer())
|
||||
->addBlockRenderer(TableCell::class, new TableCellRenderer())
|
||||
;
|
||||
}
|
||||
}
|
||||
284
vendor/league/commonmark/src/Extension/Table/TableParser.php
vendored
Normal file
284
vendor/league/commonmark/src/Extension/Table/TableParser.php
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\Paragraph;
|
||||
use League\CommonMark\Block\Parser\BlockParserInterface;
|
||||
use League\CommonMark\Context;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\EnvironmentAwareInterface;
|
||||
use League\CommonMark\EnvironmentInterface;
|
||||
|
||||
final class TableParser implements BlockParserInterface, EnvironmentAwareInterface
|
||||
{
|
||||
/**
|
||||
* @var EnvironmentInterface
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
public function parse(ContextInterface $context, Cursor $cursor): bool
|
||||
{
|
||||
$container = $context->getContainer();
|
||||
if (!$container instanceof Paragraph) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lines = $container->getStrings();
|
||||
if (count($lines) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lastLine = \array_pop($lines);
|
||||
if (\strpos($lastLine, '|') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$oldState = $cursor->saveState();
|
||||
$cursor->advanceToNextNonSpaceOrTab();
|
||||
$columns = $this->parseColumns($cursor);
|
||||
|
||||
if (empty($columns)) {
|
||||
$cursor->restoreState($oldState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$head = $this->parseRow(trim((string) $lastLine), $columns, TableCell::TYPE_HEAD);
|
||||
if (null === $head) {
|
||||
$cursor->restoreState($oldState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$table = new Table(function (Cursor $cursor, Table $table) use ($columns): bool {
|
||||
// The next line cannot be a new block start
|
||||
// This is a bit inefficient, but it's the only feasible way to check
|
||||
// given the current v1 API.
|
||||
if (self::isANewBlock($this->environment, $cursor->getLine())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$row = $this->parseRow(\trim($cursor->getLine()), $columns);
|
||||
if (null === $row) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$table->getBody()->appendChild($row);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$table->getHead()->appendChild($head);
|
||||
|
||||
if (count($lines) >= 1) {
|
||||
$paragraph = new Paragraph();
|
||||
foreach ($lines as $line) {
|
||||
$paragraph->addLine($line);
|
||||
}
|
||||
|
||||
$context->replaceContainerBlock($paragraph);
|
||||
$context->addBlock($table);
|
||||
} else {
|
||||
$context->replaceContainerBlock($table);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $line
|
||||
* @param array<int, string> $columns
|
||||
* @param string $type
|
||||
*
|
||||
* @return TableRow|null
|
||||
*/
|
||||
private function parseRow(string $line, array $columns, string $type = TableCell::TYPE_BODY): ?TableRow
|
||||
{
|
||||
$cells = $this->split(new Cursor(\trim($line)));
|
||||
|
||||
if (empty($cells)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// The header row must match the delimiter row in the number of cells
|
||||
if ($type === TableCell::TYPE_HEAD && \count($cells) !== \count($columns)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
$row = new TableRow();
|
||||
foreach ($cells as $i => $cell) {
|
||||
if (!array_key_exists($i, $columns)) {
|
||||
return $row;
|
||||
}
|
||||
|
||||
$row->appendChild(new TableCell(trim($cell), $type, $columns[$i]));
|
||||
}
|
||||
|
||||
for ($j = count($columns) - 1; $j > $i; --$j) {
|
||||
$row->appendChild(new TableCell('', $type, null));
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Cursor $cursor
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function split(Cursor $cursor): array
|
||||
{
|
||||
if ($cursor->getCharacter() === '|') {
|
||||
$cursor->advanceBy(1);
|
||||
}
|
||||
|
||||
$cells = [];
|
||||
$sb = '';
|
||||
|
||||
while (!$cursor->isAtEnd()) {
|
||||
switch ($c = $cursor->getCharacter()) {
|
||||
case '\\':
|
||||
if ($cursor->peek() === '|') {
|
||||
// Pipe is special for table parsing. An escaped pipe doesn't result in a new cell, but is
|
||||
// passed down to inline parsing as an unescaped pipe. Note that that applies even for the `\|`
|
||||
// in an input like `\\|` - in other words, table parsing doesn't support escaping backslashes.
|
||||
$sb .= '|';
|
||||
$cursor->advanceBy(1);
|
||||
} else {
|
||||
// Preserve backslash before other characters or at end of line.
|
||||
$sb .= '\\';
|
||||
}
|
||||
break;
|
||||
case '|':
|
||||
$cells[] = $sb;
|
||||
$sb = '';
|
||||
break;
|
||||
default:
|
||||
$sb .= $c;
|
||||
}
|
||||
$cursor->advanceBy(1);
|
||||
}
|
||||
|
||||
if ($sb !== '') {
|
||||
$cells[] = $sb;
|
||||
}
|
||||
|
||||
return $cells;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Cursor $cursor
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function parseColumns(Cursor $cursor): array
|
||||
{
|
||||
$columns = [];
|
||||
$pipes = 0;
|
||||
$valid = false;
|
||||
|
||||
while (!$cursor->isAtEnd()) {
|
||||
switch ($c = $cursor->getCharacter()) {
|
||||
case '|':
|
||||
$cursor->advanceBy(1);
|
||||
$pipes++;
|
||||
if ($pipes > 1) {
|
||||
// More than one adjacent pipe not allowed
|
||||
return [];
|
||||
}
|
||||
|
||||
// Need at least one pipe, even for a one-column table
|
||||
$valid = true;
|
||||
break;
|
||||
case '-':
|
||||
case ':':
|
||||
if ($pipes === 0 && !empty($columns)) {
|
||||
// Need a pipe after the first column (first column doesn't need to start with one)
|
||||
return [];
|
||||
}
|
||||
$left = false;
|
||||
$right = false;
|
||||
if ($c === ':') {
|
||||
$left = true;
|
||||
$cursor->advanceBy(1);
|
||||
}
|
||||
if ($cursor->match('/^-+/') === null) {
|
||||
// Need at least one dash
|
||||
return [];
|
||||
}
|
||||
if ($cursor->getCharacter() === ':') {
|
||||
$right = true;
|
||||
$cursor->advanceBy(1);
|
||||
}
|
||||
$columns[] = $this->getAlignment($left, $right);
|
||||
// Next, need another pipe
|
||||
$pipes = 0;
|
||||
break;
|
||||
case ' ':
|
||||
case "\t":
|
||||
// White space is allowed between pipes and columns
|
||||
$cursor->advanceToNextNonSpaceOrTab();
|
||||
break;
|
||||
default:
|
||||
// Any other character is invalid
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
if (!$valid) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
private static function getAlignment(bool $left, bool $right): ?string
|
||||
{
|
||||
if ($left && $right) {
|
||||
return TableCell::ALIGN_CENTER;
|
||||
} elseif ($left) {
|
||||
return TableCell::ALIGN_LEFT;
|
||||
} elseif ($right) {
|
||||
return TableCell::ALIGN_RIGHT;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setEnvironment(EnvironmentInterface $environment)
|
||||
{
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
private static function isANewBlock(EnvironmentInterface $environment, string $line): bool
|
||||
{
|
||||
$context = new Context(new Document(), $environment);
|
||||
$context->setNextLine($line);
|
||||
$cursor = new Cursor($line);
|
||||
|
||||
/** @var BlockParserInterface $parser */
|
||||
foreach ($environment->getBlockParsers() as $parser) {
|
||||
if ($parser->parse($context, $cursor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
39
vendor/league/commonmark/src/Extension/Table/TableRenderer.php
vendored
Normal file
39
vendor/league/commonmark/src/Extension/Table/TableRenderer.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
|
||||
final class TableRenderer implements BlockRendererInterface
|
||||
{
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
if (!$block instanceof Table) {
|
||||
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
|
||||
}
|
||||
|
||||
$attrs = $block->getData('attributes', []);
|
||||
|
||||
$separator = $htmlRenderer->getOption('inner_separator', "\n");
|
||||
|
||||
$children = $htmlRenderer->renderBlocks($block->children());
|
||||
|
||||
return new HtmlElement('table', $attrs, $separator . \trim($children) . $separator);
|
||||
}
|
||||
}
|
||||
48
vendor/league/commonmark/src/Extension/Table/TableRow.php
vendored
Normal file
48
vendor/league/commonmark/src/Extension/Table/TableRow.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\Node\Node;
|
||||
|
||||
final class TableRow extends AbstractBlock
|
||||
{
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return $block instanceof TableCell;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractBlock[]
|
||||
*/
|
||||
public function children(): iterable
|
||||
{
|
||||
return array_filter((array) parent::children(), static function (Node $child): bool {
|
||||
return $child instanceof AbstractBlock;
|
||||
});
|
||||
}
|
||||
}
|
||||
37
vendor/league/commonmark/src/Extension/Table/TableRowRenderer.php
vendored
Normal file
37
vendor/league/commonmark/src/Extension/Table/TableRowRenderer.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
|
||||
final class TableRowRenderer implements BlockRendererInterface
|
||||
{
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
if (!$block instanceof TableRow) {
|
||||
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
|
||||
}
|
||||
|
||||
$attrs = $block->getData('attributes', []);
|
||||
|
||||
$separator = $htmlRenderer->getOption('inner_separator', "\n");
|
||||
|
||||
return new HtmlElement('tr', $attrs, $separator . $htmlRenderer->renderBlocks($block->children()) . $separator);
|
||||
}
|
||||
}
|
||||
66
vendor/league/commonmark/src/Extension/Table/TableSection.php
vendored
Normal file
66
vendor/league/commonmark/src/Extension/Table/TableSection.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Element\AbstractStringContainerBlock;
|
||||
use League\CommonMark\Block\Element\InlineContainerInterface;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
|
||||
final class TableSection extends AbstractStringContainerBlock implements InlineContainerInterface
|
||||
{
|
||||
const TYPE_HEAD = 'thead';
|
||||
const TYPE_BODY = 'tbody';
|
||||
|
||||
/** @var string */
|
||||
public $type = self::TYPE_BODY;
|
||||
|
||||
public function __construct(string $type = self::TYPE_BODY)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function isHead(): bool
|
||||
{
|
||||
return self::TYPE_HEAD === $this->type;
|
||||
}
|
||||
|
||||
public function isBody(): bool
|
||||
{
|
||||
return self::TYPE_BODY === $this->type;
|
||||
}
|
||||
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return $block instanceof TableRow;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void
|
||||
{
|
||||
}
|
||||
}
|
||||
41
vendor/league/commonmark/src/Extension/Table/TableSectionRenderer.php
vendored
Normal file
41
vendor/league/commonmark/src/Extension/Table/TableSectionRenderer.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Martin Hasoň <martin.hason@gmail.com>
|
||||
* (c) Webuni s.r.o. <info@webuni.cz>
|
||||
* (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\Extension\Table;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
|
||||
final class TableSectionRenderer implements BlockRendererInterface
|
||||
{
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
if (!$block instanceof TableSection) {
|
||||
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
|
||||
}
|
||||
|
||||
if (!$block->hasChildren()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$attrs = $block->getData('attributes', []);
|
||||
|
||||
$separator = $htmlRenderer->getOption('inner_separator', "\n");
|
||||
|
||||
return new HtmlElement($block->type, $attrs, $separator . $htmlRenderer->renderBlocks($block->children()) . $separator);
|
||||
}
|
||||
}
|
||||
21
vendor/league/commonmark/src/Extension/TableOfContents/Node/TableOfContents.php
vendored
Normal file
21
vendor/league/commonmark/src/Extension/TableOfContents/Node/TableOfContents.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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\Extension\TableOfContents\Node;
|
||||
|
||||
use League\CommonMark\Block\Element\ListBlock;
|
||||
use League\CommonMark\Extension\TableOfContents\TableOfContents as DeprecatedTableOfContents;
|
||||
|
||||
final class TableOfContents extends ListBlock
|
||||
{
|
||||
}
|
||||
|
||||
\class_exists(DeprecatedTableOfContents::class);
|
||||
33
vendor/league/commonmark/src/Extension/TableOfContents/Node/TableOfContentsPlaceholder.php
vendored
Normal file
33
vendor/league/commonmark/src/Extension/TableOfContents/Node/TableOfContentsPlaceholder.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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\Extension\TableOfContents\Node;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Cursor;
|
||||
|
||||
final class TableOfContentsPlaceholder extends AbstractBlock
|
||||
{
|
||||
public function canContain(AbstractBlock $block): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isCode(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchesNextLine(Cursor $cursor): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
70
vendor/league/commonmark/src/Extension/TableOfContents/Normalizer/AsIsNormalizerStrategy.php
vendored
Normal file
70
vendor/league/commonmark/src/Extension/TableOfContents/Normalizer/AsIsNormalizerStrategy.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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\Extension\TableOfContents\Normalizer;
|
||||
|
||||
use League\CommonMark\Block\Element\ListBlock;
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
|
||||
|
||||
final class AsIsNormalizerStrategy implements NormalizerStrategyInterface
|
||||
{
|
||||
/** @var ListBlock */
|
||||
private $parentListBlock;
|
||||
/** @var int */
|
||||
private $parentLevel = 1;
|
||||
/** @var ListItem|null */
|
||||
private $lastListItem;
|
||||
|
||||
public function __construct(TableOfContents $toc)
|
||||
{
|
||||
$this->parentListBlock = $toc;
|
||||
}
|
||||
|
||||
public function addItem(int $level, ListItem $listItemToAdd): void
|
||||
{
|
||||
while ($level > $this->parentLevel) {
|
||||
// Descend downwards, creating new ListBlocks if needed, until we reach the correct depth
|
||||
if ($this->lastListItem === null) {
|
||||
$this->lastListItem = new ListItem($this->parentListBlock->getListData());
|
||||
$this->parentListBlock->appendChild($this->lastListItem);
|
||||
}
|
||||
|
||||
$newListBlock = new ListBlock($this->parentListBlock->getListData());
|
||||
$newListBlock->setStartLine($listItemToAdd->getStartLine());
|
||||
$newListBlock->setEndLine($listItemToAdd->getEndLine());
|
||||
$this->lastListItem->appendChild($newListBlock);
|
||||
$this->parentListBlock = $newListBlock;
|
||||
$this->lastListItem = null;
|
||||
|
||||
$this->parentLevel++;
|
||||
}
|
||||
|
||||
while ($level < $this->parentLevel) {
|
||||
// Search upwards for the previous parent list block
|
||||
while (true) {
|
||||
$this->parentListBlock = $this->parentListBlock->parent();
|
||||
if ($this->parentListBlock instanceof ListBlock) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->parentLevel--;
|
||||
}
|
||||
|
||||
$this->parentListBlock->appendChild($listItemToAdd);
|
||||
|
||||
$this->lastListItem = $listItemToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger autoload without causing a deprecated error
|
||||
\class_exists(TableOfContents::class);
|
||||
34
vendor/league/commonmark/src/Extension/TableOfContents/Normalizer/FlatNormalizerStrategy.php
vendored
Normal file
34
vendor/league/commonmark/src/Extension/TableOfContents/Normalizer/FlatNormalizerStrategy.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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\Extension\TableOfContents\Normalizer;
|
||||
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
|
||||
|
||||
final class FlatNormalizerStrategy implements NormalizerStrategyInterface
|
||||
{
|
||||
/** @var TableOfContents */
|
||||
private $toc;
|
||||
|
||||
public function __construct(TableOfContents $toc)
|
||||
{
|
||||
$this->toc = $toc;
|
||||
}
|
||||
|
||||
public function addItem(int $level, ListItem $listItemToAdd): void
|
||||
{
|
||||
$this->toc->appendChild($listItemToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger autoload without causing a deprecated error
|
||||
\class_exists(TableOfContents::class);
|
||||
@@ -0,0 +1,19 @@
|
||||
<?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\Extension\TableOfContents\Normalizer;
|
||||
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
|
||||
interface NormalizerStrategyInterface
|
||||
{
|
||||
public function addItem(int $level, ListItem $listItemToAdd): void;
|
||||
}
|
||||
67
vendor/league/commonmark/src/Extension/TableOfContents/Normalizer/RelativeNormalizerStrategy.php
vendored
Normal file
67
vendor/league/commonmark/src/Extension/TableOfContents/Normalizer/RelativeNormalizerStrategy.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?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\Extension\TableOfContents\Normalizer;
|
||||
|
||||
use League\CommonMark\Block\Element\ListBlock;
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
|
||||
|
||||
final class RelativeNormalizerStrategy implements NormalizerStrategyInterface
|
||||
{
|
||||
/** @var TableOfContents */
|
||||
private $toc;
|
||||
|
||||
/** @var array<int, ListItem> */
|
||||
private $listItemStack = [];
|
||||
|
||||
public function __construct(TableOfContents $toc)
|
||||
{
|
||||
$this->toc = $toc;
|
||||
}
|
||||
|
||||
public function addItem(int $level, ListItem $listItemToAdd): void
|
||||
{
|
||||
\end($this->listItemStack);
|
||||
$previousLevel = \key($this->listItemStack);
|
||||
|
||||
// Pop the stack if we're too deep
|
||||
while ($previousLevel !== null && $level < $previousLevel) {
|
||||
array_pop($this->listItemStack);
|
||||
\end($this->listItemStack);
|
||||
$previousLevel = \key($this->listItemStack);
|
||||
}
|
||||
|
||||
/** @var ListItem|false $lastListItem */
|
||||
$lastListItem = \current($this->listItemStack);
|
||||
|
||||
// Need to go one level deeper? Add that level
|
||||
if ($lastListItem !== false && $level > $previousLevel) {
|
||||
$targetListBlock = new ListBlock($lastListItem->getListData());
|
||||
$targetListBlock->setStartLine($listItemToAdd->getStartLine());
|
||||
$targetListBlock->setEndLine($listItemToAdd->getEndLine());
|
||||
$lastListItem->appendChild($targetListBlock);
|
||||
// Otherwise we're at the right level
|
||||
// If there's no stack we're adding this item directly to the TOC element
|
||||
} elseif ($lastListItem === false) {
|
||||
$targetListBlock = $this->toc;
|
||||
// Otherwise add it to the last list item
|
||||
} else {
|
||||
$targetListBlock = $lastListItem->parent();
|
||||
}
|
||||
|
||||
$targetListBlock->appendChild($listItemToAdd);
|
||||
$this->listItemStack[$level] = $listItemToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger autoload without causing a deprecated error
|
||||
\class_exists(TableOfContents::class);
|
||||
30
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContents.php
vendored
Normal file
30
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContents.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\Block\Element\ListBlock;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents as NewTableOfContents;
|
||||
|
||||
if (!class_exists(NewTableOfContents::class)) {
|
||||
@trigger_error(sprintf('TableOfContents has moved to a new namespace; use %s instead', NewTableOfContents::class), \E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
\class_alias(NewTableOfContents::class, TableOfContents::class);
|
||||
|
||||
if (false) {
|
||||
/**
|
||||
* @deprecated This class has moved to the Node sub-namespace; use that instead
|
||||
*/
|
||||
final class TableOfContents extends ListBlock
|
||||
{
|
||||
}
|
||||
}
|
||||
127
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsBuilder.php
vendored
Normal file
127
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsBuilder.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\Heading;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Exception\InvalidOptionException;
|
||||
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalink;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContentsPlaceholder;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class TableOfContentsBuilder implements ConfigurationAwareInterface
|
||||
{
|
||||
/**
|
||||
* @deprecated Use TableOfContentsGenerator::STYLE_BULLET instead
|
||||
*/
|
||||
public const STYLE_BULLET = TableOfContentsGenerator::STYLE_BULLET;
|
||||
|
||||
/**
|
||||
* @deprecated Use TableOfContentsGenerator::STYLE_ORDERED instead
|
||||
*/
|
||||
public const STYLE_ORDERED = TableOfContentsGenerator::STYLE_ORDERED;
|
||||
|
||||
/**
|
||||
* @deprecated Use TableOfContentsGenerator::NORMALIZE_DISABLED instead
|
||||
*/
|
||||
public const NORMALIZE_DISABLED = TableOfContentsGenerator::NORMALIZE_DISABLED;
|
||||
|
||||
/**
|
||||
* @deprecated Use TableOfContentsGenerator::NORMALIZE_RELATIVE instead
|
||||
*/
|
||||
public const NORMALIZE_RELATIVE = TableOfContentsGenerator::NORMALIZE_RELATIVE;
|
||||
|
||||
/**
|
||||
* @deprecated Use TableOfContentsGenerator::NORMALIZE_FLAT instead
|
||||
*/
|
||||
public const NORMALIZE_FLAT = TableOfContentsGenerator::NORMALIZE_FLAT;
|
||||
|
||||
public const POSITION_TOP = 'top';
|
||||
public const POSITION_BEFORE_HEADINGS = 'before-headings';
|
||||
public const POSITION_PLACEHOLDER = 'placeholder';
|
||||
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function onDocumentParsed(DocumentParsedEvent $event): void
|
||||
{
|
||||
$document = $event->getDocument();
|
||||
|
||||
$generator = new TableOfContentsGenerator(
|
||||
$this->config->get('table_of_contents/style', TableOfContentsGenerator::STYLE_BULLET),
|
||||
$this->config->get('table_of_contents/normalize', TableOfContentsGenerator::NORMALIZE_RELATIVE),
|
||||
(int) $this->config->get('table_of_contents/min_heading_level', 1),
|
||||
(int) $this->config->get('table_of_contents/max_heading_level', 6)
|
||||
);
|
||||
|
||||
$toc = $generator->generate($document);
|
||||
if ($toc === null) {
|
||||
// No linkable headers exist, so no TOC could be generated
|
||||
return;
|
||||
}
|
||||
|
||||
// Add custom CSS class(es), if defined
|
||||
$class = $this->config->get('table_of_contents/html_class', 'table-of-contents');
|
||||
if (!empty($class)) {
|
||||
$toc->data['attributes']['class'] = $class;
|
||||
}
|
||||
|
||||
// Add the TOC to the Document
|
||||
$position = $this->config->get('table_of_contents/position', self::POSITION_TOP);
|
||||
if ($position === self::POSITION_TOP) {
|
||||
$document->prependChild($toc);
|
||||
} elseif ($position === self::POSITION_BEFORE_HEADINGS) {
|
||||
$this->insertBeforeFirstLinkedHeading($document, $toc);
|
||||
} elseif ($position === self::POSITION_PLACEHOLDER) {
|
||||
$this->replacePlaceholders($document, $toc);
|
||||
} else {
|
||||
throw new InvalidOptionException(\sprintf('Invalid config option "%s" for "table_of_contents/position"', $position));
|
||||
}
|
||||
}
|
||||
|
||||
private function insertBeforeFirstLinkedHeading(Document $document, TableOfContents $toc): void
|
||||
{
|
||||
$walker = $document->walker();
|
||||
while ($event = $walker->next()) {
|
||||
if ($event->isEntering() && ($node = $event->getNode()) instanceof HeadingPermalink && ($parent = $node->parent()) instanceof Heading) {
|
||||
$parent->insertBefore($toc);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function replacePlaceholders(Document $document, TableOfContents $toc): void
|
||||
{
|
||||
$walker = $document->walker();
|
||||
while ($event = $walker->next()) {
|
||||
// Add the block once we find a placeholder (and we're about to leave it)
|
||||
if (!$event->getNode() instanceof TableOfContentsPlaceholder) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($event->isEntering()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$event->getNode()->replaceWith(clone $toc);
|
||||
}
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
||||
31
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsExtension.php
vendored
Normal file
31
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsExtension.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContentsPlaceholder;
|
||||
|
||||
final class TableOfContentsExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment): void
|
||||
{
|
||||
$environment->addEventListener(DocumentParsedEvent::class, [new TableOfContentsBuilder(), 'onDocumentParsed'], -150);
|
||||
|
||||
if ($environment->getConfig('table_of_contents/position') === TableOfContentsBuilder::POSITION_PLACEHOLDER) {
|
||||
$environment->addBlockParser(new TableOfContentsPlaceholderParser(), 200);
|
||||
// If a placeholder cannot be replaced with a TOC element this renderer will ensure the parser won't error out
|
||||
$environment->addBlockRenderer(TableOfContentsPlaceholder::class, new TableOfContentsPlaceholderRenderer());
|
||||
}
|
||||
}
|
||||
}
|
||||
172
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsGenerator.php
vendored
Normal file
172
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsGenerator.php
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Block\Element\Heading;
|
||||
use League\CommonMark\Block\Element\ListBlock;
|
||||
use League\CommonMark\Block\Element\ListData;
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
use League\CommonMark\Block\Element\Paragraph;
|
||||
use League\CommonMark\Exception\InvalidOptionException;
|
||||
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalink;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
|
||||
use League\CommonMark\Extension\TableOfContents\Normalizer\AsIsNormalizerStrategy;
|
||||
use League\CommonMark\Extension\TableOfContents\Normalizer\FlatNormalizerStrategy;
|
||||
use League\CommonMark\Extension\TableOfContents\Normalizer\NormalizerStrategyInterface;
|
||||
use League\CommonMark\Extension\TableOfContents\Normalizer\RelativeNormalizerStrategy;
|
||||
use League\CommonMark\Inline\Element\AbstractStringContainer;
|
||||
use League\CommonMark\Inline\Element\Link;
|
||||
|
||||
final class TableOfContentsGenerator implements TableOfContentsGeneratorInterface
|
||||
{
|
||||
public const STYLE_BULLET = ListBlock::TYPE_BULLET;
|
||||
public const STYLE_ORDERED = ListBlock::TYPE_ORDERED;
|
||||
|
||||
public const NORMALIZE_DISABLED = 'as-is';
|
||||
public const NORMALIZE_RELATIVE = 'relative';
|
||||
public const NORMALIZE_FLAT = 'flat';
|
||||
|
||||
/** @var string */
|
||||
private $style;
|
||||
/** @var string */
|
||||
private $normalizationStrategy;
|
||||
/** @var int */
|
||||
private $minHeadingLevel;
|
||||
/** @var int */
|
||||
private $maxHeadingLevel;
|
||||
|
||||
public function __construct(string $style, string $normalizationStrategy, int $minHeadingLevel, int $maxHeadingLevel)
|
||||
{
|
||||
$this->style = $style;
|
||||
$this->normalizationStrategy = $normalizationStrategy;
|
||||
$this->minHeadingLevel = $minHeadingLevel;
|
||||
$this->maxHeadingLevel = $maxHeadingLevel;
|
||||
}
|
||||
|
||||
public function generate(Document $document): ?TableOfContents
|
||||
{
|
||||
$toc = $this->createToc($document);
|
||||
|
||||
$normalizer = $this->getNormalizer($toc);
|
||||
|
||||
$firstHeading = null;
|
||||
|
||||
foreach ($this->getHeadingLinks($document) as $headingLink) {
|
||||
$heading = $headingLink->parent();
|
||||
// Make sure this is actually tied to a heading
|
||||
if (!$heading instanceof Heading) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip any headings outside the configured min/max levels
|
||||
if ($heading->getLevel() < $this->minHeadingLevel || $heading->getLevel() > $this->maxHeadingLevel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Keep track of the first heading we see - we might need this later
|
||||
$firstHeading = $firstHeading ?? $heading;
|
||||
|
||||
// Keep track of the start and end lines
|
||||
$toc->setStartLine($firstHeading->getStartLine());
|
||||
$toc->setEndLine($heading->getEndLine());
|
||||
|
||||
// Create the new link
|
||||
$link = new Link('#' . $headingLink->getSlug(), self::getHeadingText($heading));
|
||||
$paragraph = new Paragraph();
|
||||
$paragraph->setStartLine($heading->getStartLine());
|
||||
$paragraph->setEndLine($heading->getEndLine());
|
||||
$paragraph->appendChild($link);
|
||||
|
||||
$listItem = new ListItem($toc->getListData());
|
||||
$listItem->setStartLine($heading->getStartLine());
|
||||
$listItem->setEndLine($heading->getEndLine());
|
||||
$listItem->appendChild($paragraph);
|
||||
|
||||
// Add it to the correct place
|
||||
$normalizer->addItem($heading->getLevel(), $listItem);
|
||||
}
|
||||
|
||||
// Don't add the TOC if no headings were present
|
||||
if (!$toc->hasChildren() || $firstHeading === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $toc;
|
||||
}
|
||||
|
||||
private function createToc(Document $document): TableOfContents
|
||||
{
|
||||
$listData = new ListData();
|
||||
|
||||
if ($this->style === self::STYLE_BULLET) {
|
||||
$listData->type = ListBlock::TYPE_BULLET;
|
||||
} elseif ($this->style === self::STYLE_ORDERED) {
|
||||
$listData->type = ListBlock::TYPE_ORDERED;
|
||||
} else {
|
||||
throw new InvalidOptionException(\sprintf('Invalid table of contents list style "%s"', $this->style));
|
||||
}
|
||||
|
||||
$toc = new TableOfContents($listData);
|
||||
|
||||
$toc->setStartLine($document->getStartLine());
|
||||
$toc->setEndLine($document->getEndLine());
|
||||
|
||||
return $toc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $document
|
||||
*
|
||||
* @return iterable<HeadingPermalink>
|
||||
*/
|
||||
private function getHeadingLinks(Document $document)
|
||||
{
|
||||
$walker = $document->walker();
|
||||
while ($event = $walker->next()) {
|
||||
if ($event->isEntering() && ($node = $event->getNode()) instanceof HeadingPermalink) {
|
||||
yield $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getNormalizer(TableOfContents $toc): NormalizerStrategyInterface
|
||||
{
|
||||
switch ($this->normalizationStrategy) {
|
||||
case self::NORMALIZE_DISABLED:
|
||||
return new AsIsNormalizerStrategy($toc);
|
||||
case self::NORMALIZE_RELATIVE:
|
||||
return new RelativeNormalizerStrategy($toc);
|
||||
case self::NORMALIZE_FLAT:
|
||||
return new FlatNormalizerStrategy($toc);
|
||||
default:
|
||||
throw new InvalidOptionException(\sprintf('Invalid table of contents normalization strategy "%s"', $this->normalizationStrategy));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function getHeadingText(Heading $heading)
|
||||
{
|
||||
$text = '';
|
||||
|
||||
$walker = $heading->walker();
|
||||
while ($event = $walker->next()) {
|
||||
if ($event->isEntering() && ($child = $event->getNode()) instanceof AbstractStringContainer) {
|
||||
$text .= $child->getContent();
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
23
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsGeneratorInterface.php
vendored
Normal file
23
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsGeneratorInterface.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\Block\Element\Document;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
|
||||
|
||||
interface TableOfContentsGeneratorInterface
|
||||
{
|
||||
public function generate(Document $document): ?TableOfContents;
|
||||
}
|
||||
|
||||
// Trigger autoload without causing a deprecated error
|
||||
\class_exists(TableOfContents::class);
|
||||
47
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsPlaceholderParser.php
vendored
Normal file
47
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsPlaceholderParser.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\Block\Parser\BlockParserInterface;
|
||||
use League\CommonMark\ContextInterface;
|
||||
use League\CommonMark\Cursor;
|
||||
use League\CommonMark\Extension\TableOfContents\Node\TableOfContentsPlaceholder;
|
||||
use League\CommonMark\Util\ConfigurationAwareInterface;
|
||||
use League\CommonMark\Util\ConfigurationInterface;
|
||||
|
||||
final class TableOfContentsPlaceholderParser implements BlockParserInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @var ConfigurationInterface */
|
||||
private $config;
|
||||
|
||||
public function parse(ContextInterface $context, Cursor $cursor): bool
|
||||
{
|
||||
$placeholder = $this->config->get('table_of_contents/placeholder');
|
||||
if ($placeholder === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The placeholder must be the only thing on the line
|
||||
if ($cursor->match('/^' . \preg_quote($placeholder, '/') . '$/') === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$context->addBlock(new TableOfContentsPlaceholder());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration)
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
}
|
||||
24
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsPlaceholderRenderer.php
vendored
Normal file
24
vendor/league/commonmark/src/Extension/TableOfContents/TableOfContentsPlaceholderRenderer.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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\Extension\TableOfContents;
|
||||
|
||||
use League\CommonMark\Block\Element\AbstractBlock;
|
||||
use League\CommonMark\Block\Renderer\BlockRendererInterface;
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
|
||||
final class TableOfContentsPlaceholderRenderer implements BlockRendererInterface
|
||||
{
|
||||
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false)
|
||||
{
|
||||
return '<!-- table of contents -->';
|
||||
}
|
||||
}
|
||||
24
vendor/league/commonmark/src/Extension/TaskList/TaskListExtension.php
vendored
Normal file
24
vendor/league/commonmark/src/Extension/TaskList/TaskListExtension.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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\Extension\TaskList;
|
||||
|
||||
use League\CommonMark\ConfigurableEnvironmentInterface;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
|
||||
final class TaskListExtension implements ExtensionInterface
|
||||
{
|
||||
public function register(ConfigurableEnvironmentInterface $environment)
|
||||
{
|
||||
$environment->addInlineParser(new TaskListItemMarkerParser(), 35);
|
||||
$environment->addInlineRenderer(TaskListItemMarker::class, new TaskListItemMarkerRenderer());
|
||||
}
|
||||
}
|
||||
37
vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarker.php
vendored
Normal file
37
vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarker.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?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\Extension\TaskList;
|
||||
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
|
||||
final class TaskListItemMarker extends AbstractInline
|
||||
{
|
||||
/** @var bool */
|
||||
protected $checked = false;
|
||||
|
||||
public function __construct(bool $isCompleted)
|
||||
{
|
||||
$this->checked = $isCompleted;
|
||||
}
|
||||
|
||||
public function isChecked(): bool
|
||||
{
|
||||
return $this->checked;
|
||||
}
|
||||
|
||||
public function setChecked(bool $checked): self
|
||||
{
|
||||
$this->checked = $checked;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
55
vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerParser.php
vendored
Normal file
55
vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerParser.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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\Extension\TaskList;
|
||||
|
||||
use League\CommonMark\Block\Element\ListItem;
|
||||
use League\CommonMark\Block\Element\Paragraph;
|
||||
use League\CommonMark\Inline\Parser\InlineParserInterface;
|
||||
use League\CommonMark\InlineParserContext;
|
||||
|
||||
final class TaskListItemMarkerParser implements InlineParserInterface
|
||||
{
|
||||
public function getCharacters(): array
|
||||
{
|
||||
return ['['];
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$container = $inlineContext->getContainer();
|
||||
|
||||
// Checkbox must come at the beginning of the first paragraph of the list item
|
||||
if ($container->hasChildren() || !($container instanceof Paragraph && $container->parent() && $container->parent() instanceof ListItem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$oldState = $cursor->saveState();
|
||||
|
||||
$m = $cursor->match('/\[[ xX]\]/');
|
||||
if ($m === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cursor->getNextNonSpaceCharacter() === null) {
|
||||
$cursor->restoreState($oldState);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$isChecked = $m !== '[ ]';
|
||||
|
||||
$container->appendChild(new TaskListItemMarker($isChecked));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
44
vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerRenderer.php
vendored
Normal file
44
vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerRenderer.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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\Extension\TaskList;
|
||||
|
||||
use League\CommonMark\ElementRendererInterface;
|
||||
use League\CommonMark\HtmlElement;
|
||||
use League\CommonMark\Inline\Element\AbstractInline;
|
||||
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
|
||||
|
||||
final class TaskListItemMarkerRenderer implements InlineRendererInterface
|
||||
{
|
||||
/**
|
||||
* @param TaskListItemMarker $inline
|
||||
* @param ElementRendererInterface $htmlRenderer
|
||||
*
|
||||
* @return HtmlElement|string|null
|
||||
*/
|
||||
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
|
||||
{
|
||||
if (!($inline instanceof TaskListItemMarker)) {
|
||||
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
|
||||
}
|
||||
|
||||
$checkbox = new HtmlElement('input', [], '', true);
|
||||
|
||||
if ($inline->isChecked()) {
|
||||
$checkbox->setAttribute('checked', '');
|
||||
}
|
||||
|
||||
$checkbox->setAttribute('disabled', '');
|
||||
$checkbox->setAttribute('type', 'checkbox');
|
||||
|
||||
return $checkbox;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user