diff options
| author | Greg Roach <fisharebest@webtrees.net> | 2020-02-11 12:06:32 +0000 |
|---|---|---|
| committer | Greg Roach <fisharebest@webtrees.net> | 2020-02-11 12:06:32 +0000 |
| commit | 600daa5d4fa729dbec2d21fb3adffed0ae6efda9 (patch) | |
| tree | 3285f1b2135725eb53b98dd713ed67236397ff71 /vendor/league | |
| parent | 1b47c2feedb65f946198e7c18aeb4286b98ceeb5 (diff) | |
| download | webtrees-600daa5d4fa729dbec2d21fb3adffed0ae6efda9.tar.gz webtrees-600daa5d4fa729dbec2d21fb3adffed0ae6efda9.tar.bz2 webtrees-600daa5d4fa729dbec2d21fb3adffed0ae6efda9.zip | |
Update vendor code - Update markdown handler to use new CommonMark library
Diffstat (limited to 'vendor/league')
84 files changed, 2502 insertions, 817 deletions
diff --git a/vendor/league/commonmark-ext-table/CHANGELOG.md b/vendor/league/commonmark-ext-table/CHANGELOG.md deleted file mode 100644 index 0616de81eb..0000000000 --- a/vendor/league/commonmark-ext-table/CHANGELOG.md +++ /dev/null @@ -1,138 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased][unreleased] - -## [2.1.0] - 2019-09-26 - -### Fixed - - - Fixed attributes being double-escaped (#31) - -## [2.0.0] - 2019-07-13 - -### Changed - - - Changed the namespace to `League\CommonMark\Ext\Table` - - Renamed `TableRows` to `TableSection` - - Made the parser and renderers `final` - -### Removed - - - Removed the unused `TableRow::handleRemainingContents()` function - -## [1.0.0] - 2019-07-09 -### Changed - - - Increased minimum PHP version to 7.1 - - Updated to the commonmark 0.19 and 1.0 - -### Removed - - - Removed support for commonmark 0.16, 0.17 and 0.18 - -## [0.9.0] - 2018-11-28 -### Changed - - - Allowed the commonmark 0.18 - -## [0.8.0] - 2018-01-24 -### Changed - - - Replaced align attribute with text-align style - -## [0.7.1] - 2018-01-23 -### Fixed - - - Fixed undefined method in commonmark 0.17 - -## [0.7.0] - 2018-01-09 -### Changed - - - Increased minimum PHP version to 5.6 - - Updated to the commonmark 0.16 and 0.17 API - -### Fixed - - - Fixed a problem with parsing whitespaces at the end of line - -### Removed - - - Removed support for commonmark 0.14 and 0.15 API - -## [0.6.1] - 2017-01-11 -### Fixed - - - Fixed parsing of one column tables - -## [0.6.0] - 2016-09-26 -### Changed - - Updated to the commonmark 0.15 API - - Moved twig template to [webuni/commonmark-twig-renderer](https://packagist.org/packages/webuni/commonmark-twig-renderer) - -## [0.5.0] - 2016-07-13 -### Added - - - Added support for table caption (MultiMarkdown) - - Added a template for twig renderer - -### Changed - - - Updated to the commonmark 0.14 API - -## [0.4.3] - 2016-01-14 -### Added - - - Added support for commonmark 0.13 API - -## [0.4.2] - 2015-11-05 -### Added - - - Added support for commonmark 0.12 API - -## [0.4.1] - 2015-09-22 -### Added - - - Added missing tests - -## [0.4.0] - 2015-09-21 -### Changed - - - Updated to the new commonmark 0.11 API - -## [0.3.0] - 2015-07-27 -### Added - - - Added support for custom attributes in renderers - -## [0.2.0] - 2015-07-27 -### Changed - - - Updated to the new commonmark 0.10 API - -## [0.1.0] - 2015-06-24 -### Added - - Implemented GFM tables - -[unreleased]: https://github.com/thephpleague/commonmark-ext-table/compare/v2.1.0...HEAD -[2.1.0]: https://github.com/thephpleague/commonmark-ext-table/compare/v2.0.0...v2.1.0 -[2.0.0]: https://github.com/thephpleague/commonmark-ext-table/compare/1.0.0...v2.0.0 -[1.0.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.9.0...1.0.0 -[0.9.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.8.0...0.9.0 -[0.8.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.7.1...0.8.0 -[0.7.1]: https://github.com/thephpleague/commonmark-ext-table/compare/0.7.0...0.7.1 -[0.7.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.6.1...0.7.0 -[0.6.1]: https://github.com/thephpleague/commonmark-ext-table/compare/0.6.0...0.6.1 -[0.6.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.5.0...0.6.0 -[0.5.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.4.3...0.5.0 -[0.4.3]: https://github.com/thephpleague/commonmark-ext-table/compare/0.4.2...0.4.3 -[0.4.2]: https://github.com/thephpleague/commonmark-ext-table/compare/0.4.1...0.4.2 -[0.4.1]: https://github.com/thephpleague/commonmark-ext-table/compare/0.4.0...0.4.1 -[0.4.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.3.0...0.4.0 -[0.3.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.2.0...0.3.0 -[0.2.0]: https://github.com/thephpleague/commonmark-ext-table/compare/0.1.0...0.2.0 -[0.1.0]: https://github.com/thephpleague/commonmark-ext-table/commits/0.1.0 diff --git a/vendor/league/commonmark-ext-table/LICENSE b/vendor/league/commonmark-ext-table/LICENSE deleted file mode 100644 index 522628ac93..0000000000 --- a/vendor/league/commonmark-ext-table/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) Martin Hasoň <martin.hason@gmail.com>, Colin O'Dell <colinodell@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/league/commonmark-ext-table/README.md b/vendor/league/commonmark-ext-table/README.md deleted file mode 100644 index 4612bc3cd6..0000000000 --- a/vendor/league/commonmark-ext-table/README.md +++ /dev/null @@ -1,152 +0,0 @@ -CommonMark Table Extension -========================== - -[](https://packagist.org/packages/league/commonmark-ext-table) -[](https://travis-ci.org/thephpleague/commonmark-ext-table) -[](https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-table/code-structure) -[](https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-table) - -The Table extension adds the ability to create tables in CommonMark documents. - -Installation ------------- - -This project can be installed via Composer: - - composer require league/commonmark-ext-table - -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\Ext\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 -<table> -<thead> -<tr> -<th style="text-align: left">th</th> -<th style="text-align: center">th(center)</th> -<th style="text-align: right">th(right<)/th> -</tr> -</thead> -<tbody> -<tr> -<td style="text-align: left">td</td> -<td style="text-align: center">td</td> -<td style="text-align: right">td</td> -</tr> -</tbody> -</table> -``` - -### 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 | -``` - -### Table caption - -```markdown -header 1 | header 2 --------- | -------- -cell 1.1 | cell 1.2 -[Simple table] -``` - -Code: -```markdown -header 1 | header 2 --------- | -------- -cell 1.1 | cell 1.2 -[*Prototype* table][reference_table] -``` - -Result: -```html -<table> -<caption id="reference_table"><em>Prototype</em> table</caption> -<thead> -<tr> -<th>header 1</th> -<th>header 2</th> -</tr> -</thead> -<tbody> -<tr> -<td>cell 1.1</td> -<td>cell 1.2</td> -</tr> -</tbody> -</table> -<table> -``` - -Changelog ---------- - -Please refer to the [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. - -Development ------------ - -You need to have *php* or *docker* installed to develop the library. To list all available commands run: - -```bash -./run -``` - -Security --------- - -If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. - -Credits -------- - -- [Martin Hasoň](https://github.com/hason) -- [Webuni s.r.o.](https://www.webuni.cz) -- [Colin O'Dell](https://github.com/colinodell) -- [All Contributors](../../contributors) - -License -------- - -This library is licensed under the MIT license. See the [License File](LICENSE) for more information. diff --git a/vendor/league/commonmark-ext-table/composer.json b/vendor/league/commonmark-ext-table/composer.json deleted file mode 100644 index 9689c501b1..0000000000 --- a/vendor/league/commonmark-ext-table/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "league/commonmark-ext-table", - "type": "commonmark-extension", - "description": "Table extension for league/commonmark", - "keywords": ["markdown", "commonmark", "extension", "table"], - "homepage": "https://github.com/thephpleague/commonmark-ext-table", - "license": "MIT", - "authors": [ - { - "name": "Martin Hasoň", - "email": "martin.hason@gmail.com" - }, - { - "name": "Webuni s.r.o.", - "homepage": "https://www.webuni.cz" - }, - { - "name": "Colin O'Dell", - "email": "colinodell@gmail.com", - "homepage": "https://www.colinodell.com" - } - ], - "require": { - "php": "^7.1", - "league/commonmark": "~0.19.3|^1.0" - }, - "require-dev": { - "phpstan/phpstan": "~0.11", - "phpunit/phpunit": "^7.0|^8.0", - "vimeo/psalm": "^3.0", - "friendsofphp/php-cs-fixer": "^2.14", - "symfony/var-dumper": "^4.0" - }, - "autoload": { - "psr-4": { - "League\\CommonMark\\Ext\\Table\\": "src" - } - }, - "scripts": { - "test": ["@phpunit", "@phpstan", "@psalm"], - "phpstan": "phpstan analyse -l7 src", - "phpunit": "phpunit", - "psalm": "psalm", - "cs-fix": "php-cs-fixer fix --allow-risky=yes" - }, - "config": { - "preferred-install": "dist" - }, - "extra": { - "branch-alias": { - "dev-master": "2.2-dev" - } - } -} diff --git a/vendor/league/commonmark-ext-table/run b/vendor/league/commonmark-ext-table/run deleted file mode 100755 index b7d570457d..0000000000 --- a/vendor/league/commonmark-ext-table/run +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env sh -set -e - -url="https://raw.githubusercontent.com/webuni/shell-task-runner/master/runner" -[ -f ./.runner ] || wget -q "$url" -O- > .runner || curl -fso .runner "$url" -. ./.runner - -! mkdir -p $HOME/.composer/cache -if [ ! -f $HOME/.composer/auth.json ]; then echo "{}" > $HOME/.composer/auth.json; fi - -_decorator()( - if [ -n "$(command -v docker)" ]; then - _docker_run -v "$HOME/.composer/cache:/composer-cache" -v "$HOME/.composer/auth.json:/composer/auth.json" webuni/php:7.3 ./run "$@" - else - "$@" - fi -) - -# Install dependencies -task_deps()( - composer install -) - -# Static analyse -task_analyse()( - ./vendor/bin/phpstan analyse -l7 src "$@" - ./vendor/bin/psalm -) - -# Run composer -task_composer()( - composer "$@" -) - -# Fix code style -task_cs_fix()( - ./vendor/bin/php-cs-fixer fix --allow-risky=yes "$@" -) - -# Run tests -task_tests()( - ./vendor/bin/phpunit "$@" -) diff --git a/vendor/league/commonmark-ext-table/src/TableCaption.php b/vendor/league/commonmark-ext-table/src/TableCaption.php deleted file mode 100644 index b488eb8b3c..0000000000 --- a/vendor/league/commonmark-ext-table/src/TableCaption.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This is part of the league/commonmark-ext-table package. - * - * (c) Martin Hasoň <martin.hason@gmail.com> - * (c) Webuni s.r.o. <info@webuni.cz> - * (c) Colin O'Dell <colinodell@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace League\CommonMark\Ext\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; - -class TableCaption extends AbstractStringContainerBlock implements InlineContainerInterface -{ - public $id; - - public function __construct(string $caption, string $id = null) - { - parent::__construct(); - $this->finalStringContents = $caption; - $this->id = $id; - } - - 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 - { - } -} diff --git a/vendor/league/commonmark-ext-table/src/TableCaptionRenderer.php b/vendor/league/commonmark-ext-table/src/TableCaptionRenderer.php deleted file mode 100644 index a02a0bbd75..0000000000 --- a/vendor/league/commonmark-ext-table/src/TableCaptionRenderer.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This is part of the league/commonmark-ext-table package. - * - * (c) Martin Hasoň <martin.hason@gmail.com> - * (c) Webuni s.r.o. <info@webuni.cz> - * (c) Colin O'Dell <colinodell@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace League\CommonMark\Ext\Table; - -use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\Block\Renderer\BlockRendererInterface; -use League\CommonMark\ElementRendererInterface; -use League\CommonMark\HtmlElement; - -final class TableCaptionRenderer implements BlockRendererInterface -{ - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) - { - if (!$block instanceof TableCaption) { - throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); - } - - $attrs = $block->getData('attributes', []); - - if ($block->id) { - $attrs['id'] = $block->id; - } - - return new HtmlElement('caption', $attrs, $htmlRenderer->renderInlines($block->children())); - } -} diff --git a/vendor/league/commonmark-ext-table/src/TableParser.php b/vendor/league/commonmark-ext-table/src/TableParser.php deleted file mode 100644 index 63d173f332..0000000000 --- a/vendor/league/commonmark-ext-table/src/TableParser.php +++ /dev/null @@ -1,147 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This is part of the league/commonmark-ext-table package. - * - * (c) Martin Hasoň <martin.hason@gmail.com> - * (c) Webuni s.r.o. <info@webuni.cz> - * (c) Colin O'Dell <colinodell@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace League\CommonMark\Ext\Table; - -use League\CommonMark\Block\Element\Paragraph; -use League\CommonMark\Block\Parser\BlockParserInterface; -use League\CommonMark\ContextInterface; -use League\CommonMark\Cursor; -use League\CommonMark\Util\RegexHelper; - -final class TableParser implements BlockParserInterface -{ - const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; - const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\||\\\\|[^|`\\\\]+)+(?=\||$)/'; - const REGEXP_CAPTION = '/^\[(.+?)\](?:\[(.+)\])?\s*$/'; - - 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; - } - - $expressionOffset = $cursor->getNextNonSpacePosition(); - - $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $expressionOffset); - if (null === $match) { - return false; - } - - $columns = $this->parseColumns($match); - $head = $this->parseRow(trim((string) array_pop($lines)), $columns, TableCell::TYPE_HEAD); - if (null === $head) { - return false; - } - - $table = new Table(function (Cursor $cursor, Table $table) use ($columns): bool { - $row = $this->parseRow($cursor->getLine(), $columns); - if (null === $row) { - if (null !== $table->getCaption()) { - return false; - } - - if (null !== ($caption = $this->parseCaption($cursor->getLine()))) { - $table->setCaption($caption); - - return true; - } - - 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 parseColumns(array $match): array - { - $columns = []; - foreach ((array) $match[0] as $i => $column) { - if (isset($match[1][$i]) && $match[1][$i] && isset($match[2][$i]) && $match[2][$i]) { - $columns[] = TableCell::ALIGN_CENTER; - } elseif (isset($match[1][$i]) && $match[1][$i]) { - $columns[] = TableCell::ALIGN_LEFT; - } elseif (isset($match[2][$i]) && $match[2][$i]) { - $columns[] = TableCell::ALIGN_RIGHT; - } else { - $columns[] = ''; - } - } - - return $columns; - } - - private function parseRow(string $line, array $columns, string $type = TableCell::TYPE_BODY): ?TableRow - { - $cells = RegexHelper::matchAll(self::REGEXP_CELLS, $line); - - if (null === $cells || $line === $cells[0]) { - return null; - } - - $i = 0; - $row = new TableRow(); - foreach ((array) $cells[0] as $i => $cell) { - if (!isset($columns[$i])) { - return $row; - } - - $row->appendChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); - } - - for ($j = count($columns) - 1; $j > $i; --$j) { - $row->appendChild(new TableCell('', $type, null)); - } - - return $row; - } - - private function parseCaption(string $line): ?TableCaption - { - $caption = RegexHelper::matchAll(self::REGEXP_CAPTION, $line); - - if (null === $caption) { - return null; - } - - return new TableCaption($caption[1], $caption[2]); - } -} diff --git a/vendor/league/commonmark/.editorconfig b/vendor/league/commonmark/.editorconfig new file mode 100644 index 0000000000..6923a8d414 --- /dev/null +++ b/vendor/league/commonmark/.editorconfig @@ -0,0 +1,14 @@ +; top-most EditorConfig file +root = true + +# All files. +[*] +end_of_line = LF +indent_style = space +indent_size = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[.travis.yml] +indent_size = 2 diff --git a/vendor/league/commonmark/.phpstorm.meta.php b/vendor/league/commonmark/.phpstorm.meta.php index e797ee11b7..d37ba2801f 100644 --- a/vendor/league/commonmark/.phpstorm.meta.php +++ b/vendor/league/commonmark/.phpstorm.meta.php @@ -28,7 +28,7 @@ namespace PHPSTORM_META expectedArguments(\League\CommonMark\Inline\Element\Newline::__construct(), 0, argumentsSet('league_commonmark_newline_types')); expectedReturnValues(\League\CommonMark\Inline\Element\Newline::getType(), argumentsSet('league_commonmark_newline_types')); - registerArgumentsSet('league_commonmark_options', 'renderer', 'enable_em', 'enable_strong', 'use_asterisk', 'use_underscore', 'html_input', 'allow_unsafe_links', 'max_nesting_level'); + registerArgumentsSet('league_commonmark_options', 'renderer', 'enable_em', 'enable_strong', 'use_asterisk', 'use_underscore', 'unordered_list_markers', 'html_input', 'allow_unsafe_links', 'max_nesting_level'); expectedArguments(\League\CommonMark\EnvironmentInterface::getConfig(), 0, argumentsSet('league_commonmark_options')); expectedArguments(\League\CommonMark\Util\ConfigurationInterface::get(), 0, argumentsSet('league_commonmark_options')); expectedArguments(\League\CommonMark\Util\ConfigurationInterface::set(), 0, argumentsSet('league_commonmark_options')); diff --git a/vendor/league/commonmark/CHANGELOG.md b/vendor/league/commonmark/CHANGELOG.md index eaa424c8a6..2d661b9fa9 100644 --- a/vendor/league/commonmark/CHANGELOG.md +++ b/vendor/league/commonmark/CHANGELOG.md @@ -4,6 +4,38 @@ Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) princi ## [Unreleased][unreleased] +## [1.3.0] - 2020-02-08 + +### Added + + - Added (optional) **full GFM support!** 🎉🎉🎉 (#409) + - Added check to ensure Markdown input is valid UTF-8 (#401, #405) + - Added new `unordered_list_markers` configuration option (#408, #411) + +### Changed + + - Introduced several micro-optimizations for a 5-10% performance boost + +## [1.2.2] - 2020-01-15 + +This release contains the same changes as 1.1.3: + +### Fixed + + - Fixed link parsing edge case (#403) + +## [1.1.3] - 2020-01-15 + +### Fixed + + - Fixed link parsing edge case (#403) + +## [1.2.1] - 2020-01-14 + +### Changed + + - Introduced several micro-optimizations, reducing the parse time by 8% + ## [1.2.0] - 2020-01-09 ### Changed @@ -187,8 +219,12 @@ No changes were made since 1.0.0-rc1. - Removed `DelimiterStack::iterateByCharacters()` (use the new `processDelimiters()` method instead) - Removed the protected `DelimiterStack::findMatchingOpener()` method -[unreleased]: https://github.com/thephpleague/commonmark/compare/1.2.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark/compare/1.3.0...HEAD +[1.3.0]: https://github.com/thephpleague/commonmark/compare/1.2.2...1.3.0 +[1.2.2]: https://github.com/thephpleague/commonmark/compare/1.2.1...1.2.2 +[1.2.1]: https://github.com/thephpleague/commonmark/compare/1.2.0...1.2.1 [1.2.0]: https://github.com/thephpleague/commonmark/compare/1.1.2...1.2.0 +[1.1.3]: https://github.com/thephpleague/commonmark/compare/1.1.2...1.1.3 [1.1.2]: https://github.com/thephpleague/commonmark/compare/1.1.1...1.1.2 [1.1.1]: https://github.com/thephpleague/commonmark/compare/1.1.0...1.1.1 [1.1.0]: https://github.com/thephpleague/commonmark/compare/1.0.0...1.1.0 diff --git a/vendor/league/commonmark/README.md b/vendor/league/commonmark/README.md index 4732b88c36..33a3e59869 100644 --- a/vendor/league/commonmark/README.md +++ b/vendor/league/commonmark/README.md @@ -12,11 +12,11 @@  -**league/commonmark** is a highly-extensible PHP Markdown parser created by [Colin O'Dell][@colinodell] which supports the full [CommonMark] spec. It is based on the [CommonMark JS reference implementation][commonmark.js] by [John MacFarlane] \([@jgm]\). +**league/commonmark** is a highly-extensible PHP Markdown parser created by [Colin O'Dell][@colinodell] which supports the full [CommonMark] spec and [Github-Flavored Markdown]. It is based on the [CommonMark JS reference implementation][commonmark.js] by [John MacFarlane] \([@jgm]\). ## 📦 Installation & Basic Usage -This project can be installed via [Composer]: +This project requires PHP 7.1 or higher with the `mbstring` extension. To install it via [Composer] simply run: ``` bash $ composer require league/commonmark @@ -37,6 +37,21 @@ echo $converter->convertToHtml('# Hello World!'); // <h1>Hello World!</h1> ``` +Or if you want Github-Flavored Markdown, use the `GithubFlavoredMarkdownConverter` class instead: + +```php +use League\CommonMark\GithubFlavoredMarkdownConverter; + +$converter = new GithubFlavoredMarkdownConverter([ + 'html_input' => 'strip', + 'allow_unsafe_links' => false, +]); + +echo $converter->convertToHtml('# Hello World!'); + +// <h1>Hello World!</h1> +``` + Please note that only UTF-8 and ASCII encodings are supported. If your Markdown uses a different encoding please convert it to UTF-8 before running it through this library. 🔒 If you will be parsing untrusted input from users, please consider setting the `html_input` and `allow_unsafe_links` options per the example above. See <https://commonmark.thephpleague.com/security/> for more details. If you also do choose to allow raw HTML input from untrusted users, considering using a library (like [HTML Purifier](https://github.com/ezyang/htmlpurifier)) to provide additional HTML filtering. @@ -49,6 +64,18 @@ Full documentation on advanced usage, configuration, and customization can be fo Information on how to upgrade to newer versions of this library can be found at <https://commonmark.thephpleague.com/releases>. +## 💻 Github-Flavored Markdown + +The `GithubFlavoredMarkdownConverter` shown earlier is a drop-in replacement for the `CommonMarkConverter` which adds additional features found in the GFM spec: + + - Autolinks + - Disallowed raw HTML + - Strikethrough + - Tables + - Task Lists + +See the [Extensions documentation](https://commonmark.thephpleague.com/1.0/customization/extensions/) for more details on how to include only certain GFM features if you don't want them all. + ## 🗃️ Related Packages ### Integrations @@ -62,24 +89,9 @@ Information on how to upgrade to newer versions of this library can be found at - [Twig Markdown extension](https://github.com/twigphp/markdown-extension) - [Twig filter and tag](https://github.com/aptoma/twig-markdown) -### GFM Extensions - -You can easily add support for Github-Flavored Markdown by installing the [`league/commonmark-extras`](https://github.com/thephpleague/commonmark-extras) package, which includes bundles all of the extensions listed below: +### Included Extensions -| Feature | Package Name | Description | -| ------- | ------------ | ----------- | -| Autolinks | [`league/commonmark-ext-autolink`](https://github.com/thephpleague/commonmark-ext-autolink) | Automatically links URLs, emails, and (optionally) @-mentions without needing to use `<...>` | -| Smart Punctuation | [`league/commonmark-ext-smartpunct`](https://github.com/thephpleague/commonmark-ext-smartpunct) | Intelligently converts ASCII quotes, dashes, and ellipses to their Unicode equivalents | -| Strikethrough | [`league/commonmark-ext-strikethrough`](https://github.com/thephpleague/commonmark-ext-strikethrough) | Adds support for `~~strikethrough~~` syntax | -| Task Lists | [`league/commonmark-ext-task-list`](https://github.com/thephpleague/commonmark-ext-task-list) | Support for Github-style task lists | -| Tables | [`league/commonmark-ext-table`](https://github.com/thephpleague/commonmark-ext-table) | GFM-style tables | - -### Other PHP League Extensions - - - [`league/commonmark-ext-inlines-only`](https://github.com/thephpleague/commonmark-ext-inlines-only) - Renders inline text without paragraph tags or other block-level elements - - [`league/commonmark-ext-external-link`](https://github.com/thephpleague/commonmark-ext-external-link) - Mark external links, make them open in new windows, etc. - -You can add them to your project or use them as examples to [develop your own custom features](https://commonmark.thephpleague.com/customization/overview/). +See [our extension documentation](https://commonmark.thephpleague.com/1.0/customization/extensions/#included-extensions) for a full list of extensions bundled with this library. ### Community Extensions @@ -174,6 +186,10 @@ Are you interested in sponsoring development of this project? [Make a pledge](ht This project is primarily maintained by [Colin O'Dell][@colinodell]. Members of the [PHP League] Leadership Team may occasionally assist with some of these duties. +## 🗺️ Who Uses It? + +This project is used by [Laravel Framework](https://laravel.com/), [Cachet](https://cachethq.io/), [Firefly III](https://firefly-iii.org/), [Neos](https://www.neos.io/), [Daux.io](https://daux.io/), and [more](https://packagist.org/packages/league/commonmark/dependents)! + --- <div align="center"> @@ -189,6 +205,7 @@ This project is primarily maintained by [Colin O'Dell][@colinodell]. Members of [CommonMark]: http://commonmark.org/ [CommonMark spec]: http://spec.commonmark.org/ [commonmark.js]: https://github.com/jgm/commonmark.js +[Github-Flavored Markdown]: https://github.github.com/gfm/ [John MacFarlane]: http://johnmacfarlane.net [docs]: https://commonmark.thephpleague.com/ [docs-examples]: https://commonmark.thephpleague.com/customization/overview/#examples diff --git a/vendor/league/commonmark/composer.json b/vendor/league/commonmark/composer.json index 8cdc63628f..e691593b1b 100644 --- a/vendor/league/commonmark/composer.json +++ b/vendor/league/commonmark/composer.json @@ -1,8 +1,8 @@ { "name": "league/commonmark", "type": "library", - "description": "PHP Markdown parser based on the CommonMark spec", - "keywords": ["markdown","parser","commonmark"], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and Github-Flavored Markdown (GFM)", + "keywords": ["markdown","parser","commonmark","gfm","github","flavored","github-flavored","md"], "homepage": "https://commonmark.thephpleague.com", "license": "BSD-3-Clause", "authors": [ @@ -19,9 +19,6 @@ "rss": "https://github.com/thephpleague/commonmark/releases.atom", "source": "https://github.com/thephpleague/commonmark" }, - "replace": { - "colinodell/commonmark-php": "*" - }, "require": { "php": "^7.1", "ext-mbstring": "*" @@ -31,6 +28,7 @@ "cebe/markdown": "~1.0", "commonmark/commonmark.js": "0.29.1", "erusev/parsedown": "~1.0", + "github/gfm": "0.29.0", "michelf/php-markdown": "~1.4", "mikehaertl/php-shellcommand": "^1.4", "phpstan/phpstan-shim": "^0.11.5", @@ -38,8 +36,8 @@ "scrutinizer/ocular": "^1.5", "symfony/finder": "^4.2" }, - "suggest": { - "league/commonmark-extras": "Library of useful extensions including smart punctuation" + "conflict": { + "scrutinizer/ocular": "1.7.*" }, "repositories": [ { @@ -52,6 +50,17 @@ "type": "zip" } } + }, + { + "type": "package", + "package": { + "name": "github/gfm", + "version": "0.29.0", + "dist": { + "url": "https://github.com/github/cmark-gfm/archive/0.29.0.gfm.0.zip", + "type": "zip" + } + } } ], "autoload": { @@ -76,7 +85,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "config": { diff --git a/vendor/league/commonmark/src/Block/Element/BlockQuote.php b/vendor/league/commonmark/src/Block/Element/BlockQuote.php index 46bb257065..9973b69096 100644 --- a/vendor/league/commonmark/src/Block/Element/BlockQuote.php +++ b/vendor/league/commonmark/src/Block/Element/BlockQuote.php @@ -47,7 +47,7 @@ class BlockQuote extends AbstractBlock { if (!$cursor->isIndented() && $cursor->getNextNonSpaceCharacter() === '>') { $cursor->advanceToNextNonSpaceOrTab(); - $cursor->advance(); + $cursor->advanceBy(1); $cursor->advanceBySpaceOrTab(); return true; diff --git a/vendor/league/commonmark/src/Block/Parser/BlockQuoteParser.php b/vendor/league/commonmark/src/Block/Parser/BlockQuoteParser.php index 7300ede8f3..ce0f0c81b7 100644 --- a/vendor/league/commonmark/src/Block/Parser/BlockQuoteParser.php +++ b/vendor/league/commonmark/src/Block/Parser/BlockQuoteParser.php @@ -37,7 +37,7 @@ final class BlockQuoteParser implements BlockParserInterface } $cursor->advanceToNextNonSpaceOrTab(); - $cursor->advance(); + $cursor->advanceBy(1); $cursor->advanceBySpaceOrTab(); $context->addBlock(new BlockQuote()); diff --git a/vendor/league/commonmark/src/Block/Parser/FencedCodeParser.php b/vendor/league/commonmark/src/Block/Parser/FencedCodeParser.php index 56ca75717b..050d62873a 100644 --- a/vendor/league/commonmark/src/Block/Parser/FencedCodeParser.php +++ b/vendor/league/commonmark/src/Block/Parser/FencedCodeParser.php @@ -32,6 +32,11 @@ final class FencedCodeParser implements BlockParserInterface return false; } + $c = $cursor->getCharacter(); + if ($c !== ' ' && $c !== "\t" && $c !== '`' && $c !== '~') { + return false; + } + $indent = $cursor->getIndent(); $fence = $cursor->match('/^[ \t]*(?:`{3,}(?!.*`)|^~{3,})/'); if ($fence === null) { diff --git a/vendor/league/commonmark/src/Block/Parser/ListParser.php b/vendor/league/commonmark/src/Block/Parser/ListParser.php index 0ca69ab9fa..a438195587 100644 --- a/vendor/league/commonmark/src/Block/Parser/ListParser.php +++ b/vendor/league/commonmark/src/Block/Parser/ListParser.php @@ -20,10 +20,26 @@ use League\CommonMark\Block\Element\ListItem; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; +use League\CommonMark\Util\ConfigurationAwareInterface; +use League\CommonMark\Util\ConfigurationInterface; use League\CommonMark\Util\RegexHelper; -final class ListParser implements BlockParserInterface +final class ListParser implements BlockParserInterface, ConfigurationAwareInterface { + /** @var ConfigurationInterface|null */ + private $config; + + /** @var string|null */ + private $listMarkerRegex; + + /** + * {@inheritdoc} + */ + public function setConfiguration(ConfigurationInterface $configuration) + { + $this->config = $configuration; + } + /** * @param ContextInterface $context * @param Cursor $cursor @@ -45,7 +61,7 @@ final class ListParser implements BlockParserInterface $tmpCursor->advanceToNextNonSpaceOrTab(); $rest = $tmpCursor->getRemainder(); - if (\preg_match('/^[*+-]/', $rest) === 1) { + if (\preg_match($this->listMarkerRegex ?? $this->generateListMarkerRegex(), $rest) === 1) { $data = new ListData(); $data->markerOffset = $indent; $data->type = ListBlock::TYPE_UNORDERED; @@ -121,4 +137,20 @@ final class ListParser implements BlockParserInterface return $markerLength + $spacesAfterMarker; } + + private function generateListMarkerRegex(): string + { + // No configuration given - use the defaults + if ($this->config === null) { + return $this->listMarkerRegex = '/^[*+-]/'; + } + + $markers = $this->config->get('unordered_list_markers', ['*', '+', '-']); + + if (!\is_array($markers)) { + throw new \RuntimeException('Invalid configuration option "unordered_list_markers": value must be an array of strings'); + } + + return $this->listMarkerRegex = '/^[' . \preg_quote(\implode('', $markers), '/') . ']/'; + } } diff --git a/vendor/league/commonmark/src/Block/Renderer/ListItemRenderer.php b/vendor/league/commonmark/src/Block/Renderer/ListItemRenderer.php index 6f165a8af0..c9972fad5a 100644 --- a/vendor/league/commonmark/src/Block/Renderer/ListItemRenderer.php +++ b/vendor/league/commonmark/src/Block/Renderer/ListItemRenderer.php @@ -16,7 +16,9 @@ namespace League\CommonMark\Block\Renderer; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\ListItem; +use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Extension\TaskList\TaskListItemMarker; use League\CommonMark\HtmlElement; final class ListItemRenderer implements BlockRendererInterface @@ -35,7 +37,7 @@ final class ListItemRenderer implements BlockRendererInterface } $contents = $htmlRenderer->renderBlocks($block->children(), $inTightList); - if (\substr($contents, 0, 1) === '<') { + if (\substr($contents, 0, 1) === '<' && !$this->startsTaskListItem($block)) { $contents = "\n" . $contents; } if (\substr($contents, -1, 1) === '>') { @@ -48,4 +50,11 @@ final class ListItemRenderer implements BlockRendererInterface return $li; } + + private function startsTaskListItem(ListItem $block): bool + { + $firstChild = $block->firstChild(); + + return $firstChild instanceof Paragraph && $firstChild->firstChild() instanceof TaskListItemMarker; + } } diff --git a/vendor/league/commonmark/src/CommonMarkConverter.php b/vendor/league/commonmark/src/CommonMarkConverter.php index 786ada5bce..87eb2f01b9 100644 --- a/vendor/league/commonmark/src/CommonMarkConverter.php +++ b/vendor/league/commonmark/src/CommonMarkConverter.php @@ -24,7 +24,7 @@ class CommonMarkConverter extends Converter * * This might be a typical `x.y.z` version, or `x.y-dev`. */ - public const VERSION = '1.2.0'; + public const VERSION = '1.3.0'; /** @var EnvironmentInterface */ protected $environment; diff --git a/vendor/league/commonmark/src/Context.php b/vendor/league/commonmark/src/Context.php index a5799d0220..ea10a04f85 100644 --- a/vendor/league/commonmark/src/Context.php +++ b/vendor/league/commonmark/src/Context.php @@ -169,7 +169,7 @@ class Context implements ContextInterface */ public function addBlock(AbstractBlock $block) { - $this->getBlockCloser()->closeUnmatchedBlocks(); + $this->blockCloser->closeUnmatchedBlocks(); $block->setStartLine($this->lineNumber); while ($this->tip !== null && !$this->tip->canContain($block)) { @@ -190,14 +190,14 @@ class Context implements ContextInterface */ public function replaceContainerBlock(AbstractBlock $replacement) { - $this->getBlockCloser()->closeUnmatchedBlocks(); - $this->getContainer()->replaceWith($replacement); + $this->blockCloser->closeUnmatchedBlocks(); + $this->container->replaceWith($replacement); - if ($this->getTip() === $this->getContainer()) { - $this->setTip($replacement); + if ($this->tip === $this->container) { + $this->tip = $replacement; } - $this->setContainer($replacement); + $this->container = $replacement; } /** diff --git a/vendor/league/commonmark/src/Converter.php b/vendor/league/commonmark/src/Converter.php index 500f0b3e81..38d2abc4d0 100644 --- a/vendor/league/commonmark/src/Converter.php +++ b/vendor/league/commonmark/src/Converter.php @@ -50,6 +50,8 @@ class Converter implements ConverterInterface * * @param string $commonMark * + * @throws \RuntimeException + * * @return string * * @api @@ -68,6 +70,8 @@ class Converter implements ConverterInterface * * @param string $commonMark * + * @throws \RuntimeException + * * @return string */ public function __invoke(string $commonMark): string diff --git a/vendor/league/commonmark/src/ConverterInterface.php b/vendor/league/commonmark/src/ConverterInterface.php index 20d7edcc70..974a20807e 100644 --- a/vendor/league/commonmark/src/ConverterInterface.php +++ b/vendor/league/commonmark/src/ConverterInterface.php @@ -21,6 +21,8 @@ interface ConverterInterface * * @param string $commonMark * + * @throws \RuntimeException + * * @return string HTML * * @api diff --git a/vendor/league/commonmark/src/Cursor.php b/vendor/league/commonmark/src/Cursor.php index 19a31e6492..6e4e9a2091 100644 --- a/vendor/league/commonmark/src/Cursor.php +++ b/vendor/league/commonmark/src/Cursor.php @@ -61,11 +61,6 @@ class Cursor private $partiallyConsumedTab = false; /** - * @var string - */ - private $encoding; - - /** * @var bool */ private $lineContainsTabs; @@ -88,7 +83,6 @@ class Cursor $this->line = $line; $this->length = \mb_strlen($line, 'UTF-8') ?: 0; $this->isMultibyte = $this->length !== \strlen($line); - $this->encoding = $this->isMultibyte ? 'UTF-8' : 'ASCII'; $this->lineContainsTabs = false !== \strpos($line, "\t"); } @@ -169,18 +163,20 @@ class Cursor $index = $this->currentPosition; } - if (isset($this->charCache[$index])) { - return $this->charCache[$index]; - } - // Index out-of-bounds, or we're at the end if ($index < 0 || $index >= $this->length) { return null; } - return $this->charCache[$index] = $this->isMultibyte ? - \mb_substr($this->line, $index, 1, $this->encoding) : - \substr($this->line, $index, 1); + if ($this->isMultibyte) { + if (isset($this->charCache[$index])) { + return $this->charCache[$index]; + } + + return $this->charCache[$index] = \mb_substr($this->line, $index, 1, 'UTF-8'); + } + + return $this->line[$index]; } /** @@ -233,7 +229,7 @@ class Cursor // Optimization to avoid tab handling logic if we have no tabs if (!$this->lineContainsTabs || false === \strpos( $nextFewChars = $this->isMultibyte ? - \mb_substr($this->line, $this->currentPosition, $characters, $this->encoding) : + \mb_substr($this->line, $this->currentPosition, $characters, 'UTF-8') : \substr($this->line, $this->currentPosition, $characters), "\t")) { $length = \min($characters, $this->length - $this->currentPosition); @@ -322,17 +318,22 @@ class Cursor */ public function advanceToNextNonSpaceOrNewline(): int { + $remainder = $this->getRemainder(); + + // Optimization: Avoid the regex if we know there are no spaces or newlines + if (empty($remainder) || ($remainder[0] !== ' ' && $remainder[0] !== "\n")) { + $this->previousPosition = $this->currentPosition; + + return 0; + } + $matches = []; - \preg_match('/^ *(?:\n *)?/', $this->getRemainder(), $matches, \PREG_OFFSET_CAPTURE); + \preg_match('/^ *(?:\n *)?/', $remainder, $matches, \PREG_OFFSET_CAPTURE); // [0][0] contains the matched text // [0][1] contains the index of that match $increment = $matches[0][1] + \strlen($matches[0][0]); - if ($increment === 0) { - return 0; - } - $this->advanceBy($increment); return $this->currentPosition - $this->previousPosition; @@ -371,7 +372,7 @@ class Cursor } $subString = $this->isMultibyte ? - \mb_substr($this->line, $position, null, $this->encoding) : + \mb_substr($this->line, $position, null, 'UTF-8') : \substr($this->line, $position); return $prefix . $subString; @@ -415,8 +416,8 @@ class Cursor if ($this->isMultibyte) { // PREG_OFFSET_CAPTURE always returns the byte offset, not the char offset, which is annoying - $offset = \mb_strlen(\mb_strcut($subject, 0, $matches[0][1], $this->encoding), $this->encoding); - $matchLength = \mb_strlen($matches[0][0], $this->encoding); + $offset = \mb_strlen(\substr($subject, 0, $matches[0][1]), 'UTF-8'); + $matchLength = \mb_strlen($matches[0][0], 'UTF-8'); } else { $offset = $matches[0][1]; $matchLength = \strlen($matches[0][0]); @@ -482,7 +483,7 @@ class Cursor */ public function getPreviousText(): string { - return \mb_substr($this->line, $this->previousPosition, $this->currentPosition - $this->previousPosition, $this->encoding); + return \mb_substr($this->line, $this->previousPosition, $this->currentPosition - $this->previousPosition, 'UTF-8'); } /** @@ -494,7 +495,7 @@ class Cursor public function getSubstring(int $start, ?int $length = null): string { if ($this->isMultibyte) { - return \mb_substr($this->line, $start, $length, $this->encoding); + return \mb_substr($this->line, $start, $length, 'UTF-8'); } elseif ($length !== null) { return \substr($this->line, $start, $length); } diff --git a/vendor/league/commonmark/src/DocParser.php b/vendor/league/commonmark/src/DocParser.php index 299256e167..dfc87d5327 100644 --- a/vendor/league/commonmark/src/DocParser.php +++ b/vendor/league/commonmark/src/DocParser.php @@ -20,6 +20,7 @@ use League\CommonMark\Block\Element\Document; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Element\StringContainerInterface; use League\CommonMark\Event\DocumentParsedEvent; +use League\CommonMark\Exception\UnexpectedEncodingException; final class DocParser implements DocParserInterface { @@ -71,6 +72,8 @@ final class DocParser implements DocParserInterface /** * @param string $input * + * @throws \RuntimeException + * * @return Document */ public function parse(string $input): Document @@ -78,6 +81,7 @@ final class DocParser implements DocParserInterface $document = new Document(); $context = new Context($document, $this->environment); + $this->assertValidUTF8($input); $lines = $this->preProcessInput($input); foreach ($lines as $line) { $context->setNextLine($line); @@ -243,9 +247,16 @@ final class DocParser implements DocParserInterface $lastLineBlank = $container->shouldLastLineBeBlank($cursor, $context->getLineNumber()); // Propagate lastLineBlank up through parents: - while ($container instanceof AbstractBlock) { + while ($container instanceof AbstractBlock && $container->endsWithBlankLine() !== $lastLineBlank) { $container->setLastLineBlank($lastLineBlank); $container = $container->parent(); } } + + private function assertValidUTF8(string $input) + { + if (!\mb_check_encoding($input, 'UTF-8')) { + throw new UnexpectedEncodingException('Unexpected encoding - UTF-8 or ASCII was expected'); + } + } } diff --git a/vendor/league/commonmark/src/DocParserInterface.php b/vendor/league/commonmark/src/DocParserInterface.php index f43c93093e..23725ad476 100644 --- a/vendor/league/commonmark/src/DocParserInterface.php +++ b/vendor/league/commonmark/src/DocParserInterface.php @@ -18,6 +18,8 @@ interface DocParserInterface /** * @param string $input * + * @throws \RuntimeException + * * @return Document */ public function parse(string $input): Document; diff --git a/vendor/league/commonmark/src/Environment.php b/vendor/league/commonmark/src/Environment.php index 1e5e005899..eea85fdbac 100644 --- a/vendor/league/commonmark/src/Environment.php +++ b/vendor/league/commonmark/src/Environment.php @@ -21,6 +21,7 @@ use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; use League\CommonMark\Event\AbstractEvent; use League\CommonMark\Extension\CommonMarkCoreExtension; use League\CommonMark\Extension\ExtensionInterface; +use League\CommonMark\Extension\GithubFlavoredMarkdownExtension; use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\Inline\Renderer\InlineRendererInterface; use League\CommonMark\Util\Configuration; @@ -211,7 +212,9 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment */ public function getBlockParsers(): iterable { - $this->initializeExtensions(); + if (!$this->extensionsInitialized) { + $this->initializeExtensions(); + } return $this->blockParsers->getIterator(); } @@ -221,7 +224,9 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment */ public function getInlineParsersForCharacter(string $character): iterable { - $this->initializeExtensions(); + if (!$this->extensionsInitialized) { + $this->initializeExtensions(); + } if (!isset($this->inlineParsersByCharacter[$character])) { return []; @@ -235,7 +240,9 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment */ public function getDelimiterProcessors(): DelimiterProcessorCollection { - $this->initializeExtensions(); + if (!$this->extensionsInitialized) { + $this->initializeExtensions(); + } return $this->delimiterProcessors; } @@ -245,7 +252,9 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment */ public function getBlockRenderersForClass(string $blockClass): iterable { - $this->initializeExtensions(); + if (!$this->extensionsInitialized) { + $this->initializeExtensions(); + } if (!isset($this->blockRenderersByClass[$blockClass])) { return []; @@ -259,7 +268,9 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment */ public function getInlineRenderersForClass(string $inlineClass): iterable { - $this->initializeExtensions(); + if (!$this->extensionsInitialized) { + $this->initializeExtensions(); + } if (!isset($this->inlineRenderersByClass[$inlineClass])) { return []; @@ -297,11 +308,6 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment private function initializeExtensions() { - // Only initialize them once - if ($this->extensionsInitialized) { - return; - } - // Ask all extensions to register their components while (!empty($this->uninitializedExtensions)) { foreach ($this->uninitializedExtensions as $i => $extension) { @@ -349,6 +355,14 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment return $environment; } + public static function createGFMEnvironment(): EnvironmentInterface + { + $environment = self::createCommonMarkEnvironment(); + $environment->addExtension(new GithubFlavoredMarkdownExtension()); + + return $environment; + } + /** * {@inheritdoc} */ @@ -378,7 +392,9 @@ final class Environment implements EnvironmentInterface, ConfigurableEnvironment */ public function dispatch(AbstractEvent $event): void { - $this->initializeExtensions(); + if (!$this->extensionsInitialized) { + $this->initializeExtensions(); + } $type = \get_class($event); diff --git a/vendor/league/commonmark/src/Exception/UnexpectedEncodingException.php b/vendor/league/commonmark/src/Exception/UnexpectedEncodingException.php new file mode 100644 index 0000000000..ada054bc90 --- /dev/null +++ b/vendor/league/commonmark/src/Exception/UnexpectedEncodingException.php @@ -0,0 +1,16 @@ +<?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\Exception; + +final class UnexpectedEncodingException extends \RuntimeException +{ +} diff --git a/vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php b/vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php new file mode 100644 index 0000000000..76ab3dcc2e --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Autolink; + +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Event\DocumentParsedEvent; +use League\CommonMark\Extension\ExtensionInterface; + +final class AutolinkExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addEventListener(DocumentParsedEvent::class, new EmailAutolinkProcessor()); + $environment->addEventListener(DocumentParsedEvent::class, new UrlAutolinkProcessor()); + } +} diff --git a/vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkProcessor.php b/vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkProcessor.php new file mode 100644 index 0000000000..6916d3c2e2 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkProcessor.php @@ -0,0 +1,78 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Autolink; + +use League\CommonMark\Event\DocumentParsedEvent; +use League\CommonMark\Inline\Element\Link; +use League\CommonMark\Inline\Element\Text; + +final class EmailAutolinkProcessor +{ + const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/'; + + /** + * @param DocumentParsedEvent $e + * + * @return void + */ + public function __invoke(DocumentParsedEvent $e) + { + $walker = $e->getDocument()->walker(); + + while ($event = $walker->next()) { + $node = $event->getNode(); + if ($node instanceof Text && !($node->parent() instanceof Link)) { + self::processAutolinks($node); + } + } + } + + private static function processAutolinks(Text $node) + { + $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(); + } +} diff --git a/vendor/league/commonmark/src/Extension/Autolink/InlineMentionParser.php b/vendor/league/commonmark/src/Extension/Autolink/InlineMentionParser.php new file mode 100644 index 0000000000..2bbd56c545 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Autolink/InlineMentionParser.php @@ -0,0 +1,90 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Autolink; + +use League\CommonMark\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)/'); + } +} diff --git a/vendor/league/commonmark/src/Extension/Autolink/README.md b/vendor/league/commonmark/src/Extension/Autolink/README.md new file mode 100644 index 0000000000..3dfdb62477 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Autolink/README.md @@ -0,0 +1,73 @@ +# 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- diff --git a/vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkProcessor.php b/vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkProcessor.php new file mode 100644 index 0000000000..8783e4e2e7 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkProcessor.php @@ -0,0 +1,149 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Autolink; + +use League\CommonMark\Event\DocumentParsedEvent; +use League\CommonMark\Inline\Element\Link; +use League\CommonMark\Inline\Element\Text; + +final class UrlAutolinkProcessor +{ + // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php + const REGEX = '~ + (?<=^|[ \\t\\n\\x0b\\x0c\\x0d*_\\~\\(]) # Can only come at the beginning of a line, after whitespace, or certain delimiting characters + ( + # Must start with a supported scheme + auth, or "www" + (?: + (?:%s):// # protocol + (?:([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth + |www\.) + (?: + (?:[\pL\pN\pS\-\.])+(?:\.?(?:[\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name + | # or + \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address + | # or + \[ + (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) + \] # an IPv6 address + ) + (?::[0-9]+)? # a port (optional) + (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path + (?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional) + (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional) + )~ixu'; + + 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['(']; + } +} diff --git a/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php b/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php new file mode 100644 index 0000000000..7947c5e7e5 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php @@ -0,0 +1,53 @@ +<?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 x="sdf"> <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); + } + } +} diff --git a/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php b/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php new file mode 100644 index 0000000000..f5579dba5f --- /dev/null +++ b/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\DisallowedRawHtml; + +use League\CommonMark\Block\Element\HtmlBlock; +use League\CommonMark\Block\Renderer\HtmlBlockRenderer; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; +use League\CommonMark\Inline\Element\HtmlInline; +use League\CommonMark\Inline\Renderer\HtmlInlineRenderer; + +final class DisallowedRawHtmlExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addBlockRenderer(HtmlBlock::class, new DisallowedRawHtmlBlockRenderer(new HtmlBlockRenderer()), 50); + $environment->addInlineRenderer(HtmlInline::class, new DisallowedRawHtmlInlineRenderer(new HtmlInlineRenderer()), 50); + } +} diff --git a/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php b/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php new file mode 100644 index 0000000000..2783281ec9 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\DisallowedRawHtml; + +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Inline\Element\AbstractInline; +use League\CommonMark\Inline\Renderer\InlineRendererInterface; +use League\CommonMark\Util\ConfigurationAwareInterface; +use League\CommonMark\Util\ConfigurationInterface; + +final class DisallowedRawHtmlInlineRenderer implements InlineRendererInterface, ConfigurationAwareInterface +{ + 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> <title x="sdf"> <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); + } + } +} diff --git a/vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkExtension.php b/vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkExtension.php new file mode 100644 index 0000000000..9deee0bd0e --- /dev/null +++ b/vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkExtension.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\ExternalLink; + +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Event\DocumentParsedEvent; +use League\CommonMark\Extension\ExtensionInterface; + +final class ExternalLinkExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment)); + } +} diff --git a/vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkProcessor.php b/vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkProcessor.php new file mode 100644 index 0000000000..200f35c0f1 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/ExternalLink/ExternalLinkProcessor.php @@ -0,0 +1,105 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\ExternalLink; + +use League\CommonMark\EnvironmentInterface; +use League\CommonMark\Event\DocumentParsedEvent; +use League\CommonMark\Inline\Element\Link; + +final class ExternalLinkProcessor +{ + /** @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; + } +} diff --git a/vendor/league/commonmark/src/Extension/ExternalLink/README.md b/vendor/league/commonmark/src/Extension/ExternalLink/README.md new file mode 100644 index 0000000000..2eec7e22c4 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/ExternalLink/README.md @@ -0,0 +1,100 @@ +# 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 `<a>` 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 diff --git a/vendor/league/commonmark/src/Extension/GithubFlavoredMarkdownExtension.php b/vendor/league/commonmark/src/Extension/GithubFlavoredMarkdownExtension.php new file mode 100644 index 0000000000..41659c126b --- /dev/null +++ b/vendor/league/commonmark/src/Extension/GithubFlavoredMarkdownExtension.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension; + +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\Autolink\AutolinkExtension; +use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension; +use League\CommonMark\Extension\Strikethrough\StrikethroughExtension; +use League\CommonMark\Extension\Table\TableExtension; +use League\CommonMark\Extension\TaskList\TaskListExtension; + +final class GithubFlavoredMarkdownExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addExtension(new AutolinkExtension()); + $environment->addExtension(new DisallowedRawHtmlExtension()); + $environment->addExtension(new StrikethroughExtension()); + $environment->addExtension(new TableExtension()); + $environment->addExtension(new TaskListExtension()); + } +} diff --git a/vendor/league/commonmark/src/Extension/InlinesOnly/ChildRenderer.php b/vendor/league/commonmark/src/Extension/InlinesOnly/ChildRenderer.php new file mode 100644 index 0000000000..defd4ceed9 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/InlinesOnly/ChildRenderer.php @@ -0,0 +1,49 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\InlinesOnly; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Element\Document; +use League\CommonMark\Block\Element\InlineContainerInterface; +use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Inline\Element\AbstractInline; + +/** + * Simply renders child elements as-is, adding newlines as needed. + */ +final class ChildRenderer implements BlockRendererInterface +{ + /** + * {@inheritdoc} + */ + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) + { + $out = ''; + + if ($block instanceof InlineContainerInterface) { + /** @var iterable<AbstractInline> $children */ + $children = $block->children(); + $out .= $htmlRenderer->renderInlines($children); + } else { + /** @var iterable<AbstractBlock> $children */ + $children = $block->children(); + $out .= $htmlRenderer->renderBlocks($children); + } + + if (!($block instanceof Document)) { + $out .= "\n"; + } + + return $out; + } +} diff --git a/vendor/league/commonmark/src/Extension/InlinesOnly/InlinesOnlyExtension.php b/vendor/league/commonmark/src/Extension/InlinesOnly/InlinesOnlyExtension.php new file mode 100644 index 0000000000..29ffb303a5 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/InlinesOnly/InlinesOnlyExtension.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\InlinesOnly; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\Block\Element\Paragraph; +use League\CommonMark\Block\Parser as BlockParser; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor; +use League\CommonMark\Extension\ExtensionInterface; +use League\CommonMark\Inline\Element as InlineElement; +use League\CommonMark\Inline\Parser as InlineParser; +use League\CommonMark\Inline\Renderer as InlineRenderer; + +final class InlinesOnlyExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $childRenderer = new ChildRenderer(); + + $environment + ->addBlockParser(new BlockParser\LazyParagraphParser(), -200) + + ->addInlineParser(new InlineParser\NewlineParser(), 200) + ->addInlineParser(new InlineParser\BacktickParser(), 150) + ->addInlineParser(new InlineParser\EscapableParser(), 80) + ->addInlineParser(new InlineParser\EntityParser(), 70) + ->addInlineParser(new InlineParser\AutolinkParser(), 50) + ->addInlineParser(new InlineParser\HtmlInlineParser(), 40) + ->addInlineParser(new InlineParser\CloseBracketParser(), 30) + ->addInlineParser(new InlineParser\OpenBracketParser(), 20) + ->addInlineParser(new InlineParser\BangParser(), 10) + + ->addBlockRenderer(Document::class, $childRenderer, 0) + ->addBlockRenderer(Paragraph::class, $childRenderer, 0) + + ->addInlineRenderer(InlineElement\Code::class, new InlineRenderer\CodeRenderer(), 0) + ->addInlineRenderer(InlineElement\Emphasis::class, new InlineRenderer\EmphasisRenderer(), 0) + ->addInlineRenderer(InlineElement\HtmlInline::class, new InlineRenderer\HtmlInlineRenderer(), 0) + ->addInlineRenderer(InlineElement\Image::class, new InlineRenderer\ImageRenderer(), 0) + ->addInlineRenderer(InlineElement\Link::class, new InlineRenderer\LinkRenderer(), 0) + ->addInlineRenderer(InlineElement\Newline::class, new InlineRenderer\NewlineRenderer(), 0) + ->addInlineRenderer(InlineElement\Strong::class, new InlineRenderer\StrongRenderer(), 0) + ->addInlineRenderer(InlineElement\Text::class, new InlineRenderer\TextRenderer(), 0) + ; + + if ($environment->getConfig('use_asterisk', true)) { + $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*')); + } + if ($environment->getConfig('use_underscore', true)) { + $environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_')); + } + } +} diff --git a/vendor/league/commonmark/src/Extension/InlinesOnly/README.md b/vendor/league/commonmark/src/Extension/InlinesOnly/README.md new file mode 100644 index 0000000000..c8eb410c0c --- /dev/null +++ b/vendor/league/commonmark/src/Extension/InlinesOnly/README.md @@ -0,0 +1,25 @@ +# 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 diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/PunctuationParser.php b/vendor/league/commonmark/src/Extension/SmartPunct/PunctuationParser.php new file mode 100644 index 0000000000..4247333035 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/PunctuationParser.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) + * - (c) John MacFarlane + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\SmartPunct; + +use League\CommonMark\Inline\Element\Text; +use League\CommonMark\Inline\Parser\InlineParserInterface; +use League\CommonMark\InlineParserContext; + +final class PunctuationParser implements InlineParserInterface +{ + /** + * @return string[] + */ + public function getCharacters(): array + { + return ['-', '.']; + } + + /** + * @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('/^(?<!-)(-{2,})/')) { + $count = strlen($matched); + $en_dash = '–'; + $en_count = 0; + $em_dash = '—'; + $em_count = 0; + if ($count % 3 === 0) { // If divisible by 3, use all em dashes + $em_count = $count / 3; + } elseif ($count % 2 === 0) { // If divisible by 2, use all en dashes + $en_count = $count / 2; + } elseif ($count % 3 === 2) { // If 2 extra dashes, use en dash for last 2; em dashes for rest + $em_count = ($count - 2) / 3; + $en_count = 1; + } else { // Use en dashes for last 4 hyphens; em dashes for rest + $em_count = ($count - 4) / 3; + $en_count = 2; + } + $inlineContext->getContainer()->appendChild(new Text( + str_repeat($em_dash, $em_count) . str_repeat($en_dash, $en_count) + )); + + return true; + } + + return false; + } +} diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/Quote.php b/vendor/league/commonmark/src/Extension/SmartPunct/Quote.php new file mode 100644 index 0000000000..cf3c15b406 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/Quote.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) + * - (c) John MacFarlane + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\SmartPunct; + +use League\CommonMark\Inline\Element\AbstractStringContainer; + +final class Quote extends AbstractStringContainer +{ + public const DOUBLE_QUOTE = '"'; + public const DOUBLE_QUOTE_OPENER = '“'; + public const DOUBLE_QUOTE_CLOSER = '”'; + + public const SINGLE_QUOTE = "'"; + public const SINGLE_QUOTE_OPENER = '‘'; + public const SINGLE_QUOTE_CLOSER = '’'; +} diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/QuoteParser.php b/vendor/league/commonmark/src/Extension/SmartPunct/QuoteParser.php new file mode 100644 index 0000000000..bc3ea0cd24 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/QuoteParser.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) + * - (c) John MacFarlane + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\SmartPunct; + +use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Inline\Parser\InlineParserInterface; +use League\CommonMark\InlineParserContext; +use League\CommonMark\Util\RegexHelper; + +final class QuoteParser implements InlineParserInterface +{ + public const DOUBLE_QUOTES = [Quote::DOUBLE_QUOTE, Quote::DOUBLE_QUOTE_OPENER, Quote::DOUBLE_QUOTE_CLOSER]; + public const SINGLE_QUOTES = [Quote::SINGLE_QUOTE, Quote::SINGLE_QUOTE_OPENER, Quote::SINGLE_QUOTE_CLOSER]; + + /** + * @return string[] + */ + public function getCharacters(): array + { + return array_merge(self::DOUBLE_QUOTES, self::SINGLE_QUOTES); + } + + /** + * Normalizes any quote characters found and manually adds them to the delimiter stack + * + * @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]; + } +} diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/QuoteProcessor.php b/vendor/league/commonmark/src/Extension/SmartPunct/QuoteProcessor.php new file mode 100644 index 0000000000..e8d4bc71de --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/QuoteProcessor.php @@ -0,0 +1,112 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) + * - (c) John MacFarlane + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\SmartPunct; + +use League\CommonMark\Delimiter\DelimiterInterface; +use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; +use League\CommonMark\Inline\Element\AbstractStringContainer; + +final class QuoteProcessor implements DelimiterProcessorInterface +{ + /** @var string */ + private $normalizedCharacter; + + /** @var string */ + private $openerCharacter; + + /** @var string */ + private $closerCharacter; + + /** + * 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); + } +} diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/QuoteRenderer.php b/vendor/league/commonmark/src/Extension/SmartPunct/QuoteRenderer.php new file mode 100644 index 0000000000..8cc18974b3 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/QuoteRenderer.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) + * - (c) John MacFarlane + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\SmartPunct; + +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\Inline\Element\AbstractInline; +use League\CommonMark\Inline\Renderer\InlineRendererInterface; + +final class QuoteRenderer implements InlineRendererInterface +{ + /** + * @param 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(); + } +} diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/README.md b/vendor/league/commonmark/src/Extension/SmartPunct/README.md new file mode 100644 index 0000000000..0cc1b3dc9f --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/README.md @@ -0,0 +1,47 @@ +# 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 +<p>“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!”</p> +``` + +## 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 diff --git a/vendor/league/commonmark/src/Extension/SmartPunct/SmartPunctExtension.php b/vendor/league/commonmark/src/Extension/SmartPunct/SmartPunctExtension.php new file mode 100644 index 0000000000..f3a19d8e74 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/SmartPunct/SmartPunctExtension.php @@ -0,0 +1,49 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) + * - (c) John MacFarlane + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\SmartPunct; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\Block\Element\Paragraph; +use League\CommonMark\Block\Renderer as CoreBlockRenderer; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; +use League\CommonMark\Inline\Element\Text; +use League\CommonMark\Inline\Renderer as CoreInlineRenderer; + +final class SmartPunctExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment + ->addInlineParser(new QuoteParser(), 10) + ->addInlineParser(new PunctuationParser(), 0) + + ->addDelimiterProcessor(QuoteProcessor::createDoubleQuoteProcessor( + $environment->getConfig('smartpunct/double_quote_opener', Quote::DOUBLE_QUOTE_OPENER), + $environment->getConfig('smartpunct/double_quote_closer', Quote::DOUBLE_QUOTE_CLOSER) + )) + ->addDelimiterProcessor(QuoteProcessor::createSingleQuoteProcessor( + $environment->getConfig('smartpunct/single_quote_opener', Quote::SINGLE_QUOTE_OPENER), + $environment->getConfig('smartpunct/single_quote_closer', Quote::SINGLE_QUOTE_CLOSER) + )) + + ->addBlockRenderer(Document::class, new CoreBlockRenderer\DocumentRenderer(), 0) + ->addBlockRenderer(Paragraph::class, new CoreBlockRenderer\ParagraphRenderer(), 0) + + ->addInlineRenderer(Quote::class, new QuoteRenderer(), 100) + ->addInlineRenderer(Text::class, new CoreInlineRenderer\TextRenderer(), 0) + ; + } +} diff --git a/vendor/league/commonmark/src/Extension/Strikethrough/README.md b/vendor/league/commonmark/src/Extension/Strikethrough/README.md new file mode 100644 index 0000000000..c93f622161 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Strikethrough/README.md @@ -0,0 +1,27 @@ +# 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 `<del>` 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 diff --git a/vendor/league/commonmark/src/Extension/Strikethrough/Strikethrough.php b/vendor/league/commonmark/src/Extension/Strikethrough/Strikethrough.php new file mode 100644 index 0000000000..09c8f20eb7 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Strikethrough/Strikethrough.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Strikethrough; + +use League\CommonMark\Inline\Element\AbstractInline; + +final class Strikethrough extends AbstractInline +{ + /** + * @return bool + */ + public function isContainer(): bool + { + return true; + } +} diff --git a/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughDelimiterProcessor.php b/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughDelimiterProcessor.php new file mode 100644 index 0000000000..25983435c8 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughDelimiterProcessor.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Strikethrough; + +use League\CommonMark\Delimiter\DelimiterInterface; +use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; +use League\CommonMark\Inline\Element\AbstractStringContainer; + +final class StrikethroughDelimiterProcessor implements DelimiterProcessorInterface +{ + /** + * {@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); + } +} diff --git a/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughExtension.php b/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughExtension.php new file mode 100644 index 0000000000..a77d80c2a0 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughExtension.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Strikethrough; + +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; + +final class StrikethroughExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor()); + $environment->addInlineRenderer(Strikethrough::class, new StrikethroughRenderer()); + } +} diff --git a/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughRenderer.php b/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughRenderer.php new file mode 100644 index 0000000000..8b747de5ba --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Strikethrough/StrikethroughRenderer.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> and uAfrica.com (http://uafrica.com) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Strikethrough; + +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\Inline\Element\AbstractInline; +use League\CommonMark\Inline\Renderer\InlineRendererInterface; + +final class StrikethroughRenderer implements InlineRendererInterface +{ + /** + * {@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())); + } +} diff --git a/vendor/league/commonmark/src/Extension/Table/README.md b/vendor/league/commonmark/src/Extension/Table/README.md new file mode 100644 index 0000000000..ff8de545d4 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Table/README.md @@ -0,0 +1,78 @@ +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 +<table> +<thead> +<tr> +<th style="text-align: left">th</th> +<th style="text-align: center">th(center)</th> +<th style="text-align: right">th(right<)/th> +</tr> +</thead> +<tbody> +<tr> +<td style="text-align: left">td</td> +<td style="text-align: center">td</td> +<td style="text-align: right">td</td> +</tr> +</tbody> +</table> +``` + +### 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) diff --git a/vendor/league/commonmark-ext-table/src/Table.php b/vendor/league/commonmark/src/Extension/Table/Table.php index 22aa812ee8..7d1406d907 100644 --- a/vendor/league/commonmark-ext-table/src/Table.php +++ b/vendor/league/commonmark/src/Extension/Table/Table.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; @@ -21,9 +21,8 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -class Table extends AbstractStringContainerBlock implements InlineContainerInterface +final class Table extends AbstractStringContainerBlock implements InlineContainerInterface { - private $caption; private $head; private $body; private $parser; @@ -38,7 +37,7 @@ class Table extends AbstractStringContainerBlock implements InlineContainerInter public function canContain(AbstractBlock $block): bool { - return $block instanceof TableSection || $block instanceof TableCaption; + return $block instanceof TableSection; } public function isCode(): bool @@ -46,24 +45,6 @@ class Table extends AbstractStringContainerBlock implements InlineContainerInter return false; } - public function setCaption(TableCaption $caption = null): void - { - $node = $this->getCaption(); - if ($node instanceof TableCaption) { - $node->detach(); - } - - $this->caption = $caption; - if (null !== $caption) { - $this->prependChild($caption); - } - } - - public function getCaption(): ?TableCaption - { - return $this->caption; - } - public function getHead(): TableSection { return $this->head; diff --git a/vendor/league/commonmark-ext-table/src/TableCell.php b/vendor/league/commonmark/src/Extension/Table/TableCell.php index c8b326a03b..e71b003924 100644 --- a/vendor/league/commonmark-ext-table/src/TableCell.php +++ b/vendor/league/commonmark/src/Extension/Table/TableCell.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; @@ -21,7 +21,7 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -class TableCell extends AbstractStringContainerBlock implements InlineContainerInterface +final class TableCell extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'th'; const TYPE_BODY = 'td'; diff --git a/vendor/league/commonmark-ext-table/src/TableCellRenderer.php b/vendor/league/commonmark/src/Extension/Table/TableCellRenderer.php index 400e94e546..c149633efa 100644 --- a/vendor/league/commonmark-ext-table/src/TableCellRenderer.php +++ b/vendor/league/commonmark/src/Extension/Table/TableCellRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; @@ -25,13 +25,13 @@ 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)); + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } $attrs = $block->getData('attributes', []); if ($block->align) { - $attrs['style'] = (isset($attrs['style']) ? $attrs['style'].' ' : '').'text-align: '.$block->align; + $attrs['align'] = $block->align; } return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children())); diff --git a/vendor/league/commonmark-ext-table/src/TableExtension.php b/vendor/league/commonmark/src/Extension/Table/TableExtension.php index b19ee4dc03..0046b1bea6 100644 --- a/vendor/league/commonmark-ext-table/src/TableExtension.php +++ b/vendor/league/commonmark/src/Extension/Table/TableExtension.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; @@ -26,7 +26,6 @@ final class TableExtension implements ExtensionInterface ->addBlockParser(new TableParser()) ->addBlockRenderer(Table::class, new TableRenderer()) - ->addBlockRenderer(TableCaption::class, new TableCaptionRenderer()) ->addBlockRenderer(TableSection::class, new TableSectionRenderer()) ->addBlockRenderer(TableRow::class, new TableRowRenderer()) ->addBlockRenderer(TableCell::class, new TableCellRenderer()) diff --git a/vendor/league/commonmark/src/Extension/Table/TableParser.php b/vendor/league/commonmark/src/Extension/Table/TableParser.php new file mode 100644 index 0000000000..4f53fca56a --- /dev/null +++ b/vendor/league/commonmark/src/Extension/Table/TableParser.php @@ -0,0 +1,274 @@ +<?php + +declare(strict_types=1); + +/* + * This is part of the league/commonmark package. + * + * (c) Martin Hasoň <martin.hason@gmail.com> + * (c) Webuni s.r.o. <info@webuni.cz> + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\Table; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\Block\Element\Paragraph; +use League\CommonMark\Block\Parser\BlockParserInterface; +use League\CommonMark\Context; +use League\CommonMark\ContextInterface; +use League\CommonMark\Cursor; +use League\CommonMark\EnvironmentAwareInterface; +use League\CommonMark\EnvironmentInterface; + +final class TableParser implements BlockParserInterface, EnvironmentAwareInterface +{ + /** + * @var EnvironmentInterface + */ + private $environment; + + public function parse(ContextInterface $context, Cursor $cursor): bool + { + $container = $context->getContainer(); + if (!$container instanceof Paragraph) { + return false; + } + + $lines = $container->getStrings(); + if (count($lines) !== 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; + } +} diff --git a/vendor/league/commonmark-ext-table/src/TableRenderer.php b/vendor/league/commonmark/src/Extension/Table/TableRenderer.php index 2381780dad..1d414c6162 100644 --- a/vendor/league/commonmark-ext-table/src/TableRenderer.php +++ b/vendor/league/commonmark/src/Extension/Table/TableRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; @@ -25,13 +25,15 @@ 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)); + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement('table', $attrs, $separator.$htmlRenderer->renderBlocks($block->children()).$separator); + $children = $htmlRenderer->renderBlocks($block->children()); + + return new HtmlElement('table', $attrs, $separator . \trim($children) . $separator); } } diff --git a/vendor/league/commonmark-ext-table/src/TableRow.php b/vendor/league/commonmark/src/Extension/Table/TableRow.php index 17b5e96598..1447725949 100644 --- a/vendor/league/commonmark-ext-table/src/TableRow.php +++ b/vendor/league/commonmark/src/Extension/Table/TableRow.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,14 +13,13 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; use League\CommonMark\Node\Node; -class TableRow extends AbstractBlock +final class TableRow extends AbstractBlock { public function canContain(AbstractBlock $block): bool { @@ -42,6 +41,8 @@ class TableRow extends AbstractBlock */ public function children(): iterable { - return array_filter((array) parent::children(), static function (Node $child): bool { return $child instanceof AbstractBlock; }); + return array_filter((array) parent::children(), static function (Node $child): bool { + return $child instanceof AbstractBlock; + }); } } diff --git a/vendor/league/commonmark-ext-table/src/TableRowRenderer.php b/vendor/league/commonmark/src/Extension/Table/TableRowRenderer.php index 9f4d852e1b..dbbcd13238 100644 --- a/vendor/league/commonmark-ext-table/src/TableRowRenderer.php +++ b/vendor/league/commonmark/src/Extension/Table/TableRowRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; @@ -25,13 +25,13 @@ 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)); + 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); + return new HtmlElement('tr', $attrs, $separator . $htmlRenderer->renderBlocks($block->children()) . $separator); } } diff --git a/vendor/league/commonmark-ext-table/src/TableSection.php b/vendor/league/commonmark/src/Extension/Table/TableSection.php index b19e4274dc..5d299a1625 100644 --- a/vendor/league/commonmark-ext-table/src/TableSection.php +++ b/vendor/league/commonmark/src/Extension/Table/TableSection.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; @@ -21,7 +21,7 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -class TableSection extends AbstractStringContainerBlock implements InlineContainerInterface +final class TableSection extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'thead'; const TYPE_BODY = 'tbody'; diff --git a/vendor/league/commonmark-ext-table/src/TableSectionRenderer.php b/vendor/league/commonmark/src/Extension/Table/TableSectionRenderer.php index 7ea2a33fba..02e17d3caa 100644 --- a/vendor/league/commonmark-ext-table/src/TableSectionRenderer.php +++ b/vendor/league/commonmark/src/Extension/Table/TableSectionRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the league/commonmark-ext-table package. + * This is part of the league/commonmark package. * * (c) Martin Hasoň <martin.hason@gmail.com> * (c) Webuni s.r.o. <info@webuni.cz> @@ -13,7 +13,7 @@ declare(strict_types=1); * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Table; +namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; @@ -25,7 +25,7 @@ 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)); + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } if (!$block->hasChildren()) { @@ -36,6 +36,6 @@ final class TableSectionRenderer implements BlockRendererInterface $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement($block->type, $attrs, $separator.$htmlRenderer->renderBlocks($block->children()).$separator); + return new HtmlElement($block->type, $attrs, $separator . $htmlRenderer->renderBlocks($block->children()) . $separator); } } diff --git a/vendor/league/commonmark/src/Extension/TaskList/README.md b/vendor/league/commonmark/src/Extension/TaskList/README.md new file mode 100644 index 0000000000..8d47593029 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/TaskList/README.md @@ -0,0 +1,33 @@ +# 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- diff --git a/vendor/league/commonmark/src/Extension/TaskList/TaskListExtension.php b/vendor/league/commonmark/src/Extension/TaskList/TaskListExtension.php new file mode 100644 index 0000000000..11611d315d --- /dev/null +++ b/vendor/league/commonmark/src/Extension/TaskList/TaskListExtension.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\TaskList; + +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; + +final class TaskListExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addInlineParser(new TaskListItemMarkerParser(), 35); + $environment->addInlineRenderer(TaskListItemMarker::class, new TaskListItemMarkerRenderer()); + } +} diff --git a/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarker.php b/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarker.php new file mode 100644 index 0000000000..a6cf65dc6d --- /dev/null +++ b/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarker.php @@ -0,0 +1,36 @@ +<?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; + } +} diff --git a/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerParser.php b/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerParser.php new file mode 100644 index 0000000000..24491b1680 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerParser.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\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; + } +} diff --git a/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerRenderer.php b/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerRenderer.php new file mode 100644 index 0000000000..a65513adc1 --- /dev/null +++ b/vendor/league/commonmark/src/Extension/TaskList/TaskListItemMarkerRenderer.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Extension\TaskList; + +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\Inline\Element\AbstractInline; +use League\CommonMark\Inline\Renderer\InlineRendererInterface; + +final class TaskListItemMarkerRenderer implements InlineRendererInterface +{ + /** + * @param 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; + } +} diff --git a/vendor/league/commonmark/src/GithubFlavoredMarkdownConverter.php b/vendor/league/commonmark/src/GithubFlavoredMarkdownConverter.php new file mode 100644 index 0000000000..ef4b5946a1 --- /dev/null +++ b/vendor/league/commonmark/src/GithubFlavoredMarkdownConverter.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the league/commonmark package. + * + * (c) Colin O'Dell <colinodell@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark; + +/** + * Converts Github Flavored Markdown to HTML. + */ +class GithubFlavoredMarkdownConverter extends CommonMarkConverter +{ + /** + * Create a new commonmark converter instance. + * + * @param array $config + * @param EnvironmentInterface|null $environment + */ + public function __construct(array $config = [], EnvironmentInterface $environment = null) + { + if ($environment === null) { + $environment = Environment::createGFMEnvironment(); + } + + parent::__construct($config, $environment); + } +} diff --git a/vendor/league/commonmark/src/HtmlElement.php b/vendor/league/commonmark/src/HtmlElement.php index 19f997538c..93f1046305 100644 --- a/vendor/league/commonmark/src/HtmlElement.php +++ b/vendor/league/commonmark/src/HtmlElement.php @@ -137,6 +137,8 @@ class HtmlElement if ($this->contents !== '') { $result .= '>' . $this->getContentsAsString() . '</' . $this->tagName . '>'; + } elseif ($this->selfClosing && $this->tagName === 'input') { + $result .= '>'; } elseif ($this->selfClosing) { $result .= ' />'; } else { diff --git a/vendor/league/commonmark/src/Inline/Parser/BacktickParser.php b/vendor/league/commonmark/src/Inline/Parser/BacktickParser.php index 608fa7b86a..896771e494 100644 --- a/vendor/league/commonmark/src/Inline/Parser/BacktickParser.php +++ b/vendor/league/commonmark/src/Inline/Parser/BacktickParser.php @@ -38,9 +38,6 @@ final class BacktickParser implements InlineParserInterface $cursor = $inlineContext->getCursor(); $ticks = $cursor->match('/^`+/'); - if ($ticks === '') { - return false; - } $currentPosition = $cursor->getPosition(); $previousState = $cursor->saveState(); @@ -53,7 +50,7 @@ final class BacktickParser implements InlineParserInterface if ( !empty($c) && - \substr($c, 0, 1) === ' ' && + $c[0] === ' ' && \substr($c, -1, 1) === ' ' && \preg_match('/[^ ]/', $c) ) { diff --git a/vendor/league/commonmark/src/Inline/Parser/CloseBracketParser.php b/vendor/league/commonmark/src/Inline/Parser/CloseBracketParser.php index 03c57ee648..f187e27686 100644 --- a/vendor/league/commonmark/src/Inline/Parser/CloseBracketParser.php +++ b/vendor/league/commonmark/src/Inline/Parser/CloseBracketParser.php @@ -68,7 +68,7 @@ final class CloseBracketParser implements InlineParserInterface, EnvironmentAwar $startPos = $cursor->getPosition(); $previousState = $cursor->saveState(); - $cursor->advance(); + $cursor->advanceBy(1); // Check to see if we have a link/image if (!($link = $this->tryParseLink($cursor, $inlineContext->getReferenceMap(), $opener, $startPos))) { @@ -149,7 +149,7 @@ final class CloseBracketParser implements InlineParserInterface, EnvironmentAwar $previousState = $cursor->saveState(); - $cursor->advance(); + $cursor->advanceBy(1); $cursor->advanceToNextNonSpaceOrNewline(); if (($dest = LinkParserHelper::parseLinkDestination($cursor)) === null) { $cursor->restoreState($previousState); @@ -167,12 +167,14 @@ final class CloseBracketParser implements InlineParserInterface, EnvironmentAwar $cursor->advanceToNextNonSpaceOrNewline(); - if ($cursor->match('/^\\)/') === null) { + if ($cursor->getCharacter() !== ')') { $cursor->restoreState($previousState); return false; } + $cursor->advanceBy(1); + return ['url' => $dest, 'title' => $title]; } diff --git a/vendor/league/commonmark/src/Inline/Parser/EscapableParser.php b/vendor/league/commonmark/src/Inline/Parser/EscapableParser.php index 6bbaf435dd..6da015e99e 100644 --- a/vendor/league/commonmark/src/Inline/Parser/EscapableParser.php +++ b/vendor/league/commonmark/src/Inline/Parser/EscapableParser.php @@ -37,10 +37,6 @@ final class EscapableParser implements InlineParserInterface public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); - if ($cursor->getCharacter() !== '\\') { - return false; - } - $nextChar = $cursor->peek(); if ($nextChar === "\n") { @@ -55,7 +51,7 @@ final class EscapableParser implements InlineParserInterface return true; } - $cursor->advance(); + $cursor->advanceBy(1); $inlineContext->getContainer()->appendChild(new Text('\\')); return true; diff --git a/vendor/league/commonmark/src/Inline/Parser/HtmlInlineParser.php b/vendor/league/commonmark/src/Inline/Parser/HtmlInlineParser.php index 8f0650ec8a..5dc52e11a4 100644 --- a/vendor/league/commonmark/src/Inline/Parser/HtmlInlineParser.php +++ b/vendor/league/commonmark/src/Inline/Parser/HtmlInlineParser.php @@ -35,8 +35,7 @@ final class HtmlInlineParser implements InlineParserInterface */ public function parse(InlineParserContext $inlineContext): bool { - $cursor = $inlineContext->getCursor(); - if ($m = $cursor->match('/^' . RegexHelper::PARTIAL_HTMLTAG . '/i')) { + if ($m = $inlineContext->getCursor()->match('/^' . RegexHelper::PARTIAL_HTMLTAG . '/i')) { $inlineContext->getContainer()->appendChild(new HtmlInline($m)); return true; diff --git a/vendor/league/commonmark/src/Inline/Parser/NewlineParser.php b/vendor/league/commonmark/src/Inline/Parser/NewlineParser.php index 6ac4077733..d32e8a37b4 100644 --- a/vendor/league/commonmark/src/Inline/Parser/NewlineParser.php +++ b/vendor/league/commonmark/src/Inline/Parser/NewlineParser.php @@ -35,12 +35,12 @@ final class NewlineParser implements InlineParserInterface */ public function parse(InlineParserContext $inlineContext): bool { - $inlineContext->getCursor()->advance(); + $inlineContext->getCursor()->advanceBy(1); // Check previous inline for trailing spaces $spaces = 0; $lastInline = $inlineContext->getContainer()->lastChild(); - if ($lastInline && $lastInline instanceof Text) { + if ($lastInline instanceof Text) { $trimmed = \rtrim($lastInline->getContent(), ' '); $spaces = \strlen($lastInline->getContent()) - \strlen($trimmed); if ($spaces) { diff --git a/vendor/league/commonmark/src/Inline/Parser/OpenBracketParser.php b/vendor/league/commonmark/src/Inline/Parser/OpenBracketParser.php index d11edc3039..06f52c84c4 100644 --- a/vendor/league/commonmark/src/Inline/Parser/OpenBracketParser.php +++ b/vendor/league/commonmark/src/Inline/Parser/OpenBracketParser.php @@ -35,11 +35,7 @@ final class OpenBracketParser implements InlineParserInterface */ public function parse(InlineParserContext $inlineContext): bool { - if ($inlineContext->getCursor()->getCharacter() !== '[') { - return false; - } - - $inlineContext->getCursor()->advance(); + $inlineContext->getCursor()->advanceBy(1); $node = new Text('[', ['delim' => true]); $inlineContext->getContainer()->appendChild($node); diff --git a/vendor/league/commonmark/src/InlineParserEngine.php b/vendor/league/commonmark/src/InlineParserEngine.php index f7d4b086d5..46469b3795 100644 --- a/vendor/league/commonmark/src/InlineParserEngine.php +++ b/vendor/league/commonmark/src/InlineParserEngine.php @@ -42,7 +42,8 @@ final class InlineParserEngine public function parse(AbstractStringContainerBlock $container, ReferenceMapInterface $referenceMap) { $inlineParserContext = new InlineParserContext($container, $referenceMap); - while (($character = $inlineParserContext->getCursor()->getCharacter()) !== null) { + $cursor = $inlineParserContext->getCursor(); + while (($character = $cursor->getCharacter()) !== null) { if (!$this->parseCharacter($character, $inlineParserContext)) { $this->addPlainText($character, $container, $inlineParserContext); } @@ -76,10 +77,10 @@ final class InlineParserEngine private function parseDelimiters(DelimiterProcessorInterface $delimiterProcessor, InlineParserContext $inlineContext): bool { - $character = $inlineContext->getCursor()->getCharacter(); + $cursor = $inlineContext->getCursor(); + $character = $cursor->getCharacter(); $numDelims = 0; - $cursor = $inlineContext->getCursor(); $charBefore = $cursor->peek(-1); if ($charBefore === null) { $charBefore = "\n"; @@ -102,7 +103,7 @@ final class InlineParserEngine list($canOpen, $canClose) = self::determineCanOpenOrClose($charBefore, $charAfter, $character, $delimiterProcessor); - $node = new Text($cursor->getPreviousText(), [ + $node = new Text(\str_repeat($character, $numDelims), [ 'delim' => true, ]); $inlineContext->getContainer()->appendChild($node); @@ -140,7 +141,7 @@ final class InlineParserEngine $text = $inlineParserContext->getCursor()->match($this->environment->getInlineParserCharacterRegex()); // This might fail if we're currently at a special character which wasn't parsed; if so, just add that character if ($text === null) { - $inlineParserContext->getCursor()->advance(); + $inlineParserContext->getCursor()->advanceBy(1); $text = $character; } diff --git a/vendor/league/commonmark/src/Reference/ReferenceParser.php b/vendor/league/commonmark/src/Reference/ReferenceParser.php index c9bea6b571..fb250e2a86 100644 --- a/vendor/league/commonmark/src/Reference/ReferenceParser.php +++ b/vendor/league/commonmark/src/Reference/ReferenceParser.php @@ -67,7 +67,7 @@ final class ReferenceParser } // Advance past the colon - $cursor->advance(); + $cursor->advanceBy(1); // Link URL $cursor->advanceToNextNonSpaceOrNewline(); diff --git a/vendor/league/commonmark/src/Util/LinkParserHelper.php b/vendor/league/commonmark/src/Util/LinkParserHelper.php index bfb01d5e08..95355a2f00 100644 --- a/vendor/league/commonmark/src/Util/LinkParserHelper.php +++ b/vendor/league/commonmark/src/Util/LinkParserHelper.php @@ -98,22 +98,22 @@ final class LinkParserHelper $openParens = 0; while (($c = $cursor->getCharacter()) !== null) { - if ($c === '\\' && RegexHelper::isEscapable($cursor->peek())) { + if ($c === '\\' && $cursor->peek() !== null && RegexHelper::isEscapable($cursor->peek())) { $cursor->advanceBy(2); } elseif ($c === '(') { - $cursor->advance(); + $cursor->advanceBy(1); $openParens++; } elseif ($c === ')') { if ($openParens < 1) { break; } - $cursor->advance(); + $cursor->advanceBy(1); $openParens--; } elseif (\preg_match(RegexHelper::REGEX_WHITESPACE_CHAR, $c)) { break; } else { - $cursor->advance(); + $cursor->advanceBy(1); } } diff --git a/vendor/league/flysystem/composer.json b/vendor/league/flysystem/composer.json index 92ab3889eb..72b0787c26 100644 --- a/vendor/league/flysystem/composer.json +++ b/vendor/league/flysystem/composer.json @@ -20,7 +20,7 @@ }, "require-dev": { "phpspec/phpspec": "^3.4", - "phpunit/phpunit": "^5.7.10" + "phpunit/phpunit": "^5.7.26" }, "autoload": { "psr-4": { diff --git a/vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php b/vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php index fb8aa49cfa..95a6b4d09e 100644 --- a/vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php +++ b/vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php @@ -558,7 +558,7 @@ abstract class AbstractFtpAdapter extends AbstractAdapter protected function normalizePermissions($permissions) { if (is_numeric($permissions)) { - return $permissions & 0777; + return ((int) $permissions) & 0777; } // remove the type identifier diff --git a/vendor/league/flysystem/src/Adapter/Ftp.php b/vendor/league/flysystem/src/Adapter/Ftp.php index cdaf711b21..7dfcc2b051 100644 --- a/vendor/league/flysystem/src/Adapter/Ftp.php +++ b/vendor/league/flysystem/src/Adapter/Ftp.php @@ -532,15 +532,8 @@ class Ftp extends AbstractFtpAdapter */ public function isConnected() { - try { - return is_resource($this->connection) && ftp_rawlist($this->connection, $this->getRoot()) !== false; - } catch (ErrorException $e) { - if (strpos($e->getMessage(), 'ftp_rawlist') === false) { - throw new ConnectionErrorException($e->getMessage()); - } - - return false; - } + return is_resource($this->connection) + && $this->getRawExecResponseCode('NOOP') === 200; } /** @@ -571,4 +564,11 @@ class Ftp extends AbstractFtpAdapter return ftp_rawlist($connection, $options . ' ' . $path); } + + private function getRawExecResponseCode($command) + { + $response = @ftp_raw($this->connection, trim($command)); + + return (int) preg_replace('/\D/', '', implode(' ', $response)); + } } |
