PKIZ!} GeneratorAwareExtensionTrait.phpnuW+Agenerator = $generator; return $instance; } } PKIZ~essVersionExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator HTML extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class HtmlExtension extends AbstractExtension { public function __construct(Translator $translator) { $translator ->getExtension('node') ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); } public function getPseudoClassTranslators(): array { return [ 'checked' => $this->translateChecked(...), 'link' => $this->translateLink(...), 'disabled' => $this->translateDisabled(...), 'enabled' => $this->translateEnabled(...), 'selected' => $this->translateSelected(...), 'invalid' => $this->translateInvalid(...), 'hover' => $this->translateHover(...), 'visited' => $this->translateVisited(...), ]; } public function getFunctionTranslators(): array { return [ 'lang' => $this->translateLang(...), ]; } public function translateChecked(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(@checked ' ."and (name(.) = 'input' or name(.) = 'command')" ."and (@type = 'checkbox' or @type = 'radio'))" ); } public function translateLink(XPathExpr $xpath): XPathExpr { return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); } public function translateDisabled(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(' .'@disabled and' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" ." or name(.) = 'option'" .')' .') or (' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" .')' .' and ancestor::fieldset[@disabled]' ); // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." } public function translateEnabled(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(' .'@href and (' ."name(.) = 'a'" ." or name(.) = 'link'" ." or name(.) = 'area'" .')' .') or (' .'(' ."name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" .')' .' and not(@disabled)' .') or (' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'keygen'" .')' .' and not (@disabled or ancestor::fieldset[@disabled])' .') or (' ."name(.) = 'option' and not(" .'@disabled or ancestor::optgroup[@disabled]' .')' .')' ); } /** * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'ancestor-or-self::*[@lang][1][starts-with(concat(' ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" .', %s)]', 'lang', Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') )); } public function translateSelected(XPathExpr $xpath): XPathExpr { return $xpath->addCondition("(@selected and name(.) = 'option')"); } public function translateInvalid(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function translateHover(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function translateVisited(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function getName(): string { return 'html'; } } PKZvzAttributeMatchingExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator attribute extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class AttributeMatchingExtension extends AbstractExtension { public function getAttributeMatchingTranslators(): array { return [ 'exists' => $this->translateExists(...), '=' => $this->translateEquals(...), '~=' => $this->translateIncludes(...), '|=' => $this->translateDashMatch(...), '^=' => $this->translatePrefixMatch(...), '$=' => $this->translateSuffixMatch(...), '*=' => $this->translateSubstringMatch(...), '!=' => $this->translateDifferent(...), ]; } public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($attribute); } public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); } public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', $attribute, Translator::getXpathLiteral(' '.$value.' ') ) : '0'); } public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf( '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', $attribute, Translator::getXpathLiteral($value), Translator::getXpathLiteral($value.'-') )); } public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and starts-with(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', $attribute, \strlen($value) - 1, Translator::getXpathLiteral($value) ) : '0'); } public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and contains(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf( $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', $attribute, Translator::getXpathLiteral($value) )); } public function getName(): string { return 'attribute-matching'; } } PKZe@OOCombinationExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator combination extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class CombinationExtension extends AbstractExtension { public function getCombinationTranslators(): array { return [ ' ' => $this->translateDescendant(...), '>' => $this->translateChild(...), '+' => $this->translateDirectAdjacent(...), '~' => $this->translateIndirectAdjacent(...), ]; } public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/descendant-or-self::*/', $combinedXpath); } public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/', $combinedXpath); } public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath ->join('/following-sibling::', $combinedXpath) ->addNameTest() ->addCondition('position() = 1'); } public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/following-sibling::', $combinedXpath); } public function getName(): string { return 'combination'; } } PKZ((FunctionExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator function extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class FunctionExtension extends AbstractExtension { public function getFunctionTranslators(): array { return [ 'nth-child' => $this->translateNthChild(...), 'nth-last-child' => $this->translateNthLastChild(...), 'nth-of-type' => $this->translateNthOfType(...), 'nth-last-of-type' => $this->translateNthLastOfType(...), 'contains' => $this->translateContains(...), 'lang' => $this->translateLang(...), ]; } /** * @throws ExpressionErrorException */ public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr { try { [$a, $b] = Parser::parseSeries($function->getArguments()); } catch (SyntaxErrorException $e) { throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e); } $xpath->addStarPrefix(); if ($addNameTest) { $xpath->addNameTest(); } if (0 === $a) { return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); } if ($a < 0) { if ($b < 1) { return $xpath->addCondition('false()'); } $sign = '<='; } else { $sign = '>='; } $expr = 'position()'; if ($last) { $expr = 'last() - '.$expr; --$b; } if (0 !== $b) { $expr .= ' - '.$b; } $conditions = [sprintf('%s %s 0', $expr, $sign)]; if (1 !== $a && -1 !== $a) { $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); } return $xpath->addCondition(implode(' and ', $conditions)); // todo: handle an+b, odd, even // an+b means every-a, plus b, e.g., 2n+1 means odd // 0n+b means b // n+0 means a=1, i.e., all elements // an means every a elements, i.e., 2n means even // -n means -1n // -1n+6 means elements 6 and previous } public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function): XPathExpr { return $this->translateNthChild($xpath, $function, true); } public function translateNthOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr { return $this->translateNthChild($xpath, $function, false, false); } /** * @throws ExpressionErrorException */ public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); } return $this->translateNthChild($xpath, $function, true, false); } /** * @throws ExpressionErrorException */ public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'contains(string(.), %s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'lang(%s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } public function getName(): string { return 'function'; } } PKZPĄ$<<AbstractExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator abstract extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ abstract class AbstractExtension implements ExtensionInterface { public function getNodeTranslators(): array { return []; } public function getCombinationTranslators(): array { return []; } public function getFunctionTranslators(): array { return []; } public function getPseudoClassTranslators(): array { return []; } public function getAttributeMatchingTranslators(): array { return []; } } PKZD{ PseudoClassExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator pseudo-class extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class PseudoClassExtension extends AbstractExtension { public function getPseudoClassTranslators(): array { return [ 'root' => $this->translateRoot(...), 'scope' => $this->translateScopePseudo(...), 'first-child' => $this->translateFirstChild(...), 'last-child' => $this->translateLastChild(...), 'first-of-type' => $this->translateFirstOfType(...), 'last-of-type' => $this->translateLastOfType(...), 'only-child' => $this->translateOnlyChild(...), 'only-of-type' => $this->translateOnlyOfType(...), 'empty' => $this->translateEmpty(...), ]; } public function translateRoot(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('not(parent::*)'); } public function translateScopePseudo(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('1'); } public function translateFirstChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = 1'); } public function translateLastChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = last()'); } /** * @throws ExpressionErrorException */ public function translateFirstOfType(XPathExpr $xpath): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = 1'); } /** * @throws ExpressionErrorException */ public function translateLastOfType(XPathExpr $xpath): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = last()'); } public function translateOnlyChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('last() = 1'); } public function translateOnlyOfType(XPathExpr $xpath): XPathExpr { $element = $xpath->getElement(); return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element)); } public function translateEmpty(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('not(*) and not(string-length())'); } public function getName(): string { return 'pseudo-class'; } } PKZccExtensionInterface.phpnuW+A * * 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\Environment\EnvironmentBuilderInterface; interface ExtensionInterface { public function register(EnvironmentBuilderInterface $environment): void; } PKZ%NodeExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator node extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class NodeExtension extends AbstractExtension { public const ELEMENT_NAME_IN_LOWER_CASE = 1; public const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; public const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; private int $flags; public function __construct(int $flags = 0) { $this->flags = $flags; } /** * @return $this */ public function setFlag(int $flag, bool $on): static { if ($on && !$this->hasFlag($flag)) { $this->flags += $flag; } if (!$on && $this->hasFlag($flag)) { $this->flags -= $flag; } return $this; } public function hasFlag(int $flag): bool { return (bool) ($this->flags & $flag); } public function getNodeTranslators(): array { return [ 'Selector' => $this->translateSelector(...), 'CombinedSelector' => $this->translateCombinedSelector(...), 'Negation' => $this->translateNegation(...), 'Function' => $this->translateFunction(...), 'Pseudo' => $this->translatePseudo(...), 'Attribute' => $this->translateAttribute(...), 'Class' => $this->translateClass(...), 'Hash' => $this->translateHash(...), 'Element' => $this->translateElement(...), ]; } public function translateSelector(Node\SelectorNode $node, Translator $translator): XPathExpr { return $translator->nodeToXPath($node->getTree()); } public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator): XPathExpr { return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); } public function translateNegation(Node\NegationNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); $subXpath = $translator->nodeToXPath($node->getSubSelector()); $subXpath->addNameTest(); if ($subXpath->getCondition()) { return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); } return $xpath->addCondition('0'); } public function translateFunction(Node\FunctionNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addFunction($xpath, $node); } public function translatePseudo(Node\PseudoNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addPseudoClass($xpath, $node->getIdentifier()); } public function translateAttribute(Node\AttributeNode $node, Translator $translator): XPathExpr { $name = $node->getAttribute(); $safe = $this->isSafeName($name); if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { $name = strtolower($name); } if ($node->getNamespace()) { $name = sprintf('%s:%s', $node->getNamespace(), $name); $safe = $safe && $this->isSafeName($node->getNamespace()); } $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); $value = $node->getValue(); $xpath = $translator->nodeToXPath($node->getSelector()); if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { $value = strtolower($value); } return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); } public function translateClass(Node\ClassNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); } public function translateHash(Node\HashNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); } public function translateElement(Node\ElementNode $node): XPathExpr { $element = $node->getElement(); if ($element && $this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { $element = strtolower($element); } if ($element) { $safe = $this->isSafeName($element); } else { $element = '*'; $safe = true; } if ($node->getNamespace()) { $element = sprintf('%s:%s', $node->getNamespace(), $element); $safe = $safe && $this->isSafeName($node->getNamespace()); } $xpath = new XPathExpr('', $element); if (!$safe) { $xpath->addNameTest(); } return $xpath; } public function getName(): string { return 'node'; } private function isSafeName(string $name): bool { return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); } } PK"Z* xEmbed/EmbedStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\CommonMark\Util\LinkParserHelper; class EmbedStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented() || $parserState->getParagraphContent() !== null || ! ($parserState->getActiveBlockParser()->isContainer())) { return BlockStart::none(); } // 0-3 leading spaces are okay $cursor->advanceToNextNonSpaceOrTab(); // The line must begin with "https://" if (! str_starts_with($cursor->getRemainder(), 'https://')) { return BlockStart::none(); } // A valid link must be found next if (($dest = LinkParserHelper::parseLinkDestination($cursor)) === null) { return BlockStart::none(); } // Skip any trailing whitespace $cursor->advanceToNextNonSpaceOrTab(); // We must be at the end of the line; otherwise, this link was not by itself if (! $cursor->isAtEnd()) { return BlockStart::none(); } return BlockStart::of(new EmbedParser($dest))->at($cursor); } } PK"ZEmbed/EmbedProcessor.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Node\NodeIterator; final class EmbedProcessor { public const FALLBACK_REMOVE = 'remove'; public const FALLBACK_LINK = 'link'; private EmbedAdapterInterface $adapter; private string $fallback; public function __construct(EmbedAdapterInterface $adapter, string $fallback = self::FALLBACK_REMOVE) { $this->adapter = $adapter; $this->fallback = $fallback; } public function __invoke(DocumentParsedEvent $event): void { $document = $event->getDocument(); $embeds = []; foreach (new NodeIterator($document) as $node) { if (! ($node instanceof Embed)) { continue; } if ($node->parent() !== $document) { $replacement = new Paragraph(); $replacement->appendChild(new Text($node->getUrl())); $node->replaceWith($replacement); } else { $embeds[] = $node; } } $this->adapter->updateEmbeds($embeds); foreach ($embeds as $embed) { if ($embed->getEmbedCode() !== null) { continue; } if ($this->fallback === self::FALLBACK_REMOVE) { $embed->detach(); } elseif ($this->fallback === self::FALLBACK_LINK) { $paragraph = new Paragraph(); $paragraph->appendChild(new Link($embed->getUrl(), $embed->getUrl())); $embed->replaceWith($paragraph); } } } } PK"Z^M`88Embed/EmbedParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; class EmbedParser implements BlockContinueParserInterface { private Embed $embed; public function __construct(string $url) { $this->embed = new Embed($url); } public function getBlock(): AbstractBlock { return $this->embed; } public function isContainer(): bool { return false; } public function canHaveLazyContinuationLines(): bool { return false; } public function canContain(AbstractBlock $childBlock): bool { return false; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { return BlockContinue::none(); } public function addLine(string $line): void { } public function closeBlock(): void { } } PK"Z⤞'Embed/Bridge/OscaroteroEmbedAdapter.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed\Bridge; use Embed\Embed as EmbedLib; use League\CommonMark\Exception\MissingDependencyException; use League\CommonMark\Extension\Embed\Embed; use League\CommonMark\Extension\Embed\EmbedAdapterInterface; final class OscaroteroEmbedAdapter implements EmbedAdapterInterface { private EmbedLib $embedLib; public function __construct(?EmbedLib $embed = null) { if ($embed === null) { if (! \class_exists(EmbedLib::class)) { throw new MissingDependencyException('The embed/embed package is not installed. Please install it with Composer to use this adapter.'); } $embed = new EmbedLib(); } $this->embedLib = $embed; } /** * {@inheritDoc} */ public function updateEmbeds(array $embeds): void { $extractors = $this->embedLib->getMulti(...\array_map(static fn (Embed $embed) => $embed->getUrl(), $embeds)); foreach ($extractors as $i => $extractor) { if ($extractor->code !== null) { $embeds[$i]->setEmbedCode($extractor->code->html); } } } } PK"Z*MEmbed/EmbedExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class EmbedExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('embed', Expect::structure([ 'adapter' => Expect::type(EmbedAdapterInterface::class), 'allowed_domains' => Expect::arrayOf('string')->default([]), 'fallback' => Expect::anyOf('link', 'remove')->default('link'), ])); } public function register(EnvironmentBuilderInterface $environment): void { $adapter = $environment->getConfiguration()->get('embed.adapter'); \assert($adapter instanceof EmbedAdapterInterface); $allowedDomains = $environment->getConfiguration()->get('embed.allowed_domains'); if ($allowedDomains !== []) { $adapter = new DomainFilteringAdapter($adapter, $allowedDomains); } $environment ->addBlockStartParser(new EmbedStartParser(), 300) ->addEventListener(DocumentParsedEvent::class, new EmbedProcessor($adapter, $environment->getConfiguration()->get('embed.fallback')), 1010) ->addRenderer(Embed::class, new EmbedRenderer()); } } PK"Z a*BBEmbed/EmbedRenderer.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; class EmbedRenderer implements NodeRendererInterface { /** * @param Embed $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer) { Embed::assertInstanceOf($node); return $node->getEmbedCode() ?? ''; } } PK"ZF#((Embed/EmbedAdapterInterface.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; /** * Interface for a service which updates the embed code(s) for the given array of embeds */ interface EmbedAdapterInterface { /** * @param Embed[] $embeds */ public function updateEmbeds(array $embeds): void; } PK"Z09   Embed/DomainFilteringAdapter.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; class DomainFilteringAdapter implements EmbedAdapterInterface { private EmbedAdapterInterface $decorated; private string $regex; /** * @param string[] $allowedDomains */ public function __construct(EmbedAdapterInterface $decorated, array $allowedDomains) { $this->decorated = $decorated; $this->regex = self::createRegex($allowedDomains); } /** * {@inheritDoc} */ public function updateEmbeds(array $embeds): void { $this->decorated->updateEmbeds(\array_values(\array_filter($embeds, function (Embed $embed): bool { return \preg_match($this->regex, $embed->getUrl()) === 1; }))); } /** * @param string[] $allowedDomains */ private static function createRegex(array $allowedDomains): string { $allowedDomains = \array_map('preg_quote', $allowedDomains); return '/^(?:https?:\/\/)?(?:[^.]+\.)*(' . \implode('|', $allowedDomains) . ')/'; } } PK"Z Embed/Embed.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Embed; use League\CommonMark\Node\Block\AbstractBlock; final class Embed extends AbstractBlock { private string $url; private ?string $embedCode; public function __construct(string $url, ?string $embedCode = null) { parent::__construct(); $this->url = $url; $this->embedCode = $embedCode; } public function getUrl(): string { return $this->url; } public function setUrl(string $url): void { $this->url = $url; } public function getEmbedCode(): ?string { return $this->embedCode; } public function setEmbedCode(?string $embedCode): void { $this->embedCode = $embedCode; } } PK"Z2nTable/TableRowRenderer.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TableRowRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param TableRow $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { TableRow::assertInstanceOf($node); $attrs = $node->data->get('attributes'); $separator = $childRenderer->getInnerSeparator(); return new HtmlElement('tr', $attrs, $separator . $childRenderer->renderNodes($node->children()) . $separator); } public function getXmlTagName(Node $node): string { return 'table_row'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z+j!!Table/TableSection.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Block\AbstractBlock; final class TableSection extends AbstractBlock { public const TYPE_HEAD = 'head'; public const TYPE_BODY = 'body'; /** * @psalm-var self::TYPE_* * @phpstan-var self::TYPE_* * * @psalm-readonly */ private string $type; /** * @psalm-param self::TYPE_* $type * * @phpstan-param self::TYPE_* $type */ public function __construct(string $type = self::TYPE_BODY) { parent::__construct(); $this->type = $type; } /** * @psalm-return self::TYPE_* * * @phpstan-return self::TYPE_* */ public function getType(): string { return $this->type; } public function isHead(): bool { return $this->type === self::TYPE_HEAD; } public function isBody(): bool { return $this->type === self::TYPE_BODY; } } PK"Zk߫Table/TableRenderer.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TableRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param Table $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Table::assertInstanceOf($node); $attrs = $node->data->get('attributes'); $separator = $childRenderer->getInnerSeparator(); $children = $childRenderer->renderNodes($node->children()); return new HtmlElement('table', $attrs, $separator . \trim($children) . $separator); } public function getXmlTagName(Node $node): string { return 'table'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"ZP88Table/TableParser.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Block\BlockContinueParserWithInlinesInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\InlineParserEngineInterface; use League\CommonMark\Util\ArrayCollection; final class TableParser extends AbstractBlockContinueParser implements BlockContinueParserWithInlinesInterface { /** @psalm-readonly */ private Table $block; /** * @var ArrayCollection * * @psalm-readonly-allow-private-mutation */ private ArrayCollection $bodyLines; /** * @var array * @psalm-var array * @phpstan-var array * * @psalm-readonly */ private array $columns; /** * @var array * * @psalm-readonly-allow-private-mutation */ private array $headerCells; /** @psalm-readonly-allow-private-mutation */ private bool $nextIsSeparatorLine = true; /** * @param array $columns * @param array $headerCells * * @psalm-param array $columns * * @phpstan-param array $columns */ public function __construct(array $columns, array $headerCells) { $this->block = new Table(); $this->bodyLines = new ArrayCollection(); $this->columns = $columns; $this->headerCells = $headerCells; } public function canHaveLazyContinuationLines(): bool { return true; } public function getBlock(): Table { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if (\strpos($cursor->getLine(), '|') === false) { return BlockContinue::none(); } return BlockContinue::at($cursor); } public function addLine(string $line): void { if ($this->nextIsSeparatorLine) { $this->nextIsSeparatorLine = false; } else { $this->bodyLines[] = $line; } } public function parseInlines(InlineParserEngineInterface $inlineParser): void { $headerColumns = \count($this->headerCells); $head = new TableSection(TableSection::TYPE_HEAD); $this->block->appendChild($head); $headerRow = new TableRow(); $head->appendChild($headerRow); for ($i = 0; $i < $headerColumns; $i++) { $cell = $this->headerCells[$i]; $tableCell = $this->parseCell($cell, $i, $inlineParser); $tableCell->setType(TableCell::TYPE_HEADER); $headerRow->appendChild($tableCell); } $body = null; foreach ($this->bodyLines as $rowLine) { $cells = self::split($rowLine); $row = new TableRow(); // Body can not have more columns than head for ($i = 0; $i < $headerColumns; $i++) { $cell = $cells[$i] ?? ''; $tableCell = $this->parseCell($cell, $i, $inlineParser); $row->appendChild($tableCell); } if ($body === null) { // It's valid to have a table without body. In that case, don't add an empty TableBody node. $body = new TableSection(); $this->block->appendChild($body); } $body->appendChild($row); } } private function parseCell(string $cell, int $column, InlineParserEngineInterface $inlineParser): TableCell { $tableCell = new TableCell(); if ($column < \count($this->columns)) { $tableCell->setAlign($this->columns[$column]); } $inlineParser->parse(\trim($cell), $tableCell); return $tableCell; } /** * @internal * * @return array */ public static function split(string $line): array { $cursor = new Cursor(\trim($line)); if ($cursor->getCurrentCharacter() === '|') { $cursor->advanceBy(1); } $cells = []; $sb = ''; while (! $cursor->isAtEnd()) { switch ($c = $cursor->getCurrentCharacter()) { 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; } } PK"Z_ITable/TableStartParser.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Block\ParagraphParser; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; final class TableStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { $paragraph = $parserState->getParagraphContent(); if ($paragraph === null || \strpos($paragraph, '|') === false) { return BlockStart::none(); } $columns = self::parseSeparator($cursor); if (\count($columns) === 0) { return BlockStart::none(); } $lines = \explode("\n", $paragraph); $lastLine = \array_pop($lines); $headerCells = TableParser::split($lastLine); if (\count($headerCells) > \count($columns)) { return BlockStart::none(); } $cursor->advanceToEnd(); $parsers = []; if (\count($lines) > 0) { $p = new ParagraphParser(); $p->addLine(\implode("\n", $lines)); $parsers[] = $p; } $parsers[] = new TableParser($columns, $headerCells); return BlockStart::of(...$parsers) ->at($cursor) ->replaceActiveBlockParser(); } /** * @return array * * @psalm-return array * * @phpstan-return array */ private static function parseSeparator(Cursor $cursor): array { $columns = []; $pipes = 0; $valid = false; while (! $cursor->isAtEnd()) { switch ($c = $cursor->getCurrentCharacter()) { 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 && \count($columns) > 0) { // 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->getCurrentCharacter() === ':') { $right = true; $cursor->advanceBy(1); } $columns[] = self::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; } /** * @psalm-return TableCell::ALIGN_*|null * * @phpstan-return TableCell::ALIGN_*|null * * @psalm-pure */ private static function getAlignment(bool $left, bool $right): ?string { if ($left && $right) { return TableCell::ALIGN_CENTER; } if ($left) { return TableCell::ALIGN_LEFT; } if ($right) { return TableCell::ALIGN_RIGHT; } return null; } } PK"ZA9 9 Table/TableCellRenderer.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Extension\Attributes\Util\AttributesHelper; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TableCellRenderer implements NodeRendererInterface, XmlNodeRendererInterface { private const DEFAULT_ATTRIBUTES = [ TableCell::ALIGN_LEFT => ['align' => 'left'], TableCell::ALIGN_CENTER => ['align' => 'center'], TableCell::ALIGN_RIGHT => ['align' => 'right'], ]; /** @var array> */ private array $alignmentAttributes; /** * @param array> $alignmentAttributes */ public function __construct(array $alignmentAttributes = self::DEFAULT_ATTRIBUTES) { $this->alignmentAttributes = $alignmentAttributes; } /** * @param TableCell $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { TableCell::assertInstanceOf($node); $attrs = $node->data->get('attributes'); if (($alignment = $node->getAlign()) !== null) { $attrs = AttributesHelper::mergeAttributes($attrs, $this->alignmentAttributes[$alignment]); } $tag = $node->getType() === TableCell::TYPE_HEADER ? 'th' : 'td'; return new HtmlElement($tag, $attrs, $childRenderer->renderNodes($node->children())); } public function getXmlTagName(Node $node): string { return 'table_cell'; } /** * @param TableCell $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { TableCell::assertInstanceOf($node); $ret = ['type' => $node->getType()]; if (($align = $node->getAlign()) !== null) { $ret['align'] = $align; } return $ret; } } PK"Z Table/TableExtension.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\CommonMark\Renderer\HtmlDecorator; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class TableExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $attributeArraySchema = Expect::arrayOf( Expect::type('string|string[]|bool'), // attribute value(s) 'string' // attribute name )->mergeDefaults(false); $builder->addSchema('table', Expect::structure([ 'wrap' => Expect::structure([ 'enabled' => Expect::bool()->default(false), 'tag' => Expect::string()->default('div'), 'attributes' => Expect::arrayOf(Expect::string()), ]), 'alignment_attributes' => Expect::structure([ 'left' => (clone $attributeArraySchema)->default(['align' => 'left']), 'center' => (clone $attributeArraySchema)->default(['align' => 'center']), 'right' => (clone $attributeArraySchema)->default(['align' => 'right']), ]), ])); } public function register(EnvironmentBuilderInterface $environment): void { $tableRenderer = new TableRenderer(); if ($environment->getConfiguration()->get('table/wrap/enabled')) { $tableRenderer = new HtmlDecorator($tableRenderer, $environment->getConfiguration()->get('table/wrap/tag'), $environment->getConfiguration()->get('table/wrap/attributes')); } $environment ->addBlockStartParser(new TableStartParser()) ->addRenderer(Table::class, $tableRenderer) ->addRenderer(TableSection::class, new TableSectionRenderer()) ->addRenderer(TableRow::class, new TableRowRenderer()) ->addRenderer(TableCell::class, new TableCellRenderer($environment->getConfiguration()->get('table/alignment_attributes'))); } } PK"Z_ %Table/TableCell.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Block\AbstractBlock; final class TableCell extends AbstractBlock { public const TYPE_HEADER = 'header'; public const TYPE_DATA = 'data'; public const ALIGN_LEFT = 'left'; public const ALIGN_RIGHT = 'right'; public const ALIGN_CENTER = 'center'; /** * @psalm-var self::TYPE_* * @phpstan-var self::TYPE_* * * @psalm-readonly-allow-private-mutation */ private string $type = self::TYPE_DATA; /** * @psalm-var self::ALIGN_*|null * @phpstan-var self::ALIGN_*|null * * @psalm-readonly-allow-private-mutation */ private ?string $align = null; /** * @psalm-param self::TYPE_* $type * @psalm-param self::ALIGN_*|null $align * * @phpstan-param self::TYPE_* $type * @phpstan-param self::ALIGN_*|null $align */ public function __construct(string $type = self::TYPE_DATA, ?string $align = null) { parent::__construct(); $this->type = $type; $this->align = $align; } /** * @psalm-return self::TYPE_* * * @phpstan-return self::TYPE_* */ public function getType(): string { return $this->type; } /** * @psalm-param self::TYPE_* $type * * @phpstan-param self::TYPE_* $type */ public function setType(string $type): void { $this->type = $type; } /** * @psalm-return self::ALIGN_*|null * * @phpstan-return self::ALIGN_*|null */ public function getAlign(): ?string { return $this->align; } /** * @psalm-param self::ALIGN_*|null $align * * @phpstan-param self::ALIGN_*|null $align */ public function setAlign(?string $align): void { $this->align = $align; } } PK"Z --Table/TableSectionRenderer.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TableSectionRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param TableSection $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer) { TableSection::assertInstanceOf($node); if (! $node->hasChildren()) { return ''; } $attrs = $node->data->get('attributes'); $separator = $childRenderer->getInnerSeparator(); $tag = $node->getType() === TableSection::TYPE_HEAD ? 'thead' : 'tbody'; return new HtmlElement($tag, $attrs, $separator . $childRenderer->renderNodes($node->children()) . $separator); } public function getXmlTagName(Node $node): string { return 'table_section'; } /** * @param TableSection $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { TableSection::assertInstanceOf($node); return [ 'type' => $node->getType(), ]; } } PK"Z2Table/TableRow.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Block\AbstractBlock; final class TableRow extends AbstractBlock { } PK"ZYTable/Table.phpnuW+A * (c) Webuni s.r.o. * (c) Colin O'Dell * * 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\Node\Block\AbstractBlock; final class Table extends AbstractBlock { } PK"ZZCC'Attributes/Event/AttributesListener.phpnuW+A * (c) 2015 Martin Hasoň * * 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\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\Extension\CommonMark\Node\Block\FencedCode; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Node\Inline\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 { foreach ($event->getDocument()->iterator() as $node) { if (! ($node instanceof Attributes || $node instanceof AttributesInline)) { continue; } [$target, $direction] = self::findTargetAndDirection($node); if ($target instanceof Node) { $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->set('attributes', $attributes); } $node->detach(); } } /** * @param Attributes|AttributesInline $node * * @return array */ private static function findTargetAndDirection($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]; } /** * Get any previous block (sibling or parent) this might apply to */ private static function getPrevious(?Node $node = null): ?Node { if ($node instanceof Attributes) { if ($node->getTarget() === Attributes::TARGET_NEXT) { return null; } if ($node->getTarget() === Attributes::TARGET_PARENT) { return $node->parent(); } } return $node instanceof Node ? $node->previous() : null; } /** * Get any previous block (sibling or parent) this might apply to */ private static function getNext(?Node $node = null): ?Node { if ($node instanceof Attributes && $node->getTarget() !== Attributes::TARGET_NEXT) { return null; } return $node instanceof Node ? $node->next() : null; } private static function isAttributesNode(Node $node): bool { return $node instanceof Attributes || $node instanceof AttributesInline; } } PK"Z C$Attributes/Node/AttributesInline.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Node\Inline\AbstractInline; final class AttributesInline extends AbstractInline { /** @var array */ private array $attributes; private bool $block; /** * @param array $attributes */ public function __construct(array $attributes, bool $block) { parent::__construct(); $this->attributes = $attributes; $this->block = $block; } /** * @return array */ public function getAttributes(): array { return $this->attributes; } /** * @param array $attributes */ public function setAttributes(array $attributes): void { $this->attributes = $attributes; } public function isBlock(): bool { return $this->block; } } PK"Z>wwAttributes/Node/Attributes.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Node\Block\AbstractBlock; final class Attributes extends AbstractBlock { public const TARGET_PARENT = 0; public const TARGET_PREVIOUS = 1; public const TARGET_NEXT = 2; /** @var array */ private array $attributes; private int $target = self::TARGET_NEXT; /** * @param array $attributes */ public function __construct(array $attributes) { parent::__construct(); $this->attributes = $attributes; } /** * @return array */ public function getAttributes(): array { return $this->attributes; } /** * @param array $attributes */ public function setAttributes(array $attributes): void { $this->attributes = $attributes; } public function getTarget(): int { return $this->target; } public function setTarget(int $target): void { $this->target = $target; } } PK"Zc>kk$Attributes/Util/AttributesHelper.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Node\Node; use League\CommonMark\Parser\Cursor; use League\CommonMark\Util\RegexHelper; /** * @internal */ final class AttributesHelper { private const SINGLE_ATTRIBUTE = '\s*([.#][_a-z0-9-]+|' . RegexHelper::PARTIAL_ATTRIBUTENAME . RegexHelper::PARTIAL_ATTRIBUTEVALUESPEC . ')\s*'; private const ATTRIBUTE_LIST = '/^{:?(' . self::SINGLE_ATTRIBUTE . ')+}/i'; /** * @return array */ public static function parseAttributes(Cursor $cursor): array { $state = $cursor->saveState(); $cursor->advanceToNextNonSpaceOrNewline(); // Quick check to see if we might have attributes if ($cursor->getCharacter() !== '{') { $cursor->restoreState($state); return []; } // Attempt to match the entire attribute list expression // While this is less performant than checking for '{' now and '}' later, it simplifies // matching individual attributes since they won't need to look ahead for the closing '}' // while dealing with the fact that attributes can technically contain curly braces. // So we'll just match the start and end braces up front. $attributeExpression = $cursor->match(self::ATTRIBUTE_LIST); if ($attributeExpression === null) { $cursor->restoreState($state); return []; } // Trim the leading '{' or '{:' and the trailing '}' $attributeExpression = \ltrim(\substr($attributeExpression, 1, -1), ':'); $attributeCursor = new Cursor($attributeExpression); /** @var array $attributes */ $attributes = []; while ($attribute = \trim((string) $attributeCursor->match('/^' . self::SINGLE_ATTRIBUTE . '/i'))) { if ($attribute[0] === '#') { $attributes['id'] = \substr($attribute, 1); continue; } if ($attribute[0] === '.') { $attributes['class'][] = \substr($attribute, 1); continue; } /** @psalm-suppress PossiblyUndefinedArrayOffset */ [$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 (isset($attributes['class'])) { $attributes['class'] = \implode(' ', (array) $attributes['class']); } return $attributes; } /** * @param Node|array $attributes1 * @param Node|array $attributes2 * * @return array */ public static function mergeAttributes($attributes1, $attributes2): array { $attributes = []; foreach ([$attributes1, $attributes2] as $arg) { if ($arg instanceof Node) { $arg = $arg->data->get('attributes'); } /** @var array $arg */ $arg = (array) $arg; if (isset($arg['class'])) { if (\is_string($arg['class'])) { $arg['class'] = \array_filter(\explode(' ', \trim($arg['class']))); } foreach ($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; } } PK"Z0dŘ"Attributes/AttributesExtension.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\Attributes\Event\AttributesListener; use League\CommonMark\Extension\Attributes\Parser\AttributesBlockStartParser; use League\CommonMark\Extension\Attributes\Parser\AttributesInlineParser; use League\CommonMark\Extension\ExtensionInterface; final class AttributesExtension implements ExtensionInterface { public function register(EnvironmentBuilderInterface $environment): void { $environment->addBlockStartParser(new AttributesBlockStartParser()); $environment->addInlineParser(new AttributesInlineParser()); $environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener(), 'processDocument']); } } PK"ZZKK0Attributes/Parser/AttributesBlockStartParser.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Util\AttributesHelper; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; final class AttributesBlockStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { $originalPosition = $cursor->getPosition(); $attributes = AttributesHelper::parseAttributes($cursor); if ($attributes === [] && $originalPosition === $cursor->getPosition()) { return BlockStart::none(); } if ($cursor->getNextNonSpaceCharacter() !== null) { return BlockStart::none(); } return BlockStart::of(new AttributesBlockContinueParser($attributes, $parserState->getActiveBlockParser()->getBlock()))->at($cursor); } } PK"ZMǯ',Attributes/Parser/AttributesInlineParser.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Node\StringContainerInterface; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class AttributesInlineParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::string('{'); } public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $char = (string) $cursor->peek(-1); $attributes = AttributesHelper::parseAttributes($cursor); if ($attributes === []) { return false; } if ($char === ' ' && ($prev = $inlineContext->getContainer()->lastChild()) instanceof StringContainerInterface) { $prev->setLiteral(\rtrim($prev->getLiteral(), ' ')); } if ($char === '') { $cursor->advanceToNextNonSpaceOrNewline(); } $node = new AttributesInline($attributes, $char === ' ' || $char === ''); $inlineContext->getContainer()->appendChild($node); return true; } } PK"Z_;0 3Attributes/Parser/AttributesBlockContinueParser.phpnuW+A * (c) 2015 Martin Hasoň * * 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\Attributes; use League\CommonMark\Extension\Attributes\Util\AttributesHelper; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class AttributesBlockContinueParser extends AbstractBlockContinueParser { private Attributes $block; private AbstractBlock $container; private bool $hasSubsequentLine = false; /** * @param array $attributes The attributes identified by the block start parser * @param AbstractBlock $container The node we were in when these attributes were discovered */ public function __construct(array $attributes, AbstractBlock $container) { $this->block = new Attributes($attributes); $this->container = $container; } public function getBlock(): AbstractBlock { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { $this->hasSubsequentLine = true; $cursor->advanceToNextNonSpaceOrTab(); // Does this next line also have attributes? $attributes = AttributesHelper::parseAttributes($cursor); $cursor->advanceToNextNonSpaceOrTab(); if ($cursor->isAtEnd() && $attributes !== []) { // It does! Merge them into what we parsed previously $this->block->setAttributes(AttributesHelper::mergeAttributes( $this->block->getAttributes(), $attributes )); // Tell the core parser we've consumed everything return BlockContinue::at($cursor); } // Okay, so there are no attributes on the next line // If this next line is blank we know we can't target the next node, it must be a previous one if ($cursor->isBlank()) { $this->block->setTarget(Attributes::TARGET_PREVIOUS); } return BlockContinue::none(); } public function closeBlock(): void { // Attributes appearing at the very end of the document won't have any last lines to check // so we can make that determination here if (! $this->hasSubsequentLine) { $this->block->setTarget(Attributes::TARGET_PREVIOUS); } // We know this block must apply to the "previous" block, but that could be a sibling or parent, // so we check the containing block to see which one it might be. if ($this->block->getTarget() === Attributes::TARGET_PREVIOUS && $this->block->parent() === $this->container) { $this->block->setTarget(Attributes::TARGET_PARENT); } } } PK"Zpܵ1 1 6Footnote/Event/FixOrphanedFootnotesAndRefsListener.phpnuW+A * * 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\Footnote; use League\CommonMark\Extension\Footnote\Node\FootnoteRef; use League\CommonMark\Node\Block\Document; use League\CommonMark\Node\Inline\Text; final class FixOrphanedFootnotesAndRefsListener { public function onDocumentParsed(DocumentParsedEvent $event): void { $document = $event->getDocument(); $map = $this->buildMapOfKnownFootnotesAndRefs($document); foreach ($map['_flat'] as $node) { if ($node instanceof FootnoteRef && ! isset($map[Footnote::class][$node->getReference()->getLabel()])) { // Found an orphaned FootnoteRef without a corresponding Footnote // Restore the original footnote ref text $node->replaceWith(new Text(\sprintf('[^%s]', $node->getReference()->getLabel()))); } // phpcs:disable SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed if ($node instanceof Footnote && ! isset($map[FootnoteRef::class][$node->getReference()->getLabel()])) { // Found an orphaned Footnote without a corresponding FootnoteRef // Remove the footnote $node->detach(); } } } /** @phpstan-ignore-next-line */ private function buildMapOfKnownFootnotesAndRefs(Document $document): array // @phpcs:ignore { $map = [ Footnote::class => [], FootnoteRef::class => [], '_flat' => [], ]; foreach ($document->iterator() as $node) { if ($node instanceof Footnote) { $map[Footnote::class][$node->getReference()->getLabel()] = true; $map['_flat'][] = $node; } elseif ($node instanceof FootnoteRef) { $map[FootnoteRef::class][$node->getReference()->getLabel()] = true; $map['_flat'][] = $node; } } return $map; } } PK"Z~& & *Footnote/Event/NumberFootnotesListener.phpnuW+A * (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(); $nextCounter = 1; $usedLabels = []; $usedCounters = []; foreach ($document->iterator() as $node) { 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 .= '__' . ++$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()->add($newReference); /* * Store created references in document for * creating FootnoteBackrefs */ $document->data->append($existingReference->getDestination(), $newReference); $usedLabels[$label] = 1; $usedCounters[$label] = $nextCounter; if ($canIncrementCounter) { $nextCounter++; } } } } PK"ZM66-Footnote/Event/AnonymousFootnotesListener.phpnuW+A * (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\Footnote; use League\CommonMark\Extension\Footnote\Node\FootnoteBackref; use League\CommonMark\Extension\Footnote\Node\FootnoteRef; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Reference\Reference; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class AnonymousFootnotesListener implements ConfigurationAwareInterface { private ConfigurationInterface $config; public function onDocumentParsed(DocumentParsedEvent $event): void { $document = $event->getDocument(); foreach ($document->iterator() as $node) { if (! $node instanceof FootnoteRef || ($text = $node->getContent()) === null) { continue; } // Anonymous footnote needs to create a footnote from its content $existingReference = $node->getReference(); $newReference = new Reference( $existingReference->getLabel(), '#' . $this->config->get('footnote/ref_id_prefix') . $existingReference->getLabel(), $existingReference->getTitle() ); $paragraph = new Paragraph(); $paragraph->appendChild(new Text($text)); $paragraph->appendChild(new FootnoteBackref($newReference)); $footnote = new Footnote($newReference); $footnote->appendChild($paragraph); $document->appendChild($footnote); } } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } } PK"Z>r *Footnote/Event/GatherFootnotesListener.phpnuW+A * (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\Footnote; use League\CommonMark\Extension\Footnote\Node\FootnoteBackref; use League\CommonMark\Extension\Footnote\Node\FootnoteContainer; use League\CommonMark\Node\Block\Document; use League\CommonMark\Node\NodeIterator; use League\CommonMark\Reference\Reference; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class GatherFootnotesListener implements ConfigurationAwareInterface { private ConfigurationInterface $config; public function onDocumentParsed(DocumentParsedEvent $event): void { $document = $event->getDocument(); $footnotes = []; foreach ($document->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) { if (! $node instanceof Footnote) { continue; } // Look for existing reference with footnote label $ref = $document->getReferenceMap()->get($node->getReference()->getLabel()); if ($ref !== null) { // Use numeric title to get footnotes order $footnotes[(int) $ref->getTitle()] = $node; } else { // Footnote call is missing, append footnote at the end $footnotes[\PHP_INT_MAX] = $node; } $key = '#' . $this->config->get('footnote/footnote_id_prefix') . $node->getReference()->getDestination(); if ($document->data->has($key)) { $this->createBackrefs($node, $document->data->get($key)); } } // 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; } /** * Look for all footnote refs pointing to this footnote and create each footnote backrefs. * * @param Footnote $node The target footnote * @param Reference[] $backrefs References to create backrefs for */ private function createBackrefs(Footnote $node, array $backrefs): void { // Backrefs should be added to the child paragraph $target = $node->lastChild(); if ($target === null) { // This should never happen, but you never know $target = $node; } foreach ($backrefs as $backref) { $target->appendChild(new FootnoteBackref(new Reference( $backref->getLabel(), '#' . $this->config->get('footnote/ref_id_prefix') . $backref->getLabel(), $backref->getTitle() ))); } } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } } PK"ZBFootnote/Node/Footnote.phpnuW+A * (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\Node\Block\AbstractBlock; use League\CommonMark\Reference\ReferenceInterface; use League\CommonMark\Reference\ReferenceableInterface; final class Footnote extends AbstractBlock implements ReferenceableInterface { /** @psalm-readonly */ private ReferenceInterface $reference; public function __construct(ReferenceInterface $reference) { parent::__construct(); $this->reference = $reference; } public function getReference(): ReferenceInterface { return $this->reference; } } PK"ZwggFootnote/Node/FootnoteRef.phpnuW+A * (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\Node\Inline\AbstractInline; use League\CommonMark\Reference\ReferenceInterface; use League\CommonMark\Reference\ReferenceableInterface; final class FootnoteRef extends AbstractInline implements ReferenceableInterface { private ReferenceInterface $reference; /** @psalm-readonly */ private ?string $content = null; /** * @param array $data */ public function __construct(ReferenceInterface $reference, ?string $content = null, array $data = []) { parent::__construct(); $this->reference = $reference; $this->content = $content; if (\count($data) > 0) { $this->data->import($data); } } public function getReference(): ReferenceInterface { return $this->reference; } public function setReference(ReferenceInterface $reference): void { $this->reference = $reference; } public function getContent(): ?string { return $this->content; } } PK"ZX#Footnote/Node/FootnoteContainer.phpnuW+A * (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\Node\Block\AbstractBlock; final class FootnoteContainer extends AbstractBlock { } PK"Zu.1f!Footnote/Node/FootnoteBackref.phpnuW+A * (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\Node\Inline\AbstractInline; use League\CommonMark\Reference\ReferenceInterface; use League\CommonMark\Reference\ReferenceableInterface; /** * Link from the footnote on the bottom of the document back to the reference */ final class FootnoteBackref extends AbstractInline implements ReferenceableInterface { /** @psalm-readonly */ private ReferenceInterface $reference; public function __construct(ReferenceInterface $reference) { parent::__construct(); $this->reference = $reference; } public function getReference(): ReferenceInterface { return $this->reference; } } PK"Z Footnote/FootnoteExtension.phpnuW+A * (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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\CommonMark\Extension\Footnote\Event\AnonymousFootnotesListener; use League\CommonMark\Extension\Footnote\Event\FixOrphanedFootnotesAndRefsListener; 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\FootnoteRefParser; use League\CommonMark\Extension\Footnote\Parser\FootnoteStartParser; 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; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class FootnoteExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('footnote', Expect::structure([ 'backref_class' => Expect::string('footnote-backref'), 'backref_symbol' => Expect::string('↩'), 'container_add_hr' => Expect::bool(true), 'container_class' => Expect::string('footnotes'), 'ref_class' => Expect::string('footnote-ref'), 'ref_id_prefix' => Expect::string('fnref:'), 'footnote_class' => Expect::string('footnote'), 'footnote_id_prefix' => Expect::string('fn:'), ])); } public function register(EnvironmentBuilderInterface $environment): void { $environment->addBlockStartParser(new FootnoteStartParser(), 51); $environment->addInlineParser(new AnonymousFootnoteRefParser(), 35); $environment->addInlineParser(new FootnoteRefParser(), 51); $environment->addRenderer(FootnoteContainer::class, new FootnoteContainerRenderer()); $environment->addRenderer(Footnote::class, new FootnoteRenderer()); $environment->addRenderer(FootnoteRef::class, new FootnoteRefRenderer()); $environment->addRenderer(FootnoteBackref::class, new FootnoteBackrefRenderer()); $environment->addEventListener(DocumentParsedEvent::class, [new AnonymousFootnotesListener(), 'onDocumentParsed'], 40); $environment->addEventListener(DocumentParsedEvent::class, [new FixOrphanedFootnotesAndRefsListener(), 'onDocumentParsed'], 30); $environment->addEventListener(DocumentParsedEvent::class, [new NumberFootnotesListener(), 'onDocumentParsed'], 20); $environment->addEventListener(DocumentParsedEvent::class, [new GatherFootnotesListener(), 'onDocumentParsed'], 10); } } PK"Z)v@&Footnote/Renderer/FootnoteRenderer.phpnuW+A * (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\Extension\Footnote\Node\Footnote; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class FootnoteRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { private ConfigurationInterface $config; /** * @param Footnote $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Footnote::assertInstanceOf($node); $attrs = $node->data->getData('attributes'); $attrs->append('class', $this->config->get('footnote/footnote_class')); $attrs->set('id', $this->config->get('footnote/footnote_id_prefix') . \mb_strtolower($node->getReference()->getLabel(), 'UTF-8')); $attrs->set('role', 'doc-endnote'); return new HtmlElement( 'li', $attrs->export(), $childRenderer->renderNodes($node->children()), true ); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'footnote'; } /** * @param Footnote $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { Footnote::assertInstanceOf($node); return [ 'reference' => $node->getReference()->getLabel(), ]; } } PK"ZaX X -Footnote/Renderer/FootnoteBackrefRenderer.phpnuW+A * (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\Extension\Footnote\Node\FootnoteBackref; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class FootnoteBackrefRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { public const DEFAULT_SYMBOL = '↩'; private ConfigurationInterface $config; /** * @param FootnoteBackref $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): string { FootnoteBackref::assertInstanceOf($node); $attrs = $node->data->getData('attributes'); $attrs->append('class', $this->config->get('footnote/backref_class')); $attrs->set('rev', 'footnote'); $attrs->set('href', \mb_strtolower($node->getReference()->getDestination(), 'UTF-8')); $attrs->set('role', 'doc-backlink'); $symbol = $this->config->get('footnote/backref_symbol'); \assert(\is_string($symbol)); return ' ' . new HtmlElement('a', $attrs->export(), \htmlspecialchars($symbol), true); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'footnote_backref'; } /** * @param FootnoteBackref $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { FootnoteBackref::assertInstanceOf($node); return [ 'reference' => $node->getReference()->getLabel(), ]; } } PK"Zf )Footnote/Renderer/FootnoteRefRenderer.phpnuW+A * (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\Extension\Footnote\Node\FootnoteRef; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class FootnoteRefRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { private ConfigurationInterface $config; /** * @param FootnoteRef $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { FootnoteRef::assertInstanceOf($node); $attrs = $node->data->getData('attributes'); $attrs->append('class', $this->config->get('footnote/ref_class')); $attrs->set('href', \mb_strtolower($node->getReference()->getDestination(), 'UTF-8')); $attrs->set('role', 'doc-noteref'); $idPrefix = $this->config->get('footnote/ref_id_prefix'); return new HtmlElement( 'sup', [ 'id' => $idPrefix . \mb_strtolower($node->getReference()->getLabel(), 'UTF-8'), ], new HtmlElement( 'a', $attrs->export(), $node->getReference()->getTitle() ), true ); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'footnote_ref'; } /** * @param FootnoteRef $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { FootnoteRef::assertInstanceOf($node); return [ 'reference' => $node->getReference()->getLabel(), ]; } } PK"Z/ڰAA/Footnote/Renderer/FootnoteContainerRenderer.phpnuW+A * (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\Extension\Footnote\Node\FootnoteContainer; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class FootnoteContainerRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { private ConfigurationInterface $config; /** * @param FootnoteContainer $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { FootnoteContainer::assertInstanceOf($node); $attrs = $node->data->getData('attributes'); $attrs->append('class', $this->config->get('footnote/container_class')); $attrs->set('role', 'doc-endnotes'); $contents = new HtmlElement('ol', [], $childRenderer->renderNodes($node->children())); if ($this->config->get('footnote/container_add_hr')) { $contents = [new HtmlElement('hr', [], null, true), $contents]; } return new HtmlElement('div', $attrs->export(), $contents); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'footnote_container'; } /** * @return array */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z * (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\Environment\EnvironmentAwareInterface; use League\CommonMark\Environment\EnvironmentInterface; use League\CommonMark\Extension\Footnote\Node\FootnoteRef; use League\CommonMark\Normalizer\TextNormalizerInterface; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Reference\Reference; use League\Config\ConfigurationInterface; final class AnonymousFootnoteRefParser implements InlineParserInterface, EnvironmentAwareInterface { private ConfigurationInterface $config; /** @psalm-readonly-allow-private-mutation */ private TextNormalizerInterface $slugNormalizer; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex('\^\[([^\]]+)\]'); } public function parse(InlineParserContext $inlineContext): bool { $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength()); [$label] = $inlineContext->getSubMatches(); $reference = $this->createReference($label); $inlineContext->getContainer()->appendChild(new FootnoteRef($reference, $label)); return true; } private function createReference(string $label): Reference { $refLabel = $this->slugNormalizer->normalize($label, ['length' => 20]); return new Reference( $refLabel, '#' . $this->config->get('footnote/footnote_id_prefix') . $refLabel, $label ); } public function setEnvironment(EnvironmentInterface $environment): void { $this->config = $environment->getConfiguration(); $this->slugNormalizer = $environment->getSlugNormalizer(); } } PK"Zd"Footnote/Parser/FootnoteParser.phpnuW+A * (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\Footnote; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Reference\ReferenceInterface; final class FootnoteParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private Footnote $block; /** @psalm-readonly-allow-private-mutation */ private ?int $indentation = null; public function __construct(ReferenceInterface $reference) { $this->block = new Footnote($reference); } public function getBlock(): Footnote { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if ($cursor->isBlank()) { return BlockContinue::at($cursor); } if ($cursor->isIndented()) { $this->indentation ??= $cursor->getIndent(); $cursor->advanceBy($this->indentation, true); return BlockContinue::at($cursor); } return BlockContinue::none(); } public function isContainer(): bool { return true; } public function canContain(AbstractBlock $childBlock): bool { return true; } } PK"ZzɎ%Footnote/Parser/FootnoteRefParser.phpnuW+A * (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\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Reference\Reference; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class FootnoteRefParser implements InlineParserInterface, ConfigurationAwareInterface { private ConfigurationInterface $config; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex('\[\^([^\s\]]+)\]'); } public function parse(InlineParserContext $inlineContext): bool { $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength()); [$label] = $inlineContext->getSubMatches(); $inlineContext->getContainer()->appendChild(new FootnoteRef($this->createReference($label))); return true; } private function createReference(string $label): Reference { return new Reference( $label, '#' . $this->config->get('footnote/footnote_id_prefix') . $label, $label ); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } } PK"ZI'Footnote/Parser/FootnoteStartParser.phpnuW+A * (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\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\CommonMark\Reference\Reference; use League\CommonMark\Util\RegexHelper; final class FootnoteStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented() || $parserState->getLastMatchedBlockParser()->canHaveLazyContinuationLines()) { return BlockStart::none(); } $match = RegexHelper::matchFirst( '/^\[\^([^\s^\]]+)\]\:(?:\s|$)/', $cursor->getLine(), $cursor->getNextNonSpacePosition() ); if (! $match) { return BlockStart::none(); } $cursor->advanceToNextNonSpaceOrTab(); $cursor->advanceBy(\strlen($match[0])); $str = $cursor->getRemainder(); \preg_replace('/^\[\^([^\s^\]]+)\]\:(?:\s|$)/', '', $str); if (\preg_match('/^\[\^([^\s^\]]+)\]\:(?:\s|$)/', $match[0], $matches) !== 1) { return BlockStart::none(); } $reference = new Reference($matches[1], $matches[1], $matches[1]); $footnoteParser = new FootnoteParser($reference); return BlockStart::of($footnoteParser)->at($cursor); } } PK"Z8),TableOfContents/TableOfContentsGenerator.phpnuW+A * * 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\Extension\CommonMark\Node\Block\Heading; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListData; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; 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\Node\Block\Document; use League\CommonMark\Node\NodeIterator; use League\CommonMark\Node\RawMarkupContainerInterface; use League\CommonMark\Node\StringContainerHelper; use League\Config\Exception\InvalidConfigurationException; 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'; /** @psalm-readonly */ private string $style; /** @psalm-readonly */ private string $normalizationStrategy; /** @psalm-readonly */ private int $minHeadingLevel; /** @psalm-readonly */ private int $maxHeadingLevel; /** @psalm-readonly */ private string $fragmentPrefix; public function __construct(string $style, string $normalizationStrategy, int $minHeadingLevel, int $maxHeadingLevel, string $fragmentPrefix) { $this->style = $style; $this->normalizationStrategy = $normalizationStrategy; $this->minHeadingLevel = $minHeadingLevel; $this->maxHeadingLevel = $maxHeadingLevel; $this->fragmentPrefix = $fragmentPrefix; if ($fragmentPrefix !== '') { $this->fragmentPrefix .= '-'; } } 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 ??= $heading; // Keep track of the start and end lines $toc->setStartLine($firstHeading->getStartLine()); $toc->setEndLine($heading->getEndLine()); // Create the new link $link = new Link('#' . $this->fragmentPrefix . $headingLink->getSlug(), StringContainerHelper::getChildText($heading, [RawMarkupContainerInterface::class])); $listItem = new ListItem($toc->getListData()); $listItem->setStartLine($heading->getStartLine()); $listItem->setEndLine($heading->getEndLine()); $listItem->appendChild($link); // 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 InvalidConfigurationException(\sprintf('Invalid table of contents list style: "%s"', $this->style)); } $toc = new TableOfContents($listData); $toc->setStartLine($document->getStartLine()); $toc->setEndLine($document->getEndLine()); return $toc; } /** * @return iterable */ private function getHeadingLinks(Document $document): iterable { foreach ($document->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) { if (! $node instanceof Heading) { continue; } foreach ($node->children() as $child) { if ($child instanceof HeadingPermalink) { yield $child; } } } } 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 InvalidConfigurationException(\sprintf('Invalid table of contents normalization strategy: "%s"', $this->normalizationStrategy)); } } } PK"Z;ۿ6TableOfContents/TableOfContentsPlaceholderRenderer.phpnuW+A * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TableOfContentsPlaceholderRenderer implements NodeRendererInterface, XmlNodeRendererInterface { public function render(Node $node, ChildNodeRendererInterface $childRenderer): string { return ''; } public function getXmlTagName(Node $node): string { return 'table_of_contents_placeholder'; } /** * @return array */ public function getXmlAttributes(Node $node): array { return []; } } PK"Zvh+TableOfContents/TableOfContentsRenderer.phpnuW+A * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TableOfContentsRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** @var NodeRendererInterface&XmlNodeRendererInterface */ private $innerRenderer; /** * @psalm-param NodeRendererInterface&XmlNodeRendererInterface $innerRenderer * * @phpstan-param NodeRendererInterface&XmlNodeRendererInterface $innerRenderer */ public function __construct(NodeRendererInterface $innerRenderer) { $this->innerRenderer = $innerRenderer; } /** * {@inheritDoc} */ public function render(Node $node, ChildNodeRendererInterface $childRenderer) { return $this->innerRenderer->render($node, $childRenderer); } public function getXmlTagName(Node $node): string { return 'table_of_contents'; } /** * @return array */ public function getXmlAttributes(Node $node): array { return $this->innerRenderer->getXmlAttributes($node); } } PK"ZSH:TableOfContents/Normalizer/NormalizerStrategyInterface.phpnuW+A * * 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\Extension\CommonMark\Node\Block\ListItem; interface NormalizerStrategyInterface { public function addItem(int $level, ListItem $listItemToAdd): void; } PK"ZIe e 5TableOfContents/Normalizer/AsIsNormalizerStrategy.phpnuW+A * * 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\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Extension\TableOfContents\Node\TableOfContents; final class AsIsNormalizerStrategy implements NormalizerStrategyInterface { /** @psalm-readonly-allow-private-mutation */ private ListBlock $parentListBlock; /** @psalm-readonly-allow-private-mutation */ private int $parentLevel = 1; /** @psalm-readonly-allow-private-mutation */ private ?ListItem $lastListItem = null; 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 $search = $this->parentListBlock; while ($search = $search->parent()) { if ($search instanceof ListBlock) { $this->parentListBlock = $search; break; } } $this->parentLevel--; } $this->parentListBlock->appendChild($listItemToAdd); $this->lastListItem = $listItemToAdd; } } PK"ZUTi9TableOfContents/Normalizer/RelativeNormalizerStrategy.phpnuW+A * * 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\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Extension\TableOfContents\Node\TableOfContents; final class RelativeNormalizerStrategy implements NormalizerStrategyInterface { /** @psalm-readonly */ private TableOfContents $toc; /** * @var array * * @psalm-readonly-allow-private-mutation */ private array $listItemStack = []; public function __construct(TableOfContents $toc) { $this->toc = $toc; } public function addItem(int $level, ListItem $listItemToAdd): void { $previousLevel = \array_key_last($this->listItemStack); // Pop the stack if we're too deep while ($previousLevel !== null && $level < $previousLevel) { \array_pop($this->listItemStack); $previousLevel = \array_key_last($this->listItemStack); } $lastListItem = \end($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; } } PK"Z @HH5TableOfContents/Normalizer/FlatNormalizerStrategy.phpnuW+A * * 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\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Extension\TableOfContents\Node\TableOfContents; final class FlatNormalizerStrategy implements NormalizerStrategyInterface { /** @psalm-readonly */ private TableOfContents $toc; public function __construct(TableOfContents $toc) { $this->toc = $toc; } public function addItem(int $level, ListItem $listItemToAdd): void { $this->toc->appendChild($listItemToAdd); } } PK"Zè3TableOfContents/Node/TableOfContentsPlaceholder.phpnuW+A * * 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\Node\Block\AbstractBlock; final class TableOfContentsPlaceholder extends AbstractBlock { } PK"Z_(TableOfContents/Node/TableOfContents.phpnuW+A * * 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\Extension\CommonMark\Node\Block\ListBlock; final class TableOfContents extends ListBlock { } PK"ZDM..5TableOfContents/TableOfContentsGeneratorInterface.phpnuW+A * * 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\Extension\TableOfContents\Node\TableOfContents; use League\CommonMark\Node\Block\Document; interface TableOfContentsGeneratorInterface { public function generate(Document $document): ?TableOfContents; } PK"Z5a*TableOfContents/TableOfContentsBuilder.phpnuW+A * * 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\Event\DocumentParsedEvent; use League\CommonMark\Extension\CommonMark\Node\Block\Heading; use League\CommonMark\Extension\HeadingPermalink\HeadingPermalink; use League\CommonMark\Extension\TableOfContents\Node\TableOfContents; use League\CommonMark\Extension\TableOfContents\Node\TableOfContentsPlaceholder; use League\CommonMark\Node\Block\Document; use League\CommonMark\Node\NodeIterator; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; use League\Config\Exception\InvalidConfigurationException; final class TableOfContentsBuilder implements ConfigurationAwareInterface { public const POSITION_TOP = 'top'; public const POSITION_BEFORE_HEADINGS = 'before-headings'; public const POSITION_PLACEHOLDER = 'placeholder'; /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; public function onDocumentParsed(DocumentParsedEvent $event): void { $document = $event->getDocument(); $generator = new TableOfContentsGenerator( (string) $this->config->get('table_of_contents/style'), (string) $this->config->get('table_of_contents/normalize'), (int) $this->config->get('table_of_contents/min_heading_level'), (int) $this->config->get('table_of_contents/max_heading_level'), (string) $this->config->get('heading_permalink/fragment_prefix'), ); $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'); if ($class !== null) { $toc->data->append('attributes/class', $class); } // Add the TOC to the Document $position = $this->config->get('table_of_contents/position'); 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 InvalidConfigurationException::forConfigOption('table_of_contents/position', $position); } } private function insertBeforeFirstLinkedHeading(Document $document, TableOfContents $toc): void { foreach ($document->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) { if (! $node instanceof Heading) { continue; } foreach ($node->children() as $child) { if ($child instanceof HeadingPermalink) { $node->insertBefore($toc); return; } } } } private function replacePlaceholders(Document $document, TableOfContents $toc): void { foreach ($document->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) { // Add the block once we find a placeholder if (! $node instanceof TableOfContentsPlaceholder) { continue; } $node->replaceWith(clone $toc); } } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } } PK"Z[ 4TableOfContents/TableOfContentsPlaceholderParser.phpnuW+A * * 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\Extension\TableOfContents\Node\TableOfContentsPlaceholder; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class TableOfContentsPlaceholderParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private TableOfContentsPlaceholder $block; public function __construct() { $this->block = new TableOfContentsPlaceholder(); } public function getBlock(): TableOfContentsPlaceholder { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { return BlockContinue::none(); } public static function blockStartParser(): BlockStartParserInterface { return new class () implements BlockStartParserInterface, ConfigurationAwareInterface { /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { $placeholder = $this->config->get('table_of_contents/placeholder'); if ($placeholder === null) { return BlockStart::none(); } // The placeholder must be the only thing on the line if ($cursor->match('/^' . \preg_quote($placeholder, '/') . '$/') === null) { return BlockStart::none(); } return BlockStart::of(new TableOfContentsPlaceholderParser())->at($cursor); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } }; } } PK"Z{z z ,TableOfContents/TableOfContentsExtension.phpnuW+A * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Renderer\Block\ListBlockRenderer; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\CommonMark\Extension\TableOfContents\Node\TableOfContents; use League\CommonMark\Extension\TableOfContents\Node\TableOfContentsPlaceholder; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class TableOfContentsExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('table_of_contents', Expect::structure([ 'position' => Expect::anyOf(TableOfContentsBuilder::POSITION_BEFORE_HEADINGS, TableOfContentsBuilder::POSITION_PLACEHOLDER, TableOfContentsBuilder::POSITION_TOP)->default(TableOfContentsBuilder::POSITION_TOP), 'style' => Expect::anyOf(ListBlock::TYPE_BULLET, ListBlock::TYPE_ORDERED)->default(ListBlock::TYPE_BULLET), 'normalize' => Expect::anyOf(TableOfContentsGenerator::NORMALIZE_RELATIVE, TableOfContentsGenerator::NORMALIZE_FLAT, TableOfContentsGenerator::NORMALIZE_DISABLED)->default(TableOfContentsGenerator::NORMALIZE_RELATIVE), 'min_heading_level' => Expect::int()->min(1)->max(6)->default(1), 'max_heading_level' => Expect::int()->min(1)->max(6)->default(6), 'html_class' => Expect::string()->default('table-of-contents'), 'placeholder' => Expect::anyOf(Expect::string(), Expect::null())->default(null), ])); } public function register(EnvironmentBuilderInterface $environment): void { $environment->addRenderer(TableOfContents::class, new TableOfContentsRenderer(new ListBlockRenderer())); $environment->addEventListener(DocumentParsedEvent::class, [new TableOfContentsBuilder(), 'onDocumentParsed'], -150); // phpcs:ignore SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed if ($environment->getConfiguration()->get('table_of_contents/position') === TableOfContentsBuilder::POSITION_PLACEHOLDER) { $environment->addBlockStartParser(TableOfContentsPlaceholderParser::blockStartParser(), 200); // If a placeholder cannot be replaced with a TOC element this renderer will ensure the parser won't error out $environment->addRenderer(TableOfContentsPlaceholder::class, new TableOfContentsPlaceholderRenderer()); } } } PK"Zmk22,SmartPunct/ReplaceUnpairedQuotesListener.phpnuW+A * * 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\Event\DocumentParsedEvent; use League\CommonMark\Node\Inline\AdjacentTextMerger; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Node\Query; /** * Identifies any lingering Quote nodes that were missing pairs and converts them into Text nodes */ final class ReplaceUnpairedQuotesListener { public function __invoke(DocumentParsedEvent $event): void { $query = (new Query())->where(Query::type(Quote::class)); foreach ($query->findAll($event->getDocument()) as $quote) { \assert($quote instanceof Quote); $literal = $quote->getLiteral(); if ($literal === Quote::SINGLE_QUOTE) { $literal = Quote::SINGLE_QUOTE_CLOSER; } elseif ($literal === Quote::DOUBLE_QUOTE) { $literal = Quote::DOUBLE_QUOTE_OPENER; } $quote->replaceWith($new = new Text($literal)); AdjacentTextMerger::mergeWithDirectlyAdjacentNodes($new); } } } PK"ZТrrSmartPunct/DashParser.phpnuW+A * * 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\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class DashParser implements InlineParserInterface { private const EN_DASH = '–'; private const EM_DASH = '—'; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex('(?getFullMatchLength(); $inlineContext->getCursor()->advanceBy($count); $enCount = 0; $emCount = 0; if ($count % 3 === 0) { // If divisible by 3, use all em dashes $emCount = (int) ($count / 3); } elseif ($count % 2 === 0) { // If divisible by 2, use all en dashes $enCount = (int) ($count / 2); } elseif ($count % 3 === 2) { // If 2 extra dashes, use en dash for last 2; em dashes for rest $emCount = (int) (($count - 2) / 3); $enCount = 1; } else { // Use en dashes for last 4 hyphens; em dashes for rest $emCount = (int) (($count - 4) / 3); $enCount = 2; } $inlineContext->getContainer()->appendChild(new Text( \str_repeat(self::EM_DASH, $emCount) . \str_repeat(self::EN_DASH, $enCount) )); return true; } } PK"Z%d; ; SmartPunct/QuoteProcessor.phpnuW+A * * 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\Node\Inline\AbstractStringContainer; final class QuoteProcessor implements DelimiterProcessorInterface { /** @psalm-readonly */ private string $normalizedCharacter; /** @psalm-readonly */ private string $openerCharacter; /** @psalm-readonly */ private string $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): void { $opener->insertAfter(new Quote($this->openerCharacter)); $closer->insertBefore(new Quote($this->closerCharacter)); } /** * Create a double-quote processor */ 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 */ 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); } } PK"Z,K SmartPunct/QuoteParser.phpnuW+A * * 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\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\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]; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::oneOf(...\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 { $char = $inlineContext->getFullMatch(); $cursor = $inlineContext->getCursor(); $normalizedCharacter = $this->getNormalizedQuoteCharacter($char); $charBefore = $cursor->peek(-1); if ($charBefore === null) { $charBefore = "\n"; } $cursor->advance(); $charAfter = $cursor->getCurrentCharacter(); 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, true)) { return Quote::DOUBLE_QUOTE; } if (\in_array($character, self::SINGLE_QUOTES, true)) { return Quote::SINGLE_QUOTE; } return $character; } /** * @return bool[] */ private function determineFlanking(string $charBefore, string $charAfter): array { $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]; } } PK"Z 4$OOSmartPunct/EllipsesParser.phpnuW+A * * 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\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class EllipsesParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::oneOf('...', '. . .'); } public function parse(InlineParserContext $inlineContext): bool { $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength()); $inlineContext->getContainer()->appendChild(new Text('…')); return true; } } PK"Z2"? "SmartPunct/SmartPunctExtension.phpnuW+A * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\CommonMark\Node\Block\Document; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Renderer\Block as CoreBlockRenderer; use League\CommonMark\Renderer\Inline as CoreInlineRenderer; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class SmartPunctExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('smartpunct', Expect::structure([ 'double_quote_opener' => Expect::string(Quote::DOUBLE_QUOTE_OPENER), 'double_quote_closer' => Expect::string(Quote::DOUBLE_QUOTE_CLOSER), 'single_quote_opener' => Expect::string(Quote::SINGLE_QUOTE_OPENER), 'single_quote_closer' => Expect::string(Quote::SINGLE_QUOTE_CLOSER), ])); } public function register(EnvironmentBuilderInterface $environment): void { $environment ->addInlineParser(new QuoteParser(), 10) ->addInlineParser(new DashParser(), 0) ->addInlineParser(new EllipsesParser(), 0) ->addDelimiterProcessor(QuoteProcessor::createDoubleQuoteProcessor( $environment->getConfiguration()->get('smartpunct/double_quote_opener'), $environment->getConfiguration()->get('smartpunct/double_quote_closer') )) ->addDelimiterProcessor(QuoteProcessor::createSingleQuoteProcessor( $environment->getConfiguration()->get('smartpunct/single_quote_opener'), $environment->getConfiguration()->get('smartpunct/single_quote_closer') )) ->addEventListener(DocumentParsedEvent::class, new ReplaceUnpairedQuotesListener()) ->addRenderer(Document::class, new CoreBlockRenderer\DocumentRenderer(), 0) ->addRenderer(Paragraph::class, new CoreBlockRenderer\ParagraphRenderer(), 0) ->addRenderer(Text::class, new CoreInlineRenderer\TextRenderer(), 0); } } PK"ZK{AASmartPunct/Quote.phpnuW+A * * 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\Node\Inline\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 = '’'; } PK"Z_88"CommonMark/Node/Block/ListData.phpnuW+A * * 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\CommonMark\Node\Block; class ListData { public ?int $start = null; public int $padding = 0; /** * @psalm-var ListBlock::TYPE_* * @phpstan-var ListBlock::TYPE_* */ public string $type; /** * @psalm-var ListBlock::DELIM_*|null * @phpstan-var ListBlock::DELIM_*|null */ public ?string $delimiter = null; public ?string $bulletChar = null; public int $markerOffset; public function equals(ListData $data): bool { return $this->type === $data->type && $this->delimiter === $data->delimiter && $this->bulletChar === $data->bulletChar; } } PK"Z[&CommonMark/Node/Block/IndentedCode.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Node\StringContainerInterface; final class IndentedCode extends AbstractBlock implements StringContainerInterface { private string $literal = ''; public function getLiteral(): string { return $this->literal; } public function setLiteral(string $literal): void { $this->literal = $literal; } } PK"Z5i@@"CommonMark/Node/Block/ListItem.phpnuW+A * * 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\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; class ListItem extends AbstractBlock { /** @psalm-readonly */ protected ListData $listData; public function __construct(ListData $listData) { parent::__construct(); $this->listData = $listData; } public function getListData(): ListData { return $this->listData; } } PK"Zt>Pbb!CommonMark/Node/Block/Heading.phpnuW+A * * 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\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; final class Heading extends AbstractBlock { private int $level; public function __construct(int $level) { parent::__construct(); $this->level = $level; } public function getLevel(): int { return $this->level; } public function setLevel(int $level): void { $this->level = $level; } } PK"Z0''#CommonMark/Node/Block/HtmlBlock.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Node\RawMarkupContainerInterface; final class HtmlBlock extends AbstractBlock implements RawMarkupContainerInterface { // Any changes to these constants should be reflected in .phpstorm.meta.php public const TYPE_1_CODE_CONTAINER = 1; public const TYPE_2_COMMENT = 2; public const TYPE_3 = 3; public const TYPE_4 = 4; public const TYPE_5_CDATA = 5; public const TYPE_6_BLOCK_ELEMENT = 6; public const TYPE_7_MISC_ELEMENT = 7; /** * @psalm-var self::TYPE_* $type * @phpstan-var self::TYPE_* $type */ private int $type; private string $literal = ''; /** * @psalm-param self::TYPE_* $type * * @phpstan-param self::TYPE_* $type */ public function __construct(int $type) { parent::__construct(); $this->type = $type; } /** * @psalm-return self::TYPE_* * * @phpstan-return self::TYPE_* */ public function getType(): int { return $this->type; } /** * @psalm-param self::TYPE_* $type * * @phpstan-param self::TYPE_* $type */ public function setType(int $type): void { $this->type = $type; } public function getLiteral(): string { return $this->literal; } public function setLiteral(string $literal): void { $this->literal = $literal; } } PK"Z`I$CommonMark/Node/Block/BlockQuote.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; class BlockQuote extends AbstractBlock { } PK"Zщ8#CommonMark/Node/Block/ListBlock.phpnuW+A * * 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\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Node\Block\TightBlockInterface; class ListBlock extends AbstractBlock implements TightBlockInterface { public const TYPE_BULLET = 'bullet'; public const TYPE_ORDERED = 'ordered'; public const DELIM_PERIOD = 'period'; public const DELIM_PAREN = 'paren'; protected bool $tight = false; /** @psalm-readonly */ protected ListData $listData; public function __construct(ListData $listData) { parent::__construct(); $this->listData = $listData; } public function getListData(): ListData { return $this->listData; } public function isTight(): bool { return $this->tight; } public function setTight(bool $tight): void { $this->tight = $tight; } } PK"Z>'CommonMark/Node/Block/ThematicBreak.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; class ThematicBreak extends AbstractBlock { } PK"Z>l>$CommonMark/Node/Block/FencedCode.phpnuW+A * * 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\CommonMark\Node\Block; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Node\StringContainerInterface; final class FencedCode extends AbstractBlock implements StringContainerInterface { private ?string $info = null; private string $literal = ''; private int $length; private string $char; private int $offset; public function __construct(int $length, string $char, int $offset) { parent::__construct(); $this->length = $length; $this->char = $char; $this->offset = $offset; } public function getInfo(): ?string { return $this->info; } /** * @return string[] */ public function getInfoWords(): array { return \preg_split('/\s+/', $this->info ?? '') ?: []; } public function setInfo(string $info): void { $this->info = $info; } public function getLiteral(): string { return $this->literal; } public function setLiteral(string $literal): void { $this->literal = $literal; } public function getChar(): string { return $this->char; } public function setChar(string $char): void { $this->char = $char; } public function getLength(): int { return $this->length; } public function setLength(int $length): void { $this->length = $length; } public function getOffset(): int { return $this->offset; } public function setOffset(int $offset): void { $this->offset = $offset; } } PK"Z놘oo.CommonMark/Node/Inline/AbstractWebResource.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\AbstractInline; abstract class AbstractWebResource extends AbstractInline { protected string $url; public function __construct(string $url) { parent::__construct(); $this->url = $url; } public function getUrl(): string { return $this->url; } public function setUrl(string $url): void { $this->url = $url; } } PK"Z <̋#CommonMark/Node/Inline/Emphasis.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\AbstractInline; use League\CommonMark\Node\Inline\DelimitedInterface; final class Emphasis extends AbstractInline implements DelimitedInterface { private string $delimiter; public function __construct(string $delimiter = '_') { parent::__construct(); $this->delimiter = $delimiter; } public function getOpeningDelimiter(): string { return $this->delimiter; } public function getClosingDelimiter(): string { return $this->delimiter; } } PK"Zh66CommonMark/Node/Inline/Code.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\AbstractStringContainer; class Code extends AbstractStringContainer { } PK"Zx%CommonMark/Node/Inline/HtmlInline.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\AbstractStringContainer; use League\CommonMark\Node\RawMarkupContainerInterface; final class HtmlInline extends AbstractStringContainer implements RawMarkupContainerInterface { } PK"Z0֝TTCommonMark/Node/Inline/Link.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\Text; class Link extends AbstractWebResource { protected ?string $title = null; public function __construct(string $url, ?string $label = null, ?string $title = null) { parent::__construct($url); if ($label !== null && $label !== '') { $this->appendChild(new Text($label)); } $this->title = $title; } public function getTitle(): ?string { if ($this->title === '') { return null; } return $this->title; } public function setTitle(?string $title): void { $this->title = $title; } } PK"Z!CommonMark/Node/Inline/Strong.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\AbstractInline; use League\CommonMark\Node\Inline\DelimitedInterface; final class Strong extends AbstractInline implements DelimitedInterface { private string $delimiter; public function __construct(string $delimiter = '**') { parent::__construct(); $this->delimiter = $delimiter; } public function getOpeningDelimiter(): string { return $this->delimiter; } public function getClosingDelimiter(): string { return $this->delimiter; } } PK"ZP2UU CommonMark/Node/Inline/Image.phpnuW+A * * 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\CommonMark\Node\Inline; use League\CommonMark\Node\Inline\Text; class Image extends AbstractWebResource { protected ?string $title = null; public function __construct(string $url, ?string $label = null, ?string $title = null) { parent::__construct($url); if ($label !== null && $label !== '') { $this->appendChild(new Text($label)); } $this->title = $title; } public function getTitle(): ?string { if ($this->title === '') { return null; } return $this->title; } public function setTitle(?string $title): void { $this->title = $title; } } PK"Z&t++/CommonMark/Renderer/Block/HtmlBlockRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlFilter; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class HtmlBlockRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; /** * @param HtmlBlock $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): string { HtmlBlock::assertInstanceOf($node); $htmlInput = $this->config->get('html_input'); return HtmlFilter::filter($node->getLiteral(), $htmlInput); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'html_block'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z#t22.CommonMark/Renderer/Block/ListItemRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Extension\TaskList\TaskListItemMarker; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class ListItemRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param ListItem $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { ListItem::assertInstanceOf($node); $contents = $childRenderer->renderNodes($node->children()); if (\substr($contents, 0, 1) === '<' && ! $this->startsTaskListItem($node)) { $contents = "\n" . $contents; } if (\substr($contents, -1, 1) === '>') { $contents .= "\n"; } $attrs = $node->data->get('attributes'); return new HtmlElement('li', $attrs, $contents); } public function getXmlTagName(Node $node): string { return 'item'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } private function startsTaskListItem(ListItem $block): bool { $firstChild = $block->firstChild(); return $firstChild instanceof Paragraph && $firstChild->firstChild() instanceof TaskListItemMarker; } } PK"Z@4))0CommonMark/Renderer/Block/FencedCodeRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Util\Xml; use League\CommonMark\Xml\XmlNodeRendererInterface; final class FencedCodeRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param FencedCode $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { FencedCode::assertInstanceOf($node); $attrs = $node->data->getData('attributes'); $infoWords = $node->getInfoWords(); if (\count($infoWords) !== 0 && $infoWords[0] !== '') { $attrs->append('class', 'language-' . $infoWords[0]); } return new HtmlElement( 'pre', [], new HtmlElement('code', $attrs->export(), Xml::escape($node->getLiteral())) ); } public function getXmlTagName(Node $node): string { return 'code_block'; } /** * @param FencedCode $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { FencedCode::assertInstanceOf($node); if (($info = $node->getInfo()) === null || $info === '') { return []; } return ['info' => $info]; } } PK"Z3CommonMark/Renderer/Block/ThematicBreakRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ThematicBreak; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class ThematicBreakRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param ThematicBreak $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { ThematicBreak::assertInstanceOf($node); $attrs = $node->data->get('attributes'); return new HtmlElement('hr', $attrs, '', true); } public function getXmlTagName(Node $node): string { return 'thematic_break'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z>9@ /CommonMark/Renderer/Block/ListBlockRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class ListBlockRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param ListBlock $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { ListBlock::assertInstanceOf($node); $listData = $node->getListData(); $tag = $listData->type === ListBlock::TYPE_BULLET ? 'ul' : 'ol'; $attrs = $node->data->get('attributes'); if ($listData->start !== null && $listData->start !== 1) { $attrs['start'] = (string) $listData->start; } $innerSeparator = $childRenderer->getInnerSeparator(); return new HtmlElement($tag, $attrs, $innerSeparator . $childRenderer->renderNodes($node->children()) . $innerSeparator); } public function getXmlTagName(Node $node): string { return 'list'; } /** * @param ListBlock $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { ListBlock::assertInstanceOf($node); $data = $node->getListData(); if ($data->type === ListBlock::TYPE_BULLET) { return [ 'type' => $data->type, 'tight' => $node->isTight() ? 'true' : 'false', ]; } return [ 'type' => $data->type, 'start' => $data->start ?? 1, 'tight' => $node->isTight(), 'delimiter' => $data->delimiter ?? ListBlock::DELIM_PERIOD, ]; } } PK"Z@ %0CommonMark/Renderer/Block/BlockQuoteRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\BlockQuote; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class BlockQuoteRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param BlockQuote $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { BlockQuote::assertInstanceOf($node); $attrs = $node->data->get('attributes'); $filling = $childRenderer->renderNodes($node->children()); $innerSeparator = $childRenderer->getInnerSeparator(); if ($filling === '') { return new HtmlElement('blockquote', $attrs, $innerSeparator); } return new HtmlElement( 'blockquote', $attrs, $innerSeparator . $filling . $innerSeparator ); } public function getXmlTagName(Node $node): string { return 'block_quote'; } /** * @param BlockQuote $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z-CommonMark/Renderer/Block/HeadingRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\Heading; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class HeadingRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param Heading $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Heading::assertInstanceOf($node); $tag = 'h' . $node->getLevel(); $attrs = $node->data->get('attributes'); return new HtmlElement($tag, $attrs, $childRenderer->renderNodes($node->children())); } public function getXmlTagName(Node $node): string { return 'heading'; } /** * @param Heading $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { Heading::assertInstanceOf($node); return ['level' => $node->getLevel()]; } } PK"Zn3`cc2CommonMark/Renderer/Block/IndentedCodeRenderer.phpnuW+A * * 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\CommonMark\Renderer\Block; use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Util\Xml; use League\CommonMark\Xml\XmlNodeRendererInterface; final class IndentedCodeRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param IndentedCode $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { IndentedCode::assertInstanceOf($node); $attrs = $node->data->get('attributes'); return new HtmlElement( 'pre', [], new HtmlElement('code', $attrs, Xml::escape($node->getLiteral())) ); } public function getXmlTagName(Node $node): string { return 'code_block'; } /** * @return array */ public function getXmlAttributes(Node $node): array { return []; } } PK"ZS>qL9 9 +CommonMark/Renderer/Inline/LinkRenderer.phpnuW+A * * 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\CommonMark\Renderer\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Util\RegexHelper; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class LinkRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; /** * @param Link $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Link::assertInstanceOf($node); $attrs = $node->data->get('attributes'); $forbidUnsafeLinks = ! $this->config->get('allow_unsafe_links'); if (! ($forbidUnsafeLinks && RegexHelper::isLinkPotentiallyUnsafe($node->getUrl()))) { $attrs['href'] = $node->getUrl(); } if (($title = $node->getTitle()) !== null) { $attrs['title'] = $title; } if (isset($attrs['target']) && $attrs['target'] === '_blank' && ! isset($attrs['rel'])) { $attrs['rel'] = 'noopener noreferrer'; } return new HtmlElement('a', $attrs, $childRenderer->renderNodes($node->children())); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'link'; } /** * @param Link $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { Link::assertInstanceOf($node); return [ 'destination' => $node->getUrl(), 'title' => $node->getTitle() ?? '', ]; } } PK"ZyZ'-CommonMark/Renderer/Inline/StrongRenderer.phpnuW+A * * 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\CommonMark\Renderer\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Strong; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class StrongRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param Strong $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Strong::assertInstanceOf($node); $attrs = $node->data->get('attributes'); return new HtmlElement('strong', $attrs, $childRenderer->renderNodes($node->children())); } public function getXmlTagName(Node $node): string { return 'strong'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z(+CommonMark/Renderer/Inline/CodeRenderer.phpnuW+A * * 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\CommonMark\Renderer\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Code; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Util\Xml; use League\CommonMark\Xml\XmlNodeRendererInterface; final class CodeRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param Code $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Code::assertInstanceOf($node); $attrs = $node->data->get('attributes'); return new HtmlElement('code', $attrs, Xml::escape($node->getLiteral())); } public function getXmlTagName(Node $node): string { return 'code'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z ?/CommonMark/Renderer/Inline/EmphasisRenderer.phpnuW+A * * 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\CommonMark\Renderer\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Emphasis; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class EmphasisRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param Emphasis $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Emphasis::assertInstanceOf($node); $attrs = $node->data->get('attributes'); return new HtmlElement('em', $attrs, $childRenderer->renderNodes($node->children())); } public function getXmlTagName(Node $node): string { return 'emph'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Z] ,CommonMark/Renderer/Inline/ImageRenderer.phpnuW+A * * 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\CommonMark\Renderer\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Image; use League\CommonMark\Node\Inline\Newline; use League\CommonMark\Node\Node; use League\CommonMark\Node\NodeIterator; use League\CommonMark\Node\StringContainerInterface; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Util\RegexHelper; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class ImageRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; /** * @param Image $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Image::assertInstanceOf($node); $attrs = $node->data->get('attributes'); $forbidUnsafeLinks = ! $this->config->get('allow_unsafe_links'); if ($forbidUnsafeLinks && RegexHelper::isLinkPotentiallyUnsafe($node->getUrl())) { $attrs['src'] = ''; } else { $attrs['src'] = $node->getUrl(); } $attrs['alt'] = $this->getAltText($node); if (($title = $node->getTitle()) !== null) { $attrs['title'] = $title; } return new HtmlElement('img', $attrs, '', true); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'image'; } /** * @param Image $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { Image::assertInstanceOf($node); return [ 'destination' => $node->getUrl(), 'title' => $node->getTitle() ?? '', ]; } private function getAltText(Image $node): string { $altText = ''; foreach ((new NodeIterator($node)) as $n) { if ($n instanceof StringContainerInterface) { $altText .= $n->getLiteral(); } elseif ($n instanceof Newline) { $altText .= "\n"; } } return $altText; } } PK"Z 221CommonMark/Renderer/Inline/HtmlInlineRenderer.phpnuW+A * * 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\CommonMark\Renderer\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\HtmlInline; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlFilter; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class HtmlInlineRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; /** * @param HtmlInline $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): string { HtmlInline::assertInstanceOf($node); $htmlInput = $this->config->get('html_input'); return HtmlFilter::filter($node->getLiteral(), $htmlInput); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function getXmlTagName(Node $node): string { return 'html_inline'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK"Zh{UU&CommonMark/CommonMarkCoreExtension.phpnuW+A * * 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\CommonMark; use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\CommonMark\Node as CoreNode; use League\CommonMark\Parser as CoreParser; use League\CommonMark\Renderer as CoreRenderer; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class CommonMarkCoreExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('commonmark', Expect::structure([ 'use_asterisk' => Expect::bool(true), 'use_underscore' => Expect::bool(true), 'enable_strong' => Expect::bool(true), 'enable_em' => Expect::bool(true), 'unordered_list_markers' => Expect::listOf('string')->min(1)->default(['*', '+', '-'])->mergeDefaults(false), ])); } // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma,Squiz.WhiteSpace.SemicolonSpacing.Incorrect public function register(EnvironmentBuilderInterface $environment): void { $environment ->addBlockStartParser(new Parser\Block\BlockQuoteStartParser(), 70) ->addBlockStartParser(new Parser\Block\HeadingStartParser(), 60) ->addBlockStartParser(new Parser\Block\FencedCodeStartParser(), 50) ->addBlockStartParser(new Parser\Block\HtmlBlockStartParser(), 40) ->addBlockStartParser(new Parser\Block\ThematicBreakStartParser(), 20) ->addBlockStartParser(new Parser\Block\ListBlockStartParser(), 10) ->addBlockStartParser(new Parser\Block\IndentedCodeStartParser(), -100) ->addInlineParser(new CoreParser\Inline\NewlineParser(), 200) ->addInlineParser(new Parser\Inline\BacktickParser(), 150) ->addInlineParser(new Parser\Inline\EscapableParser(), 80) ->addInlineParser(new Parser\Inline\EntityParser(), 70) ->addInlineParser(new Parser\Inline\AutolinkParser(), 50) ->addInlineParser(new Parser\Inline\HtmlInlineParser(), 40) ->addInlineParser(new Parser\Inline\CloseBracketParser(), 30) ->addInlineParser(new Parser\Inline\OpenBracketParser(), 20) ->addInlineParser(new Parser\Inline\BangParser(), 10) ->addRenderer(Node\Block\BlockQuote::class, new Renderer\Block\BlockQuoteRenderer(), 0) ->addRenderer(CoreNode\Block\Document::class, new CoreRenderer\Block\DocumentRenderer(), 0) ->addRenderer(Node\Block\FencedCode::class, new Renderer\Block\FencedCodeRenderer(), 0) ->addRenderer(Node\Block\Heading::class, new Renderer\Block\HeadingRenderer(), 0) ->addRenderer(Node\Block\HtmlBlock::class, new Renderer\Block\HtmlBlockRenderer(), 0) ->addRenderer(Node\Block\IndentedCode::class, new Renderer\Block\IndentedCodeRenderer(), 0) ->addRenderer(Node\Block\ListBlock::class, new Renderer\Block\ListBlockRenderer(), 0) ->addRenderer(Node\Block\ListItem::class, new Renderer\Block\ListItemRenderer(), 0) ->addRenderer(CoreNode\Block\Paragraph::class, new CoreRenderer\Block\ParagraphRenderer(), 0) ->addRenderer(Node\Block\ThematicBreak::class, new Renderer\Block\ThematicBreakRenderer(), 0) ->addRenderer(Node\Inline\Code::class, new Renderer\Inline\CodeRenderer(), 0) ->addRenderer(Node\Inline\Emphasis::class, new Renderer\Inline\EmphasisRenderer(), 0) ->addRenderer(Node\Inline\HtmlInline::class, new Renderer\Inline\HtmlInlineRenderer(), 0) ->addRenderer(Node\Inline\Image::class, new Renderer\Inline\ImageRenderer(), 0) ->addRenderer(Node\Inline\Link::class, new Renderer\Inline\LinkRenderer(), 0) ->addRenderer(CoreNode\Inline\Newline::class, new CoreRenderer\Inline\NewlineRenderer(), 0) ->addRenderer(Node\Inline\Strong::class, new Renderer\Inline\StrongRenderer(), 0) ->addRenderer(CoreNode\Inline\Text::class, new CoreRenderer\Inline\TextRenderer(), 0) ; if ($environment->getConfiguration()->get('commonmark/use_asterisk')) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*')); } if ($environment->getConfiguration()->get('commonmark/use_underscore')) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_')); } } } PK"ZhN =CommonMark/Delimiter/Processor/EmphasisDelimiterProcessor.phpnuW+A * * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js) * - (c) John MacFarlane * * Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java) * - (c) Atlassian Pty Ltd * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Delimiter\Processor; use League\CommonMark\Delimiter\DelimiterInterface; use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; use League\CommonMark\Extension\CommonMark\Node\Inline\Emphasis; use League\CommonMark\Extension\CommonMark\Node\Inline\Strong; use League\CommonMark\Node\Inline\AbstractStringContainer; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class EmphasisDelimiterProcessor implements DelimiterProcessorInterface, ConfigurationAwareInterface { /** @psalm-readonly */ private string $char; /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; /** * @param string $char The emphasis character to use (typically '*' or '_') */ public function __construct(string $char) { $this->char = $char; } public function getOpeningCharacter(): string { return $this->char; } public function getClosingCharacter(): string { return $this->char; } public function getMinLength(): int { return 1; } public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int { // "Multiple of 3" rule for internal delimiter runs if (($opener->canClose() || $closer->canOpen()) && $closer->getOriginalLength() % 3 !== 0 && ($opener->getOriginalLength() + $closer->getOriginalLength()) % 3 === 0) { return 0; } // Calculate actual number of delimiters used from this closer if ($opener->getLength() >= 2 && $closer->getLength() >= 2) { if ($this->config->get('commonmark/enable_strong')) { return 2; } return 0; } if ($this->config->get('commonmark/enable_em')) { return 1; } return 0; } public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse): void { if ($delimiterUse === 1) { $emphasis = new Emphasis($this->char); } elseif ($delimiterUse === 2) { $emphasis = new Strong($this->char . $this->char); } else { return; } $next = $opener->next(); while ($next !== null && $next !== $closer) { $tmp = $next->next(); $emphasis->appendChild($next); $next = $tmp; } $opener->insertAfter($emphasis); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } } PK"Z}v##{ { *CommonMark/Parser/Block/ListItemParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListData; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class ListItemParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private ListItem $block; private bool $hadBlankLine = false; public function __construct(ListData $listData) { $this->block = new ListItem($listData); } public function getBlock(): ListItem { return $this->block; } public function isContainer(): bool { return true; } public function canContain(AbstractBlock $childBlock): bool { if ($this->hadBlankLine) { // We saw a blank line in this list item, that means the list block is loose. // // spec: if any of its constituent list items directly contain two block-level elements with a blank line // between them $parent = $this->block->parent(); if ($parent instanceof ListBlock) { $parent->setTight(false); } } return true; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if ($cursor->isBlank()) { if ($this->block->firstChild() === null) { // Blank line after empty list item return BlockContinue::none(); } $activeBlock = $activeBlockParser->getBlock(); // If the active block is a code block, blank lines in it should not affect if the list is tight. $this->hadBlankLine = $activeBlock instanceof Paragraph || $activeBlock instanceof ListItem; $cursor->advanceToNextNonSpaceOrTab(); return BlockContinue::at($cursor); } $contentIndent = $this->block->getListData()->markerOffset + $this->getBlock()->getListData()->padding; if ($cursor->getIndent() >= $contentIndent) { $cursor->advanceBy($contentIndent, true); return BlockContinue::at($cursor); } // Note: We'll hit this case for lazy continuation lines, they will get added later. return BlockContinue::none(); } } PK"Z0CommonMark/Parser/Block/ListBlockStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListData; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\CommonMark\Util\RegexHelper; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class ListBlockStartParser implements BlockStartParserInterface, ConfigurationAwareInterface { /** @psalm-readonly-allow-private-mutation */ private ?ConfigurationInterface $config = null; /** @psalm-readonly-allow-private-mutation */ private ?string $listMarkerRegex = null; public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented()) { return BlockStart::none(); } $listData = $this->parseList($cursor, $parserState->getParagraphContent() !== null); if ($listData === null) { return BlockStart::none(); } $listItemParser = new ListItemParser($listData); // prepend the list block if needed $matched = $parserState->getLastMatchedBlockParser(); if (! ($matched instanceof ListBlockParser) || ! $listData->equals($matched->getBlock()->getListData())) { $listBlockParser = new ListBlockParser($listData); // We start out with assuming a list is tight. If we find a blank line, we set it to loose later. $listBlockParser->getBlock()->setTight(true); return BlockStart::of($listBlockParser, $listItemParser)->at($cursor); } return BlockStart::of($listItemParser)->at($cursor); } private function parseList(Cursor $cursor, bool $inParagraph): ?ListData { $indent = $cursor->getIndent(); $tmpCursor = clone $cursor; $tmpCursor->advanceToNextNonSpaceOrTab(); $rest = $tmpCursor->getRemainder(); if (\preg_match($this->listMarkerRegex ?? $this->generateListMarkerRegex(), $rest) === 1) { $data = new ListData(); $data->markerOffset = $indent; $data->type = ListBlock::TYPE_BULLET; $data->delimiter = null; $data->bulletChar = $rest[0]; $markerLength = 1; } elseif (($matches = RegexHelper::matchFirst('/^(\d{1,9})([.)])/', $rest)) && (! $inParagraph || $matches[1] === '1')) { $data = new ListData(); $data->markerOffset = $indent; $data->type = ListBlock::TYPE_ORDERED; $data->start = (int) $matches[1]; $data->delimiter = $matches[2] === '.' ? ListBlock::DELIM_PERIOD : ListBlock::DELIM_PAREN; $data->bulletChar = null; $markerLength = \strlen($matches[0]); } else { return null; } // Make sure we have spaces after $nextChar = $tmpCursor->peek($markerLength); if (! ($nextChar === null || $nextChar === "\t" || $nextChar === ' ')) { return null; } // If it interrupts paragraph, make sure first line isn't blank if ($inParagraph && ! RegexHelper::matchAt(RegexHelper::REGEX_NON_SPACE, $rest, $markerLength)) { return null; } $cursor->advanceToNextNonSpaceOrTab(); // to start of marker $cursor->advanceBy($markerLength, true); // to end of marker $data->padding = self::calculateListMarkerPadding($cursor, $markerLength); return $data; } private static function calculateListMarkerPadding(Cursor $cursor, int $markerLength): int { $start = $cursor->saveState(); $spacesStartCol = $cursor->getColumn(); while ($cursor->getColumn() - $spacesStartCol < 5) { if (! $cursor->advanceBySpaceOrTab()) { break; } } $blankItem = $cursor->peek() === null; $spacesAfterMarker = $cursor->getColumn() - $spacesStartCol; if ($spacesAfterMarker >= 5 || $spacesAfterMarker < 1 || $blankItem) { $cursor->restoreState($start); $cursor->advanceBySpaceOrTab(); return $markerLength + 1; } return $markerLength + $spacesAfterMarker; } private function generateListMarkerRegex(): string { // No configuration given - use the defaults if ($this->config === null) { return $this->listMarkerRegex = '/^[*+-]/'; } $markers = $this->config->get('commonmark/unordered_list_markers'); \assert(\is_array($markers)); return $this->listMarkerRegex = '/^[' . \preg_quote(\implode('', $markers), '/') . ']/'; } } PK"ZCe3CommonMark/Parser/Block/IndentedCodeStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; final class IndentedCodeStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if (! $cursor->isIndented()) { return BlockStart::none(); } if ($parserState->getActiveBlockParser()->getBlock() instanceof Paragraph) { return BlockStart::none(); } if ($cursor->isBlank()) { return BlockStart::none(); } $cursor->advanceBy(Cursor::INDENT_LEVEL, true); return BlockStart::of(new IndentedCodeParser())->at($cursor); } } PK"Z*P .CommonMark/Parser/Block/HeadingStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\CommonMark\Util\RegexHelper; class HeadingStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented() || ! \in_array($cursor->getNextNonSpaceCharacter(), ['#', '-', '='], true)) { return BlockStart::none(); } $cursor->advanceToNextNonSpaceOrTab(); if ($atxHeading = self::getAtxHeader($cursor)) { return BlockStart::of($atxHeading)->at($cursor); } $setextHeadingLevel = self::getSetextHeadingLevel($cursor); if ($setextHeadingLevel > 0) { $content = $parserState->getParagraphContent(); if ($content !== null) { $cursor->advanceToEnd(); return BlockStart::of(new HeadingParser($setextHeadingLevel, $content)) ->at($cursor) ->replaceActiveBlockParser(); } } return BlockStart::none(); } private static function getAtxHeader(Cursor $cursor): ?HeadingParser { $match = RegexHelper::matchFirst('/^#{1,6}(?:[ \t]+|$)/', $cursor->getRemainder()); if (! $match) { return null; } $cursor->advanceToNextNonSpaceOrTab(); $cursor->advanceBy(\strlen($match[0])); $level = \strlen(\trim($match[0])); $str = $cursor->getRemainder(); $str = \preg_replace('/^[ \t]*#+[ \t]*$/', '', $str); \assert(\is_string($str)); $str = \preg_replace('/[ \t]+#+[ \t]*$/', '', $str); \assert(\is_string($str)); return new HeadingParser($level, $str); } private static function getSetextHeadingLevel(Cursor $cursor): int { $match = RegexHelper::matchFirst('/^(?:=+|-+)[ \t]*$/', $cursor->getRemainder()); if ($match === null) { return 0; } return $match[0][0] === '=' ? 1 : 2; } } PK"ZXѷ1CommonMark/Parser/Block/FencedCodeStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; final class FencedCodeStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented() || ! \in_array($cursor->getNextNonSpaceCharacter(), ['`', '~'], true)) { return BlockStart::none(); } $indent = $cursor->getIndent(); $fence = $cursor->match('/^[ \t]*(?:`{3,}(?!.*`)|~{3,})/'); if ($fence === null) { return BlockStart::none(); } // fenced code block $fence = \ltrim($fence, " \t"); return BlockStart::of(new FencedCodeParser(\strlen($fence), $fence[0], $indent))->at($cursor); } } PK"Z:A.CommonMark/Parser/Block/IndentedCodeParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Util\ArrayCollection; final class IndentedCodeParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private IndentedCode $block; /** @var ArrayCollection */ private ArrayCollection $strings; public function __construct() { $this->block = new IndentedCode(); $this->strings = new ArrayCollection(); } public function getBlock(): IndentedCode { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if ($cursor->isIndented()) { $cursor->advanceBy(Cursor::INDENT_LEVEL, true); return BlockContinue::at($cursor); } if ($cursor->isBlank()) { $cursor->advanceToNextNonSpaceOrTab(); return BlockContinue::at($cursor); } return BlockContinue::none(); } public function addLine(string $line): void { $this->strings[] = $line; } public function closeBlock(): void { $reversed = \array_reverse($this->strings->toArray(), true); foreach ($reversed as $index => $line) { if ($line !== '' && $line !== "\n" && ! \preg_match('/^(\n *)$/', $line)) { break; } unset($reversed[$index]); } $fixed = \array_reverse($reversed); $tmp = \implode("\n", $fixed); if (\substr($tmp, -1) !== "\n") { $tmp .= "\n"; } $this->block->setLiteral($tmp); } } PK"Z{j+CommonMark/Parser/Block/HtmlBlockParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Util\RegexHelper; final class HtmlBlockParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private HtmlBlock $block; private string $content = ''; private bool $finished = false; /** * @psalm-param HtmlBlock::TYPE_* $blockType * * @phpstan-param HtmlBlock::TYPE_* $blockType */ public function __construct(int $blockType) { $this->block = new HtmlBlock($blockType); } public function getBlock(): HtmlBlock { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if ($this->finished) { return BlockContinue::none(); } if ($cursor->isBlank() && \in_array($this->block->getType(), [HtmlBlock::TYPE_6_BLOCK_ELEMENT, HtmlBlock::TYPE_7_MISC_ELEMENT], true)) { return BlockContinue::none(); } return BlockContinue::at($cursor); } public function addLine(string $line): void { if ($this->content !== '') { $this->content .= "\n"; } $this->content .= $line; // Check for end condition // phpcs:disable SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed if ($this->block->getType() <= HtmlBlock::TYPE_5_CDATA) { if (\preg_match(RegexHelper::getHtmlBlockCloseRegex($this->block->getType()), $line) === 1) { $this->finished = true; } } } public function closeBlock(): void { $this->block->setLiteral($this->content); $this->content = ''; } } PK"Z7Bq ,CommonMark/Parser/Block/FencedCodeParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Util\ArrayCollection; use League\CommonMark\Util\RegexHelper; final class FencedCodeParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private FencedCode $block; /** @var ArrayCollection */ private ArrayCollection $strings; public function __construct(int $fenceLength, string $fenceChar, int $fenceOffset) { $this->block = new FencedCode($fenceLength, $fenceChar, $fenceOffset); $this->strings = new ArrayCollection(); } public function getBlock(): FencedCode { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { // Check for closing code fence if (! $cursor->isIndented() && $cursor->getNextNonSpaceCharacter() === $this->block->getChar()) { $match = RegexHelper::matchFirst('/^(?:`{3,}|~{3,})(?= *$)/', $cursor->getLine(), $cursor->getNextNonSpacePosition()); if ($match !== null && \strlen($match[0]) >= $this->block->getLength()) { // closing fence - we're at end of line, so we can finalize now return BlockContinue::finished(); } } // Skip optional spaces of fence offset // Optimization: don't attempt to match if we're at a non-space position if ($cursor->getNextNonSpacePosition() > $cursor->getPosition()) { $cursor->match('/^ {0,' . $this->block->getOffset() . '}/'); } return BlockContinue::at($cursor); } public function addLine(string $line): void { $this->strings[] = $line; } public function closeBlock(): void { // first line becomes info string $firstLine = $this->strings->first(); if ($firstLine === false) { $firstLine = ''; } $this->block->setInfo(RegexHelper::unescape(\trim($firstLine))); if ($this->strings->count() === 1) { $this->block->setLiteral(''); } else { $this->block->setLiteral(\implode("\n", $this->strings->slice(1)) . "\n"); } } } PK"ZnL)CommonMark/Parser/Block/HeadingParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\Heading; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Block\BlockContinueParserWithInlinesInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\InlineParserEngineInterface; final class HeadingParser extends AbstractBlockContinueParser implements BlockContinueParserWithInlinesInterface { /** @psalm-readonly */ private Heading $block; private string $content; public function __construct(int $level, string $content) { $this->block = new Heading($level); $this->content = $content; } public function getBlock(): Heading { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { return BlockContinue::none(); } public function parseInlines(InlineParserEngineInterface $inlineParser): void { $inlineParser->parse($this->content, $this->block); } } PK"ZW4CommonMark/Parser/Block/ThematicBreakStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\CommonMark\Util\RegexHelper; final class ThematicBreakStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented()) { return BlockStart::none(); } $match = RegexHelper::matchAt(RegexHelper::REGEX_THEMATIC_BREAK, $cursor->getLine(), $cursor->getNextNonSpacePosition()); if ($match === null) { return BlockStart::none(); } // Advance to the end of the string, consuming the entire line (of the thematic break) $cursor->advanceToEnd(); return BlockStart::of(new ThematicBreakParser())->at($cursor); } } PK"ZKz**,CommonMark/Parser/Block/BlockQuoteParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\BlockQuote; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class BlockQuoteParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private BlockQuote $block; public function __construct() { $this->block = new BlockQuote(); } public function getBlock(): BlockQuote { return $this->block; } public function isContainer(): bool { return true; } public function canContain(AbstractBlock $childBlock): bool { return true; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if (! $cursor->isIndented() && $cursor->getNextNonSpaceCharacter() === '>') { $cursor->advanceToNextNonSpaceOrTab(); $cursor->advanceBy(1); $cursor->advanceBySpaceOrTab(); return BlockContinue::at($cursor); } return BlockContinue::none(); } } PK"ZϲdD D +CommonMark/Parser/Block/ListBlockParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock; use League\CommonMark\Extension\CommonMark\Node\Block\ListData; use League\CommonMark\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class ListBlockParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private ListBlock $block; private bool $hadBlankLine = false; private int $linesAfterBlank = 0; public function __construct(ListData $listData) { $this->block = new ListBlock($listData); } public function getBlock(): ListBlock { return $this->block; } public function isContainer(): bool { return true; } public function canContain(AbstractBlock $childBlock): bool { if (! $childBlock instanceof ListItem) { return false; } // Another list item is being added to this list block. // If the previous line was blank, that means this list // block is "loose" (not tight). if ($this->hadBlankLine && $this->linesAfterBlank === 1) { $this->block->setTight(false); $this->hadBlankLine = false; } return true; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if ($cursor->isBlank()) { $this->hadBlankLine = true; $this->linesAfterBlank = 0; } elseif ($this->hadBlankLine) { $this->linesAfterBlank++; } // List blocks themselves don't have any markers, only list items. So try to stay in the list. // If there is a block start other than list item, canContain makes sure that this list is closed. return BlockContinue::at($cursor); } } PK"Zᄖ/CommonMark/Parser/Block/ThematicBreakParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\ThematicBreak; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class ThematicBreakParser extends AbstractBlockContinueParser { /** @psalm-readonly */ private ThematicBreak $block; public function __construct() { $this->block = new ThematicBreak(); } public function getBlock(): ThematicBreak { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { // a horizontal rule can never container > 1 line, so fail to match return BlockContinue::none(); } } PK"ZYY1CommonMark/Parser/Block/BlockQuoteStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; final class BlockQuoteStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented()) { return BlockStart::none(); } if ($cursor->getNextNonSpaceCharacter() !== '>') { return BlockStart::none(); } $cursor->advanceToNextNonSpaceOrTab(); $cursor->advanceBy(1); $cursor->advanceBySpaceOrTab(); return BlockStart::of(new BlockQuoteParser())->at($cursor); } } PK"Z} VV0CommonMark/Parser/Block/HtmlBlockStartParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\CommonMark\Parser\Block; use League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; use League\CommonMark\Util\RegexHelper; final class HtmlBlockStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented() || $cursor->getNextNonSpaceCharacter() !== '<') { return BlockStart::none(); } $tmpCursor = clone $cursor; $tmpCursor->advanceToNextNonSpaceOrTab(); $line = $tmpCursor->getRemainder(); for ($blockType = 1; $blockType <= 7; $blockType++) { /** @psalm-var HtmlBlock::TYPE_* $blockType */ /** @phpstan-var HtmlBlock::TYPE_* $blockType */ $match = RegexHelper::matchAt( RegexHelper::getHtmlBlockOpenRegex($blockType), $line ); if ($match !== null && ($blockType < 7 || $this->isType7BlockAllowed($cursor, $parserState))) { return BlockStart::of(new HtmlBlockParser($blockType))->at($cursor); } } return BlockStart::none(); } private function isType7BlockAllowed(Cursor $cursor, MarkdownParserStateInterface $parserState): bool { // Type 7 blocks can't interrupt paragraphs if ($parserState->getLastMatchedBlockParser()->getBlock() instanceof Paragraph) { return false; } // Even lazy ones return ! $parserState->getActiveBlockParser()->canHaveLazyContinuationLines(); } } PK"Z,kk,CommonMark/Parser/Inline/EscapableParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Node\Inline\Newline; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Util\RegexHelper; final class EscapableParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::string('\\'); } public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $nextChar = $cursor->peek(); if ($nextChar === "\n") { $cursor->advanceBy(2); $inlineContext->getContainer()->appendChild(new Newline(Newline::HARDBREAK)); return true; } if ($nextChar !== null && RegexHelper::isEscapable($nextChar)) { $cursor->advanceBy(2); $inlineContext->getContainer()->appendChild(new Text($nextChar)); return true; } $cursor->advanceBy(1); $inlineContext->getContainer()->appendChild(new Text('\\')); return true; } } PK"Z9E)CommonMark/Parser/Inline/EntityParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Util\Html5EntityDecoder; use League\CommonMark\Util\RegexHelper; final class EntityParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex(RegexHelper::PARTIAL_ENTITY); } public function parse(InlineParserContext $inlineContext): bool { $entity = $inlineContext->getFullMatch(); $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength()); $inlineContext->getContainer()->appendChild(new Text(Html5EntityDecoder::decode($entity))); return true; } } PK"ZLbb+CommonMark/Parser/Inline/AutolinkParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Util\UrlEncoder; final class AutolinkParser implements InlineParserInterface { private const EMAIL_REGEX = '<([a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>'; private const OTHER_LINK_REGEX = '<([A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]*)>'; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex(self::EMAIL_REGEX . '|' . self::OTHER_LINK_REGEX); } public function parse(InlineParserContext $inlineContext): bool { $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength()); $matches = $inlineContext->getMatches(); if ($matches[1] !== '') { $inlineContext->getContainer()->appendChild(new Link('mailto:' . UrlEncoder::unescapeAndEncode($matches[1]), $matches[1])); return true; } if ($matches[2] !== '') { $inlineContext->getContainer()->appendChild(new Link(UrlEncoder::unescapeAndEncode($matches[2]), $matches[2])); return true; } return false; // This should never happen } } PK"Z^™/CommonMark/Parser/Inline/CloseBracketParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Environment\EnvironmentAwareInterface; use League\CommonMark\Environment\EnvironmentInterface; use League\CommonMark\Extension\CommonMark\Node\Inline\AbstractWebResource; use League\CommonMark\Extension\CommonMark\Node\Inline\Image; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; use League\CommonMark\Extension\Mention\Mention; use League\CommonMark\Node\Inline\AdjacentTextMerger; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Reference\ReferenceInterface; use League\CommonMark\Reference\ReferenceMapInterface; use League\CommonMark\Util\LinkParserHelper; use League\CommonMark\Util\RegexHelper; final class CloseBracketParser implements InlineParserInterface, EnvironmentAwareInterface { /** @psalm-readonly-allow-private-mutation */ private EnvironmentInterface $environment; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::string(']'); } public function parse(InlineParserContext $inlineContext): bool { // Look through stack of delimiters for a [ or ! $opener = $inlineContext->getDelimiterStack()->searchByCharacter(['[', '!']); if ($opener === null) { return false; } if (! $opener->isActive()) { // no matched opener; remove from emphasis stack $inlineContext->getDelimiterStack()->removeDelimiter($opener); return false; } $cursor = $inlineContext->getCursor(); $startPos = $cursor->getPosition(); $previousState = $cursor->saveState(); $cursor->advanceBy(1); // Check to see if we have a link/image // Inline link? if ($result = $this->tryParseInlineLinkAndTitle($cursor)) { $link = $result; } elseif ($link = $this->tryParseReference($cursor, $inlineContext->getReferenceMap(), $opener->getIndex(), $startPos)) { $reference = $link; $link = ['url' => $link->getDestination(), 'title' => $link->getTitle()]; } else { // No match $inlineContext->getDelimiterStack()->removeDelimiter($opener); // Remove this opener from stack $cursor->restoreState($previousState); return false; } $isImage = $opener->getChar() === '!'; $inline = $this->createInline($link['url'], $link['title'], $isImage, $reference ?? null); $opener->getInlineNode()->replaceWith($inline); while (($label = $inline->next()) !== null) { // Is there a Mention or Link contained within this link? // CommonMark does not allow nested links, so we'll restore the original text. if ($label instanceof Mention) { $label->replaceWith($replacement = new Text($label->getPrefix() . $label->getIdentifier())); $inline->appendChild($replacement); } elseif ($label instanceof Link) { foreach ($label->children() as $child) { $label->insertBefore($child); } $label->detach(); } else { $inline->appendChild($label); } } // Process delimiters such as emphasis inside link/image $delimiterStack = $inlineContext->getDelimiterStack(); $stackBottom = $opener->getPrevious(); $delimiterStack->processDelimiters($stackBottom, $this->environment->getDelimiterProcessors()); $delimiterStack->removeAll($stackBottom); // Merge any adjacent Text nodes together AdjacentTextMerger::mergeChildNodes($inline); // processEmphasis will remove this and later delimiters. // Now, for a link, we also remove earlier link openers (no links in links) if (! $isImage) { $inlineContext->getDelimiterStack()->removeEarlierMatches('['); } return true; } public function setEnvironment(EnvironmentInterface $environment): void { $this->environment = $environment; } /** * @return array|null */ private function tryParseInlineLinkAndTitle(Cursor $cursor): ?array { if ($cursor->getCurrentCharacter() !== '(') { return null; } $previousState = $cursor->saveState(); $cursor->advanceBy(1); $cursor->advanceToNextNonSpaceOrNewline(); if (($dest = LinkParserHelper::parseLinkDestination($cursor)) === null) { $cursor->restoreState($previousState); return null; } $cursor->advanceToNextNonSpaceOrNewline(); $previousCharacter = $cursor->peek(-1); // We know from previous lines that we've advanced at least one space so far, so this next call should never be null \assert(\is_string($previousCharacter)); $title = ''; // make sure there's a space before the title: if (\preg_match(RegexHelper::REGEX_WHITESPACE_CHAR, $previousCharacter)) { $title = LinkParserHelper::parseLinkTitle($cursor) ?? ''; } $cursor->advanceToNextNonSpaceOrNewline(); if ($cursor->getCurrentCharacter() !== ')') { $cursor->restoreState($previousState); return null; } $cursor->advanceBy(1); return ['url' => $dest, 'title' => $title]; } private function tryParseReference(Cursor $cursor, ReferenceMapInterface $referenceMap, ?int $openerIndex, int $startPos): ?ReferenceInterface { if ($openerIndex === null) { return null; } $savePos = $cursor->saveState(); $beforeLabel = $cursor->getPosition(); $n = LinkParserHelper::parseLinkLabel($cursor); if ($n === 0 || $n === 2) { $start = $openerIndex; $length = $startPos - $openerIndex; } else { $start = $beforeLabel + 1; $length = $n - 2; } $referenceLabel = $cursor->getSubstring($start, $length); if ($n === 0) { // If shortcut reference link, rewind before spaces we skipped $cursor->restoreState($savePos); } return $referenceMap->get($referenceLabel); } private function createInline(string $url, string $title, bool $isImage, ?ReferenceInterface $reference = null): AbstractWebResource { if ($isImage) { $inline = new Image($url, null, $title); } else { $inline = new Link($url, null, $title); } if ($reference) { $inline->data->set('reference', $reference); } return $inline; } } PK"Z5^^+CommonMark/Parser/Inline/BacktickParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\Code; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class BacktickParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex('`+'); } public function parse(InlineParserContext $inlineContext): bool { $ticks = $inlineContext->getFullMatch(); $cursor = $inlineContext->getCursor(); $cursor->advanceBy($inlineContext->getFullMatchLength()); $currentPosition = $cursor->getPosition(); $previousState = $cursor->saveState(); while ($matchingTicks = $cursor->match('/`+/m')) { if ($matchingTicks !== $ticks) { continue; } $code = $cursor->getSubstring($currentPosition, $cursor->getPosition() - $currentPosition - \strlen($ticks)); $c = \preg_replace('/\n/m', ' ', $code) ?? ''; if ( $c !== '' && $c[0] === ' ' && \substr($c, -1, 1) === ' ' && \preg_match('/[^ ]/', $c) ) { $c = \substr($c, 1, -1); } $inlineContext->getContainer()->appendChild(new Code($c)); return true; } // If we got here, we didn't match a closing backtick sequence $cursor->restoreState($previousState); $inlineContext->getContainer()->appendChild(new Text($ticks)); return true; } } PK"ZƊ>dd'CommonMark/Parser/Inline/BangParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Delimiter\Delimiter; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class BangParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::string('!['); } public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $cursor->advanceBy(2); $node = new Text('![', ['delim' => true]); $inlineContext->getContainer()->appendChild($node); // Add entry to stack for this opener $delimiter = new Delimiter('!', 1, $node, true, false, $cursor->getPosition()); $inlineContext->getDelimiterStack()->push($delimiter); return true; } } PK"Z{-CommonMark/Parser/Inline/HtmlInlineParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Extension\CommonMark\Node\Inline\HtmlInline; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Util\RegexHelper; final class HtmlInlineParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex(RegexHelper::PARTIAL_HTMLTAG)->caseSensitive(); } public function parse(InlineParserContext $inlineContext): bool { $inline = $inlineContext->getFullMatch(); $inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength()); $inlineContext->getContainer()->appendChild(new HtmlInline($inline)); return true; } } PK"Z%aa.CommonMark/Parser/Inline/OpenBracketParser.phpnuW+A * * 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\CommonMark\Parser\Inline; use League\CommonMark\Delimiter\Delimiter; use League\CommonMark\Node\Inline\Text; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class OpenBracketParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::string('['); } public function parse(InlineParserContext $inlineContext): bool { $inlineContext->getCursor()->advanceBy(1); $node = new Text('[', ['delim' => true]); $inlineContext->getContainer()->appendChild($node); // Add entry to stack for this opener $delimiter = new Delimiter('[', 1, $node, true, false, $inlineContext->getCursor()->getPosition()); $inlineContext->getDelimiterStack()->push($delimiter); return true; } } PK"ZdC:DescriptionList/Event/ConsecutiveDescriptionListMerger.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Event; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\DescriptionList\Node\DescriptionList; use League\CommonMark\Node\NodeIterator; final class ConsecutiveDescriptionListMerger { public function __invoke(DocumentParsedEvent $event): void { foreach ($event->getDocument()->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) { if (! $node instanceof DescriptionList) { continue; } if (! ($prev = $node->previous()) instanceof DescriptionList) { continue; } // There's another description list behind this one; merge the current one into that foreach ($node->children() as $child) { $prev->appendChild($child); } $node->detach(); } } } PK"Z#_1DescriptionList/Event/LooseDescriptionHandler.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Event; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\DescriptionList\Node\Description; use League\CommonMark\Extension\DescriptionList\Node\DescriptionList; use League\CommonMark\Extension\DescriptionList\Node\DescriptionTerm; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Node\Inline\Newline; use League\CommonMark\Node\NodeIterator; final class LooseDescriptionHandler { public function __invoke(DocumentParsedEvent $event): void { foreach ($event->getDocument()->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $description) { if (! $description instanceof Description) { continue; } // Does this description need to be added to a list? if (! $description->parent() instanceof DescriptionList) { $list = new DescriptionList(); // Taking any preceding paragraphs with it if (($paragraph = $description->previous()) instanceof Paragraph) { $list->appendChild($paragraph); } $description->replaceWith($list); $list->appendChild($description); } // Is this description preceded by a paragraph that should really be a term? if (! (($paragraph = $description->previous()) instanceof Paragraph)) { continue; } // Convert the paragraph into one or more terms $term = new DescriptionTerm(); $paragraph->replaceWith($term); foreach ($paragraph->children() as $child) { if ($child instanceof Newline) { $newTerm = new DescriptionTerm(); $term->insertAfter($newTerm); $term = $newTerm; continue; } $term->appendChild($child); } } } } PK"Zl (DescriptionList/Node/DescriptionTerm.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Node; use League\CommonMark\Node\Block\AbstractBlock; class DescriptionTerm extends AbstractBlock { } PK"Zx(DescriptionList/Node/DescriptionList.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Node; use League\CommonMark\Node\Block\AbstractBlock; class DescriptionList extends AbstractBlock { } PK"Z_>XCC$DescriptionList/Node/Description.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Node; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Node\Block\TightBlockInterface; class Description extends AbstractBlock implements TightBlockInterface { private bool $tight; public function __construct(bool $tight = false) { parent::__construct(); $this->tight = $tight; } public function isTight(): bool { return $this->tight; } public function setTight(bool $tight): void { $this->tight = $tight; } } PK"ZV""4DescriptionList/Renderer/DescriptionTermRenderer.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Renderer; use League\CommonMark\Extension\DescriptionList\Node\DescriptionTerm; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; final class DescriptionTermRenderer implements NodeRendererInterface { /** * @param DescriptionTerm $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { DescriptionTerm::assertInstanceOf($node); return new HtmlElement('dt', [], $childRenderer->renderNodes($node->children())); } } PK"ZH!0DescriptionList/Renderer/DescriptionRenderer.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Renderer; use League\CommonMark\Extension\DescriptionList\Node\Description; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; final class DescriptionRenderer implements NodeRendererInterface { /** * @param Description $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Description::assertInstanceOf($node); return new HtmlElement('dd', [], $childRenderer->renderNodes($node->children())); } } PK"ZZpww4DescriptionList/Renderer/DescriptionListRenderer.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Renderer; use League\CommonMark\Extension\DescriptionList\Node\DescriptionList; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; final class DescriptionListRenderer implements NodeRendererInterface { /** * @param DescriptionList $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): HtmlElement { DescriptionList::assertInstanceOf($node); $separator = $childRenderer->getBlockSeparator(); return new HtmlElement('dl', [], $separator . $childRenderer->renderNodes($node->children()) . $separator); } } PK"Zc0oo,DescriptionList/DescriptionListExtension.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList; use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\DescriptionList\Event\ConsecutiveDescriptionListMerger; use League\CommonMark\Extension\DescriptionList\Event\LooseDescriptionHandler; use League\CommonMark\Extension\DescriptionList\Node\Description; use League\CommonMark\Extension\DescriptionList\Node\DescriptionList; use League\CommonMark\Extension\DescriptionList\Node\DescriptionTerm; use League\CommonMark\Extension\DescriptionList\Parser\DescriptionStartParser; use League\CommonMark\Extension\DescriptionList\Renderer\DescriptionListRenderer; use League\CommonMark\Extension\DescriptionList\Renderer\DescriptionRenderer; use League\CommonMark\Extension\DescriptionList\Renderer\DescriptionTermRenderer; use League\CommonMark\Extension\ExtensionInterface; final class DescriptionListExtension implements ExtensionInterface { public function register(EnvironmentBuilderInterface $environment): void { $environment->addBlockStartParser(new DescriptionStartParser()); $environment->addEventListener(DocumentParsedEvent::class, new LooseDescriptionHandler(), 1001); $environment->addEventListener(DocumentParsedEvent::class, new ConsecutiveDescriptionListMerger(), 1000); $environment->addRenderer(DescriptionList::class, new DescriptionListRenderer()); $environment->addRenderer(DescriptionTerm::class, new DescriptionTermRenderer()); $environment->addRenderer(Description::class, new DescriptionRenderer()); } } PK"Z9۞  8DescriptionList/Parser/DescriptionTermContinueParser.phpnuW+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DescriptionList\Parser; use League\CommonMark\Extension\DescriptionList\Node\DescriptionTerm; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Block\BlockContinueParserWithInlinesInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\InlineParserEngineInterface; final class DescriptionTermContinueParser extends AbstractBlockContinueParser implements BlockContinueParserWithInlinesInterface { private DescriptionTerm $block; private string $term; public function __construct(string $term) { $this->block = new DescriptionTerm(); $this->term = $term; } public function getBlock(): DescriptionTerm { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { return BlockContinue::finished(); } public function parseInlines(InlineParserEngineInterface $inlineParser): void { if ($this->term !== '') { $inlineParser->parse($this->term, $this->block); } } } PK"Z`H 1DescriptionList/Parser/DescriptionStartParser.phpnuW+A * * 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\DescriptionList\Parser; use League\CommonMark\Extension\DescriptionList\Node\Description; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Parser\Block\BlockStart; use League\CommonMark\Parser\Block\BlockStartParserInterface; use League\CommonMark\Parser\Cursor; use League\CommonMark\Parser\MarkdownParserStateInterface; final class DescriptionStartParser implements BlockStartParserInterface { public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart { if ($cursor->isIndented()) { return BlockStart::none(); } $cursor->advanceToNextNonSpaceOrTab(); if ($cursor->match('/^:[ \t]+/') === null) { return BlockStart::none(); } $terms = $parserState->getParagraphContent(); $activeBlock = $parserState->getActiveBlockParser()->getBlock(); if ($terms !== null && $terms !== '') { // New description; tight; term(s) sitting in pending block that we will replace return BlockStart::of(...[new DescriptionListContinueParser()], ...self::splitTerms($terms), ...[new DescriptionContinueParser(true, $cursor->getPosition())]) ->at($cursor) ->replaceActiveBlockParser(); } if ($activeBlock instanceof Paragraph && $activeBlock->parent() instanceof Description) { // Additional description in the same list as the parent description return BlockStart::of(new DescriptionContinueParser(true, $cursor->getPosition()))->at($cursor); } if ($activeBlock->lastChild() instanceof Paragraph) { // New description; loose; term(s) sitting in previous closed paragraph block return BlockStart::of(new DescriptionContinueParser(false, $cursor->getPosition()))->at($cursor); } // No preceding terms return BlockStart::none(); } /** * @return array */ private static function splitTerms(string $terms): array { $ret = []; foreach (\explode("\n", $terms) as $term) { $ret[] = new DescriptionTermContinueParser($term); } return $ret; } } PK"ZK\\4DescriptionList/Parser/DescriptionContinueParser.phpnuW+A * * 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\DescriptionList\Parser; use League\CommonMark\Extension\DescriptionList\Node\Description; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class DescriptionContinueParser extends AbstractBlockContinueParser { private Description $block; private int $indentation; public function __construct(bool $tight, int $indentation) { $this->block = new Description($tight); $this->indentation = $indentation; } public function getBlock(): Description { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { if ($cursor->isBlank()) { if ($this->block->firstChild() === null) { // Blank line after empty item return BlockContinue::none(); } $cursor->advanceToNextNonSpaceOrTab(); return BlockContinue::at($cursor); } if ($cursor->getIndent() >= $this->indentation) { $cursor->advanceBy($this->indentation, true); return BlockContinue::at($cursor); } return BlockContinue::none(); } public function isContainer(): bool { return true; } public function canContain(AbstractBlock $childBlock): bool { return true; } } PK"Zx8DescriptionList/Parser/DescriptionListContinueParser.phpnuW+A * * 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\DescriptionList\Parser; use League\CommonMark\Extension\DescriptionList\Node\Description; use League\CommonMark\Extension\DescriptionList\Node\DescriptionList; use League\CommonMark\Extension\DescriptionList\Node\DescriptionTerm; use League\CommonMark\Node\Block\AbstractBlock; use League\CommonMark\Parser\Block\AbstractBlockContinueParser; use League\CommonMark\Parser\Block\BlockContinue; use League\CommonMark\Parser\Block\BlockContinueParserInterface; use League\CommonMark\Parser\Cursor; final class DescriptionListContinueParser extends AbstractBlockContinueParser { private DescriptionList $block; public function __construct() { $this->block = new DescriptionList(); } public function getBlock(): DescriptionList { return $this->block; } public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue { return BlockContinue::at($cursor); } public function isContainer(): bool { return true; } public function canContain(AbstractBlock $childBlock): bool { return $childBlock instanceof DescriptionTerm || $childBlock instanceof Description; } } PK"ZT/ Mention/MentionParser.phpnuW+A * * 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\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class MentionParser implements InlineParserInterface { /** @psalm-readonly */ private string $name; /** @psalm-readonly */ private string $prefix; /** @psalm-readonly */ private string $identifierPattern; /** @psalm-readonly */ private MentionGeneratorInterface $mentionGenerator; public function __construct(string $name, string $prefix, string $identifierPattern, MentionGeneratorInterface $mentionGenerator) { $this->name = $name; $this->prefix = $prefix; $this->identifierPattern = $identifierPattern; $this->mentionGenerator = $mentionGenerator; } public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::join( InlineParserMatch::string($this->prefix), InlineParserMatch::regex($this->identifierPattern) ); } public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); // The prefix 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; } [$prefix, $identifier] = $inlineContext->getSubMatches(); $mention = $this->mentionGenerator->generateMention(new Mention($this->name, $prefix, $identifier)); if ($mention === null) { return false; } $cursor->advanceBy($inlineContext->getFullMatchLength()); $inlineContext->getContainer()->appendChild($mention); return true; } public static function createWithStringTemplate(string $name, string $prefix, string $mentionRegex, string $urlTemplate): MentionParser { return new self($name, $prefix, $mentionRegex, new StringTemplateLinkGenerator($urlTemplate)); } public static function createWithCallback(string $name, string $prefix, string $mentionRegex, callable $callback): MentionParser { return new self($name, $prefix, $mentionRegex, new CallbackGenerator($callback)); } } PK"ZFMention/Mention.phpnuW+A * * 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\Extension\CommonMark\Node\Inline\Link; use League\CommonMark\Node\Inline\Text; class Mention extends Link { private string $name; private string $prefix; private string $identifier; public function __construct(string $name, string $prefix, string $identifier, ?string $label = null) { $this->name = $name; $this->prefix = $prefix; $this->identifier = $identifier; parent::__construct('', $label ?? \sprintf('%s%s', $prefix, $identifier)); } public function getLabel(): ?string { if (($labelNode = $this->findLabelNode()) === null) { return null; } return $labelNode->getLiteral(); } public function getIdentifier(): string { return $this->identifier; } public function getName(): ?string { return $this->name; } public function getPrefix(): string { return $this->prefix; } public function hasUrl(): bool { return $this->url !== ''; } /** * @return $this */ public function setLabel(string $label): self { if (($labelNode = $this->findLabelNode()) === null) { $labelNode = new Text(); $this->prependChild($labelNode); } $labelNode->setLiteral($label); return $this; } private function findLabelNode(): ?Text { foreach ($this->children() as $child) { if ($child instanceof Text) { return $child; } } return null; } } PK"Z<@( Mention/MentionExtension.phpnuW+A * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\CommonMark\Extension\Mention\Generator\MentionGeneratorInterface; use League\Config\ConfigurationBuilderInterface; use League\Config\Exception\InvalidConfigurationException; use Nette\Schema\Expect; final class MentionExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $isAValidPartialRegex = static function (string $regex): bool { $regex = '/' . $regex . '/i'; return @\preg_match($regex, '') !== false; }; $builder->addSchema('mentions', Expect::arrayOf( Expect::structure([ 'prefix' => Expect::string()->required(), 'pattern' => Expect::string()->assert($isAValidPartialRegex, 'Pattern must not include starting/ending delimiters (like "/")')->required(), 'generator' => Expect::anyOf( Expect::type(MentionGeneratorInterface::class), Expect::string(), Expect::type('callable') )->required(), ]) )); } public function register(EnvironmentBuilderInterface $environment): void { $mentions = $environment->getConfiguration()->get('mentions'); foreach ($mentions as $name => $mention) { if ($mention['generator'] instanceof MentionGeneratorInterface) { $environment->addInlineParser(new MentionParser($name, $mention['prefix'], $mention['pattern'], $mention['generator'])); } elseif (\is_string($mention['generator'])) { $environment->addInlineParser(MentionParser::createWithStringTemplate($name, $mention['prefix'], $mention['pattern'], $mention['generator'])); } elseif (\is_callable($mention['generator'])) { $environment->addInlineParser(MentionParser::createWithCallback($name, $mention['prefix'], $mention['pattern'], $mention['generator'])); } else { throw new InvalidConfigurationException(\sprintf('The "generator" provided for the "%s" MentionParser configuration must be a string template, callable, or an object that implements %s.', $name, MentionGeneratorInterface::class)); } } } } PK"ZU|/Mention/Generator/MentionGeneratorInterface.phpnuW+A * * 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\Node\Inline\AbstractInline; interface MentionGeneratorInterface { public function generateMention(Mention $mention): ?AbstractInline; } PK"ZGGG'Mention/Generator/CallbackGenerator.phpnuW+A * * 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\Exception\LogicException; use League\CommonMark\Extension\Mention\Mention; use League\CommonMark\Node\Inline\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; } /** * @throws LogicException */ public function generateMention(Mention $mention): ?AbstractInline { $result = \call_user_func($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 LogicException('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'); } } PK"Z ݖNN1Mention/Generator/StringTemplateLinkGenerator.phpnuW+A * * 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\Node\Inline\AbstractInline; final class StringTemplateLinkGenerator implements MentionGeneratorInterface { private string $urlTemplate; public function __construct(string $urlTemplate) { $this->urlTemplate = $urlTemplate; } public function generateMention(Mention $mention): ?AbstractInline { $mention->setUrl(\sprintf($this->urlTemplate, $mention->getIdentifier())); return $mention; } } PK"ZG "ConfigurableExtensionInterface.phpnuW+A * * 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\Config\ConfigurationBuilderInterface; interface ConfigurableExtensionInterface extends ExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void; } PK"Z"MYY%TaskList/TaskListItemMarkerParser.phpnuW+A * * 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\Extension\CommonMark\Node\Block\ListItem; use League\CommonMark\Node\Block\Paragraph; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class TaskListItemMarkerParser implements InlineParserInterface { public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::oneOf('[ ]', '[x]'); } 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(); $cursor->advanceBy(3); if ($cursor->getNextNonSpaceCharacter() === null) { $cursor->restoreState($oldState); return false; } $isChecked = $inlineContext->getFullMatch() !== '[ ]'; $container->appendChild(new TaskListItemMarker($isChecked)); return true; } } PK"Z7'TaskList/TaskListItemMarkerRenderer.phpnuW+A * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class TaskListItemMarkerRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param TaskListItemMarker $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { TaskListItemMarker::assertInstanceOf($node); $attrs = $node->data->get('attributes'); $checkbox = new HtmlElement('input', $attrs, '', true); if ($node->isChecked()) { $checkbox->setAttribute('checked', ''); } $checkbox->setAttribute('disabled', ''); $checkbox->setAttribute('type', 'checkbox'); return $checkbox; } public function getXmlTagName(Node $node): string { return 'task_list_item_marker'; } /** * @param TaskListItemMarker $node * * @return array * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { TaskListItemMarker::assertInstanceOf($node); if ($node->isChecked()) { return ['checked' => 'checked']; } return []; } } PK"Z-88TaskList/TaskListItemMarker.phpnuW+A * * 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\Node\Inline\AbstractInline; final class TaskListItemMarker extends AbstractInline { /** @psalm-readonly-allow-private-mutation */ private bool $checked; public function __construct(bool $isCompleted) { parent::__construct(); $this->checked = $isCompleted; } public function isChecked(): bool { return $this->checked; } public function setChecked(bool $checked): void { $this->checked = $checked; } } PK"Z,TaskList/TaskListExtension.phpnuW+A * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\ExtensionInterface; final class TaskListExtension implements ExtensionInterface { public function register(EnvironmentBuilderInterface $environment): void { $environment->addInlineParser(new TaskListItemMarkerParser(), 35); $environment->addRenderer(TaskListItemMarker::class, new TaskListItemMarkerRenderer()); } } PK"ZRE0DisallowedRawHtml/DisallowedRawHtmlExtension.phpnuW+A * * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock; use League\CommonMark\Extension\CommonMark\Node\Inline\HtmlInline; use League\CommonMark\Extension\CommonMark\Renderer\Block\HtmlBlockRenderer; use League\CommonMark\Extension\CommonMark\Renderer\Inline\HtmlInlineRenderer; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class DisallowedRawHtmlExtension implements ConfigurableExtensionInterface { private const DEFAULT_DISALLOWED_TAGS = [ 'title', 'textarea', 'style', 'xmp', 'iframe', 'noembed', 'noframes', 'script', 'plaintext', ]; public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('disallowed_raw_html', Expect::structure([ 'disallowed_tags' => Expect::listOf('string')->default(self::DEFAULT_DISALLOWED_TAGS)->mergeDefaults(false), ])); } public function register(EnvironmentBuilderInterface $environment): void { $environment->addRenderer(HtmlBlock::class, new DisallowedRawHtmlRenderer(new HtmlBlockRenderer()), 50); $environment->addRenderer(HtmlInline::class, new DisallowedRawHtmlRenderer(new HtmlInlineRenderer()), 50); } } PK"Zj L/DisallowedRawHtml/DisallowedRawHtmlRenderer.phpnuW+A * * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class DisallowedRawHtmlRenderer implements NodeRendererInterface, ConfigurationAwareInterface { /** @psalm-readonly */ private NodeRendererInterface $innerRenderer; /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; public function __construct(NodeRendererInterface $innerRenderer) { $this->innerRenderer = $innerRenderer; } public function render(Node $node, ChildNodeRendererInterface $childRenderer): ?string { $rendered = (string) $this->innerRenderer->render($node, $childRenderer); if ($rendered === '') { return ''; } $tags = (array) $this->config->get('disallowed_raw_html/disallowed_tags'); if (\count($tags) === 0) { return $rendered; } $regex = \sprintf('/<(\/?(?:%s)[ \/>])/i', \implode('|', \array_map('preg_quote', $tags))); // Match these types of tags: <title/> <title /> return \preg_replace($regex, '<$1', $rendered); } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; if ($this->innerRenderer instanceof ConfigurationAwareInterface) { $this->innerRenderer->setConfiguration($configuration); } } } PK������"Z����.��HeadingPermalink/HeadingPermalinkProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Environment\EnvironmentAwareInterface; use League\CommonMark\Environment\EnvironmentInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\CommonMark\Node\Block\Heading; use League\CommonMark\Node\NodeIterator; use League\CommonMark\Node\RawMarkupContainerInterface; use League\CommonMark\Node\StringContainerHelper; use League\CommonMark\Normalizer\TextNormalizerInterface; use League\Config\ConfigurationInterface; use League\Config\Exception\InvalidConfigurationException; /** * Searches the Document for Heading elements and adds HeadingPermalinks to each one */ final class HeadingPermalinkProcessor implements EnvironmentAwareInterface { public const INSERT_BEFORE = 'before'; public const INSERT_AFTER = 'after'; public const INSERT_NONE = 'none'; /** @psalm-readonly-allow-private-mutation */ private TextNormalizerInterface $slugNormalizer; /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; public function setEnvironment(EnvironmentInterface $environment): void { $this->config = $environment->getConfiguration(); $this->slugNormalizer = $environment->getSlugNormalizer(); } public function __invoke(DocumentParsedEvent $e): void { $min = (int) $this->config->get('heading_permalink/min_heading_level'); $max = (int) $this->config->get('heading_permalink/max_heading_level'); $applyToHeading = (bool) $this->config->get('heading_permalink/apply_id_to_heading'); $idPrefix = (string) $this->config->get('heading_permalink/id_prefix'); $slugLength = (int) $this->config->get('slug_normalizer/max_length'); $headingClass = (string) $this->config->get('heading_permalink/heading_class'); if ($idPrefix !== '') { $idPrefix .= '-'; } foreach ($e->getDocument()->iterator(NodeIterator::FLAG_BLOCKS_ONLY) as $node) { if ($node instanceof Heading && $node->getLevel() >= $min && $node->getLevel() <= $max) { $this->addHeadingLink($node, $slugLength, $idPrefix, $applyToHeading, $headingClass); } } } private function addHeadingLink(Heading $heading, int $slugLength, string $idPrefix, bool $applyToHeading, string $headingClass): void { $text = StringContainerHelper::getChildText($heading, [RawMarkupContainerInterface::class]); $slug = $this->slugNormalizer->normalize($text, [ 'node' => $heading, 'length' => $slugLength, ]); if ($applyToHeading) { $heading->data->set('attributes/id', $idPrefix . $slug); } if ($headingClass !== '') { $heading->data->append('attributes/class', $headingClass); } $headingLinkAnchor = new HeadingPermalink($slug); switch ($this->config->get('heading_permalink/insert')) { case self::INSERT_BEFORE: $heading->prependChild($headingLinkAnchor); return; case self::INSERT_AFTER: $heading->appendChild($headingLinkAnchor); return; case self::INSERT_NONE: return; default: throw new InvalidConfigurationException("Invalid configuration value for heading_permalink/insert; expected 'before', 'after', or 'none'"); } } } PK������"ZCOS��S��.��HeadingPermalink/HeadingPermalinkExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; /** * Extension which automatically anchor links to heading elements */ final class HeadingPermalinkExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('heading_permalink', Expect::structure([ 'min_heading_level' => Expect::int()->min(1)->max(6)->default(1), 'max_heading_level' => Expect::int()->min(1)->max(6)->default(6), 'insert' => Expect::anyOf(HeadingPermalinkProcessor::INSERT_BEFORE, HeadingPermalinkProcessor::INSERT_AFTER, HeadingPermalinkProcessor::INSERT_NONE)->default(HeadingPermalinkProcessor::INSERT_BEFORE), 'id_prefix' => Expect::string()->default('content'), 'apply_id_to_heading' => Expect::bool()->default(false), 'heading_class' => Expect::string()->default(''), 'fragment_prefix' => Expect::string()->default('content'), 'html_class' => Expect::string()->default('heading-permalink'), 'title' => Expect::string()->default('Permalink'), 'symbol' => Expect::string()->default(HeadingPermalinkRenderer::DEFAULT_SYMBOL), 'aria_hidden' => Expect::bool()->default(true), ])); } public function register(EnvironmentBuilderInterface $environment): void { $environment->addEventListener(DocumentParsedEvent::class, new HeadingPermalinkProcessor(), -100); $environment->addRenderer(HeadingPermalink::class, new HeadingPermalinkRenderer()); } } PK������"ZC@ �� ��-��HeadingPermalink/HeadingPermalinkRenderer.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; /** * Renders the HeadingPermalink elements */ final class HeadingPermalinkRenderer implements NodeRendererInterface, XmlNodeRendererInterface, ConfigurationAwareInterface { public const DEFAULT_SYMBOL = '¶'; /** @psalm-readonly-allow-private-mutation */ private ConfigurationInterface $config; public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } /** * @param HeadingPermalink $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { HeadingPermalink::assertInstanceOf($node); $slug = $node->getSlug(); $fragmentPrefix = (string) $this->config->get('heading_permalink/fragment_prefix'); if ($fragmentPrefix !== '') { $fragmentPrefix .= '-'; } $attrs = $node->data->getData('attributes'); $appendId = ! $this->config->get('heading_permalink/apply_id_to_heading'); if ($appendId) { $idPrefix = (string) $this->config->get('heading_permalink/id_prefix'); if ($idPrefix !== '') { $idPrefix .= '-'; } $attrs->set('id', $idPrefix . $slug); } $attrs->set('href', '#' . $fragmentPrefix . $slug); $attrs->append('class', $this->config->get('heading_permalink/html_class')); $hidden = $this->config->get('heading_permalink/aria_hidden'); if ($hidden) { $attrs->set('aria-hidden', 'true'); } $attrs->set('title', $this->config->get('heading_permalink/title')); $symbol = $this->config->get('heading_permalink/symbol'); \assert(\is_string($symbol)); return new HtmlElement('a', $attrs->export(), \htmlspecialchars($symbol), false); } public function getXmlTagName(Node $node): string { return 'heading_permalink'; } /** * @param HeadingPermalink $node * * @return array<string, scalar> * * @psalm-suppress MoreSpecificImplementedParamType */ public function getXmlAttributes(Node $node): array { HeadingPermalink::assertInstanceOf($node); return [ 'slug' => $node->getSlug(), ]; } } PK������"ZrE{����%��HeadingPermalink/HeadingPermalink.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Node\Inline\AbstractInline; /** * Represents an anchor link within a heading */ final class HeadingPermalink extends AbstractInline { /** @psalm-readonly */ private string $slug; public function __construct(string $slug) { parent::__construct(); $this->slug = $slug; } public function getSlug(): string { return $this->slug; } } PK������"Z����#��GithubFlavoredMarkdownExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Environment\EnvironmentBuilderInterface; 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(EnvironmentBuilderInterface $environment): void { $environment->addExtension(new AutolinkExtension()); $environment->addExtension(new DisallowedRawHtmlExtension()); $environment->addExtension(new StrikethroughExtension()); $environment->addExtension(new TableExtension()); $environment->addExtension(new TaskListExtension()); } } PK������"Z3W����&��ExternalLink/ExternalLinkExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class ExternalLinkExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $applyOptions = [ ExternalLinkProcessor::APPLY_NONE, ExternalLinkProcessor::APPLY_ALL, ExternalLinkProcessor::APPLY_INTERNAL, ExternalLinkProcessor::APPLY_EXTERNAL, ]; $builder->addSchema('external_link', Expect::structure([ 'internal_hosts' => Expect::type('string|string[]'), 'open_in_new_window' => Expect::bool(false), 'html_class' => Expect::string()->default(''), 'nofollow' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_NONE), 'noopener' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL), 'noreferrer' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL), ])); } public function register(EnvironmentBuilderInterface $environment): void { $environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment->getConfiguration()), -50); } } PK������"Z(ؔ@ �� ��&��ExternalLink/ExternalLinkProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Event\DocumentParsedEvent; use League\CommonMark\Extension\CommonMark\Node\Inline\Link; use League\Config\ConfigurationInterface; final class ExternalLinkProcessor { public const APPLY_NONE = ''; public const APPLY_ALL = 'all'; public const APPLY_EXTERNAL = 'external'; public const APPLY_INTERNAL = 'internal'; /** @psalm-readonly */ private ConfigurationInterface $config; public function __construct(ConfigurationInterface $config) { $this->config = $config; } public function __invoke(DocumentParsedEvent $e): void { $internalHosts = $this->config->get('external_link/internal_hosts'); $openInNewWindow = $this->config->get('external_link/open_in_new_window'); $classes = $this->config->get('external_link/html_class'); foreach ($e->getDocument()->iterator() as $link) { if (! ($link instanceof Link)) { continue; } $host = \parse_url($link->getUrl(), PHP_URL_HOST); if (! \is_string($host)) { // Something is terribly wrong with this URL continue; } if (self::hostMatches($host, $internalHosts)) { $link->data->set('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->set('external', true); $this->applyRelAttribute($link, true); if ($openInNewWindow) { $link->data->set('attributes/target', '_blank'); } if ($classes !== '') { $link->data->append('attributes/class', $classes); } } private function applyRelAttribute(Link $link, bool $isExternal): void { $options = [ 'nofollow' => $this->config->get('external_link/nofollow'), 'noopener' => $this->config->get('external_link/noopener'), 'noreferrer' => $this->config->get('external_link/noreferrer'), ]; foreach ($options as $type => $option) { switch (true) { case $option === self::APPLY_ALL: case $isExternal && $option === self::APPLY_EXTERNAL: case ! $isExternal && $option === self::APPLY_INTERNAL: $link->data->append('attributes/rel', $type); } } } /** * @internal This method is only public so we can easily test it. DO NOT USE THIS OUTSIDE OF THIS EXTENSION! * * @param mixed $compareTo */ public static function hostMatches(string $host, $compareTo): bool { foreach ((array) $compareTo as $c) { if (\strpos($c, '/') === 0) { if (\preg_match($c, $host)) { return true; } } elseif ($c === $host) { return true; } } return false; } } PK������"Zzol��l����Autolink/UrlAutolinkParser.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\CommonMark\Node\Inline\Link; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class UrlAutolinkParser implements InlineParserInterface { private const ALLOWED_AFTER = [null, ' ', "\t", "\n", "\x0b", "\x0c", "\x0d", '*', '_', '~', '(']; // RegEx adapted from https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/Validator/Constraints/UrlValidator.php private const REGEX = '~ ( # Must start with a supported scheme + auth, or "www" (?: (?:%s):// # protocol (?:(?:(?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+)@)? # basic auth |www\.) (?: (?: (?:xn--[a-z0-9-]++\.)*+xn--[a-z0-9-]++ # a domain name using punycode | (?:[\pL\pN\pS\pM\-\_]++\.)+[\pL\pN\pM]++ # a multi-level domain name | [a-z0-9\-\_]++ # a single-level 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[] * * @psalm-readonly */ private array $prefixes = ['www']; /** @psalm-readonly */ private string $finalRegex; /** * @param array<int, string> $allowedProtocols */ public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) { $this->finalRegex = \sprintf(self::REGEX, \implode('|', $allowedProtocols)); foreach ($allowedProtocols as $protocol) { $this->prefixes[] = $protocol . '://'; } } public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::oneOf(...$this->prefixes); } public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); // Autolinks can only come at the beginning of a line, after whitespace, or certain delimiting characters $previousChar = $cursor->peek(-1); if (! \in_array($previousChar, self::ALLOWED_AFTER, true)) { return false; } // Check if we have a valid URL if (! \preg_match($this->finalRegex, $cursor->getRemainder(), $matches)) { return false; } $url = $matches[0]; // Does the URL end with punctuation that should be stripped? if (\preg_match('/(.+?)([?!.,:*_~]+)$/', $url, $matches)) { // Add the punctuation later $url = $matches[1]; } // Does the URL end with something that looks like an entity reference? if (\preg_match('/(.+)(&[A-Za-z0-9]+;)$/', $url, $matches)) { $url = $matches[1]; } // Does the URL need unmatched parens chopped off? if (\substr($url, -1) === ')' && ($diff = self::diffParens($url)) > 0) { $url = \substr($url, 0, -$diff); } $cursor->advanceBy(\mb_strlen($url, 'UTF-8')); // Auto-prefix 'http://' onto 'www' URLs if (\substr($url, 0, 4) === 'www.') { $inlineContext->getContainer()->appendChild(new Link('http://' . $url, $url)); return true; } $inlineContext->getContainer()->appendChild(new Link($url, $url)); return true; } /** * @psalm-pure */ 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['(']; } } PK������"Z_���� ��Autolink/EmailAutolinkParser.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\CommonMark\Node\Inline\Link; use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\InlineParserContext; final class EmailAutolinkParser implements InlineParserInterface { private const REGEX = '[A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+'; public function getMatchDefinition(): InlineParserMatch { return InlineParserMatch::regex(self::REGEX); } public function parse(InlineParserContext $inlineContext): bool { $email = $inlineContext->getFullMatch(); // The last character cannot be - or _ if (\in_array(\substr($email, -1), ['-', '_'], true)) { return false; } // Does the URL end with punctuation that should be stripped? if (\substr($email, -1) === '.') { $email = \substr($email, 0, -1); } $inlineContext->getCursor()->advanceBy(\strlen($email)); $inlineContext->getContainer()->appendChild(new Link('mailto:' . $email, $email)); return true; } } PK������"Z;������Autolink/AutolinkExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\ExtensionInterface; final class AutolinkExtension implements ExtensionInterface { public function register(EnvironmentBuilderInterface $environment): void { $environment->addInlineParser(new EmailAutolinkParser()); $environment->addInlineParser(new UrlAutolinkParser()); } } PK������"Zj@����-��FrontMatter/Data/LibYamlFrontMatterParser.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\FrontMatter\Data; use League\CommonMark\Exception\MissingDependencyException; use League\CommonMark\Extension\FrontMatter\Exception\InvalidFrontMatterException; final class LibYamlFrontMatterParser implements FrontMatterDataParserInterface { public static function capable(): ?LibYamlFrontMatterParser { if (! \extension_loaded('yaml')) { return null; } return new LibYamlFrontMatterParser(); } /** * {@inheritDoc} */ public function parse(string $frontMatter) { if (! \extension_loaded('yaml')) { throw new MissingDependencyException('Failed to parse yaml: "ext-yaml" extension is missing'); } $result = @\yaml_parse($frontMatter); if ($result === false) { throw new InvalidFrontMatterException('Failed to parse front matter'); } return $result; } } PK������"ZC����3��FrontMatter/Data/FrontMatterDataParserInterface.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\FrontMatter\Data; use League\CommonMark\Extension\FrontMatter\Exception\InvalidFrontMatterException; interface FrontMatterDataParserInterface { /** * @return mixed|null The parsed data (which may be null, if the input represents a null value) * * @throws InvalidFrontMatterException if parsing fails */ public function parse(string $frontMatter); } PK������"Z˃1��1��1��FrontMatter/Data/SymfonyYamlFrontMatterParser.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\FrontMatter\Data; use League\CommonMark\Exception\MissingDependencyException; use League\CommonMark\Extension\FrontMatter\Exception\InvalidFrontMatterException; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Yaml; final class SymfonyYamlFrontMatterParser implements FrontMatterDataParserInterface { /** * {@inheritDoc} */ public function parse(string $frontMatter) { if (! \class_exists(Yaml::class)) { throw new MissingDependencyException('Failed to parse yaml: "symfony/yaml" library is missing'); } try { return Yaml::parse($frontMatter); } catch (ParseException $ex) { throw InvalidFrontMatterException::wrap($ex); } } } PK������"Z5$����5��FrontMatter/Exception/InvalidFrontMatterException.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter\Exception; use League\CommonMark\Exception\CommonMarkException; class InvalidFrontMatterException extends \RuntimeException implements CommonMarkException { public static function wrap(\Throwable $t): self { return new InvalidFrontMatterException('Failed to parse front matter: ' . $t->getMessage(), 0, $t); } } PK������"Zds����6��FrontMatter/Listener/FrontMatterPostRenderListener.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter\Listener; use League\CommonMark\Event\DocumentRenderedEvent; use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter; final class FrontMatterPostRenderListener { public function __invoke(DocumentRenderedEvent $event): void { if ($event->getOutput()->getDocument()->data->get('front_matter', null) === null) { return; } $frontMatter = $event->getOutput()->getDocument()->data->get('front_matter'); $event->replaceOutput(new RenderedContentWithFrontMatter( $event->getOutput()->getDocument(), $event->getOutput()->getContent(), $frontMatter )); } } PK������"Z6E����-��FrontMatter/Listener/FrontMatterPreParser.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter\Listener; use League\CommonMark\Event\DocumentPreParsedEvent; use League\CommonMark\Extension\FrontMatter\FrontMatterParserInterface; final class FrontMatterPreParser { private FrontMatterParserInterface $parser; public function __construct(FrontMatterParserInterface $parser) { $this->parser = $parser; } public function __invoke(DocumentPreParsedEvent $event): void { $content = $event->getMarkdown()->getContent(); $parsed = $this->parser->parse($content); $event->getDocument()->data->set('front_matter', $parsed->getFrontMatter()); $event->replaceMarkdown($parsed); } } PK������"ZNY ����5��FrontMatter/Output/RenderedContentWithFrontMatter.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter\Output; use League\CommonMark\Extension\FrontMatter\FrontMatterProviderInterface; use League\CommonMark\Node\Block\Document; use League\CommonMark\Output\RenderedContent; /** * @psalm-immutable */ final class RenderedContentWithFrontMatter extends RenderedContent implements FrontMatterProviderInterface { /** * @var mixed * * @psalm-readonly */ private $frontMatter; /** * @param Document $document The parsed Document object * @param string $content The final HTML * @param mixed|null $frontMatter Any parsed front matter */ public function __construct(Document $document, string $content, $frontMatter) { parent::__construct($document, $content); $this->frontMatter = $frontMatter; } /** * {@inheritDoc} */ public function getFrontMatter() { return $this->frontMatter; } } PK������"Ziҍ' ��' ��!��FrontMatter/FrontMatterParser.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\FrontMatter; use League\CommonMark\Extension\FrontMatter\Data\FrontMatterDataParserInterface; use League\CommonMark\Extension\FrontMatter\Exception\InvalidFrontMatterException; use League\CommonMark\Extension\FrontMatter\Input\MarkdownInputWithFrontMatter; use League\CommonMark\Parser\Cursor; final class FrontMatterParser implements FrontMatterParserInterface { /** @psalm-readonly */ private FrontMatterDataParserInterface $frontMatterParser; private const REGEX_FRONT_MATTER = '/^---\\R.*?\\R---\\R/s'; public function __construct(FrontMatterDataParserInterface $frontMatterParser) { $this->frontMatterParser = $frontMatterParser; } /** * @throws InvalidFrontMatterException if the front matter cannot be parsed */ public function parse(string $markdownContent): MarkdownInputWithFrontMatter { $cursor = new Cursor($markdownContent); // Locate the front matter $frontMatter = $cursor->match(self::REGEX_FRONT_MATTER); if ($frontMatter === null) { return new MarkdownInputWithFrontMatter($markdownContent); } // Trim the last line (ending ---s and newline) $frontMatter = \preg_replace('/---\R$/', '', $frontMatter); if ($frontMatter === null) { return new MarkdownInputWithFrontMatter($markdownContent); } // Parse the resulting YAML data $data = $this->frontMatterParser->parse($frontMatter); // Advance through any remaining newlines which separated the front matter from the Markdown text $trailingNewlines = $cursor->match('/^\R+/'); // Calculate how many lines the Markdown is offset from the front matter by counting the number of newlines // Don't forget to add 1 because we stripped one out when trimming the trailing delims $lineOffset = \preg_match_all('/\R/', $frontMatter . $trailingNewlines) + 1; return new MarkdownInputWithFrontMatter($cursor->getRemainder(), $lineOffset, $data); } } PK������"Z����2��FrontMatter/Input/MarkdownInputWithFrontMatter.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter\Input; use League\CommonMark\Extension\FrontMatter\FrontMatterProviderInterface; use League\CommonMark\Input\MarkdownInput; final class MarkdownInputWithFrontMatter extends MarkdownInput implements FrontMatterProviderInterface { /** @var mixed|null */ private $frontMatter; /** * @param string $content Markdown content without the raw front matter * @param int $lineOffset Line offset (based on number of front matter lines removed) * @param mixed|null $frontMatter Parsed front matter */ public function __construct(string $content, int $lineOffset = 0, $frontMatter = null) { parent::__construct($content, $lineOffset); $this->frontMatter = $frontMatter; } /** * {@inheritDoc} */ public function getFrontMatter() { return $this->frontMatter; } } PK������"ZOj����$��FrontMatter/FrontMatterExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\FrontMatter; use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentPreParsedEvent; use League\CommonMark\Event\DocumentRenderedEvent; use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Extension\FrontMatter\Data\FrontMatterDataParserInterface; use League\CommonMark\Extension\FrontMatter\Data\LibYamlFrontMatterParser; use League\CommonMark\Extension\FrontMatter\Data\SymfonyYamlFrontMatterParser; use League\CommonMark\Extension\FrontMatter\Listener\FrontMatterPostRenderListener; use League\CommonMark\Extension\FrontMatter\Listener\FrontMatterPreParser; final class FrontMatterExtension implements ExtensionInterface { /** @psalm-readonly */ private FrontMatterParserInterface $frontMatterParser; public function __construct(?FrontMatterDataParserInterface $dataParser = null) { $this->frontMatterParser = new FrontMatterParser($dataParser ?? LibYamlFrontMatterParser::capable() ?? new SymfonyYamlFrontMatterParser()); } public function getFrontMatterParser(): FrontMatterParserInterface { return $this->frontMatterParser; } public function register(EnvironmentBuilderInterface $environment): void { $environment->addEventListener(DocumentPreParsedEvent::class, new FrontMatterPreParser($this->frontMatterParser)); $environment->addEventListener(DocumentRenderedEvent::class, new FrontMatterPostRenderListener(), -500); } } PK������"Zcֿ����,��FrontMatter/FrontMatterProviderInterface.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter; interface FrontMatterProviderInterface { /** * @return mixed|null */ public function getFrontMatter(); } PK������"ZR)n����*��FrontMatter/FrontMatterParserInterface.phpnu�W+A��������<?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. */ declare(strict_types=1); namespace League\CommonMark\Extension\FrontMatter; use League\CommonMark\Extension\FrontMatter\Input\MarkdownInputWithFrontMatter; interface FrontMatterParserInterface { public function parse(string $markdownContent): MarkdownInputWithFrontMatter; } PK������"Zt~����$��InlinesOnly/InlinesOnlyExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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 as Core; use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\CommonMark; use League\CommonMark\Extension\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class InlinesOnlyExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('commonmark', Expect::structure([ 'use_asterisk' => Expect::bool(true), 'use_underscore' => Expect::bool(true), 'enable_strong' => Expect::bool(true), 'enable_em' => Expect::bool(true), ])); } // phpcs:disable Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma,Squiz.WhiteSpace.SemicolonSpacing.Incorrect public function register(EnvironmentBuilderInterface $environment): void { $childRenderer = new ChildRenderer(); $environment ->addInlineParser(new Core\Parser\Inline\NewlineParser(), 200) ->addInlineParser(new CommonMark\Parser\Inline\BacktickParser(), 150) ->addInlineParser(new CommonMark\Parser\Inline\EscapableParser(), 80) ->addInlineParser(new CommonMark\Parser\Inline\EntityParser(), 70) ->addInlineParser(new CommonMark\Parser\Inline\AutolinkParser(), 50) ->addInlineParser(new CommonMark\Parser\Inline\HtmlInlineParser(), 40) ->addInlineParser(new CommonMark\Parser\Inline\CloseBracketParser(), 30) ->addInlineParser(new CommonMark\Parser\Inline\OpenBracketParser(), 20) ->addInlineParser(new CommonMark\Parser\Inline\BangParser(), 10) ->addRenderer(Core\Node\Block\Document::class, $childRenderer, 0) ->addRenderer(Core\Node\Block\Paragraph::class, $childRenderer, 0) ->addRenderer(CommonMark\Node\Inline\Code::class, new CommonMark\Renderer\Inline\CodeRenderer(), 0) ->addRenderer(CommonMark\Node\Inline\Emphasis::class, new CommonMark\Renderer\Inline\EmphasisRenderer(), 0) ->addRenderer(CommonMark\Node\Inline\HtmlInline::class, new CommonMark\Renderer\Inline\HtmlInlineRenderer(), 0) ->addRenderer(CommonMark\Node\Inline\Image::class, new CommonMark\Renderer\Inline\ImageRenderer(), 0) ->addRenderer(CommonMark\Node\Inline\Link::class, new CommonMark\Renderer\Inline\LinkRenderer(), 0) ->addRenderer(Core\Node\Inline\Newline::class, new Core\Renderer\Inline\NewlineRenderer(), 0) ->addRenderer(CommonMark\Node\Inline\Strong::class, new CommonMark\Renderer\Inline\StrongRenderer(), 0) ->addRenderer(Core\Node\Inline\Text::class, new Core\Renderer\Inline\TextRenderer(), 0) ; if ($environment->getConfiguration()->get('commonmark/use_asterisk')) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*')); } if ($environment->getConfiguration()->get('commonmark/use_underscore')) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_')); } } } PK������"Z1'������InlinesOnly/ChildRenderer.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Node\Block\Document; use League\CommonMark\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; /** * Simply renders child elements as-is, adding newlines as needed. */ final class ChildRenderer implements NodeRendererInterface { public function render(Node $node, ChildNodeRendererInterface $childRenderer): string { $out = $childRenderer->renderNodes($node->children()); if (! $node instanceof Document) { $out .= $childRenderer->getBlockSeparator(); } return $out; } } PK������"Zoa����0��DefaultAttributes/DefaultAttributesExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\DefaultAttributes; use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ConfigurableExtensionInterface; use League\Config\ConfigurationBuilderInterface; use Nette\Schema\Expect; final class DefaultAttributesExtension implements ConfigurableExtensionInterface { public function configureSchema(ConfigurationBuilderInterface $builder): void { $builder->addSchema('default_attributes', Expect::arrayOf( Expect::arrayOf( Expect::type('string|string[]|bool|callable'), // attribute value(s) 'string' // attribute name ), 'string' // node FQCN )->default([])); } public function register(EnvironmentBuilderInterface $environment): void { $environment->addEventListener(DocumentParsedEvent::class, [new ApplyDefaultAttributesProcessor(), 'onDocumentParsed']); } } PK������"ZGO��O��5��DefaultAttributes/ApplyDefaultAttributesProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\DefaultAttributes; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\Attributes\Util\AttributesHelper; use League\Config\ConfigurationAwareInterface; use League\Config\ConfigurationInterface; final class ApplyDefaultAttributesProcessor implements ConfigurationAwareInterface { private ConfigurationInterface $config; public function onDocumentParsed(DocumentParsedEvent $event): void { /** @var array<string, array<string, mixed>> $map */ $map = $this->config->get('default_attributes'); // Don't bother iterating if no default attributes are configured if (! $map) { return; } foreach ($event->getDocument()->iterator() as $node) { // Check to see if any default attributes were defined if (($attributesToApply = $map[\get_class($node)] ?? []) === []) { continue; } $newAttributes = []; foreach ($attributesToApply as $name => $value) { if (\is_callable($value)) { $value = $value($node); // Callables are allowed to return `null` indicating that no changes should be made if ($value !== null) { $newAttributes[$name] = $value; } } else { $newAttributes[$name] = $value; } } // Merge these attributes into the node if (\count($newAttributes) > 0) { $node->data->set('attributes', AttributesHelper::mergeAttributes($node, $newAttributes)); } } } public function setConfiguration(ConfigurationInterface $configuration): void { $this->config = $configuration; } } PK������"ZY6������Strikethrough/Strikethrough.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Node\Inline\AbstractInline; use League\CommonMark\Node\Inline\DelimitedInterface; final class Strikethrough extends AbstractInline implements DelimitedInterface { private string $delimiter; public function __construct(string $delimiter = '~~') { parent::__construct(); $this->delimiter = $delimiter; } public function getOpeningDelimiter(): string { return $this->delimiter; } public function getClosingDelimiter(): string { return $this->delimiter; } } PK������"ZȈ\;��;��'��Strikethrough/StrikethroughRenderer.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Node\Node; use League\CommonMark\Renderer\ChildNodeRendererInterface; use League\CommonMark\Renderer\NodeRendererInterface; use League\CommonMark\Util\HtmlElement; use League\CommonMark\Xml\XmlNodeRendererInterface; final class StrikethroughRenderer implements NodeRendererInterface, XmlNodeRendererInterface { /** * @param Strikethrough $node * * {@inheritDoc} * * @psalm-suppress MoreSpecificImplementedParamType */ public function render(Node $node, ChildNodeRendererInterface $childRenderer): \Stringable { Strikethrough::assertInstanceOf($node); return new HtmlElement('del', $node->data->get('attributes'), $childRenderer->renderNodes($node->children())); } public function getXmlTagName(Node $node): string { return 'strikethrough'; } /** * {@inheritDoc} */ public function getXmlAttributes(Node $node): array { return []; } } PK������"Z}'��'��(��Strikethrough/StrikethroughExtension.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Environment\EnvironmentBuilderInterface; use League\CommonMark\Extension\ExtensionInterface; final class StrikethroughExtension implements ExtensionInterface { public function register(EnvironmentBuilderInterface $environment): void { $environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor()); $environment->addRenderer(Strikethrough::class, new StrikethroughRenderer()); } } PK������"ZL8y����1��Strikethrough/StrikethroughDelimiterProcessor.phpnu�W+A��������<?php declare(strict_types=1); /* * 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\Node\Inline\AbstractStringContainer; final class StrikethroughDelimiterProcessor implements DelimiterProcessorInterface { public function getOpeningCharacter(): string { return '~'; } public function getClosingCharacter(): string { return '~'; } public function getMinLength(): int { return 1; } public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int { if ($opener->getLength() > 2 && $closer->getLength() > 2) { return 0; } if ($opener->getLength() !== $closer->getLength()) { return 0; } return \min($opener->getLength(), $closer->getLength()); } public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse): void { $strikethrough = new Strikethrough(\str_repeat('~', $delimiterUse)); $tmp = $opener->next(); while ($tmp !== null && $tmp !== $closer) { $next = $tmp->next(); $strikethrough->appendChild($tmp); $tmp = $next; } $opener->insertAfter($strikethrough); } } PK��������IZ!}���� ����������������GeneratorAwareExtensionTrait.phpnu�W+A��������PK��������IZ~es��s��������������.��VersionExtension.phpnu�W+A��������PK��������IZ,8L��L����������������BarcodeExtension.phpnu�W+A��������PK��������IZ'2$��2$��������������u��DateTimeExtension.phpnu�W+A��������PK��������IZ`$o �� �� ������������,��Helper.phpnu�W+A��������PK��������IZ����������������9��CountryExtension.phpnu�W+A��������PK��������IZ#`�������������������;��ExtensionNotFound.phpnu�W+A��������PK��������IZ- o��o��������������<��NumberExtension.phpnu�W+A��������PK��������IZgRc����������������A��BloodExtension.phpnu�W+A��������PK��������IZ'1����������������D��GeneratorAwareExtension.phpnu�W+A��������PK��������IZ|l&#��#��������������NF��FileExtension.phpnu�W+A��������PK��������IZk?������ ������������H��Extension.phpnu�W+A��������PK��������IZLkm��m��������������I��ColorExtension.phpnu�W+A��������PK��������IZ����������������N��AddressExtension.phpnu�W+A��������PK��������IZ+-����������������Q��CompanyExtension.phpnu�W+A��������PK��������IZ8mKXb��b��������������S��PersonExtension.phpnu�W+A��������PK��������IZ Um��m��������������AX��PhoneNumberExtension.phpnu�W+A��������PK��������IZ{ɮT��T��������������Y��UuidExtension.phpnu�W+A��������PK��������Z1a߰����������������[��HtmlExtension.phpnu�W+A��������PK��������Zvz����������������|r��AttributeMatchingExtension.phpnu�W+A��������PK��������Ze@O��O��������������v��CombinationExtension.phpnu�W+A��������PK��������Z(��(�������������� ��FunctionExtension.phpnu�W+A��������PK��������ZPĄ$<��<��������������z��AbstractExtension.phpnu�W+A��������PK��������ZD{ �� ����������������PseudoClassExtension.phpnu�W+A��������PK��������Zc��c�������������� ��ExtensionInterface.phpnu�W+A��������PK��������Z%������������������NodeExtension.phpnu�W+A��������PK��������"Z* x������������������Embed/EmbedStartParser.phpnu�W+A��������PK��������"Z������������������Embed/EmbedProcessor.phpnu�W+A��������PK��������"Z^M`8��8����������������Embed/EmbedParser.phpnu�W+A��������PK��������"Z⤞����'������������z��Embed/Bridge/OscaroteroEmbedAdapter.phpnu�W+A��������PK��������"Z*M����������������o��Embed/EmbedExtension.phpnu�W+A��������PK��������"Z a*B��B����������������Embed/EmbedRenderer.phpnu�W+A��������PK��������"ZF#(��(��������������%��Embed/EmbedAdapterInterface.phpnu�W+A��������PK��������"Z09 �� �� ��������������Embed/DomainFilteringAdapter.phpnu�W+A��������PK��������"Z ���������������� ��Embed/Embed.phpnu�W+A��������PK��������"Z2n����������������H��Table/TableRowRenderer.phpnu�W+A��������PK��������"Z+j!��!��������������J�Table/TableSection.phpnu�W+A��������PK��������"Zk߫�����������������Table/TableRenderer.phpnu�W+A��������PK��������"Z�P8��8�������������� �Table/TableParser.phpnu�W+A��������PK��������"Z_I����������������J$�Table/TableStartParser.phpnu�W+A��������PK��������"ZA9 ��9 ��������������i6�Table/TableCellRenderer.phpnu�W+A��������PK��������"Z �� ��������������@�Table/TableExtension.phpnu�W+A��������PK��������"Z_ %����������������J�Table/TableCell.phpnu�W+A��������PK��������"Z -��-��������������S�Table/TableSectionRenderer.phpnu�W+A��������PK��������"Z2����������������J[�Table/TableRow.phpnu�W+A��������PK��������"ZY����������������y]�Table/Table.phpnu�W+A��������PK��������"ZZC��C��'������������_�Attributes/Event/AttributesListener.phpnu�W+A��������PK��������"Z C����$������������<q�Attributes/Node/AttributesInline.phpnu�W+A��������PK��������"Z>w��w��������������Yv�Attributes/Node/Attributes.phpnu�W+A��������PK��������"Zc>k��k��$������������|�Attributes/Util/AttributesHelper.phpnu�W+A��������PK��������"Z0dŘ����"������������ݍ�Attributes/AttributesExtension.phpnu�W+A��������PK��������"ZZK��K��0������������ǒ�Attributes/Parser/AttributesBlockStartParser.phpnu�W+A��������PK��������"ZMǯ'����,������������r�Attributes/Parser/AttributesInlineParser.phpnu�W+A��������PK��������"Z_;0 �� ��3������������h�Attributes/Parser/AttributesBlockContinueParser.phpnu�W+A��������PK��������"Zpܵ1 ��1 ��6�������������Footnote/Event/FixOrphanedFootnotesAndRefsListener.phpnu�W+A��������PK��������"Z~& ��& ��*�������������Footnote/Event/NumberFootnotesListener.phpnu�W+A��������PK��������"ZM6��6��-�������������Footnote/Event/AnonymousFootnotesListener.phpnu�W+A��������PK��������"Z>r �� ��*������������.�Footnote/Event/GatherFootnotesListener.phpnu�W+A��������PK��������"ZB����������������_�Footnote/Node/Footnote.phpnu�W+A��������PK��������"Zwg��g��������������?�Footnote/Node/FootnoteRef.phpnu�W+A��������PK��������"ZX����#�������������Footnote/Node/FootnoteContainer.phpnu�W+A��������PK��������"Zu.1f����!�������������Footnote/Node/FootnoteBackref.phpnu�W+A��������PK��������"Z �� ��������������`�Footnote/FootnoteExtension.phpnu�W+A��������PK��������"Z)v@�����&�������������Footnote/Renderer/FootnoteRenderer.phpnu�W+A��������PK��������"ZaX ��X ��-�������������Footnote/Renderer/FootnoteBackrefRenderer.phpnu�W+A��������PK��������"Zf �� ��)������������o�Footnote/Renderer/FootnoteRefRenderer.phpnu�W+A��������PK��������"Z/ڰA��A��/�������������Footnote/Renderer/FootnoteContainerRenderer.phpnu�W+A��������PK��������"Z<zq��q��.������������)�Footnote/Parser/AnonymousFootnoteRefParser.phpnu�W+A��������PK��������"Zd����"������������"�Footnote/Parser/FootnoteParser.phpnu�W+A��������PK��������"ZzɎ����%������������N*�Footnote/Parser/FootnoteRefParser.phpnu�W+A��������PK��������"ZI����'������������N1�Footnote/Parser/FootnoteStartParser.phpnu�W+A��������PK��������"Z8)����,������������8�TableOfContents/TableOfContentsGenerator.phpnu�W+A��������PK��������"Z;ۿ����6������������P�TableOfContents/TableOfContentsPlaceholderRenderer.phpnu�W+A��������PK��������"Zvh����+������������4U�TableOfContents/TableOfContentsRenderer.phpnu�W+A��������PK��������"ZSH����:������������[�TableOfContents/Normalizer/NormalizerStrategyInterface.phpnu�W+A��������PK��������"ZIe ��e ��5������������]�TableOfContents/Normalizer/AsIsNormalizerStrategy.phpnu�W+A��������PK��������"ZUTi����9������������g�TableOfContents/Normalizer/RelativeNormalizerStrategy.phpnu�W+A��������PK��������"Z @H��H��5������������p�TableOfContents/Normalizer/FlatNormalizerStrategy.phpnu�W+A��������PK��������"Zè����3������������~t�TableOfContents/Node/TableOfContentsPlaceholder.phpnu�W+A��������PK��������"Z_����(������������v�TableOfContents/Node/TableOfContents.phpnu�W+A��������PK��������"Z�DM.��.��5������������x�TableOfContents/TableOfContentsGeneratorInterface.phpnu�W+A��������PK��������"Z5a����*������������L{�TableOfContents/TableOfContentsBuilder.phpnu�W+A��������PK��������"Z[ �� ��4�������������TableOfContents/TableOfContentsPlaceholderParser.phpnu�W+A��������PK��������"Z{z ��z ��,�������������TableOfContents/TableOfContentsExtension.phpnu�W+A��������PK��������"Zmk2��2��,�������������SmartPunct/ReplaceUnpairedQuotesListener.phpnu�W+A��������PK��������"ZТr��r��������������I�SmartPunct/DashParser.phpnu�W+A��������PK��������"Z%d; ��; ���������������SmartPunct/QuoteProcessor.phpnu�W+A��������PK��������"Z,K �� ���������������SmartPunct/QuoteParser.phpnu�W+A��������PK��������"Z 4$O��O���������������SmartPunct/EllipsesParser.phpnu�W+A��������PK��������"Z2"? �� ��"������������4�SmartPunct/SmartPunctExtension.phpnu�W+A��������PK��������"ZK{A��A���������������SmartPunct/Quote.phpnu�W+A��������PK��������"Z_8��8��"�������������CommonMark/Node/Block/ListData.phpnu�W+A��������PK��������"Z[����&�������������CommonMark/Node/Block/IndentedCode.phpnu�W+A��������PK��������"Z5i@��@��"������������S�CommonMark/Node/Block/ListItem.phpnu�W+A��������PK��������"Zt>Pb��b��!�������������CommonMark/Node/Block/Heading.phpnu�W+A��������PK��������"Z0'��'��#�������������CommonMark/Node/Block/HtmlBlock.phpnu�W+A��������PK��������"Z`I����$�������������CommonMark/Node/Block/BlockQuote.phpnu�W+A��������PK��������"Zщ8����#�������������CommonMark/Node/Block/ListBlock.phpnu�W+A��������PK��������"Z>����'������������q�CommonMark/Node/Block/ThematicBreak.phpnu�W+A��������PK��������"Z>l>����$������������u�CommonMark/Node/Block/FencedCode.phpnu�W+A��������PK��������"Z놘o��o��.��������������CommonMark/Node/Inline/AbstractWebResource.phpnu�W+A��������PK��������"Z <̋����#�������������CommonMark/Node/Inline/Emphasis.phpnu�W+A��������PK��������"Zh6��6���������������CommonMark/Node/Inline/Code.phpnu�W+A��������PK��������"Zx����%������������T �CommonMark/Node/Inline/HtmlInline.phpnu�W+A��������PK��������"Z0֝T��T��������������J�CommonMark/Node/Inline/Link.phpnu�W+A��������PK��������"Z����!�������������CommonMark/Node/Inline/Strong.phpnu�W+A��������PK��������"ZP2U��U�� ������������+�CommonMark/Node/Inline/Image.phpnu�W+A��������PK��������"Z&t+��+��/�������������CommonMark/Renderer/Block/HtmlBlockRenderer.phpnu�W+A��������PK��������"Z#t2��2��.������������Z#�CommonMark/Renderer/Block/ListItemRenderer.phpnu�W+A��������PK��������"Z@4)��)��0������������+�CommonMark/Renderer/Block/FencedCodeRenderer.phpnu�W+A��������PK��������"Z����3������������s4�CommonMark/Renderer/Block/ThematicBreakRenderer.phpnu�W+A��������PK��������"Z>9@ �� ��/������������:�CommonMark/Renderer/Block/ListBlockRenderer.phpnu�W+A��������PK��������"Z@ %����0������������D�CommonMark/Renderer/Block/BlockQuoteRenderer.phpnu�W+A��������PK��������"Z����-������������L�CommonMark/Renderer/Block/HeadingRenderer.phpnu�W+A��������PK��������"Zn3`c��c��2������������S�CommonMark/Renderer/Block/IndentedCodeRenderer.phpnu�W+A��������PK��������"ZS>qL9 ��9 ��+������������Z�CommonMark/Renderer/Inline/LinkRenderer.phpnu�W+A��������PK��������"ZyZ'����-������������e�CommonMark/Renderer/Inline/StrongRenderer.phpnu�W+A��������PK��������"Z(����+������������Qk�CommonMark/Renderer/Inline/CodeRenderer.phpnu�W+A��������PK��������"Z ?����/������������q�CommonMark/Renderer/Inline/EmphasisRenderer.phpnu�W+A��������PK��������"Z] �� ��,������������w�CommonMark/Renderer/Inline/ImageRenderer.phpnu�W+A��������PK��������"Z 2��2��1������������ �CommonMark/Renderer/Inline/HtmlInlineRenderer.phpnu�W+A��������PK��������"Zh{U��U��&�������������CommonMark/CommonMarkCoreExtension.phpnu�W+A��������PK��������"ZhN �� ��=������������H�CommonMark/Delimiter/Processor/EmphasisDelimiterProcessor.phpnu�W+A��������PK��������"Z}v##{ ��{ ��*������������J�CommonMark/Parser/Block/ListItemParser.phpnu�W+A��������PK��������"Z����0�������������CommonMark/Parser/Block/ListBlockStartParser.phpnu�W+A��������PK��������"ZCe����3������������y�CommonMark/Parser/Block/IndentedCodeStartParser.phpnu�W+A��������PK��������"Z*P �� ��.�������������CommonMark/Parser/Block/HeadingStartParser.phpnu�W+A��������PK��������"ZXѷ����1�������������CommonMark/Parser/Block/FencedCodeStartParser.phpnu�W+A��������PK��������"Z:A����.�������������CommonMark/Parser/Block/IndentedCodeParser.phpnu�W+A��������PK��������"Z{j����+�������������CommonMark/Parser/Block/HtmlBlockParser.phpnu�W+A��������PK��������"Z7Bq �� ��,������������j�CommonMark/Parser/Block/FencedCodeParser.phpnu�W+A��������PK��������"ZnL����)��������������CommonMark/Parser/Block/HeadingParser.phpnu�W+A��������PK��������"ZW����4�������������CommonMark/Parser/Block/ThematicBreakStartParser.phpnu�W+A��������PK��������"ZKz*��*��,������������> �CommonMark/Parser/Block/BlockQuoteParser.phpnu�W+A��������PK��������"ZϲdD ��D ��+�������������CommonMark/Parser/Block/ListBlockParser.phpnu�W+A��������PK��������"Zᄖ����/������������c�CommonMark/Parser/Block/ThematicBreakParser.phpnu�W+A��������PK��������"ZY��Y��1������������X!�CommonMark/Parser/Block/BlockQuoteStartParser.phpnu�W+A��������PK��������"Z} V��V��0������������&�CommonMark/Parser/Block/HtmlBlockStartParser.phpnu�W+A��������PK��������"Z,k��k��,������������.�CommonMark/Parser/Inline/EscapableParser.phpnu�W+A��������PK��������"Z9E����)������������5�CommonMark/Parser/Inline/EntityParser.phpnu�W+A��������PK��������"ZLb��b��+������������:�CommonMark/Parser/Inline/AutolinkParser.phpnu�W+A��������PK��������"Z^™����/������������B�CommonMark/Parser/Inline/CloseBracketParser.phpnu�W+A��������PK��������"Z5^��^��+������������_�CommonMark/Parser/Inline/BacktickParser.phpnu�W+A��������PK��������"ZƊ>d��d��'������������h�CommonMark/Parser/Inline/BangParser.phpnu�W+A��������PK��������"Z{����-������������\n�CommonMark/Parser/Inline/HtmlInlineParser.phpnu�W+A��������PK��������"Z%a��a��.������������s�CommonMark/Parser/Inline/OpenBracketParser.phpnu�W+A��������PK��������"ZdC����:������������uy�DescriptionList/Event/ConsecutiveDescriptionListMerger.phpnu�W+A��������PK��������"Z#_����1������������r~�DescriptionList/Event/LooseDescriptionHandler.phpnu�W+A��������PK��������"Zl ����(�������������DescriptionList/Node/DescriptionTerm.phpnu�W+A��������PK��������"Zx����(�������������DescriptionList/Node/DescriptionList.phpnu�W+A��������PK��������"Z_>XC��C��$�������������DescriptionList/Node/Description.phpnu�W+A��������PK��������"ZV"��"��4������������T�DescriptionList/Renderer/DescriptionTermRenderer.phpnu�W+A��������PK��������"ZH!����0������������ړ�DescriptionList/Renderer/DescriptionRenderer.phpnu�W+A��������PK��������"ZZpw��w��4������������L�DescriptionList/Renderer/DescriptionListRenderer.phpnu�W+A��������PK��������"Zc0o��o��,������������'�DescriptionList/DescriptionListExtension.phpnu�W+A��������PK��������"Z9۞ �� ��8�������������DescriptionList/Parser/DescriptionTermContinueParser.phpnu�W+A��������PK��������"Z`H �� ��1������������c�DescriptionList/Parser/DescriptionStartParser.phpnu�W+A��������PK��������"ZK\��\��4�������������DescriptionList/Parser/DescriptionContinueParser.phpnu�W+A��������PK��������"Zx����8�������������DescriptionList/Parser/DescriptionListContinueParser.phpnu�W+A��������PK��������"ZT/ �� ���������������Mention/MentionParser.phpnu�W+A��������PK��������"ZF�����������������Mention/Mention.phpnu�W+A��������PK��������"Z<@( �� ���������������Mention/MentionExtension.phpnu�W+A��������PK��������"ZU|����/�������������Mention/Generator/MentionGeneratorInterface.phpnu�W+A��������PK��������"ZGG��G��'������������R�Mention/Generator/CallbackGenerator.phpnu�W+A��������PK��������"Z ݖN��N��1�������������Mention/Generator/StringTemplateLinkGenerator.phpnu�W+A��������PK��������"ZG ����"�������������ConfigurableExtensionInterface.phpnu�W+A��������PK��������"Z"MY��Y��%�������������TaskList/TaskListItemMarkerParser.phpnu�W+A��������PK��������"Z7����'�������������TaskList/TaskListItemMarkerRenderer.phpnu�W+A��������PK��������"Z-8��8����������������TaskList/TaskListItemMarker.phpnu�W+A��������PK��������"Z,�����������������TaskList/TaskListExtension.phpnu�W+A��������PK��������"ZRE����0�������������DisallowedRawHtml/DisallowedRawHtmlExtension.phpnu�W+A��������PK��������"Zj L����/������������ �DisallowedRawHtml/DisallowedRawHtmlRenderer.phpnu�W+A��������PK��������"Z����.�������������HeadingPermalink/HeadingPermalinkProcessor.phpnu�W+A��������PK��������"ZCOS��S��.������������6%�HeadingPermalink/HeadingPermalinkExtension.phpnu�W+A��������PK��������"ZC@ �� ��-������������-�HeadingPermalink/HeadingPermalinkRenderer.phpnu�W+A��������PK��������"ZrE{����%������������%:�HeadingPermalink/HeadingPermalink.phpnu�W+A��������PK��������"Z����#������������`=�GithubFlavoredMarkdownExtension.phpnu�W+A��������PK��������"Z3W����&������������PB�ExternalLink/ExternalLinkExtension.phpnu�W+A��������PK��������"Z(ؔ@ �� ��&������������I�ExternalLink/ExternalLinkProcessor.phpnu�W+A��������PK��������"Zzol��l��������������W�Autolink/UrlAutolinkParser.phpnu�W+A��������PK��������"Z_���� ������������ys�Autolink/EmailAutolinkParser.phpnu�W+A��������PK��������"Z;����������������ry�Autolink/AutolinkExtension.phpnu�W+A��������PK��������"Zj@����-������������|�FrontMatter/Data/LibYamlFrontMatterParser.phpnu�W+A��������PK��������"ZC����3�������������FrontMatter/Data/FrontMatterDataParserInterface.phpnu�W+A��������PK��������"Z˃1��1��1�������������FrontMatter/Data/SymfonyYamlFrontMatterParser.phpnu�W+A��������PK��������"Z5$����5������������Q�FrontMatter/Exception/InvalidFrontMatterException.phpnu�W+A��������PK��������"Zds����6������������F�FrontMatter/Listener/FrontMatterPostRenderListener.phpnu�W+A��������PK��������"Z6E����-�������������FrontMatter/Listener/FrontMatterPreParser.phpnu�W+A��������PK��������"ZNY ����5�������������FrontMatter/Output/RenderedContentWithFrontMatter.phpnu�W+A��������PK��������"Ziҍ' ��' ��!�������������FrontMatter/FrontMatterParser.phpnu�W+A��������PK��������"Z����2������������h�FrontMatter/Input/MarkdownInputWithFrontMatter.phpnu�W+A��������PK��������"ZOj����$������������l�FrontMatter/FrontMatterExtension.phpnu�W+A��������PK��������"Zcֿ����,�������������FrontMatter/FrontMatterProviderInterface.phpnu�W+A��������PK��������"ZR)n����*������������ձ�FrontMatter/FrontMatterParserInterface.phpnu�W+A��������PK��������"Zt~����$������������?�InlinesOnly/InlinesOnlyExtension.phpnu�W+A��������PK��������"Z1'�����������������InlinesOnly/ChildRenderer.phpnu�W+A��������PK��������"Zoa����0�������������DefaultAttributes/DefaultAttributesExtension.phpnu�W+A��������PK��������"ZGO��O��5������������u�DefaultAttributes/ApplyDefaultAttributesProcessor.phpnu�W+A��������PK��������"ZY6����������������)�Strikethrough/Strikethrough.phpnu�W+A��������PK��������"ZȈ\;��;��'������������ �Strikethrough/StrikethroughRenderer.phpnu�W+A��������PK��������"Z}'��'��(�������������Strikethrough/StrikethroughExtension.phpnu�W+A��������PK��������"ZL8y����1�������������Strikethrough/StrikethroughDelimiterProcessor.phpnu�W+A��������PK������P�����