Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!żŒ‘  (Strikethrough/StrikethroughExtension.phpnuÕIw¶“ and uAfrica.com (http://uafrica.com) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Strikethrough; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; final class StrikethroughExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor()); $environment->addInlineRenderer(Strikethrough::class, new StrikethroughRenderer()); } } PK!ÄØČ>Strikethrough/README.mdnuÕIw¶“# Strikethrough support for `league/commonmark` This extension adds strikethrough Markdown support for the [league/commonmark](link-league-commonmark) PHP Markdown parsing engine, which itself is based on the CommonMark spec. It allows users to use `~~` in order to indicate text that should be rendered within `` tags. ## Usage Extensions can be added to any new `Environment`: ```php use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; use League\CommonMark\Extension\Strikethrough\StrikethroughExtension; // Obtain a pre-configured Environment with all the CommonMark parsers/renderers ready-to-go $environment = Environment::createCommonMarkEnvironment(); // Add this extension $environment->addExtension(new StrikethroughExtension()); // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter($config, $environment); echo $converter->convertToHtml('This extension is ~~good~~ great!'); ``` [link-league-commonmark]: https://github.com/thephpleague/commonmark PK!쨖Y))Strikethrough/Strikethrough.phpnuÕIw¶“ and uAfrica.com (http://uafrica.com) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Strikethrough; use League\CommonMark\Inline\Element\AbstractInline; final class Strikethrough extends AbstractInline { /** * @return bool */ public function isContainer(): bool { return true; } } PK!†‘ŸŸ'Strikethrough/StrikethroughRenderer.phpnuÕIw¶“ and uAfrica.com (http://uafrica.com) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Strikethrough; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Inline\Renderer\InlineRendererInterface; final class StrikethroughRenderer implements InlineRendererInterface { /** * {@inheritdoc} */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { if (!($inline instanceof Strikethrough)) { throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline)); } return new HtmlElement('del', $inline->getData('attributes', []), $htmlRenderer->renderInlines($inline->children())); } } PK!U»,§1Strikethrough/StrikethroughDelimiterProcessor.phpnuÕIw¶“ and uAfrica.com (http://uafrica.com) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Strikethrough; use League\CommonMark\Delimiter\DelimiterInterface; use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; use League\CommonMark\Inline\Element\AbstractStringContainer; final class StrikethroughDelimiterProcessor implements DelimiterProcessorInterface { /** * {@inheritdoc} */ public function getOpeningCharacter(): string { return '~'; } /** * {@inheritdoc} */ public function getClosingCharacter(): string { return '~'; } /** * {@inheritdoc} */ public function getMinLength(): int { return 2; } /** * {@inheritdoc} */ public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int { $min = \min($opener->getLength(), $closer->getLength()); return $min >= 2 ? $min : 0; } /** * {@inheritdoc} */ public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse) { $strikethrough = new Strikethrough(); $tmp = $opener->next(); while ($tmp !== null && $tmp !== $closer) { $next = $tmp->next(); $strikethrough->appendChild($tmp); $tmp = $next; } $opener->insertAfter($strikethrough); } } PK!že°Ā{{#GithubFlavoredMarkdownExtension.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\Autolink\AutolinkExtension; use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension; use League\CommonMark\Extension\Strikethrough\StrikethroughExtension; use League\CommonMark\Extension\Table\TableExtension; use League\CommonMark\Extension\TaskList\TaskListExtension; final class GithubFlavoredMarkdownExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment->addExtension(new AutolinkExtension()); $environment->addExtension(new DisallowedRawHtmlExtension()); $environment->addExtension(new StrikethroughExtension()); $environment->addExtension(new TableExtension()); $environment->addExtension(new TaskListExtension()); } } PK!ļ́/bbSmartPunct/README.mdnuÕIw¶“# Smart Punctuation for `league/commonmark` Intelligently converts ASCII quotes, dashes, and ellipses to their Unicode equivalents. For use with the [`league/commonmark` Markdown parser for PHP](https://github.com/thephpleague/commonmark). For example, this Markdown... ```md "CommonMark is the PHP League's Markdown parser," she said. "It's super-configurable... you can even use additional extensions to expand its capabilities -- just like this one!" ``` Will result in this HTML: ```html

ā€œCommonMark is the PHP League’s Markdown parser,ā€ she said. ā€œIt’s super-configurable… you can even use additional extensions to expand its capabilities – just like this one!ā€

``` ## Usage Extensions can be added to any new `Environment`: ``` php use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; use League\CommonMark\Extension\SmartPunct\SmartPunctExtension; // Obtain a pre-configured Environment with all the CommonMark parsers/renderers ready-to-go $environment = Environment::createCommonMarkEnvironment(); // Add this extension $environment->addExtension(new SmartPunctExtension()); // Set your configuration $config = [ 'smartpunct' => [ 'double_quote_opener' => 'ā€œ', 'double_quote_closer' => 'ā€', 'single_quote_opener' => 'ā€˜', 'single_quote_closer' => '’', ], ]; // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter($config, $environment); echo $converter->convertToHtml('# Hello World!'); ``` [link-league-commonmark]: https://github.com/thephpleague/commonmark PK!š¼’.$$SmartPunct/QuoteRenderer.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\SmartPunct; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Inline\Renderer\InlineRendererInterface; final class QuoteRenderer implements InlineRendererInterface { /** * @param AbstractInline $inline * @param ElementRendererInterface $htmlRenderer * * @return HtmlElement|string|null */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { if (!$inline instanceof Quote) { throw new \InvalidArgumentException(sprintf('Expected an instance of "%s", got "%s" instead', Quote::class, get_class($inline))); } // Handles unpaired quotes which remain after processing delimiters if ($inline->getContent() === Quote::SINGLE_QUOTE) { // Render as an apostrophe return Quote::SINGLE_QUOTE_CLOSER; } elseif ($inline->getContent() === Quote::DOUBLE_QUOTE) { // Render as an opening quote return Quote::DOUBLE_QUOTE_OPENER; } return $inline->getContent(); } } PK! ›Äžōō SmartPunct/PunctuationParser.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\SmartPunct; use League\CommonMark\Inline\Element\Text; use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; final class PunctuationParser implements InlineParserInterface { /** * @return string[] */ public function getCharacters(): array { return ['-', '.']; } /** * @param InlineParserContext $inlineContext * * @return bool */ public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $ch = $cursor->getCharacter(); // Ellipses if ($ch === '.' && $matched = $cursor->match('/^\\.( ?\\.)\\1/')) { $inlineContext->getContainer()->appendChild(new Text('…')); return true; } // Em/En-dashes elseif ($ch === '-' && $matched = $cursor->match('/^(?getContainer()->appendChild(new Text( str_repeat($em_dash, $em_count) . str_repeat($en_dash, $en_count) )); return true; } return false; } } PK!Ņj#ݳ ³ SmartPunct/QuoteParser.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\SmartPunct; use League\CommonMark\Delimiter\Delimiter; use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; use League\CommonMark\Util\RegexHelper; final class QuoteParser implements InlineParserInterface { public const DOUBLE_QUOTES = [Quote::DOUBLE_QUOTE, Quote::DOUBLE_QUOTE_OPENER, Quote::DOUBLE_QUOTE_CLOSER]; public const SINGLE_QUOTES = [Quote::SINGLE_QUOTE, Quote::SINGLE_QUOTE_OPENER, Quote::SINGLE_QUOTE_CLOSER]; /** * @return string[] */ public function getCharacters(): array { return array_merge(self::DOUBLE_QUOTES, self::SINGLE_QUOTES); } /** * Normalizes any quote characters found and manually adds them to the delimiter stack * * @param InlineParserContext $inlineContext * * @return bool */ public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $normalizedCharacter = $this->getNormalizedQuoteCharacter($cursor->getCharacter()); $charBefore = $cursor->peek(-1); if ($charBefore === null) { $charBefore = "\n"; } $cursor->advance(); $charAfter = $cursor->getCharacter(); if ($charAfter === null) { $charAfter = "\n"; } [$leftFlanking, $rightFlanking] = $this->determineFlanking($charBefore, $charAfter); $canOpen = $leftFlanking && !$rightFlanking; $canClose = $rightFlanking; $node = new Quote($normalizedCharacter, ['delim' => true]); $inlineContext->getContainer()->appendChild($node); // Add entry to stack to this opener $inlineContext->getDelimiterStack()->push(new Delimiter($normalizedCharacter, 1, $node, $canOpen, $canClose)); return true; } /** * @param string $character * * @return string|null */ private function getNormalizedQuoteCharacter($character) { if (in_array($character, self::DOUBLE_QUOTES)) { return Quote::DOUBLE_QUOTE; } elseif (in_array($character, self::SINGLE_QUOTES)) { return Quote::SINGLE_QUOTE; } return $character; } /** * @param string $charBefore * @param string $charAfter * * @return bool[] */ private function determineFlanking($charBefore, $charAfter) { $afterIsWhitespace = preg_match('/\pZ|\s/u', $charAfter); $afterIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charAfter); $beforeIsWhitespace = preg_match('/\pZ|\s/u', $charBefore); $beforeIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charBefore); $leftFlanking = !$afterIsWhitespace && !($afterIsPunctuation && !$beforeIsWhitespace && !$beforeIsPunctuation); $rightFlanking = !$beforeIsWhitespace && !($beforeIsPunctuation && !$afterIsWhitespace && !$afterIsPunctuation); return [$leftFlanking, $rightFlanking]; } } PK!®~žSmartPunct/Quote.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\SmartPunct; use League\CommonMark\Inline\Element\AbstractStringContainer; final class Quote extends AbstractStringContainer { public const DOUBLE_QUOTE = '"'; public const DOUBLE_QUOTE_OPENER = 'ā€œ'; public const DOUBLE_QUOTE_CLOSER = 'ā€'; public const SINGLE_QUOTE = "'"; public const SINGLE_QUOTE_OPENER = 'ā€˜'; public const SINGLE_QUOTE_CLOSER = '’'; } PK!@Žļļ"SmartPunct/SmartPunctExtension.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\SmartPunct; use League\CommonMark\Block\Element\Document; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Renderer as CoreBlockRenderer; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Inline\Element\Text; use League\CommonMark\Inline\Renderer as CoreInlineRenderer; final class SmartPunctExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment ->addInlineParser(new QuoteParser(), 10) ->addInlineParser(new PunctuationParser(), 0) ->addDelimiterProcessor(QuoteProcessor::createDoubleQuoteProcessor( $environment->getConfig('smartpunct/double_quote_opener', Quote::DOUBLE_QUOTE_OPENER), $environment->getConfig('smartpunct/double_quote_closer', Quote::DOUBLE_QUOTE_CLOSER) )) ->addDelimiterProcessor(QuoteProcessor::createSingleQuoteProcessor( $environment->getConfig('smartpunct/single_quote_opener', Quote::SINGLE_QUOTE_OPENER), $environment->getConfig('smartpunct/single_quote_closer', Quote::SINGLE_QUOTE_CLOSER) )) ->addBlockRenderer(Document::class, new CoreBlockRenderer\DocumentRenderer(), 0) ->addBlockRenderer(Paragraph::class, new CoreBlockRenderer\ParagraphRenderer(), 0) ->addInlineRenderer(Quote::class, new QuoteRenderer(), 100) ->addInlineRenderer(Text::class, new CoreInlineRenderer\TextRenderer(), 0) ; } } PK!ɹV SmartPunct/QuoteProcessor.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\SmartPunct; use League\CommonMark\Delimiter\DelimiterInterface; use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; use League\CommonMark\Inline\Element\AbstractStringContainer; final class QuoteProcessor implements DelimiterProcessorInterface { /** @var string */ private $normalizedCharacter; /** @var string */ private $openerCharacter; /** @var string */ private $closerCharacter; /** * QuoteProcessor constructor. * * @param string $char * @param string $opener * @param string $closer */ private function __construct(string $char, string $opener, string $closer) { $this->normalizedCharacter = $char; $this->openerCharacter = $opener; $this->closerCharacter = $closer; } /** * {@inheritdoc} */ public function getOpeningCharacter(): string { return $this->normalizedCharacter; } /** * {@inheritdoc} */ public function getClosingCharacter(): string { return $this->normalizedCharacter; } /** * {@inheritdoc} */ public function getMinLength(): int { return 1; } /** * {@inheritdoc} */ public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int { return 1; } /** * {@inheritdoc} */ public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse) { $opener->insertAfter(new Quote($this->openerCharacter)); $closer->insertBefore(new Quote($this->closerCharacter)); } /** * Create a double-quote processor * * @param string $opener * @param string $closer * * @return QuoteProcessor */ public static function createDoubleQuoteProcessor(string $opener = Quote::DOUBLE_QUOTE_OPENER, string $closer = Quote::DOUBLE_QUOTE_CLOSER): self { return new self(Quote::DOUBLE_QUOTE, $opener, $closer); } /** * Create a single-quote processor * * @param string $opener * @param string $closer * * @return QuoteProcessor */ public static function createSingleQuoteProcessor(string $opener = Quote::SINGLE_QUOTE_OPENER, string $closer = Quote::SINGLE_QUOTE_CLOSER): self { return new self(Quote::SINGLE_QUOTE, $opener, $closer); } } PK!Ķh–„Autolink/AutolinkExtension.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Autolink; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ExtensionInterface; final class AutolinkExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment->addEventListener(DocumentParsedEvent::class, new EmailAutolinkProcessor()); $environment->addEventListener(DocumentParsedEvent::class, new UrlAutolinkProcessor()); } } PK!›#nµµ#Autolink/EmailAutolinkProcessor.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Autolink; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Inline\Element\Link; use League\CommonMark\Inline\Element\Text; final class EmailAutolinkProcessor { const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/'; /** * @param DocumentParsedEvent $e * * @return void */ public function __invoke(DocumentParsedEvent $e) { $walker = $e->getDocument()->walker(); while ($event = $walker->next()) { $node = $event->getNode(); if ($node instanceof Text && !($node->parent() instanceof Link)) { self::processAutolinks($node); } } } private static function processAutolinks(Text $node) { $contents = \preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); if ($contents === false || \count($contents) === 1) { return; } $leftovers = ''; foreach ($contents as $i => $content) { if ($i % 2 === 0) { $text = $leftovers . $content; if ($text !== '') { $node->insertBefore(new Text($leftovers . $content)); } $leftovers = ''; continue; } // Does the URL end with punctuation that should be stripped? if (\substr($content, -1) === '.') { // Add the punctuation later $content = \substr($content, 0, -1); $leftovers = '.'; } // The last character cannot be - or _ if (\in_array(\substr($content, -1), ['-', '_'])) { $node->insertBefore(new Text($content . $leftovers)); $leftovers = ''; continue; } $node->insertBefore(new Link('mailto:' . $content, $content)); } $node->detach(); } } PK!¼EéŠ  Autolink/README.mdnuÕIw¶“# URL and email autolinking extension for `league/commonmark` This extension adds [GFM-style autolinking][link-gfm-spec-autolinking] to the [`league/commonmark` Markdown parser for PHP][link-league-commonmark]. It automatically link URLs and email addresses even when the CommonMark `<...>` autolink syntax is not used. It also provides a parser to autolink `@mentions` to Twitter, Github, or any custom service you wish, though this is disabled by default. ## Usage Configure your `Environment` as usual and simply add the `AutolinkExtension` provided by this package: ```php use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; use League\CommonMark\Extension\Autolink\AutolinkExtension; // Obtain a pre-configured Environment with all the CommonMark parsers/renderers ready-to-go $environment = Environment::createCommonMarkEnvironment(); // Add this extension $environment->addExtension(new AutolinkExtension()); // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter([], $environment); echo $converter->convertToHtml('I successfully installed the https://github.com/thephpleague/commonmark project with the Autolink extension!'); ``` ## `@mention` Autolinking This extension also provides functionality to automatically link "mentions" like `@colinodell` to Twitter, Github, or any other site of your choice! For Twitter: ```php use League\CommonMark\Environment; use League\CommonMark\Extension\Autolink\InlineMentionParser; $environment = Environment::createCommonMarkEnvironment(); $environment->addInlineParser(InlineMentionParser::createTwitterHandleParser()); // TODO: Instantiate your converter and convert some Markdown ``` For GitHub: ```php use League\CommonMark\Environment; use League\CommonMark\Extension\Autolink\InlineMentionParser; $environment = Environment::createCommonMarkEnvironment(); $environment->addInlineParser(InlineMentionParser::createGithubHandleParser()); // TODO: Instantiate your converter and convert some Markdown ``` Or configure your own custom one: ```php use League\CommonMark\Environment; use League\CommonMark\Extension\Autolink\InlineMentionParser; $environment = Environment::createCommonMarkEnvironment(); $environment->addInlineParser(new InlineMentionParser('https://www.example.com/users/%s/profile')); // TODO: Instantiate your converter and convert some Markdown ``` When creating your own, you can provide two parameters to the constructor: - A URL template where `%s` is replaced with the username (required) - A regular expression to parse and validate the username (optional - defaults to `'/^[A-Za-z0-9_]+(?!\w)/'`) [link-league-commonmark]: https://github.com/thephpleague/commonmark [link-gfm-spec-autolinking]: https://github.github.com/gfm/#autolinks-extension- PK!p ŽMM!Autolink/UrlAutolinkProcessor.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\Autolink; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Inline\Element\Link; use League\CommonMark\Inline\Element\Text; final class UrlAutolinkProcessor { // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php const REGEX = '~ (?<=^|[ \\t\\n\\x0b\\x0c\\x0d*_\\~\\(]) # Can only come at the beginning of a line, after whitespace, or certain delimiting characters ( # Must start with a supported scheme + auth, or "www" (?: (?:%s):// # protocol (?:([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth |www\.) (?: (?:[\pL\pN\pS\-\.])+(?:\.?(?:[\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name | # or \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address | # or \[ (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) \] # an IPv6 address ) (?::[0-9]+)? # a port (optional) (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path (?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional) (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional) )~ixu'; private $finalRegex; public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) { $this->finalRegex = \sprintf(self::REGEX, \implode('|', $allowedProtocols)); } /** * @param DocumentParsedEvent $e * * @return void */ public function __invoke(DocumentParsedEvent $e) { $walker = $e->getDocument()->walker(); while ($event = $walker->next()) { $node = $event->getNode(); if ($node instanceof Text && !($node->parent() instanceof Link)) { self::processAutolinks($node, $this->finalRegex); } } } private static function processAutolinks(Text $node, $regex) { $contents = \preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); if ($contents === false || \count($contents) === 1) { return; } $leftovers = ''; foreach ($contents as $i => $content) { // Even-indexed elements are things before/after the URLs if ($i % 2 === 0) { // Insert any left-over characters here as well $text = $leftovers . $content; if ($text !== '') { $node->insertBefore(new Text($leftovers . $content)); } $leftovers = ''; continue; } $leftovers = ''; // Does the URL end with punctuation that should be stripped? if (\preg_match('/(.+)([?!.,:*_~]+)$/', $content, $matches)) { // Add the punctuation later $content = $matches[1]; $leftovers = $matches[2]; } // Does the URL end with something that looks like an entity reference? if (\preg_match('/(.+)(&[A-Za-z0-9]+;)$/', $content, $matches)) { $content = $matches[1]; $leftovers = $matches[2] . $leftovers; } // Does the URL need its closing paren chopped off? if (\substr($content, -1) === ')' && self::hasMoreCloserParensThanOpeners($content)) { $content = \substr($content, 0, -1); $leftovers = ')' . $leftovers; } self::addLink($node, $content); } $node->detach(); } private static function addLink(Text $node, $url) { // Auto-prefix 'http://' onto 'www' URLs if (\substr($url, 0, 4) === 'www.') { $node->insertBefore(new Link('http://' . $url, $url)); return; } $node->insertBefore(new Link($url, $url)); } /** * @param string $content * * @return bool */ private static function hasMoreCloserParensThanOpeners($content) { // 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 the last character 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!CpŪ Ū Autolink/InlineMentionParser.phpnuÕIw¶“ * * 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\Inline\Element\Link; use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; final class InlineMentionParser implements InlineParserInterface { /** @var string */ private $linkPattern; /** @var string */ private $handleRegex; /** * @param string $linkPattern * @param string $handleRegex */ public function __construct($linkPattern, $handleRegex = '/^[A-Za-z0-9_]+(?!\w)/') { $this->linkPattern = $linkPattern; $this->handleRegex = $handleRegex; } /** * {@inheritdoc} */ public function getCharacters(): array { return ['@']; } /** * {@inheritdoc} */ public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); // The @ symbol must not have any other characters immediately prior $previousChar = $cursor->peek(-1); if ($previousChar !== null && $previousChar !== ' ') { // peek() doesn't modify the cursor, so no need to restore state first return false; } // Save the cursor state in case we need to rewind and bail $previousState = $cursor->saveState(); // Advance past the @ symbol to keep parsing simpler $cursor->advance(); // Parse the handle $handle = $cursor->match($this->handleRegex); if (empty($handle)) { // Regex failed to match; this isn't a valid Twitter handle $cursor->restoreState($previousState); return false; } $url = \sprintf($this->linkPattern, $handle); $inlineContext->getContainer()->appendChild(new Link($url, '@' . $handle)); return true; } public static function createTwitterHandleParser() { return new self('https://twitter.com/%s', '/^[A-Za-z0-9_]{1,15}(?!\w)/'); } public static function createGithubHandleParser() { // RegEx adapted from https://github.com/shinnn/github-username-regex/blob/master/index.js return new self('https://www.github.com/%s', '/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)/'); } } PK!,ķ  Table/TableExtension.phpnuÕIw¶“ * (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\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; final class TableExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment): void { $environment ->addBlockParser(new TableParser()) ->addBlockRenderer(Table::class, new TableRenderer()) ->addBlockRenderer(TableSection::class, new TableSectionRenderer()) ->addBlockRenderer(TableRow::class, new TableRowRenderer()) ->addBlockRenderer(TableCell::class, new TableCellRenderer()) ; } } PK!5—ĻĻTable/README.mdnuÕIw¶“CommonMark Table Extension ========================== The Table extension adds the ability to create tables in CommonMark documents. Usage ----- Configure your `Environment` as usual and simply add the `TableExtension` provided by this package: ```php use League\CommonMark\Converter; use League\CommonMark\DocParser; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; use League\CommonMark\Extension\Table\TableExtension; // Obtain a pre-configured Environment with all the standard CommonMark parsers/renderers ready-to-go $environment = Environment::createCommonMarkEnvironment(); // Add this extension $environment->addExtension(new TableExtension()); // Instantiate the converter engine and start converting some Markdown! $converter = new Converter(new DocParser($environment), new HtmlRenderer($environment)); echo $converter->convertToHtml('# Hello World!'); ``` Syntax ------ This package is fully compatible with GFM-style tables: ### Simple Code: ```markdown th | th(center) | th(right) ---|:----------:|----------: td | td | td ``` Result: ```html
th th(center) th(right<)/th>
td td td
``` ### Advanced ```markdown | header 1 | header 2 | header 2 | | :------- | :------: | -------: | | cell 1.1 | cell 1.2 | cell 1.3 | | cell 2.1 | cell 2.2 | cell 2.3 | ``` Credits ------- - [Martin Hasoň](https://github.com/hason) - [Webuni s.r.o.](https://www.webuni.cz) - [Colin O'Dell](https://github.com/colinodell) PK!nŁŅ5££Table/TableRowRenderer.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; final class TableRowRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableRow) { throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); return new HtmlElement('tr', $attrs, $separator . $htmlRenderer->renderBlocks($block->children()) . $separator); } } PK!Wņ(½  Table/TableCellRenderer.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; final class TableCellRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableCell) { throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } $attrs = $block->getData('attributes', []); if ($block->align) { $attrs['align'] = $block->align; } return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children())); } } PK!Ūdą"KKTable/TableCell.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; final class TableCell extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'th'; const TYPE_BODY = 'td'; const ALIGN_LEFT = 'left'; const ALIGN_RIGHT = 'right'; const ALIGN_CENTER = 'center'; public $type = self::TYPE_BODY; public $align; public function __construct(string $string = '', string $type = self::TYPE_BODY, string $align = null) { parent::__construct(); $this->finalStringContents = $string; $this->addLine($string); $this->type = $type; $this->align = $align; } public function canContain(AbstractBlock $block): bool { return false; } public function isCode(): bool { return false; } public function matchesNextLine(Cursor $cursor): bool { return false; } public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } } PK!وśūūTable/TableSectionRenderer.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; final class TableSectionRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableSection) { throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } if (!$block->hasChildren()) { return ''; } $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); return new HtmlElement($block->type, $attrs, $separator . $htmlRenderer->renderBlocks($block->children()) . $separator); } } PK!É,Zå  Table/Table.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; final class Table extends AbstractStringContainerBlock implements InlineContainerInterface { private $head; private $body; private $parser; public function __construct(\Closure $parser) { parent::__construct(); $this->appendChild($this->head = new TableSection(TableSection::TYPE_HEAD)); $this->appendChild($this->body = new TableSection(TableSection::TYPE_BODY)); $this->parser = $parser; } public function canContain(AbstractBlock $block): bool { return $block instanceof TableSection; } public function isCode(): bool { return false; } public function getHead(): TableSection { return $this->head; } public function getBody(): TableSection { return $this->body; } public function matchesNextLine(Cursor $cursor): bool { return call_user_func($this->parser, $cursor, $this); } public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } } PK!ŽHX)ĒĒTable/TableRenderer.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; final class TableRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof Table) { throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); $children = $htmlRenderer->renderBlocks($block->children()); return new HtmlElement('table', $attrs, $separator . \trim($children) . $separator); } } PK!Æ ®Table/TableSection.phpnuÕIw¶“ * (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\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; final class TableSection extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'thead'; const TYPE_BODY = 'tbody'; public $type = self::TYPE_BODY; public function __construct(string $type = self::TYPE_BODY) { parent::__construct(); $this->type = $type; } public function isHead(): bool { return self::TYPE_HEAD === $this->type; } public function isBody(): bool { return self::TYPE_BODY === $this->type; } public function canContain(AbstractBlock $block): bool { return $block instanceof TableRow; } public function isCode(): bool { return false; } public function matchesNextLine(Cursor $cursor): bool { return false; } public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } } PK!lX * (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\Block\Element\AbstractBlock; use League\CommonMark\Cursor; use League\CommonMark\Node\Node; final class TableRow extends AbstractBlock { public function canContain(AbstractBlock $block): bool { return $block instanceof TableCell; } public function isCode(): bool { return false; } public function matchesNextLine(Cursor $cursor): bool { return false; } /** * @return AbstractBlock[] */ public function children(): iterable { return array_filter((array) parent::children(), static function (Node $child): bool { return $child instanceof AbstractBlock; }); } } PK!ĆłÉßßTable/TableParser.phpnuÕIw¶“ * (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\Block\Element\Document; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Parser\BlockParserInterface; use League\CommonMark\Context; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; use League\CommonMark\EnvironmentAwareInterface; use League\CommonMark\EnvironmentInterface; final class TableParser implements BlockParserInterface, EnvironmentAwareInterface { /** * @var EnvironmentInterface */ private $environment; public function parse(ContextInterface $context, Cursor $cursor): bool { $container = $context->getContainer(); if (!$container instanceof Paragraph) { return false; } $lines = $container->getStrings(); if (count($lines) !== 1) { return false; } if (\strpos($lines[0], '|') === false) { return false; } $oldState = $cursor->saveState(); $cursor->advanceToNextNonSpaceOrTab(); $columns = $this->parseColumns($cursor); if (empty($columns)) { $cursor->restoreState($oldState); return false; } $head = $this->parseRow(trim((string) array_pop($lines)), $columns, TableCell::TYPE_HEAD); if (null === $head) { $cursor->restoreState($oldState); return false; } $table = new Table(function (Cursor $cursor, Table $table) use ($columns): bool { // The next line cannot be a new block start // This is a bit inefficient, but it's the only feasible way to check // given the current v1 API. if (self::isANewBlock($this->environment, $cursor->getLine())) { return false; } $row = $this->parseRow(\trim($cursor->getLine()), $columns); if (null === $row) { return false; } $table->getBody()->appendChild($row); return true; }); $table->getHead()->appendChild($head); if (count($lines) >= 1) { $paragraph = new Paragraph(); foreach ($lines as $line) { $paragraph->addLine($line); } $context->replaceContainerBlock($paragraph); $context->addBlock($table); } else { $context->replaceContainerBlock($table); } return true; } private function parseRow(string $line, array $columns, string $type = TableCell::TYPE_BODY): ?TableRow { $cells = $this->split(new Cursor(\trim($line))); if (empty($cells)) { return null; } // The header row must match the delimiter row in the number of cells if ($type === TableCell::TYPE_HEAD && \count($cells) !== \count($columns)) { return null; } $i = 0; $row = new TableRow(); foreach ($cells as $i => $cell) { if (!array_key_exists($i, $columns)) { return $row; } $row->appendChild(new TableCell(trim($cell), $type, $columns[$i])); } for ($j = count($columns) - 1; $j > $i; --$j) { $row->appendChild(new TableCell('', $type, null)); } return $row; } private function split(Cursor $cursor): array { if ($cursor->getCharacter() === '|') { $cursor->advanceBy(1); } $cells = []; $sb = ''; while (!$cursor->isAtEnd()) { switch ($c = $cursor->getCharacter()) { case '\\': if ($cursor->peek() === '|') { // Pipe is special for table parsing. An escaped pipe doesn't result in a new cell, but is // passed down to inline parsing as an unescaped pipe. Note that that applies even for the `\|` // in an input like `\\|` - in other words, table parsing doesn't support escaping backslashes. $sb .= '|'; $cursor->advanceBy(1); } else { // Preserve backslash before other characters or at end of line. $sb .= '\\'; } break; case '|': $cells[] = $sb; $sb = ''; break; default: $sb .= $c; } $cursor->advanceBy(1); } if ($sb !== '') { $cells[] = $sb; } return $cells; } /** * @param Cursor $cursor * * @return array */ private function parseColumns(Cursor $cursor): array { $columns = []; $pipes = 0; $valid = false; while (!$cursor->isAtEnd()) { switch ($c = $cursor->getCharacter()) { case '|': $cursor->advanceBy(1); $pipes++; if ($pipes > 1) { // More than one adjacent pipe not allowed return []; } // Need at least one pipe, even for a one-column table $valid = true; break; case '-': case ':': if ($pipes === 0 && !empty($columns)) { // Need a pipe after the first column (first column doesn't need to start with one) return []; } $left = false; $right = false; if ($c === ':') { $left = true; $cursor->advanceBy(1); } if ($cursor->match('/^-+/') === null) { // Need at least one dash return []; } if ($cursor->getCharacter() === ':') { $right = true; $cursor->advanceBy(1); } $columns[] = $this->getAlignment($left, $right); // Next, need another pipe $pipes = 0; break; case ' ': case "\t": // White space is allowed between pipes and columns $cursor->advanceToNextNonSpaceOrTab(); break; default: // Any other character is invalid return []; } } if (!$valid) { return []; } return $columns; } private static function getAlignment(bool $left, bool $right): ?string { if ($left && $right) { return TableCell::ALIGN_CENTER; } elseif ($left) { return TableCell::ALIGN_LEFT; } elseif ($right) { return TableCell::ALIGN_RIGHT; } return null; } /** * {@inheritdoc} */ public function setEnvironment(EnvironmentInterface $environment) { $this->environment = $environment; } private static function isANewBlock(EnvironmentInterface $environment, string $line): bool { $context = new Context(new Document(), $environment); $context->setNextLine($line); $cursor = new Cursor($line); /** @var BlockParserInterface $parser */ foreach ($environment->getBlockParsers() as $parser) { if ($parser->parse($context, $cursor)) { return true; } } return false; } } PK!pv³InlinesOnly/ChildRenderer.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\InlinesOnly; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\Document; use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\Inline\Element\AbstractInline; /** * Simply renders child elements as-is, adding newlines as needed. */ final class ChildRenderer implements BlockRendererInterface { /** * {@inheritdoc} */ public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { $out = ''; if ($block instanceof InlineContainerInterface) { /** @var iterable $children */ $children = $block->children(); $out .= $htmlRenderer->renderInlines($children); } else { /** @var iterable $children */ $children = $block->children(); $out .= $htmlRenderer->renderBlocks($children); } if (!($block instanceof Document)) { $out .= "\n"; } return $out; } } PK!1xóÆććInlinesOnly/README.mdnuÕIw¶“# Inline-only extension for `league/commonmark` This extension configures the [`league/commonmark` Markdown parser for PHP](https://github.com/thephpleague/commonmark) to only render inline elements - no paragraph tags, headers, code blocks, etc. ## Usage Although you normally add extra extensions to the default core one, we're not going to do that here, because this is essentially a slimmed-down version of the core extension: ```php use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; use League\CommonMark\Extension\InlinesOnly\InlinesOnlyExtension; // Create a new, empty environment $environment = new Environment(); // Add this extension $environment->addExtension(new InlinesOnlyExtension()); // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter($config, $environment); echo $converter->convertToHtml('**Hello World!**'); ``` [link-league-commonmark]: https://github.com/thephpleague/commonmark PK!ĄIē  $InlinesOnly/InlinesOnlyExtension.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\InlinesOnly; use League\CommonMark\Block\Element\Document; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Parser as BlockParser; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor; use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Inline\Element as InlineElement; use League\CommonMark\Inline\Parser as InlineParser; use League\CommonMark\Inline\Renderer as InlineRenderer; final class InlinesOnlyExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $childRenderer = new ChildRenderer(); $environment ->addBlockParser(new BlockParser\LazyParagraphParser(), -200) ->addInlineParser(new InlineParser\NewlineParser(), 200) ->addInlineParser(new InlineParser\BacktickParser(), 150) ->addInlineParser(new InlineParser\EscapableParser(), 80) ->addInlineParser(new InlineParser\EntityParser(), 70) ->addInlineParser(new InlineParser\AutolinkParser(), 50) ->addInlineParser(new InlineParser\HtmlInlineParser(), 40) ->addInlineParser(new InlineParser\CloseBracketParser(), 30) ->addInlineParser(new InlineParser\OpenBracketParser(), 20) ->addInlineParser(new InlineParser\BangParser(), 10) ->addBlockRenderer(Document::class, $childRenderer, 0) ->addBlockRenderer(Paragraph::class, $childRenderer, 0) ->addInlineRenderer(InlineElement\Code::class, new InlineRenderer\CodeRenderer(), 0) ->addInlineRenderer(InlineElement\Emphasis::class, new InlineRenderer\EmphasisRenderer(), 0) ->addInlineRenderer(InlineElement\HtmlInline::class, new InlineRenderer\HtmlInlineRenderer(), 0) ->addInlineRenderer(InlineElement\Image::class, new InlineRenderer\ImageRenderer(), 0) ->addInlineRenderer(InlineElement\Link::class, new InlineRenderer\LinkRenderer(), 0) ->addInlineRenderer(InlineElement\Newline::class, new InlineRenderer\NewlineRenderer(), 0) ->addInlineRenderer(InlineElement\Strong::class, new InlineRenderer\StrongRenderer(), 0) ->addInlineRenderer(InlineElement\Text::class, new InlineRenderer\TextRenderer(), 0) ; if ($environment->getConfig('use_asterisk', true)) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*')); } if ($environment->getConfig('use_underscore', true)) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_')); } } } PK!B÷NNCommonMarkCoreExtension.phpnuÕIw¶“ * * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension; use League\CommonMark\Block\Element as BlockElement; use League\CommonMark\Block\Parser as BlockParser; use League\CommonMark\Block\Renderer as BlockRenderer; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor; use League\CommonMark\Inline\Element as InlineElement; use League\CommonMark\Inline\Parser as InlineParser; use League\CommonMark\Inline\Renderer as InlineRenderer; final class CommonMarkCoreExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment ->addBlockParser(new BlockParser\BlockQuoteParser(), 70) ->addBlockParser(new BlockParser\ATXHeadingParser(), 60) ->addBlockParser(new BlockParser\FencedCodeParser(), 50) ->addBlockParser(new BlockParser\HtmlBlockParser(), 40) ->addBlockParser(new BlockParser\SetExtHeadingParser(), 30) ->addBlockParser(new BlockParser\ThematicBreakParser(), 20) ->addBlockParser(new BlockParser\ListParser(), 10) ->addBlockParser(new BlockParser\IndentedCodeParser(), -100) ->addBlockParser(new BlockParser\LazyParagraphParser(), -200) ->addInlineParser(new InlineParser\NewlineParser(), 200) ->addInlineParser(new InlineParser\BacktickParser(), 150) ->addInlineParser(new InlineParser\EscapableParser(), 80) ->addInlineParser(new InlineParser\EntityParser(), 70) ->addInlineParser(new InlineParser\AutolinkParser(), 50) ->addInlineParser(new InlineParser\HtmlInlineParser(), 40) ->addInlineParser(new InlineParser\CloseBracketParser(), 30) ->addInlineParser(new InlineParser\OpenBracketParser(), 20) ->addInlineParser(new InlineParser\BangParser(), 10) ->addBlockRenderer(BlockElement\BlockQuote::class, new BlockRenderer\BlockQuoteRenderer(), 0) ->addBlockRenderer(BlockElement\Document::class, new BlockRenderer\DocumentRenderer(), 0) ->addBlockRenderer(BlockElement\FencedCode::class, new BlockRenderer\FencedCodeRenderer(), 0) ->addBlockRenderer(BlockElement\Heading::class, new BlockRenderer\HeadingRenderer(), 0) ->addBlockRenderer(BlockElement\HtmlBlock::class, new BlockRenderer\HtmlBlockRenderer(), 0) ->addBlockRenderer(BlockElement\IndentedCode::class, new BlockRenderer\IndentedCodeRenderer(), 0) ->addBlockRenderer(BlockElement\ListBlock::class, new BlockRenderer\ListBlockRenderer(), 0) ->addBlockRenderer(BlockElement\ListItem::class, new BlockRenderer\ListItemRenderer(), 0) ->addBlockRenderer(BlockElement\Paragraph::class, new BlockRenderer\ParagraphRenderer(), 0) ->addBlockRenderer(BlockElement\ThematicBreak::class, new BlockRenderer\ThematicBreakRenderer(), 0) ->addInlineRenderer(InlineElement\Code::class, new InlineRenderer\CodeRenderer(), 0) ->addInlineRenderer(InlineElement\Emphasis::class, new InlineRenderer\EmphasisRenderer(), 0) ->addInlineRenderer(InlineElement\HtmlInline::class, new InlineRenderer\HtmlInlineRenderer(), 0) ->addInlineRenderer(InlineElement\Image::class, new InlineRenderer\ImageRenderer(), 0) ->addInlineRenderer(InlineElement\Link::class, new InlineRenderer\LinkRenderer(), 0) ->addInlineRenderer(InlineElement\Newline::class, new InlineRenderer\NewlineRenderer(), 0) ->addInlineRenderer(InlineElement\Strong::class, new InlineRenderer\StrongRenderer(), 0) ->addInlineRenderer(InlineElement\Text::class, new InlineRenderer\TextRenderer(), 0) ; if ($environment->getConfig('use_asterisk', true)) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*')); } if ($environment->getConfig('use_underscore', true)) { $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_')); } } } PK!§?“Ē Ē ExternalLink/README.mdnuÕIw¶“# Extension to denote external links for `league/commonmark` This extension to the [`league/commonmark` PHP Markdown parser][link-league-commonmark] can detect links to external sites and adjust the markup accordingly: - Adds a `rel="noopener noreferrer"` attribute - Optionally adds any custom HTML classes ## Usage Configure your `Environment` as usual and simply add the `ExternalLinkExtension` provided by this package: ```php use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; use League\CommonMark\Extension\ExternalLink\ExternalLinkExtension; // Obtain a pre-configured Environment with all the CommonMark parsers/renderers ready-to-go $environment = Environment::createCommonMarkEnvironment(); // Add this extension $environment->addExtension(new ExternalLinkExtension()); // Set your configuration $config = [ 'external_link' => [ 'internal_hosts' => 'www.example.com', 'open_in_new_window' => true, 'html_class' => 'external-link', ], ]; // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter($config, $environment); echo $converter->convertToHtml('I successfully installed the https://github.com/thephpleague/commonmark project with the Autolink extension!'); ``` ## Configuration This extension supports three configuration options under the `external_link` configuration: ### `internal_hosts` This option defines a whitelist of hosts which are considered non-external and should not receive the external link treatment. This can be a single host name, like `'example.com'`, which must match exactly. If you need to match subdomains, use a regular expression like `'/(^|\.)example\.com$/'`. Note that you must use `/` characters to delimit your regex. This configuration option also accepts an array of multiple strings and/or regexes: ```php $config = [ 'external_link' => [ 'internal_hosts' => ['foo.example.com', 'bar.example.com', '/(^|\.)google\.com$/], ], ]; ``` By default, if this option is not provided, all links will be considered external. ### `open_in_new_window` This option (which defaults to `false`) determines whether any external links should open in a new tab/window. ### `html_class` This option allows you to provide a `string` containing one or more HTML classes that should be added to the external link `` tags: No classes are added by default. ## Advanced Rendering When an external link is detected, the `ExternalLinkProcessor` will set the `external` data option on the `Link` node to either `true` or `false`. You can therefore create a [custom link renderer](https://commonmark.thephpleague.com/customization/inline-rendering/) which checks this value and behaves accordingly: ```php class MyCustomLinkRenderer implements InlineRendererInterface { /** * @param Link $inline * @param ElementRendererInterface $htmlRenderer * * @return HtmlElement */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { if (!($inline instanceof Link)) { throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline)); } if ($inline->getData('external')) { // This is an external link - render it accordingly } else { // This is an internal link } // ... } } ``` [link-league-commonmark]: https://github.com/thephpleague/commonmark PK!7ēš”ŅŅ&ExternalLink/ExternalLinkExtension.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\ExternalLink; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Extension\ExtensionInterface; final class ExternalLinkExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment)); } } PK![{\eU U &ExternalLink/ExternalLinkProcessor.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\ExternalLink; use League\CommonMark\EnvironmentInterface; use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Inline\Element\Link; final class ExternalLinkProcessor { /** @var EnvironmentInterface */ private $environment; /** * @param EnvironmentInterface $environment */ public function __construct(EnvironmentInterface $environment) { $this->environment = $environment; } /** * @param DocumentParsedEvent $e */ public function __invoke(DocumentParsedEvent $e) { $internalHosts = $this->environment->getConfig('external_link/internal_hosts', []); $openInNewWindow = $this->environment->getConfig('external_link/open_in_new_window', false); $classes = $this->environment->getConfig('external_link/html_class', ''); $walker = $e->getDocument()->walker(); while ($event = $walker->next()) { if ($event->isEntering() && $event->getNode() instanceof Link) { /** @var Link $link */ $link = $event->getNode(); $host = parse_url($link->getUrl(), PHP_URL_HOST); if (empty($host)) { // Something is terribly wrong with this URL continue; } if (self::hostMatches($host, $internalHosts)) { $link->data['external'] = false; continue; } // Host does not match our list $this->markLinkAsExternal($link, $openInNewWindow, $classes); } } } /** * @param Link $link * @param bool $openInNewWindow * @param string $classes */ private function markLinkAsExternal(Link $link, bool $openInNewWindow, string $classes): void { $link->data['external'] = true; $link->data['attributes'] = $link->getData('attributes', []); $link->data['attributes']['rel'] = 'noopener noreferrer'; if ($openInNewWindow) { $link->data['attributes']['target'] = '_blank'; } if (!empty($classes)) { $link->data['attributes']['class'] = trim(($link->data['attributes']['class'] ?? '') . ' ' . $classes); } } /** * @param string $host * @param mixed $compareTo * * @return bool * * @internal This method is only public so we can easily test it. DO NOT USE THIS OUTSIDE OF THIS EXTENSION! */ public static function hostMatches(string $host, $compareTo) { foreach ((array) $compareTo as $c) { if (strpos($c, '/') === 0) { if (preg_match($c, $host)) { return true; } } elseif ($c === $host) { return true; } } return false; } } PK!w¹—ˆ†5DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.phpnuÕIw¶“ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DisallowedRawHtml; use League\CommonMark\ElementRendererInterface; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Inline\Renderer\InlineRendererInterface; use League\CommonMark\Util\ConfigurationAwareInterface; use League\CommonMark\Util\ConfigurationInterface; final class DisallowedRawHtmlInlineRenderer implements InlineRendererInterface, ConfigurationAwareInterface { private $htmlInlineRenderer; public function __construct(InlineRendererInterface $htmlBlockRenderer) { $this->htmlInlineRenderer = $htmlBlockRenderer; } /** * {@inheritdoc} */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { $rendered = $this->htmlInlineRenderer->render($inline, $htmlRenderer); if ($rendered === '') { return ''; } // Match these types of tags: <title/> <title /> return preg_replace('/<(\/?(?:title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext)[ \/>])/i', '<$1', $rendered); } /** * {@inheritdoc} */ public function setConfiguration(ConfigurationInterface $configuration) { if ($this->htmlInlineRenderer instanceof ConfigurationAwareInterface) { $this->htmlInlineRenderer->setConfiguration($configuration); } } } PK�������!�”9X„ �� ��0��DisallowedRawHtml/DisallowedRawHtmlExtension.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DisallowedRawHtml; use League\CommonMark\Block\Element\HtmlBlock; use League\CommonMark\Block\Renderer\HtmlBlockRenderer; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Inline\Element\HtmlInline; use League\CommonMark\Inline\Renderer\HtmlInlineRenderer; final class DisallowedRawHtmlExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment->addBlockRenderer(HtmlBlock::class, new DisallowedRawHtmlBlockRenderer(new HtmlBlockRenderer()), 50); $environment->addInlineRenderer(HtmlInline::class, new DisallowedRawHtmlInlineRenderer(new HtmlInlineRenderer()), 50); } } PK�������!�ķ„Ś �� ��4��DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\DisallowedRawHtml; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\Util\ConfigurationAwareInterface; use League\CommonMark\Util\ConfigurationInterface; final class DisallowedRawHtmlBlockRenderer implements BlockRendererInterface, ConfigurationAwareInterface { private $htmlBlockRenderer; public function __construct(BlockRendererInterface $htmlBlockRenderer) { $this->htmlBlockRenderer = $htmlBlockRenderer; } /** * {@inheritdoc} */ public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { $rendered = $this->htmlBlockRenderer->render($block, $htmlRenderer, $inTightList); if ($rendered === '') { return ''; } // Match these types of tags: <title> <title/> <title /> return preg_replace('/<(\/?(?:title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext)[ \/>])/i', '<$1', $rendered); } /** * {@inheritdoc} */ public function setConfiguration(ConfigurationInterface $configuration) { if ($this->htmlBlockRenderer instanceof ConfigurationAwareInterface) { $this->htmlBlockRenderer->setConfiguration($configuration); } } } PK�������!� †ßX��X����TaskList/README.mdnu�ÕIw¶“��������# GFM-style task list extension for `league/commonmark` This extension adds [GFM-style task list items][link-gfm-spec-task-lists] to the [`league/commonmark` Markdown parser for PHP][link-league-commonmark]. ## Usage Configure your `Environment` as usual and simply add the `TaskListExtension` provided by this package: ```php use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; use League\CommonMark\Extension\TaskList\TaskListExtension; // Obtain a pre-configured Environment with all the CommonMark parsers/renderers ready-to-go $environment = Environment::createCommonMarkEnvironment(); // Add this extension $environment->addExtension(new TaskListExtension()); // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter([], $environment); $markdown = <<<EOT - [x] Install this extension - [ ] ??? - [ ] Profit! EOT; echo $converter->convertToHtml($markdown); ``` [link-league-commonmark]: https://github.com/thephpleague/commonmark [link-gfm-spec-task-lists]: https://github.github.com/gfm/#task-list-items-extension- PK�������!�@ĢŁ£ė��ė����TaskList/TaskListItemMarker.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\TaskList; use League\CommonMark\Inline\Element\AbstractInline; final class TaskListItemMarker extends AbstractInline { protected $checked = false; public function __construct(bool $isCompleted) { $this->checked = $isCompleted; } public function isChecked(): bool { return $this->checked; } public function setChecked(bool $checked): self { $this->checked = $checked; return $this; } } PK�������!�ņy‚����'��TaskList/TaskListItemMarkerRenderer.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\TaskList; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Inline\Renderer\InlineRendererInterface; final class TaskListItemMarkerRenderer implements InlineRendererInterface { /** * @param AbstractInline $inline * @param ElementRendererInterface $htmlRenderer * * @return HtmlElement|string|null */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { if (!($inline instanceof TaskListItemMarker)) { throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline)); } $checkbox = new HtmlElement('input', [], '', true); if ($inline->isChecked()) { $checkbox->setAttribute('checked', ''); } $checkbox->setAttribute('disabled', ''); $checkbox->setAttribute('type', 'checkbox'); return $checkbox; } } PK�������!�QdfČq��q��%��TaskList/TaskListItemMarkerParser.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\TaskList; use League\CommonMark\Block\Element\ListItem; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; final class TaskListItemMarkerParser implements InlineParserInterface { /** * @return string[] */ public function getCharacters(): array { return ['[']; } /** * @param InlineParserContext $inlineContext * * @return bool */ public function parse(InlineParserContext $inlineContext): bool { $container = $inlineContext->getContainer(); // Checkbox must come at the beginning of the first paragraph of the list item if ($container->hasChildren() || !($container instanceof Paragraph && $container->parent() && $container->parent() instanceof ListItem)) { return false; } $cursor = $inlineContext->getCursor(); $oldState = $cursor->saveState(); $m = $cursor->match('/\[[ xX]\]/'); if ($m === null) { return false; } if ($cursor->getNextNonSpaceCharacter() === null) { $cursor->restoreState($oldState); return false; } $isChecked = $m !== '[ ]'; $container->appendChild(new TaskListItemMarker($isChecked)); return true; } } PK�������!�µŽ¶dŻ��Ż����TaskList/TaskListExtension.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension\TaskList; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; final class TaskListExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { $environment->addInlineParser(new TaskListItemMarkerParser(), 35); $environment->addInlineRenderer(TaskListItemMarker::class, new TaskListItemMarkerRenderer()); } } PK�������!�ÆLGĢA��A����ExtensionInterface.phpnu�ÕIw¶“��������<?php /* * This file is part of the league/commonmark package. * * (c) Colin O'Dell <colinodell@gmail.com> * * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js) * - (c) John MacFarlane * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace League\CommonMark\Extension; use League\CommonMark\ConfigurableEnvironmentInterface; interface ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment); } PK���������!�żŒ‘ �� ��(����������������Strikethrough/StrikethroughExtension.phpnu�ÕIw¶“��������PK���������!�ÄØČ>����������������c��Strikethrough/README.mdnu�ÕIw¶“��������PK���������!�쨖Y)��)��������������É��Strikethrough/Strikethrough.phpnu�ÕIw¶“��������PK���������!�†‘ŸŸ����'������������A ��Strikethrough/StrikethroughRenderer.phpnu�ÕIw¶“��������PK���������!�U»,§����1������������¦��Strikethrough/StrikethroughDelimiterProcessor.phpnu�ÕIw¶“��������PK���������!�že°Ā{��{��#������������ˆ��GithubFlavoredMarkdownExtension.phpnu�ÕIw¶“��������PK���������!�ļ́/b��b��������������V��SmartPunct/README.mdnu�ÕIw¶“��������PK���������!�š¼’.$��$��������������ü ��SmartPunct/QuoteRenderer.phpnu�ÕIw¶“��������PK���������!� ›Äžō��ō�� ������������l'��SmartPunct/PunctuationParser.phpnu�ÕIw¶“��������PK���������!�Ņj#ݳ ��³ ��������������°0��SmartPunct/QuoteParser.phpnu�ÕIw¶“��������PK���������!�®~ž����������������­>��SmartPunct/Quote.phpnu�ÕIw¶“��������PK���������!�@Žļ��ļ��"������������ B��SmartPunct/SmartPunctExtension.phpnu�ÕIw¶“��������PK���������!�ɹV �� ��������������NJ��SmartPunct/QuoteProcessor.phpnu�ÕIw¶“��������PK���������!�Ķh–„����������������¤U��Autolink/AutolinkExtension.phpnu�ÕIw¶“��������PK���������!�›#nµ��µ��#������������Y��Autolink/EmailAutolinkProcessor.phpnu�ÕIw¶“��������PK���������!�¼EéŠ �� ��������������b��Autolink/README.mdnu�ÕIw¶“��������PK���������!�p ŽM��M��!������������km��Autolink/UrlAutolinkProcessor.phpnu�ÕIw¶“��������PK���������!�CpŪ ��Ū �� ������������ ‰��Autolink/InlineMentionParser.phpnu�ÕIw¶“��������PK���������!�,�ķ �� ��������������4“��Table/TableExtension.phpnu�ÕIw¶“��������PK���������!�5—Ļ��Ļ��������������…—��Table/README.mdnu�ÕIw¶“��������PK���������!�nŁŅ5£��£��������������“ž��Table/TableRowRenderer.phpnu�ÕIw¶“��������PK���������!�Wņ(½ �� ��������������€£��Table/TableCellRenderer.phpnu�ÕIw¶“��������PK���������!�Ūdą"K��K��������������kØ��Table/TableCell.phpnu�ÕIw¶“��������PK���������!�وśū��ū��������������ł®��Table/TableSectionRenderer.phpnu�ÕIw¶“��������PK���������!�É,Zå �� ��������������B“��Table/Table.phpnu�ÕIw¶“��������PK���������!�ŽHX)Ē��Ē��������������!»��Table/TableRenderer.phpnu�ÕIw¶“��������PK���������!�Æ ®����������������/Ą��Table/TableSection.phpnu�ÕIw¶“��������PK���������!�lX<EH��H��������������ŽĘ��Table/TableRow.phpnu�ÕIw¶“��������PK���������!�ĆłÉß��ß��������������Ė��Table/TableParser.phpnu�ÕIw¶“��������PK���������!�pv��³��������������<ė��InlinesOnly/ChildRenderer.phpnu�ÕIw¶“��������PK���������!�1xóÆć��ć��������������<ń��InlinesOnly/README.mdnu�ÕIw¶“��������PK���������!�ĄIē �� ��$������������dõ��InlinesOnly/InlinesOnlyExtension.phpnu�ÕIw¶“��������PK���������!�B÷N��N��������������½�CommonMarkCoreExtension.phpnu�ÕIw¶“��������PK���������!�§?“Ē ��Ē ��������������V�ExternalLink/README.mdnu�ÕIw¶“��������PK���������!�7ēš”Ņ��Ņ��&������������c"�ExternalLink/ExternalLinkExtension.phpnu�ÕIw¶“��������PK���������!�[{\eU ��U ��&������������‹%�ExternalLink/ExternalLinkProcessor.phpnu�ÕIw¶“��������PK���������!�w¹—ˆ��†��5������������62�DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.phpnu�ÕIw¶“��������PK���������!�”9X„ �� ��0������������!9�DisallowedRawHtml/DisallowedRawHtmlExtension.phpnu�ÕIw¶“��������PK���������!�ķ„Ś �� ��4������������‹=�DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.phpnu�ÕIw¶“��������PK���������!� †ßX��X��������������D�TaskList/README.mdnu�ÕIw¶“��������PK���������!�@ĢŁ£ė��ė��������������)I�TaskList/TaskListItemMarker.phpnu�ÕIw¶“��������PK���������!�ņy‚����'������������cL�TaskList/TaskListItemMarkerRenderer.phpnu�ÕIw¶“��������PK���������!�QdfČq��q��%������������ÉQ�TaskList/TaskListItemMarkerParser.phpnu�ÕIw¶“��������PK���������!�µŽ¶dŻ��Ż��������������X�TaskList/TaskListExtension.phpnu�ÕIw¶“��������PK���������!�ÆLGĢA��A��������������ŗ[�ExtensionInterface.phpnu�ÕIw¶“��������PK����-�-�w��A^���