From 14b7a1aa49499a986f6d8a5bfd5d210cd79439be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 26 May 2015 16:20:45 +0200 Subject: [PATCH 001/231] Initial table extension for league/commonmark --- .formatter.yml | 13 +++++ .gitattributes | 5 ++ .gitignore | 4 ++ CHANGELOG.md | 7 +++ LICENSE | 19 ++++++ README.md | 50 ++++++++++++++++ composer.json | 32 +++++++++++ phpunit.xml.dist | 19 ++++++ src/Table.php | 118 ++++++++++++++++++++++++++++++++++++++ src/TableCell.php | 62 ++++++++++++++++++++ src/TableCellRenderer.php | 33 +++++++++++ src/TableExtension.php | 39 +++++++++++++ src/TableParser.php | 89 ++++++++++++++++++++++++++++ src/TableRenderer.php | 35 +++++++++++ src/TableRow.php | 46 +++++++++++++++ src/TableRowRenderer.php | 35 +++++++++++ src/TableRows.php | 54 +++++++++++++++++ src/TableRowsRenderer.php | 39 +++++++++++++ 18 files changed, 699 insertions(+) create mode 100644 .formatter.yml create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/Table.php create mode 100644 src/TableCell.php create mode 100644 src/TableCellRenderer.php create mode 100644 src/TableExtension.php create mode 100644 src/TableParser.php create mode 100644 src/TableRenderer.php create mode 100644 src/TableRow.php create mode 100644 src/TableRowRenderer.php create mode 100644 src/TableRows.php create mode 100644 src/TableRowsRenderer.php diff --git a/.formatter.yml b/.formatter.yml new file mode 100644 index 0000000000..e18428b4d7 --- /dev/null +++ b/.formatter.yml @@ -0,0 +1,13 @@ +use-sort: + sort-type: alph + +header: | + /* + * This is part of the webuni/commonmark-table-extension package. + * + * (c) Martin Hasoň + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..30a6771dd1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +/tests export-ignore +/.formatter.yml export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/phpunit.xml.dist export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..e975f4868b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/composer.lock +/phpunit.xml +/tests/ +/vendor/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..0f49bc4a02 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +0.1.0 +----- + + * Initial implementation diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..641237b61c --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Martin Hasoň + +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/README.md b/README.md new file mode 100644 index 0000000000..0610292a5c --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +CommonMark Table Extension +========================== + +The Table extension adds the ability to create tables in CommonMark documents. + +Installation +------------ + +This project can be installed via Composer: + + composer require webuni/commonmark-table-extension + +Usage +----- + +```php +use League\CommonMark\DocParser; +use League\CommonMark\Environment; +use League\CommonMark\HtmlRenderer; +use Webuni\CommonMark\TableExtension\TableExtension; + +$environment = Environment::createCommonMarkEnvironment(); +$environment->addExtension(new TableExtension()); + +$parser = new DocParser($environment); +$renderer = new HtmlRenderer($environment); + +// Here's our sample input +$markdown = '# Hello World!'; + +$documentAST = $parser->parse($markdown); +echo $renderer->renderBlock($documentAST); +``` + +Syntax +------ + +```markdown +th | th(center) | th(right) +---|:----------:|----------: +td | td | td +``` + +```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 | +``` + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..2d18971bb9 --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "webuni/commonmark-table-extension", + "type": "library", + "description": "The table extension for CommonMark PHP implementation", + "keywords": ["markdown","table","commonmark"], + "homepage": "https://github.com/webuni/commonmark-table-extension", + "license": "MIT", + "authors": [ + { + "name": "Martin Hasoň", + "email": "martin.hason@gmail.com", + "role": "Lead Developer" + } + ], + "require": { + "league/commonmark": ">=0.7" + }, + "require-dev": { + "league/commonmark": "@dev", + "phpunit/phpunit": "~4.3" + }, + "autoload": { + "psr-4": { + "Webuni\\CommonMark\\TableExtension\\": "src" + } + }, + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..6953ab54ff --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,19 @@ + + + + + + ./tests/ + + + diff --git a/src/Table.php b/src/Table.php new file mode 100644 index 0000000000..af49589643 --- /dev/null +++ b/src/Table.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\ContextInterface; +use League\CommonMark\Cursor; +use League\CommonMark\Util\ArrayCollection; +use League\CommonMark\Util\RegexHelper; + +class Table extends AbstractBlock +{ + private $head; + private $body; + private $columns; + + public function __construct($columns = array()) + { + parent::__construct(); + + $this->columns = $columns; + parent::addChild($this->head = new TableRows(TableRows::TYPE_HEAD)); + parent::addChild($this->body = new TableRows(TableRows::TYPE_BODY)); + } + + public function canContain(AbstractBlock $block) + { + return $block instanceof TableRows; + } + + public function acceptsLines() + { + return true; + } + + public function isCode() + { + return false; + } + + public function addChild(AbstractBlock $childBlock) + { + throw new \OutOfRangeException('The Table block has a fixed number children'); + } + + public function removeChild(AbstractBlock $childBlock) + { + throw new \OutOfRangeException('The Table block has a fixed number children'); + } + + public function replaceChild(ContextInterface $context, AbstractBlock $original, AbstractBlock $replacement) + { + throw new \OutOfRangeException('The Table block has a fixed number children'); + } + + public function getHead() + { + return $this->head; + } + + public function getBody() + { + return $this->body; + } + + public function matchesNextLine(Cursor $cursor) + { + return !$cursor->isBlank() && RegexHelper::matchAll(TableRow::REGEXP_CELLS, $cursor->getLine()); + } + + public function finalize(ContextInterface $context) + { + parent::finalize($context); + + $part = $this->head; + foreach ($this->getStrings() as $line) { + if (RegexHelper::matchAll(TableRow::REGEXP_DEFINITION, $line)) { + $part = $this->body; + continue; + } + + $part->addChild($row = new TableRow()); + $columns = RegexHelper::matchAll(TableRow::REGEXP_CELLS, $line); + foreach ($columns[0] as $i => $column) { + $row->addChild(new TableCell( + trim($column), + TableRows::TYPE_HEAD === $part->type ? TableCell::TYPE_HEAD : TableCell::TYPE_BODY, + isset($this->columns[$i]) ? $this->columns[$i] : null + )); + } + + if ($i >= count($this->columns) - 1) { + continue; + } + + for ($j = count($this->columns) - 1; $j > $i; $j--) { + $row->addChild(new TableCell('', TableRows::TYPE_HEAD === $part->type ? TableCell::TYPE_HEAD : TableCell::TYPE_BODY), null); + } + } + + $this->strings = new ArrayCollection(); + } + + public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + { + $cursor->advanceToFirstNonSpace(); + $this->addLine(trim($cursor->getRemainder())); + } +} diff --git a/src/TableCell.php b/src/TableCell.php new file mode 100644 index 0000000000..ce3f8a5156 --- /dev/null +++ b/src/TableCell.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Element\AbstractInlineContainer; +use League\CommonMark\ContextInterface; +use League\CommonMark\Cursor; + +class TableCell extends AbstractInlineContainer +{ + const TYPE_HEAD = 'th'; + const TYPE_BODY = 'td'; + + const ALIGN_LEFT = 'left'; + const ALIGN_RIGHT = 'right'; + const ALIGN_CENTER = 'center'; + + public $type = self::TYPE_BODY; + public $align; + + public function __construct($string = '', $type = self::TYPE_BODY, $align = null) + { + parent::__construct(); + $this->finalStringContents = $string; + $this->type = $type; + $this->align = $align; + } + + public function canContain(AbstractBlock $block) + { + return false; + } + + public function acceptsLines() + { + return false; + } + + public function isCode() + { + return false; + } + + public function matchesNextLine(Cursor $cursor) + { + return false; + } + + public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + { + } +} diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php new file mode 100644 index 0000000000..892a29e2ec --- /dev/null +++ b/src/TableCellRenderer.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\HtmlRendererInterface; + +class TableCellRenderer implements BlockRendererInterface +{ + public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + { + if (!($block instanceof TableCell)) { + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + } + + return new HtmlElement( + $block->type, + null === $block->align ? array() : array('align' => $block->align), + $htmlRenderer->renderInlines($block->getInlines()) + ); + } +} diff --git a/src/TableExtension.php b/src/TableExtension.php new file mode 100644 index 0000000000..659de9434f --- /dev/null +++ b/src/TableExtension.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Extension\Extension; + +class TableExtension extends Extension +{ + public function getBlockParsers() + { + return array( + new TableParser(), + ); + } + + public function getBlockRenderers() + { + return array( + __NAMESPACE__.'\\Table' => new TableRenderer(), + __NAMESPACE__.'\\TableRows' => new TableRowsRenderer(), + __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), + __NAMESPACE__.'\\TableCell' => new TableCellRenderer(), + ); + } + + public function getName() + { + return 'table'; + } +} diff --git a/src/TableParser.php b/src/TableParser.php new file mode 100644 index 0000000000..bf2568bb7f --- /dev/null +++ b/src/TableParser.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\Paragraph; +use League\CommonMark\Block\Parser\AbstractBlockParser; +use League\CommonMark\ContextInterface; +use League\CommonMark\Cursor; +use League\CommonMark\Util\RegexHelper; + +class TableParser extends AbstractBlockParser +{ + public function parse(ContextInterface $context, Cursor $cursor) + { + $container = $context->getContainer(); + if (!$container instanceof Paragraph) { + return false; + } + + $lines = $context->getContainer()->getStrings(); + if (count($lines) < 1) { + return false; + } + + $match = RegexHelper::matchAll(TableRow::REGEXP_DEFINITION, $cursor->getLine(), $cursor->getFirstNonSpacePosition()); + if ($match === null) { + return false; + } + + $columns = array(); + 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[] = null; + } + } + + $table = new Table($columns); + $table->addLine(trim(array_pop($lines))); + + if (count($lines) >= 1) { + $paragraph = new Paragraph(); + foreach ($lines as $line) { + $paragraph->addLine($line); + } + + $context->replaceContainerBlock($paragraph); + $container->addChild($table); + } else { + $context->replaceContainerBlock($table); + } + + return true; + } +} + + + + + + + + + + + + + + + + + + + + diff --git a/src/TableRenderer.php b/src/TableRenderer.php new file mode 100644 index 0000000000..131de3bd1c --- /dev/null +++ b/src/TableRenderer.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\HtmlRendererInterface; + +class TableRenderer implements BlockRendererInterface +{ + public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + { + if (!($block instanceof Table)) { + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + } + + $separator = $htmlRenderer->getOption('inner_separator', "\n"); + + return new HtmlElement( + 'table', + array(), + $separator . $htmlRenderer->renderBlocks($block->getChildren()) . $separator + ); + } +} diff --git a/src/TableRow.php b/src/TableRow.php new file mode 100644 index 0000000000..1b362e4a80 --- /dev/null +++ b/src/TableRow.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\ContextInterface; +use League\CommonMark\Cursor; + +class TableRow extends AbstractBlock +{ + const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; + const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\\\\|\\\\\||[^|`\\\\]+|`)+(?=\||$)/'; + + public function canContain(AbstractBlock $block) + { + return $block instanceof TableCell; + } + + public function acceptsLines() + { + return false; + } + + public function isCode() + { + return false; + } + + public function matchesNextLine(Cursor $cursor) + { + return false; + } + + public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + { + } +} diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php new file mode 100644 index 0000000000..2a31d46c9d --- /dev/null +++ b/src/TableRowRenderer.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\HtmlRendererInterface; + +class TableRowRenderer implements BlockRendererInterface +{ + public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + { + if (!($block instanceof TableRow)) { + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + } + + $separator = $htmlRenderer->getOption('inner_separator', "\n"); + + return new HtmlElement( + 'tr', + array(), + $separator . $htmlRenderer->renderBlocks($block->getChildren()) . $separator + ); + } +} diff --git a/src/TableRows.php b/src/TableRows.php new file mode 100644 index 0000000000..f1bda3e1f9 --- /dev/null +++ b/src/TableRows.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\ContextInterface; +use League\CommonMark\Cursor; + +class TableRows extends AbstractBlock +{ + const TYPE_HEAD = 'thead'; + const TYPE_BODY = 'tbody'; + + public $type = self::TYPE_BODY; + + public function __construct($type = self::TYPE_BODY) + { + parent::__construct(); + $this->type = $type; + } + + public function canContain(AbstractBlock $block) + { + return $block instanceof TableRow; + } + + public function acceptsLines() + { + return false; + } + + public function isCode() + { + return false; + } + + public function matchesNextLine(Cursor $cursor) + { + return false; + } + + public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + { + } +} diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php new file mode 100644 index 0000000000..3d5bd0cbc3 --- /dev/null +++ b/src/TableRowsRenderer.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\HtmlElement; +use League\CommonMark\HtmlRendererInterface; + +class TableRowsRenderer implements BlockRendererInterface +{ + public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + { + if (!($block instanceof TableRows)) { + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + } + + if (!$block->hasChildren()) { + return; + } + + $separator = $htmlRenderer->getOption('inner_separator', "\n"); + + return new HtmlElement( + $block->type, + array(), + $separator . $htmlRenderer->renderBlocks($block->getChildren()) . $separator + ); + } +} From 7272a1b6591dcd3380ac35be3044a856b0cb5be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jun 2015 10:08:44 +0200 Subject: [PATCH 002/231] Moved parsing logic from nodes to parser --- CHANGELOG.md | 3 +- README.md | 10 ++---- composer.json | 5 ++- src/Table.php | 46 +++--------------------- src/TableParser.php | 88 ++++++++++++++++++++++++++++----------------- src/TableRow.php | 3 -- 6 files changed, 67 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f49bc4a02..9caad2d6ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,4 +4,5 @@ CHANGELOG 0.1.0 ----- - * Initial implementation + * Implemented GFM tables + diff --git a/README.md b/README.md index 0610292a5c..8a6587cf08 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Usage ----- ```php +use League\CommonMark\Converter; use League\CommonMark\DocParser; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; @@ -22,14 +23,9 @@ use Webuni\CommonMark\TableExtension\TableExtension; $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new TableExtension()); -$parser = new DocParser($environment); -$renderer = new HtmlRenderer($environment); +$converter = new Converter(new DocParser($environment), new HtmlRenderer($environment)); -// Here's our sample input -$markdown = '# Hello World!'; - -$documentAST = $parser->parse($markdown); -echo $renderer->renderBlock($documentAST); +echo $converter->convertToHtml('# Hello World!'); ``` Syntax diff --git a/composer.json b/composer.json index 2d18971bb9..5a59ac2739 100644 --- a/composer.json +++ b/composer.json @@ -13,11 +13,10 @@ } ], "require": { - "league/commonmark": ">=0.7" + "league/commonmark": ">=0.9" }, "require-dev": { - "league/commonmark": "@dev", - "phpunit/phpunit": "~4.3" + "phpunit/phpunit": "^4.3" }, "autoload": { "psr-4": { diff --git a/src/Table.php b/src/Table.php index af49589643..d6c40f109d 100644 --- a/src/Table.php +++ b/src/Table.php @@ -14,22 +14,19 @@ use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -use League\CommonMark\Util\ArrayCollection; -use League\CommonMark\Util\RegexHelper; class Table extends AbstractBlock { private $head; private $body; - private $columns; + private $parser; - public function __construct($columns = array()) + public function __construct(\Closure $parser) { parent::__construct(); - - $this->columns = $columns; parent::addChild($this->head = new TableRows(TableRows::TYPE_HEAD)); parent::addChild($this->body = new TableRows(TableRows::TYPE_BODY)); + $this->parser = $parser; } public function canContain(AbstractBlock $block) @@ -74,45 +71,10 @@ public function getBody() public function matchesNextLine(Cursor $cursor) { - return !$cursor->isBlank() && RegexHelper::matchAll(TableRow::REGEXP_CELLS, $cursor->getLine()); - } - - public function finalize(ContextInterface $context) - { - parent::finalize($context); - - $part = $this->head; - foreach ($this->getStrings() as $line) { - if (RegexHelper::matchAll(TableRow::REGEXP_DEFINITION, $line)) { - $part = $this->body; - continue; - } - - $part->addChild($row = new TableRow()); - $columns = RegexHelper::matchAll(TableRow::REGEXP_CELLS, $line); - foreach ($columns[0] as $i => $column) { - $row->addChild(new TableCell( - trim($column), - TableRows::TYPE_HEAD === $part->type ? TableCell::TYPE_HEAD : TableCell::TYPE_BODY, - isset($this->columns[$i]) ? $this->columns[$i] : null - )); - } - - if ($i >= count($this->columns) - 1) { - continue; - } - - for ($j = count($this->columns) - 1; $j > $i; $j--) { - $row->addChild(new TableCell('', TableRows::TYPE_HEAD === $part->type ? TableCell::TYPE_HEAD : TableCell::TYPE_BODY), null); - } - } - - $this->strings = new ArrayCollection(); + return call_user_func($this->parser, $cursor); } public function handleRemainingContents(ContextInterface $context, Cursor $cursor) { - $cursor->advanceToFirstNonSpace(); - $this->addLine(trim($cursor->getRemainder())); } } diff --git a/src/TableParser.php b/src/TableParser.php index bf2568bb7f..33eeadbd27 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -19,38 +19,45 @@ class TableParser extends AbstractBlockParser { + const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; + const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\\\\|\\\\\||[^|`\\\\]+)+(?=\||$)/'; + public function parse(ContextInterface $context, Cursor $cursor) { $container = $context->getContainer(); + if (!$container instanceof Paragraph) { return false; } - $lines = $context->getContainer()->getStrings(); + $lines = $container->getStrings(); if (count($lines) < 1) { return false; } - $match = RegexHelper::matchAll(TableRow::REGEXP_DEFINITION, $cursor->getLine(), $cursor->getFirstNonSpacePosition()); - if ($match === null) { + $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $cursor->getFirstNonSpacePosition()); + if (null === $match) { return false; } - $columns = array(); - 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[] = null; - } + $columns = $this->parseColumns($match); + $row = $this->parseRow(trim(array_pop($lines)), $columns, TableCell::TYPE_HEAD); + if (null === $row) { + return false; } - $table = new Table($columns); - $table->addLine(trim(array_pop($lines))); + $table = new Table(function (Cursor $cursor) use (&$table, $columns) { + $row = $this->parseRow($cursor->getLine(), $columns); + if (null === $row) { + return false; + } + + $table->getBody()->addChild($row); + + return true; + }); + + $table->getHead()->addChild($row); if (count($lines) >= 1) { $paragraph = new Paragraph(); @@ -59,31 +66,48 @@ public function parse(ContextInterface $context, Cursor $cursor) } $context->replaceContainerBlock($paragraph); - $container->addChild($table); + $context->addBlock($table); } else { $context->replaceContainerBlock($table); } return true; } -} - - - - - - - - - - - - - - + private function parseColumns(array $match) + { + $columns = array(); + 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[] = null; + } + } + return $columns; + } + private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) + { + $cells = RegexHelper::matchAll(self::REGEXP_CELLS, $line); + if (null === $cells || !is_array($cells[0])) { + return null; + } + $row = new TableRow(); + foreach ($cells[0] as $i => $cell) { + $row->addChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); + } + for ($j = count($columns) - 1; $j > $i; $j--) { + $row->addChild(new TableCell('', $type, null)); + } + return $row; + } +} diff --git a/src/TableRow.php b/src/TableRow.php index 1b362e4a80..a0dc5ceb52 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -17,9 +17,6 @@ class TableRow extends AbstractBlock { - const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; - const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\\\\|\\\\\||[^|`\\\\]+|`)+(?=\||$)/'; - public function canContain(AbstractBlock $block) { return $block instanceof TableCell; From a3201f41b75c6a2629f41ff4a47a4b5e9f47e8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jun 2015 10:31:00 +0200 Subject: [PATCH 003/231] Fixed CS --- .formatter.yml | 13 ------------- .gitattributes | 5 +++-- .gitignore | 1 + .php_cs | 30 ++++++++++++++++++++++++++++++ composer.json | 3 ++- src/TableCellRenderer.php | 8 ++------ src/TableExtension.php | 12 ++++++------ src/TableParser.php | 6 +++--- src/TableRenderer.php | 8 ++------ src/TableRowRenderer.php | 8 ++------ src/TableRowsRenderer.php | 8 ++------ 11 files changed, 53 insertions(+), 49 deletions(-) delete mode 100644 .formatter.yml create mode 100644 .php_cs diff --git a/.formatter.yml b/.formatter.yml deleted file mode 100644 index e18428b4d7..0000000000 --- a/.formatter.yml +++ /dev/null @@ -1,13 +0,0 @@ -use-sort: - sort-type: alph - -header: | - /* - * This is part of the webuni/commonmark-table-extension package. - * - * (c) Martin Hasoň - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - diff --git a/.gitattributes b/.gitattributes index 30a6771dd1..0505009a18 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ -/tests export-ignore -/.formatter.yml export-ignore /.gitattributes export-ignore /.gitignore export-ignore +/.php_cs export-ignore +/.php_cs.cache export-ignore /phpunit.xml.dist export-ignore +/tests export-ignore diff --git a/.gitignore b/.gitignore index e975f4868b..076bfaae31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.php_cs.cache /composer.lock /phpunit.xml /tests/ diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000000..c115da7d67 --- /dev/null +++ b/.php_cs @@ -0,0 +1,30 @@ + + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF; + +Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($header); + +$finder = Symfony\CS\Finder\DefaultFinder::create() + ->in(array(__DIR__)) + ->exclude(array('Tests/Fixtures')) +; + +return Symfony\CS\Config\Config::create() + ->level(Symfony\CS\FixerInterface::SYMFONY_LEVEL) + ->fixers(array( + 'header_comment', + 'align_double_arrow', + 'newline_after_open_tag', + 'ordered_use', + 'short_array_syntax', + )) + ->setUsingCache(true) + ->finder($finder) +; diff --git a/composer.json b/composer.json index 5a59ac2739..0867185d16 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "league/commonmark": ">=0.9" }, "require-dev": { - "phpunit/phpunit": "^4.3" + "phpunit/phpunit": "^4.3", + "fabpot/php-cs-fixer": "^1.9" }, "autoload": { "psr-4": { diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 892a29e2ec..72e9e5e9ab 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -21,13 +21,9 @@ class TableCellRenderer implements BlockRendererInterface public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof TableCell)) { - throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } - return new HtmlElement( - $block->type, - null === $block->align ? array() : array('align' => $block->align), - $htmlRenderer->renderInlines($block->getInlines()) - ); + return new HtmlElement($block->type, null === $block->align ? [] : ['align' => $block->align], $htmlRenderer->renderInlines($block->getInlines())); } } diff --git a/src/TableExtension.php b/src/TableExtension.php index 659de9434f..03b8a46584 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -17,19 +17,19 @@ class TableExtension extends Extension { public function getBlockParsers() { - return array( + return [ new TableParser(), - ); + ]; } public function getBlockRenderers() { - return array( - __NAMESPACE__.'\\Table' => new TableRenderer(), + return [ + __NAMESPACE__.'\\Table' => new TableRenderer(), __NAMESPACE__.'\\TableRows' => new TableRowsRenderer(), - __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), + __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), __NAMESPACE__.'\\TableCell' => new TableCellRenderer(), - ); + ]; } public function getName() diff --git a/src/TableParser.php b/src/TableParser.php index 33eeadbd27..dd0c11b1dc 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -76,7 +76,7 @@ public function parse(ContextInterface $context, Cursor $cursor) private function parseColumns(array $match) { - $columns = 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; @@ -96,7 +96,7 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) { $cells = RegexHelper::matchAll(self::REGEXP_CELLS, $line); if (null === $cells || !is_array($cells[0])) { - return null; + return; } $row = new TableRow(); @@ -104,7 +104,7 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) $row->addChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); } - for ($j = count($columns) - 1; $j > $i; $j--) { + for ($j = count($columns) - 1; $j > $i; --$j) { $row->addChild(new TableCell('', $type, null)); } diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 131de3bd1c..f61de378d5 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -21,15 +21,11 @@ class TableRenderer implements BlockRendererInterface public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof Table)) { - throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement( - 'table', - array(), - $separator . $htmlRenderer->renderBlocks($block->getChildren()) . $separator - ); + return new HtmlElement('table', [], $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); } } diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index 2a31d46c9d..369e1768fc 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -21,15 +21,11 @@ class TableRowRenderer implements BlockRendererInterface public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof TableRow)) { - throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement( - 'tr', - array(), - $separator . $htmlRenderer->renderBlocks($block->getChildren()) . $separator - ); + return new HtmlElement('tr', [], $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); } } diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 3d5bd0cbc3..92e59f5580 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -21,7 +21,7 @@ class TableRowsRenderer implements BlockRendererInterface public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof TableRows)) { - throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); + throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } if (!$block->hasChildren()) { @@ -30,10 +30,6 @@ public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement( - $block->type, - array(), - $separator . $htmlRenderer->renderBlocks($block->getChildren()) . $separator - ); + return new HtmlElement($block->type, [], $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); } } From f74b4a7a30666dcd1e606428f984c1d04fbfe65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jun 2015 10:52:08 +0200 Subject: [PATCH 004/231] Used travis CI --- .gitattributes | 1 + .travis.yml | 23 +++++++++++++++++++++++ README.md | 2 ++ composer.json | 1 + 4 files changed, 27 insertions(+) create mode 100644 .travis.yml diff --git a/.gitattributes b/.gitattributes index 0505009a18..0643eb7535 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,5 +2,6 @@ /.gitignore export-ignore /.php_cs export-ignore /.php_cs.cache export-ignore +/.travis.yml export-ignore /phpunit.xml.dist export-ignore /tests export-ignore diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..aa2b43f2ea --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +language: php + +sudo: false + +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +cache: + directories: + - $HOME/.composer/cache + - vendor + +before_script: + - composer self-update + - composer install --prefer-source --no-interaction + +script: + - php vendor/bin/phpunit + - php vendor/bin/php-cs-fixer fix --dry-run diff --git a/README.md b/README.md index 8a6587cf08..fccbe91aff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ CommonMark Table Extension ========================== +[![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) + The Table extension adds the ability to create tables in CommonMark documents. Installation diff --git a/composer.json b/composer.json index 0867185d16..47e763021a 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ } ], "require": { + "php": ">=5.4", "league/commonmark": ">=0.9" }, "require-dev": { From 8c8a53e07619cefb44a9431c58fa3e58dc6554c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jun 2015 11:58:44 +0200 Subject: [PATCH 005/231] Added code quality badges --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fccbe91aff..8851bbcf24 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ CommonMark Table Extension ========================== [![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) +[![SensioLabsInsight](https://img.shields.io/sensiolabs/i/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b.svg?style=flat-square)](https://insight.sensiolabs.com/projects/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b) The Table extension adds the ability to create tables in CommonMark documents. @@ -11,7 +13,7 @@ Installation This project can be installed via Composer: composer require webuni/commonmark-table-extension - + Usage ----- From 34d17b90b4aa0d7ca48a761da13dc8bcc53a1350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jun 2015 12:08:37 +0200 Subject: [PATCH 006/231] Added packagist badget --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8851bbcf24..ebd1857bc6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ CommonMark Table Extension ========================== +[![Packagist](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg)](https://packagist.org/packages/webuni/commonmark-table-extension) [![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) [![SensioLabsInsight](https://img.shields.io/sensiolabs/i/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b.svg?style=flat-square)](https://insight.sensiolabs.com/projects/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b) From 3c66713747fbbe1c97d882f6d16a5dc69d466d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jun 2015 12:13:50 +0200 Subject: [PATCH 007/231] Updated version to 0.2 --- README.md | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ebd1857bc6..c09840523e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ CommonMark Table Extension ========================== -[![Packagist](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg)](https://packagist.org/packages/webuni/commonmark-table-extension) +[![Packagist](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg?style=flat-square)](https://packagist.org/packages/webuni/commonmark-table-extension) [![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) [![SensioLabsInsight](https://img.shields.io/sensiolabs/i/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b.svg?style=flat-square)](https://insight.sensiolabs.com/projects/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b) diff --git a/composer.json b/composer.json index 47e763021a..1786033fd8 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.1-dev" + "dev-master": "0.2-dev" } } } From b72053615ed59c39b91c9e70ef59d12d323270c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Mon, 27 Jul 2015 14:05:01 +0200 Subject: [PATCH 008/231] Updated to the new API --- composer.json | 4 ++-- src/TableCellRenderer.php | 4 ++-- src/TableRenderer.php | 4 ++-- src/TableRowRenderer.php | 4 ++-- src/TableRowsRenderer.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 1786033fd8..0bde323228 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": ">=5.4", - "league/commonmark": ">=0.9" + "league/commonmark": "0.10.*|0.11.*" }, "require-dev": { "phpunit/phpunit": "^4.3", @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.3-dev" } } } diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 72e9e5e9ab..dfebcd401a 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -13,12 +13,12 @@ use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\HtmlRendererInterface; class TableCellRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof TableCell)) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); diff --git a/src/TableRenderer.php b/src/TableRenderer.php index f61de378d5..ed0d113bba 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -13,12 +13,12 @@ use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\HtmlRendererInterface; class TableRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof Table)) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index 369e1768fc..c8f93d5814 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -13,12 +13,12 @@ use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\HtmlRendererInterface; class TableRowRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof TableRow)) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 92e59f5580..eadec9ec6d 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -13,12 +13,12 @@ use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\HtmlRendererInterface; class TableRowsRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, HtmlRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { if (!($block instanceof TableRows)) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); From d64d452d0d5800e168b0f105745677c2a61c5041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Mon, 27 Jul 2015 14:16:49 +0200 Subject: [PATCH 009/231] Added support for custom attributes in renderers --- composer.json | 2 +- src/TableCellRenderer.php | 11 ++++++++++- src/TableRenderer.php | 7 ++++++- src/TableRowRenderer.php | 7 ++++++- src/TableRowsRenderer.php | 7 ++++++- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 0bde323228..2cd7bbb495 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.3-dev" + "dev-master": "0.4-dev" } } } diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index dfebcd401a..90711bff4c 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -24,6 +24,15 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } - return new HtmlElement($block->type, null === $block->align ? [] : ['align' => $block->align], $htmlRenderer->renderInlines($block->getInlines())); + $attrs = []; + foreach ($block->getData('attributes', []) as $key => $value) { + $attrs[$key] = $htmlRenderer->escape($value, true); + } + + if ($block->align) { + $attrs['align'] = $block->align; + } + + return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->getInlines())); } } diff --git a/src/TableRenderer.php b/src/TableRenderer.php index ed0d113bba..60ec6fbfa0 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -24,8 +24,13 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } + $attrs = []; + foreach ($block->getData('attributes', []) as $key => $value) { + $attrs[$key] = $htmlRenderer->escape($value, true); + } + $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement('table', [], $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); + return new HtmlElement('table', $attrs, $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); } } diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index c8f93d5814..5366cf4636 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -24,8 +24,13 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } + $attrs = []; + foreach ($block->getData('attributes', []) as $key => $value) { + $attrs[$key] = $htmlRenderer->escape($value, true); + } + $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement('tr', [], $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); + return new HtmlElement('tr', $attrs, $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); } } diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index eadec9ec6d..3385e3163d 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -28,8 +28,13 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende return; } + $attrs = []; + foreach ($block->getData('attributes', []) as $key => $value) { + $attrs[$key] = $htmlRenderer->escape($value, true); + } + $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement($block->type, [], $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); + return new HtmlElement($block->type, $attrs, $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); } } From de8083ccfaa8ef9469c935f8493266eb81634dc1 Mon Sep 17 00:00:00 2001 From: Johan Meiring Date: Thu, 30 Jul 2015 09:32:17 +0200 Subject: [PATCH 010/231] first commit --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..eea3eb610e --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# commonmark-ext From d2ee2d6241d7d78ac42e5aaca202b4db5c451b24 Mon Sep 17 00:00:00 2001 From: Walther Lalk Date: Thu, 30 Jul 2015 09:48:06 +0200 Subject: [PATCH 011/231] Add skeleton files and basic composer file --- .gitignore | 1 + LICENSE | 24 ++++++++++++++++++++++++ composer.json | 19 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 composer.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..57872d0f1e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..a974ca1cd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +The MIT License + +uAfrica.com (http://uafrica.com) +Copyright (c), uAfrica.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. + +uAfrica.com diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..56844d2446 --- /dev/null +++ b/composer.json @@ -0,0 +1,19 @@ +{ + "name": "uafrica/commonmark-ext", + "description": "Extended parsers and renders for The PHP League CommonMark parser", + "require": { + "league/commonmark": "^0.10.0" + }, + "license": "MIT", + "authors": [ + { + "name": "Johan Meiring", + "email": "johan@uafrica.com" + } + ], + "autoload": { + "psr-4": { + "CommonMarkExt\\": "src/" + } + } +} From 55a87bf2c0706c93e3c30c2c8f1505cb3c32c29b Mon Sep 17 00:00:00 2001 From: Walther Lalk Date: Thu, 30 Jul 2015 09:58:24 +0200 Subject: [PATCH 012/231] Include phpunit --- composer.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 56844d2446..2dd42e1934 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,8 @@ "name": "uafrica/commonmark-ext", "description": "Extended parsers and renders for The PHP League CommonMark parser", "require": { - "league/commonmark": "^0.10.0" + "league/commonmark": "^0.10.0", + "phpunit/phpunit": "^4.7" }, "license": "MIT", "authors": [ @@ -15,5 +16,10 @@ "psr-4": { "CommonMarkExt\\": "src/" } - } + }, + "autoload-dev": { + "psr-4": { + "CommonMarkExt\\Tests\\": "tests/" + } + }, } From 7b005eceb83ee839e6dedb76eeb827dbe9e408c4 Mon Sep 17 00:00:00 2001 From: Walther Lalk Date: Thu, 30 Jul 2015 09:59:44 +0200 Subject: [PATCH 013/231] Remove silly comma --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2dd42e1934..3365f1ba58 100644 --- a/composer.json +++ b/composer.json @@ -21,5 +21,5 @@ "psr-4": { "CommonMarkExt\\Tests\\": "tests/" } - }, + } } From 8fa79ab7d9614e01887eb6cb7fd73b58d49afcd2 Mon Sep 17 00:00:00 2001 From: Johan Meiring Date: Thu, 30 Jul 2015 14:07:16 +0200 Subject: [PATCH 014/231] Adds code which seems to work --- .gitignore | 3 + README.md | 31 +++++- composer.json | 3 +- phpunit.xml.dist | 30 ++++++ src/Strikethrough/Strikethrough.php | 8 ++ src/Strikethrough/StrikethroughParser.php | 55 +++++++++++ src/Strikethrough/StrikethroughRenderer.php | 29 ++++++ tests/FakeHtmlRenderer.php | 95 +++++++++++++++++++ tests/StrikethroughTests/IntegrationTest.php | 51 ++++++++++ .../StrikethroughParserTest.php | 46 +++++++++ .../StrikethroughRendererTest.php | 43 +++++++++ 11 files changed, 392 insertions(+), 2 deletions(-) create mode 100644 phpunit.xml.dist create mode 100644 src/Strikethrough/Strikethrough.php create mode 100644 src/Strikethrough/StrikethroughParser.php create mode 100644 src/Strikethrough/StrikethroughRenderer.php create mode 100644 tests/FakeHtmlRenderer.php create mode 100644 tests/StrikethroughTests/IntegrationTest.php create mode 100644 tests/StrikethroughTests/StrikethroughParserTest.php create mode 100644 tests/StrikethroughTests/StrikethroughRendererTest.php diff --git a/.gitignore b/.gitignore index 57872d0f1e..7b43c0b61c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ /vendor/ +/build/ +/.idea/ +composer.lock \ No newline at end of file diff --git a/README.md b/README.md index eea3eb610e..85c94b9e68 100644 --- a/README.md +++ b/README.md @@ -1 +1,30 @@ -# commonmark-ext +# uafrica/commonmark-ext + +[![Latest Version](https://img.shields.io/packagist/v/uafrica/commonmark-ext.svg?style=flat-square)](https://packagist.org/packages/uafrica/commonmark-ext) +[![Software License](http://img.shields.io/badge/License-MIT-brightgreen.svg?style=flat-square)](LICENSE) + +**uafrica/commonmark-ext** is a collection of custom parsers and renderers for the [league-commonmark] Markdown +parsing engine, which itself is based on the CommonMark spec. + +## Current Custom Parsers and Renderers +* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. + +## Installation + +This project can be installed via [Composer]: + +``` bash +$ composer require uafrica/commonmark-ext +``` + +## Testing + +``` bash +$ ./vendor/bin/phpunit +``` + +## License + +**uafrica/commonmark-ext** is licensed under the MIT. See the `LICENSE` file for more details. + +[league-commonmark]: https://github.com/thephpleague/commonmark diff --git a/composer.json b/composer.json index 3365f1ba58..0ebc2ec085 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,7 @@ { "name": "uafrica/commonmark-ext", - "description": "Extended parsers and renders for The PHP League CommonMark parser", + "description": "Extended parsers and renderers for The PHP League CommonMark parser", + "keywords": ["markdown", "strikethrough", "strikeout", "commonmark"], "require": { "league/commonmark": "^0.10.0", "phpunit/phpunit": "^4.7" diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..3357af9425 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + tests + + + + + src/ + + + + + + + + + + + diff --git a/src/Strikethrough/Strikethrough.php b/src/Strikethrough/Strikethrough.php new file mode 100644 index 0000000000..62d9ccc6ab --- /dev/null +++ b/src/Strikethrough/Strikethrough.php @@ -0,0 +1,8 @@ +getCursor(); + $character = $cursor->getCharacter(); + if ($cursor->peek(1) !== $character) { + return false; + } + + $tildes = $cursor->match('/^~~+/'); + if ($tildes === '') { + return false; + } + $previous_state = $cursor->saveState(); + while ($matching_tildes = $cursor->match('/~~+/m')) { + if ($matching_tildes === $tildes) { + $text = mb_substr($cursor->getLine(), $previous_state->getCurrentPosition(), + $cursor->getPosition() - $previous_state->getCurrentPosition() - strlen($tildes), 'utf-8'); + $text = preg_replace('/[ \n]+/', ' ', $text); + $inline_context->getInlines() + ->add(new Strikethrough(trim($text))); + return true; + } + } + // If we got here, we didn't match a closing tilde pair sequence + $cursor->restoreState($previous_state); + $inline_context->getInlines() + ->add(new Text($tildes)); + + return true; + } +} diff --git a/src/Strikethrough/StrikethroughRenderer.php b/src/Strikethrough/StrikethroughRenderer.php new file mode 100644 index 0000000000..b27ab44aff --- /dev/null +++ b/src/Strikethrough/StrikethroughRenderer.php @@ -0,0 +1,29 @@ +getData('attributes', []) as $key => $value) { + $attrs[$key] = $htmlRenderer->escape($value, true); + } + + return new HtmlElement('del', $attrs, $htmlRenderer->escape($inline->getContent())); + } +} diff --git a/tests/FakeHtmlRenderer.php b/tests/FakeHtmlRenderer.php new file mode 100644 index 0000000000..380db6b9d4 --- /dev/null +++ b/tests/FakeHtmlRenderer.php @@ -0,0 +1,95 @@ + + * + * 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: https://github.com/thephpleague/commonmark/blob/master/LICENSE + */ + +namespace CommonMarkExt\Tests; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Inline\Element\AbstractInline; + +class FakeHtmlRenderer implements ElementRendererInterface +{ + protected $options; + + /** + * @param string $option + * @param mixed|null $value + */ + public function setOption($option, $value) + { + $this->options[$option] = $value; + } + + /** + * @param string $option + * @param mixed|null $default + * + * @return mixed|null + */ + public function getOption($option, $default = null) + { + if (!isset($this->options[$option])) { + return $default; + } + + return $this->options[$option]; + } + + /** + * @param string $string + * @param bool $preserveEntities + * + * @return string + */ + public function escape($string, $preserveEntities = false) + { + return '::escape::' . $string; + } + + /** + * @param AbstractInline[] $inlines + * + * @return string + */ + public function renderInlines($inlines) + { + return '::inlines::'; + } + + /** + * @param AbstractBlock $block + * @param bool $inTightList + * + * @throws \RuntimeException + * + * @return string + */ + public function renderBlock(AbstractBlock $block, $inTightList = false) + { + return '::block::'; + } + + /** + * @param AbstractBlock[] $blocks + * @param bool $inTightList + * + * @return string + */ + public function renderBlocks($blocks, $inTightList = false) + { + return '::blocks::'; + } +} diff --git a/tests/StrikethroughTests/IntegrationTest.php b/tests/StrikethroughTests/IntegrationTest.php new file mode 100644 index 0000000000..b39580c3e1 --- /dev/null +++ b/tests/StrikethroughTests/IntegrationTest.php @@ -0,0 +1,51 @@ +addInlineParser(new StrikethroughParser()); + $environment->addInlineRenderer('CommonMarkExt\Strikethrough\Strikethrough', new StrikethroughRenderer()); + + $parser = new DocParser($environment); + $renderer = new HtmlRenderer($environment); + + $document = $parser->parse($string); + + $html = $renderer->renderBlock($document); +// +// $converter = new CommonMarkConverter($environment->getConfig()); +// $html = $converter->convertToHtml($string); + + $this->assertSame($expected, $html); + } + + /** + * @return array + */ + public function dataForIntegrationTest() + { + return [ + ['This is a test without any strikethroughs', "

This is a test without any strikethroughs

\n"], + ['This is a test without any ~valid~ strikethroughs', "

This is a test without any ~valid~ strikethroughs

\n"], + ['This is a test `without` any ~valid~ strikethroughs', "

This is a test without any ~valid~ strikethroughs

\n"], + ['This is a ~~unit~~ integration test', "

This is a unit integration test

\n"], + ]; + } +} \ No newline at end of file diff --git a/tests/StrikethroughTests/StrikethroughParserTest.php b/tests/StrikethroughTests/StrikethroughParserTest.php new file mode 100644 index 0000000000..32b7366613 --- /dev/null +++ b/tests/StrikethroughTests/StrikethroughParserTest.php @@ -0,0 +1,46 @@ +advanceBy($first_tilde_pos); + $inline_context = new InlineParserContext($cursor); + $context_stub = $this->getMock('League\CommonMark\ContextInterface'); + $parser = new StrikethroughParser(); + $parser->parse($context_stub, $inline_context); + $inlines = $inline_context->getInlines(); + $this->assertCount(1, $inlines); + $this->assertTrue($inlines->first() instanceof Strikethrough); + /** @var Strikethrough $text */ + $text = $inlines->first(); + $this->assertEquals($expected, $text->getContent()); + } + + /** + * @return array + */ + public function dataForTestParse() + { + return [ + ['This is just an ~~integration~~ unit test', 'integration'], + ['Из: твоя ~~feature~~ ветка', 'feature'], + ['Из: твоя ~~тест~~ ветка', 'тест'], + ]; + } +} diff --git a/tests/StrikethroughTests/StrikethroughRendererTest.php b/tests/StrikethroughTests/StrikethroughRendererTest.php new file mode 100644 index 0000000000..b6f635baeb --- /dev/null +++ b/tests/StrikethroughTests/StrikethroughRendererTest.php @@ -0,0 +1,43 @@ +renderer = new StrikethroughRenderer(); + } + + public function testRender() + { + $inline = new Strikethrough('reviewed text'); + $inline->data['attributes'] = ['id' => 'id']; + $fake_renderer = new FakeHtmlRenderer(); + $result = $this->renderer->render($inline, $fake_renderer); + $this->assertTrue($result instanceof HtmlElement); + $this->assertEquals('del', $result->getTagName()); + $this->assertContains('reviewed text', $result->getContents(true)); + $this->assertEquals(['id' => '::escape::id'], $result->getAllAttributes()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRenderWithInvalidType() + { + $inline = $this->getMockForAbstractClass('League\CommonMark\Inline\Element\AbstractInline'); + $fake_renderer = new FakeHtmlRenderer(); + $this->renderer->render($inline, $fake_renderer); + } +} From e21a9321a28b0ace5d81cc0f493af79a81b79a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Mon, 21 Sep 2015 08:00:34 +0200 Subject: [PATCH 015/231] Updated to the new commonmark 0.11 API --- CHANGELOG.md | 19 +++++++++++++++++-- composer.json | 5 +++-- src/Table.php | 33 ++++++++++++--------------------- src/TableCell.php | 4 ++-- src/TableCellRenderer.php | 2 +- src/TableParser.php | 8 ++++---- src/TableRenderer.php | 2 +- src/TableRowRenderer.php | 2 +- src/TableRowsRenderer.php | 2 +- 9 files changed, 42 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9caad2d6ad..89775f81a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,23 @@ CHANGELOG ========= -0.1.0 ------ +0.4.0 (2015-09-21) +------------------ + + * Updated to the new commonmark 0.11 API + +0.3.0 (2015-07-27) +------------------ + + * Added support for custom attributes in renderers + +0.2.0 (2015-07-27) +------------------ + + * Updated to the new commonmark 0.10 API + +0.1.0 (2015-06-24) +------------------ * Implemented GFM tables diff --git a/composer.json b/composer.json index 2cd7bbb495..658a83c931 100644 --- a/composer.json +++ b/composer.json @@ -14,11 +14,12 @@ ], "require": { "php": ">=5.4", - "league/commonmark": "0.10.*|0.11.*" + "league/commonmark": "^0.11" }, "require-dev": { "phpunit/phpunit": "^4.3", - "fabpot/php-cs-fixer": "^1.9" + "fabpot/php-cs-fixer": "^1.9", + "symfony/var-dumper": "^2.7" }, "autoload": { "psr-4": { diff --git a/src/Table.php b/src/Table.php index d6c40f109d..0417a322d5 100644 --- a/src/Table.php +++ b/src/Table.php @@ -17,15 +17,13 @@ class Table extends AbstractBlock { - private $head; - private $body; private $parser; public function __construct(\Closure $parser) { parent::__construct(); - parent::addChild($this->head = new TableRows(TableRows::TYPE_HEAD)); - parent::addChild($this->body = new TableRows(TableRows::TYPE_BODY)); + $this->appendChild(new TableRows(TableRows::TYPE_HEAD)); + $this->appendChild(new TableRows(TableRows::TYPE_BODY)); $this->parser = $parser; } @@ -44,29 +42,22 @@ public function isCode() return false; } - public function addChild(AbstractBlock $childBlock) - { - throw new \OutOfRangeException('The Table block has a fixed number children'); - } - - public function removeChild(AbstractBlock $childBlock) - { - throw new \OutOfRangeException('The Table block has a fixed number children'); - } - - public function replaceChild(ContextInterface $context, AbstractBlock $original, AbstractBlock $replacement) - { - throw new \OutOfRangeException('The Table block has a fixed number children'); - } - public function getHead() { - return $this->head; + foreach ($this->children() as $child) { + if ($child instanceof TableRows && TableRows::TYPE_HEAD === $child->type) { + return $child; + } + } } public function getBody() { - return $this->body; + foreach ($this->children() as $child) { + if ($child instanceof TableRows && TableRows::TYPE_BODY === $child->type) { + return $child; + } + } } public function matchesNextLine(Cursor $cursor) diff --git a/src/TableCell.php b/src/TableCell.php index ce3f8a5156..1f2636783c 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -12,11 +12,11 @@ namespace Webuni\CommonMark\TableExtension; use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\Block\Element\AbstractInlineContainer; +use League\CommonMark\Block\Element\InlineContainer; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -class TableCell extends AbstractInlineContainer +class TableCell extends AbstractBlock implements InlineContainer { const TYPE_HEAD = 'th'; const TYPE_BODY = 'td'; diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 90711bff4c..6881ba60ed 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -33,6 +33,6 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs['align'] = $block->align; } - return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->getInlines())); + return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children())); } } diff --git a/src/TableParser.php b/src/TableParser.php index dd0c11b1dc..4aa844a47f 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -52,12 +52,12 @@ public function parse(ContextInterface $context, Cursor $cursor) return false; } - $table->getBody()->addChild($row); + $table->getBody()->appendChild($row); return true; }); - $table->getHead()->addChild($row); + $table->getHead()->appendChild($row); if (count($lines) >= 1) { $paragraph = new Paragraph(); @@ -101,11 +101,11 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) $row = new TableRow(); foreach ($cells[0] as $i => $cell) { - $row->addChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); + $row->appendChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); } for ($j = count($columns) - 1; $j > $i; --$j) { - $row->addChild(new TableCell('', $type, null)); + $row->appendChild(new TableCell('', $type, null)); } return $row; diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 60ec6fbfa0..5aaa6c0ad5 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -31,6 +31,6 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement('table', $attrs, $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); + return new HtmlElement('table', $attrs, $separator.$htmlRenderer->renderBlocks($block->children()).$separator); } } diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index 5366cf4636..75af83f23b 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -31,6 +31,6 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement('tr', $attrs, $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); + return new HtmlElement('tr', $attrs, $separator.$htmlRenderer->renderBlocks($block->children()).$separator); } } diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 3385e3163d..11ba185493 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -35,6 +35,6 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $separator = $htmlRenderer->getOption('inner_separator', "\n"); - return new HtmlElement($block->type, $attrs, $separator.$htmlRenderer->renderBlocks($block->getChildren()).$separator); + return new HtmlElement($block->type, $attrs, $separator.$htmlRenderer->renderBlocks($block->children()).$separator); } } From 569bdc491abe1dc25f2346e946b19695c4045e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 22 Sep 2015 23:06:47 +0200 Subject: [PATCH 016/231] Added missing tests --- .gitignore | 1 - src/Resources/commonmark-table.twig | 15 +++++ src/Table.php | 4 +- src/TableRows.php | 10 +++ tests/functional/LocalDataTest.php | 65 ++++++++++++++++++ tests/functional/data/aesthetic_table.html | 18 +++++ tests/functional/data/aesthetic_table.md | 4 ++ tests/functional/data/aligned_table.html | 21 ++++++ tests/functional/data/aligned_table.md | 4 ++ tests/functional/data/simple_table.html | 37 +++++++++++ tests/functional/data/simple_table.md | 11 ++++ tests/functional/data/table-aligned.html | 16 +++++ tests/functional/data/table-aligned.md | 3 + .../data/table-and-block-elements.html | 66 +++++++++++++++++++ .../data/table-and-block-elements.md | 28 ++++++++ .../data/table-inline-styles-in-cell.html | 14 ++++ .../data/table-inline-styles-in-cell.md | 3 + tests/functional/data/table-invalid-body.html | 16 +++++ tests/functional/data/table-invalid-body.md | 3 + tests/functional/data/table-outer-pipe.html | 14 ++++ tests/functional/data/table-outer-pipe.md | 3 + tests/functional/data/table-pipe-in-cell.html | 14 ++++ tests/functional/data/table-pipe-in-cell.md | 3 + tests/functional/data/table-zero.html | 14 ++++ tests/functional/data/table-zero.md | 3 + .../data/table_inline_markdown.html | 22 +++++++ .../functional/data/table_inline_markdown.md | 5 ++ tests/functional/data/untidy_table.html | 18 +++++ tests/functional/data/untidy_table.md | 4 ++ 29 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 src/Resources/commonmark-table.twig create mode 100644 tests/functional/LocalDataTest.php create mode 100644 tests/functional/data/aesthetic_table.html create mode 100644 tests/functional/data/aesthetic_table.md create mode 100644 tests/functional/data/aligned_table.html create mode 100644 tests/functional/data/aligned_table.md create mode 100644 tests/functional/data/simple_table.html create mode 100644 tests/functional/data/simple_table.md create mode 100644 tests/functional/data/table-aligned.html create mode 100644 tests/functional/data/table-aligned.md create mode 100644 tests/functional/data/table-and-block-elements.html create mode 100644 tests/functional/data/table-and-block-elements.md create mode 100644 tests/functional/data/table-inline-styles-in-cell.html create mode 100644 tests/functional/data/table-inline-styles-in-cell.md create mode 100644 tests/functional/data/table-invalid-body.html create mode 100644 tests/functional/data/table-invalid-body.md create mode 100644 tests/functional/data/table-outer-pipe.html create mode 100644 tests/functional/data/table-outer-pipe.md create mode 100644 tests/functional/data/table-pipe-in-cell.html create mode 100644 tests/functional/data/table-pipe-in-cell.md create mode 100644 tests/functional/data/table-zero.html create mode 100644 tests/functional/data/table-zero.md create mode 100644 tests/functional/data/table_inline_markdown.html create mode 100644 tests/functional/data/table_inline_markdown.md create mode 100644 tests/functional/data/untidy_table.html create mode 100644 tests/functional/data/untidy_table.md diff --git a/.gitignore b/.gitignore index 076bfaae31..ca07b308b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /.php_cs.cache /composer.lock /phpunit.xml -/tests/ /vendor/ diff --git a/src/Resources/commonmark-table.twig b/src/Resources/commonmark-table.twig new file mode 100644 index 0000000000..19e193b4d3 --- /dev/null +++ b/src/Resources/commonmark-table.twig @@ -0,0 +1,15 @@ +{% block table -%} + + {{ node }} +
+{% endblock %} + +{% block table_row -%} + + {{ node }} + +{% endblock %} + +{% block table_cell -%} + {{ node }} +{% endblock %} diff --git a/src/Table.php b/src/Table.php index 0417a322d5..81b76249b4 100644 --- a/src/Table.php +++ b/src/Table.php @@ -45,7 +45,7 @@ public function isCode() public function getHead() { foreach ($this->children() as $child) { - if ($child instanceof TableRows && TableRows::TYPE_HEAD === $child->type) { + if ($child instanceof TableRows && $child->isHead()) { return $child; } } @@ -54,7 +54,7 @@ public function getHead() public function getBody() { foreach ($this->children() as $child) { - if ($child instanceof TableRows && TableRows::TYPE_BODY === $child->type) { + if ($child instanceof TableRows && $child->isBody()) { return $child; } } diff --git a/src/TableRows.php b/src/TableRows.php index f1bda3e1f9..f288927f31 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -28,6 +28,16 @@ public function __construct($type = self::TYPE_BODY) $this->type = $type; } + public function isHead() + { + return self::TYPE_HEAD === $this->type; + } + + public function isBody() + { + return self::TYPE_BODY === $this->type; + } + public function canContain(AbstractBlock $block) { return $block instanceof TableRow; diff --git a/tests/functional/LocalDataTest.php b/tests/functional/LocalDataTest.php new file mode 100644 index 0000000000..51d8c8ec65 --- /dev/null +++ b/tests/functional/LocalDataTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension\tests\functional; + +use League\CommonMark\DocParser; +use League\CommonMark\Environment; +use League\CommonMark\HtmlRenderer; +use Webuni\CommonMark\TableExtension\TableExtension; + +class LocalDataTest extends \PHPUnit_Framework_TestCase +{ + private $parser; + private $renderer; + + protected function setUp() + { + $environemnt = Environment::createCommonMarkEnvironment(); + $environemnt->addExtension(new TableExtension()); + + $this->parser = new DocParser($environemnt); + $this->renderer = new HtmlRenderer($environemnt); + } + + /** + * @dataProvider dataProvider + */ + public function testExample($markdown, $html, $testName) + { + $documentAST = $this->parser->parse($markdown); + $actualResult = $this->renderer->renderBlock($documentAST); + + $failureMessage = sprintf('Unexpected result for "%s" test', $testName); + $failureMessage .= "\n=== markdown ===============\n".$markdown; + $failureMessage .= "\n=== expected ===============\n".$html; + $failureMessage .= "\n=== got ====================\n".$actualResult; + + $this->assertEquals($html, $actualResult, $failureMessage); + } + + /** + * @return array + */ + public function dataProvider() + { + $ret = []; + foreach (glob(__DIR__.'/data/*.md') as $markdownFile) { + $testName = basename($markdownFile, '.md'); + $markdown = file_get_contents($markdownFile); + $html = file_get_contents(__DIR__.'/data/'.$testName.'.html'); + + $ret[] = [$markdown, $html, $testName]; + } + + return $ret; + } +} diff --git a/tests/functional/data/aesthetic_table.html b/tests/functional/data/aesthetic_table.html new file mode 100644 index 0000000000..6415f820ac --- /dev/null +++ b/tests/functional/data/aesthetic_table.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +
header 1header 2
cell 1.1cell 1.2
cell 2.1cell 2.2
diff --git a/tests/functional/data/aesthetic_table.md b/tests/functional/data/aesthetic_table.md new file mode 100644 index 0000000000..f1a5ee6d19 --- /dev/null +++ b/tests/functional/data/aesthetic_table.md @@ -0,0 +1,4 @@ +| header 1 | header 2 | +| -------- | -------- | +| cell 1.1 | cell 1.2 | +| cell 2.1 | cell 2.2 | diff --git a/tests/functional/data/aligned_table.html b/tests/functional/data/aligned_table.html new file mode 100644 index 0000000000..4c1d319c57 --- /dev/null +++ b/tests/functional/data/aligned_table.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + +
header 1header 2header 2
cell 1.1cell 1.2cell 1.3
cell 2.1cell 2.2cell 2.3
diff --git a/tests/functional/data/aligned_table.md b/tests/functional/data/aligned_table.md new file mode 100644 index 0000000000..9d17610633 --- /dev/null +++ b/tests/functional/data/aligned_table.md @@ -0,0 +1,4 @@ +| header 1 | header 2 | header 2 | +| :------- | :------: | -------: | +| cell 1.1 | cell 1.2 | cell 1.3 | +| cell 2.1 | cell 2.2 | cell 2.3 | diff --git a/tests/functional/data/simple_table.html b/tests/functional/data/simple_table.html new file mode 100644 index 0000000000..d38b1df177 --- /dev/null +++ b/tests/functional/data/simple_table.html @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + +
header 1header 2
cell 1.1cell 1.2
cell 2.1cell 2.2
+
+ + + + + + + + + + + + + + + + + +
header 1header 2
cell 1.1cell 1.2
cell 2.1cell 2.2
diff --git a/tests/functional/data/simple_table.md b/tests/functional/data/simple_table.md new file mode 100644 index 0000000000..6312221f81 --- /dev/null +++ b/tests/functional/data/simple_table.md @@ -0,0 +1,11 @@ +header 1 | header 2 +-------- | -------- +cell 1.1 | cell 1.2 +cell 2.1 | cell 2.2 + +--- + +header 1 | header 2 +:------- | -------- +cell 1.1 | cell 1.2 +cell 2.1 | cell 2.2 diff --git a/tests/functional/data/table-aligned.html b/tests/functional/data/table-aligned.html new file mode 100644 index 0000000000..2fc996c9a8 --- /dev/null +++ b/tests/functional/data/table-aligned.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + +
thth(center)th(right)
tdtdtd
diff --git a/tests/functional/data/table-aligned.md b/tests/functional/data/table-aligned.md new file mode 100644 index 0000000000..4f6d5b3fd6 --- /dev/null +++ b/tests/functional/data/table-aligned.md @@ -0,0 +1,3 @@ +th | th(center) | th(right) +---|:----------:|----------: +td | td | td \ No newline at end of file diff --git a/tests/functional/data/table-and-block-elements.html b/tests/functional/data/table-and-block-elements.html new file mode 100644 index 0000000000..ce8168989a --- /dev/null +++ b/tests/functional/data/table-and-block-elements.html @@ -0,0 +1,66 @@ +

H1

+

H2

+ + + + + + + + + + + + + +
thth
tdtd
+
    +
  • list
  • +
  • list
  • +
+

Paragraph

+ + + + + + + + + + + + + +
thth
tdtd
+ + + + + + + + + + + + + +
thth
tdtd
+

Paragraph

+

Paragraph

+ + + + + + + + + + + + + +
thth
tdtd
+

Paragraph

diff --git a/tests/functional/data/table-and-block-elements.md b/tests/functional/data/table-and-block-elements.md new file mode 100644 index 0000000000..445973114d --- /dev/null +++ b/tests/functional/data/table-and-block-elements.md @@ -0,0 +1,28 @@ +H1 +==== + +H2 +---- + +th | th +---|--- +td | td + +* list +* list + +Paragraph +th | th +---|--- +td | td + +th | th +---|--- +td | td +Paragraph + +Paragraph +th | th +---|--- +td | td +Paragraph diff --git a/tests/functional/data/table-inline-styles-in-cell.html b/tests/functional/data/table-inline-styles-in-cell.html new file mode 100644 index 0000000000..cb2450a0e8 --- /dev/null +++ b/tests/functional/data/table-inline-styles-in-cell.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +
thth code
tdtd strong
diff --git a/tests/functional/data/table-inline-styles-in-cell.md b/tests/functional/data/table-inline-styles-in-cell.md new file mode 100644 index 0000000000..8ae10851ea --- /dev/null +++ b/tests/functional/data/table-inline-styles-in-cell.md @@ -0,0 +1,3 @@ +th | th `code` +---| ----------------- +td | td **strong** diff --git a/tests/functional/data/table-invalid-body.html b/tests/functional/data/table-invalid-body.html new file mode 100644 index 0000000000..6ec7a459ac --- /dev/null +++ b/tests/functional/data/table-invalid-body.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + +
ththth
tdtd
diff --git a/tests/functional/data/table-invalid-body.md b/tests/functional/data/table-invalid-body.md new file mode 100644 index 0000000000..7ef1ca806f --- /dev/null +++ b/tests/functional/data/table-invalid-body.md @@ -0,0 +1,3 @@ +th | th | th +---|----|---- +td | td diff --git a/tests/functional/data/table-outer-pipe.html b/tests/functional/data/table-outer-pipe.html new file mode 100644 index 0000000000..c7516473d9 --- /dev/null +++ b/tests/functional/data/table-outer-pipe.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +
thth
tdtd
diff --git a/tests/functional/data/table-outer-pipe.md b/tests/functional/data/table-outer-pipe.md new file mode 100644 index 0000000000..c20e45122c --- /dev/null +++ b/tests/functional/data/table-outer-pipe.md @@ -0,0 +1,3 @@ +| th | th | +| ---| -- +td | td | diff --git a/tests/functional/data/table-pipe-in-cell.html b/tests/functional/data/table-pipe-in-cell.html new file mode 100644 index 0000000000..2e8d7b4866 --- /dev/null +++ b/tests/functional/data/table-pipe-in-cell.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +
thth and |
t|dtd
diff --git a/tests/functional/data/table-pipe-in-cell.md b/tests/functional/data/table-pipe-in-cell.md new file mode 100644 index 0000000000..bf5f282d22 --- /dev/null +++ b/tests/functional/data/table-pipe-in-cell.md @@ -0,0 +1,3 @@ +| th | th and \| | +| ----- | ---------- | +| t\|d | td | diff --git a/tests/functional/data/table-zero.html b/tests/functional/data/table-zero.html new file mode 100644 index 0000000000..62b054c55a --- /dev/null +++ b/tests/functional/data/table-zero.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +
thth
0td
diff --git a/tests/functional/data/table-zero.md b/tests/functional/data/table-zero.md new file mode 100644 index 0000000000..291bf6478c --- /dev/null +++ b/tests/functional/data/table-zero.md @@ -0,0 +1,3 @@ +th | th +---| -- +0 | td diff --git a/tests/functional/data/table_inline_markdown.html b/tests/functional/data/table_inline_markdown.html new file mode 100644 index 0000000000..ac6b59796c --- /dev/null +++ b/tests/functional/data/table_inline_markdown.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + +
header 1header 2
cell 1.1cell 1.2
| 2.1| 2.2
\| 2.1link
diff --git a/tests/functional/data/table_inline_markdown.md b/tests/functional/data/table_inline_markdown.md new file mode 100644 index 0000000000..47d62ff8d7 --- /dev/null +++ b/tests/functional/data/table_inline_markdown.md @@ -0,0 +1,5 @@ +| _header_ 1 | **header 2** | +| ------------ | ------------ | +| _cell_ 1.1 | **cell** 1.2 | +| `|` 2.1 | \| 2.2 | +| `\|` 2.1 | [link](/) | diff --git a/tests/functional/data/untidy_table.html b/tests/functional/data/untidy_table.html new file mode 100644 index 0000000000..6415f820ac --- /dev/null +++ b/tests/functional/data/untidy_table.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +
header 1header 2
cell 1.1cell 1.2
cell 2.1cell 2.2
diff --git a/tests/functional/data/untidy_table.md b/tests/functional/data/untidy_table.md new file mode 100644 index 0000000000..cec6bfdb65 --- /dev/null +++ b/tests/functional/data/untidy_table.md @@ -0,0 +1,4 @@ +| header 1 | header 2 | +| ------------- | ----------- | +| cell 1.1 | cell 1.2 | +| cell 2.1 | cell 2.2 | From edbd1197bc1b2e1abef670f29754f40a989cca7e Mon Sep 17 00:00:00 2001 From: Walther Lalk Date: Thu, 29 Oct 2015 10:03:15 +0200 Subject: [PATCH 017/231] phpunit should be a dev dependency --- composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0ebc2ec085..f7b7989ec0 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,9 @@ "description": "Extended parsers and renderers for The PHP League CommonMark parser", "keywords": ["markdown", "strikethrough", "strikeout", "commonmark"], "require": { - "league/commonmark": "^0.10.0", + "league/commonmark": "^0.10.0" + }, + "require-dev": { "phpunit/phpunit": "^4.7" }, "license": "MIT", From 174a2729edb9b50c8fd66cad451a10ef1f12e31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 5 Nov 2015 15:44:58 +0100 Subject: [PATCH 018/231] Enabled a new release of commonmark library --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 658a83c931..daea3aa40a 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": ">=5.4", - "league/commonmark": "^0.11" + "league/commonmark": "^0.11|^0.12" }, "require-dev": { "phpunit/phpunit": "^4.3", From c4e70a3705f562cc08e0b6f80803dcfd0fa57173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Jan 2016 23:54:18 +0100 Subject: [PATCH 019/231] Enabled commonmark 0.13 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index daea3aa40a..28d8ea35d7 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": ">=5.4", - "league/commonmark": "^0.11|^0.12" + "league/commonmark": "^0.11|^0.12|^0.13" }, "require-dev": { "phpunit/phpunit": "^4.3", From 422113af98e5511fc94ae67d2c2c69536f146808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 5 Nov 2015 15:40:05 +0100 Subject: [PATCH 020/231] Add support for twig renderer --- .scrutinizer.yml | 5 ++ .styleci.yml | 9 ++++ CHANGELOG.md | 5 ++ composer.json | 1 + src/Resources/commonmark-table.html.twig | 29 ++++++++++++ src/Resources/commonmark-table.twig | 15 ------ tests/functional/LocalDataTest.php | 58 ++++++++++++++++++------ tests/functional/template.html.twig | 2 + 8 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 src/Resources/commonmark-table.html.twig delete mode 100644 src/Resources/commonmark-table.twig create mode 100644 tests/functional/template.html.twig diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..45b1aef3f4 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,5 @@ +tools: + external_code_coverage: + timeout: 900 + php_code_coverage: + enabled: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..41d199f406 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,9 @@ +preset: recommended + +enabled: + - concat_with_spaces + - strict + +disabled: + - concat_without_spaces + - phpdoc_short_description diff --git a/CHANGELOG.md b/CHANGELOG.md index 89775f81a0..6e5cbca4ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +0.5.0 (2015-09-28) +------------------ + + * Added a template for twig renderer + 0.4.0 (2015-09-21) ------------------ diff --git a/composer.json b/composer.json index 28d8ea35d7..a30eccf171 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "league/commonmark": "^0.11|^0.12|^0.13" }, "require-dev": { + "webuni/commonmark-twig-renderer": "~0.1", "phpunit/phpunit": "^4.3", "fabpot/php-cs-fixer": "^1.9", "symfony/var-dumper": "^2.7" diff --git a/src/Resources/commonmark-table.html.twig b/src/Resources/commonmark-table.html.twig new file mode 100644 index 0000000000..57bba893c6 --- /dev/null +++ b/src/Resources/commonmark-table.html.twig @@ -0,0 +1,29 @@ +{% block table -%} + + {{- options.inner_separator|default("\n") -}} + {{- block('_children') -}} + {{- options.inner_separator|default("\n") -}} + +{%- endblock %} + +{% block table_rows -%} + <{{node.type}}{{ block('_attributes') }}> + {{- options.inner_separator|default("\n") -}} + {{- block('_children') -}} + {{- options.inner_separator|default("\n") -}} + +{%- endblock %} + +{% block table_row -%} + + {{- options.inner_separator|default("\n") -}} + {{- block('_children') -}} + {{- options.inner_separator|default("\n") -}} + +{%- endblock %} + +{% block table_cell -%} + <{{ node.type }}{{ block('_attributes') }}{% if node.align %} align="{{ node.align }}"{% endif %}> + {{- block('_inline_children') -}} + +{%- endblock %} diff --git a/src/Resources/commonmark-table.twig b/src/Resources/commonmark-table.twig deleted file mode 100644 index 19e193b4d3..0000000000 --- a/src/Resources/commonmark-table.twig +++ /dev/null @@ -1,15 +0,0 @@ -{% block table -%} - - {{ node }} -
-{% endblock %} - -{% block table_row -%} - - {{ node }} - -{% endblock %} - -{% block table_cell -%} - {{ node }} -{% endblock %} diff --git a/tests/functional/LocalDataTest.php b/tests/functional/LocalDataTest.php index 51d8c8ec65..14f8b26f31 100644 --- a/tests/functional/LocalDataTest.php +++ b/tests/functional/LocalDataTest.php @@ -12,38 +12,57 @@ namespace Webuni\CommonMark\TableExtension\tests\functional; use League\CommonMark\DocParser; +use League\CommonMark\ElementRendererInterface; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; use Webuni\CommonMark\TableExtension\TableExtension; +use Webuni\CommonMark\TwigRenderer\CommonMarkTwigExtension; +use Webuni\CommonMark\TwigRenderer\TwigRenderer; class LocalDataTest extends \PHPUnit_Framework_TestCase { + /* @var Environment */ + private $environment; private $parser; - private $renderer; protected function setUp() { - $environemnt = Environment::createCommonMarkEnvironment(); - $environemnt->addExtension(new TableExtension()); + $this->environment = Environment::createCommonMarkEnvironment(); + $this->environment->addExtension(new TableExtension()); - $this->parser = new DocParser($environemnt); - $this->renderer = new HtmlRenderer($environemnt); + $this->parser = new DocParser($this->environment); } /** * @dataProvider dataProvider */ - public function testExample($markdown, $html, $testName) + public function testHtmlRenderer($markdown, $html, $testName) { - $documentAST = $this->parser->parse($markdown); - $actualResult = $this->renderer->renderBlock($documentAST); + $renderer = new HtmlRenderer($this->environment); + $this->assertCommonMark($renderer, $markdown, $html, $testName); + } - $failureMessage = sprintf('Unexpected result for "%s" test', $testName); - $failureMessage .= "\n=== markdown ===============\n".$markdown; - $failureMessage .= "\n=== expected ===============\n".$html; - $failureMessage .= "\n=== got ====================\n".$actualResult; + /** + * @dataProvider dataProvider + */ + public function testTwigRenderer($markdown, $html, $testName) + { + $loader = CommonMarkTwigExtension::createTwigLoader(); - $this->assertEquals($html, $actualResult, $failureMessage); + $ref = new \ReflectionClass('Webuni\CommonMark\TableExtension\TableExtension'); + $loader->addPath(dirname($ref->getFileName()).'/Resources'); + $loader->addPath(__DIR__); + + $twig = new \Twig_Environment($loader, [ + 'strict_variables' => true, + ]); + $twig->addExtension(new CommonMarkTwigExtension()); + + + $this->environment->mergeConfig(['renderer' => ['twig_template' => 'template.html.twig']]); + $renderer = new TwigRenderer($this->environment, $twig); + + $this->assertCommonMark($renderer, $markdown, $html, $testName); } /** @@ -62,4 +81,17 @@ public function dataProvider() return $ret; } + + private function assertCommonMark(ElementRendererInterface $renderer, $markdown, $html, $testName) + { + $documentAST = $this->parser->parse($markdown); + $actualResult = $renderer->renderBlock($documentAST); + + $failureMessage = sprintf('Unexpected result for "%s" test', $testName); + $failureMessage .= "\n=== markdown ===============\n".$markdown; + $failureMessage .= "\n=== expected ===============\n".$html; + $failureMessage .= "\n=== got ====================\n".$actualResult; + + $this->assertEquals($html, $actualResult, $failureMessage); + } } diff --git a/tests/functional/template.html.twig b/tests/functional/template.html.twig new file mode 100644 index 0000000000..856e46d65d --- /dev/null +++ b/tests/functional/template.html.twig @@ -0,0 +1,2 @@ +{% extends 'commonmark.html.twig' %} +{% use 'commonmark-table.html.twig' %} From 2158dbaec18f8cb9ea338bf4c320a98cac06de9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Jul 2016 16:42:23 +0200 Subject: [PATCH 021/231] Enable commonmark 0.14 and improve project setting --- .gitattributes | 3 ++- .php_cs | 28 ++++++++++------------------ .styleci.yml | 11 ++++------- .travis.yml | 25 ++++++++++++++----------- CHANGELOG.md | 5 +++-- LICENSE | 2 +- README.md | 1 + composer.json | 14 +++++++------- phpunit.xml.dist | 6 ++++++ 9 files changed, 48 insertions(+), 47 deletions(-) diff --git a/.gitattributes b/.gitattributes index 0643eb7535..7bdf2e0b8a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,7 +1,8 @@ /.gitattributes export-ignore /.gitignore export-ignore /.php_cs export-ignore -/.php_cs.cache export-ignore +/.scrutinizer.yml export-ignore +/.styleci.yml export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore /tests export-ignore diff --git a/.php_cs b/.php_cs index c115da7d67..99ca0bf476 100644 --- a/.php_cs +++ b/.php_cs @@ -1,30 +1,22 @@ +(c) Webuni s.r.o. For the full copyright and license information, please view the LICENSE file that was distributed with this source code. EOF; -Symfony\CS\Fixer\Contrib\HeaderCommentFixer::setHeader($header); - -$finder = Symfony\CS\Finder\DefaultFinder::create() - ->in(array(__DIR__)) - ->exclude(array('Tests/Fixtures')) -; +if (method_exists(HeaderCommentFixer::class, 'getHeader')) { + HeaderCommentFixer::setHeader($header); +} -return Symfony\CS\Config\Config::create() - ->level(Symfony\CS\FixerInterface::SYMFONY_LEVEL) - ->fixers(array( - 'header_comment', - 'align_double_arrow', - 'newline_after_open_tag', - 'ordered_use', - 'short_array_syntax', - )) - ->setUsingCache(true) - ->finder($finder) -; +return ConfigBridge::create(); diff --git a/.styleci.yml b/.styleci.yml index 41d199f406..b015c73cfb 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -1,9 +1,6 @@ -preset: recommended +preset: symfony enabled: - - concat_with_spaces - - strict - -disabled: - - concat_without_spaces - - phpdoc_short_description + - newline_after_open_tag + - ordered_use + - short_array_syntax diff --git a/.travis.yml b/.travis.yml index aa2b43f2ea..d1f59313b4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,22 +2,25 @@ language: php sudo: false -php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm - cache: directories: - $HOME/.composer/cache - - vendor + +matrix: + include: + - php: 5.5 + env: COMPOSER_FLAGS="--prefer-lowest" + - php: 5.6 + - php: 7.0 + env: PHPUNIT_COVERAGE="--coverage-clover coverage.clover" + - php: hhvm before_script: - composer self-update - - composer install --prefer-source --no-interaction + - composer update --prefer-dist --no-interaction $COMPOSER_FLAGS script: - - php vendor/bin/phpunit - - php vendor/bin/php-cs-fixer fix --dry-run + - vendor/bin/phpunit $PHPUNIT_COVERAGE + +after_script: + - if [[ "$PHPUNIT_COVERAGE" != "" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5cbca4ea..6fae3aa3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ CHANGELOG ========= -0.5.0 (2015-09-28) +0.5.0 (2016-07-13) ------------------ - * Added a template for twig renderer + * Added a template for twig renderer + * Updated to the commonmark 0.14 API 0.4.0 (2015-09-21) ------------------ diff --git a/LICENSE b/LICENSE index 641237b61c..a5d81ec8ac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015 Martin Hasoň +Copyright (c) Martin Hasoň Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c09840523e..ec6cb73075 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ CommonMark Table Extension [![Packagist](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg?style=flat-square)](https://packagist.org/packages/webuni/commonmark-table-extension) [![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) +[![StyleCI](https://styleci.io/repos/36301048/shield)](https://styleci.io/repos/36301048) [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) [![SensioLabsInsight](https://img.shields.io/sensiolabs/i/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b.svg?style=flat-square)](https://insight.sensiolabs.com/projects/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b) diff --git a/composer.json b/composer.json index a30eccf171..e8fe9f61d9 100644 --- a/composer.json +++ b/composer.json @@ -13,14 +13,14 @@ } ], "require": { - "php": ">=5.4", - "league/commonmark": "^0.11|^0.12|^0.13" + "php": "^5.5|^7.0", + "league/commonmark": "^0.11|^0.12|^0.13|^0.14" }, "require-dev": { - "webuni/commonmark-twig-renderer": "~0.1", - "phpunit/phpunit": "^4.3", - "fabpot/php-cs-fixer": "^1.9", - "symfony/var-dumper": "^2.7" + "webuni/commonmark-twig-renderer": "dev-master", + "phpunit/phpunit": "^4.3|^5.0", + "friendsofphp/php-cs-fixer": "^1.9", + "symfony/var-dumper": "^2.7|^3.0" }, "autoload": { "psr-4": { @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "0.5-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6953ab54ff..24053be817 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,4 +16,10 @@ ./tests/ + + + + src + + From e1e275393e8a00437854c8295852db7eb28b3711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Jul 2016 16:45:14 +0200 Subject: [PATCH 022/231] Fix CS --- composer.json | 1 + src/Table.php | 1 + src/TableCell.php | 1 + src/TableCellRenderer.php | 1 + src/TableExtension.php | 5 +++-- src/TableParser.php | 1 + src/TableRenderer.php | 1 + src/TableRow.php | 1 + src/TableRowRenderer.php | 1 + src/TableRows.php | 1 + src/TableRowsRenderer.php | 1 + tests/functional/LocalDataTest.php | 2 +- 12 files changed, 14 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index e8fe9f61d9..7f6d4762ce 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ "webuni/commonmark-twig-renderer": "dev-master", "phpunit/phpunit": "^4.3|^5.0", "friendsofphp/php-cs-fixer": "^1.9", + "sllh/php-cs-fixer-styleci-bridge": "^2.0", "symfony/var-dumper": "^2.7|^3.0" }, "autoload": { diff --git a/src/Table.php b/src/Table.php index 81b76249b4..89526a0db2 100644 --- a/src/Table.php +++ b/src/Table.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableCell.php b/src/TableCell.php index 1f2636783c..082cd00d76 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 6881ba60ed..f88443e873 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableExtension.php b/src/TableExtension.php index 03b8a46584..87acbde980 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -25,9 +26,9 @@ public function getBlockParsers() public function getBlockRenderers() { return [ - __NAMESPACE__.'\\Table' => new TableRenderer(), + __NAMESPACE__.'\\Table' => new TableRenderer(), __NAMESPACE__.'\\TableRows' => new TableRowsRenderer(), - __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), + __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), __NAMESPACE__.'\\TableCell' => new TableCellRenderer(), ]; } diff --git a/src/TableParser.php b/src/TableParser.php index 4aa844a47f..6499501a49 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 5aaa6c0ad5..78356955fa 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRow.php b/src/TableRow.php index a0dc5ceb52..3e772ca1b0 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index 75af83f23b..ca2aae8984 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRows.php b/src/TableRows.php index f288927f31..25e4604f5d 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 11ba185493..0f6a885c30 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/functional/LocalDataTest.php b/tests/functional/LocalDataTest.php index 14f8b26f31..5ca4d6419a 100644 --- a/tests/functional/LocalDataTest.php +++ b/tests/functional/LocalDataTest.php @@ -4,6 +4,7 @@ * This is part of the webuni/commonmark-table-extension package. * * (c) Martin Hasoň + * (c) Webuni s.r.o. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -58,7 +59,6 @@ public function testTwigRenderer($markdown, $html, $testName) ]); $twig->addExtension(new CommonMarkTwigExtension()); - $this->environment->mergeConfig(['renderer' => ['twig_template' => 'template.html.twig']]); $renderer = new TwigRenderer($this->environment, $twig); From ebe4b3997dcb466c966b2576d78cfd1ba39f3113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Jul 2016 23:19:59 +0200 Subject: [PATCH 023/231] Add support for table caption (MultiMarkdown) --- CHANGELOG.md | 1 + src/Resources/commonmark-table.html.twig | 7 ++++ src/Table.php | 23 ++++++++++- src/TableCaption.php | 49 ++++++++++++++++++++++++ src/TableCaptionRenderer.php | 39 +++++++++++++++++++ src/TableExtension.php | 1 + src/TableParser.php | 28 ++++++++++++-- tests/functional/data/table-caption.html | 41 ++++++++++++++++++++ tests/functional/data/table-caption.md | 11 ++++++ 9 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 src/TableCaption.php create mode 100644 src/TableCaptionRenderer.php create mode 100644 tests/functional/data/table-caption.html create mode 100644 tests/functional/data/table-caption.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fae3aa3d0..d379bb58eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 0.5.0 (2016-07-13) ------------------ + * Added support for table caption (MultiMarkdown) * Added a template for twig renderer * Updated to the commonmark 0.14 API diff --git a/src/Resources/commonmark-table.html.twig b/src/Resources/commonmark-table.html.twig index 57bba893c6..88adcefcd5 100644 --- a/src/Resources/commonmark-table.html.twig +++ b/src/Resources/commonmark-table.html.twig @@ -6,6 +6,13 @@ {%- endblock %} +{% block table_caption -%} + {% if node.id -%} + {% set attributes = { id: node.id } -%} + {% endif -%} + {% set attributes = none %}{{- block('_inline_children') -}} +{%- endblock %} + {% block table_rows -%} <{{node.type}}{{ block('_attributes') }}> {{- options.inner_separator|default("\n") -}} diff --git a/src/Table.php b/src/Table.php index 89526a0db2..b7dac6a7d6 100644 --- a/src/Table.php +++ b/src/Table.php @@ -30,7 +30,7 @@ public function __construct(\Closure $parser) public function canContain(AbstractBlock $block) { - return $block instanceof TableRows; + return $block instanceof TableRows || $block instanceof TableCaption; } public function acceptsLines() @@ -43,6 +43,27 @@ public function isCode() return false; } + public function setCaption(TableCaption $caption = null) + { + $node = $this->getCaption(); + if ($node instanceof TableCaption) { + $node->detach(); + } + + if ($caption instanceof TableCaption) { + $this->prependChild($caption); + } + } + + public function getCaption() + { + foreach ($this->children() as $child) { + if ($child instanceof TableCaption) { + return $child; + } + } + } + public function getHead() { foreach ($this->children() as $child) { diff --git a/src/TableCaption.php b/src/TableCaption.php new file mode 100644 index 0000000000..be4413fb1c --- /dev/null +++ b/src/TableCaption.php @@ -0,0 +1,49 @@ + + * (c) Webuni s.r.o. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Element\InlineContainer; +use League\CommonMark\Cursor; + +class TableCaption extends AbstractBlock implements InlineContainer +{ + public $id; + + public function __construct($caption, $id = null) + { + parent::__construct(); + $this->finalStringContents = $caption; + $this->id = $id; + } + + public function canContain(AbstractBlock $block) + { + return false; + } + + public function acceptsLines() + { + return false; + } + + public function isCode() + { + return false; + } + + public function matchesNextLine(Cursor $cursor) + { + return false; + } +} diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php new file mode 100644 index 0000000000..f845fccfd2 --- /dev/null +++ b/src/TableCaptionRenderer.php @@ -0,0 +1,39 @@ + + * (c) Webuni s.r.o. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Webuni\CommonMark\TableExtension; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Renderer\BlockRendererInterface; +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\HtmlElement; + +class TableCaptionRenderer implements BlockRendererInterface +{ + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + { + if (!($block instanceof TableCaption)) { + throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); + } + + $attrs = []; + foreach ($block->getData('attributes', []) as $key => $value) { + $attrs[$key] = $htmlRenderer->escape($value, true); + } + + if ($block->id) { + $attrs['id'] = $block->id; + } + + return new HtmlElement('caption', $attrs, $htmlRenderer->renderInlines($block->children())); + } +} diff --git a/src/TableExtension.php b/src/TableExtension.php index 87acbde980..30eb492793 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -27,6 +27,7 @@ public function getBlockRenderers() { return [ __NAMESPACE__.'\\Table' => new TableRenderer(), + __NAMESPACE__.'\\TableCaption' => new TableCaptionRenderer(), __NAMESPACE__.'\\TableRows' => new TableRowsRenderer(), __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), __NAMESPACE__.'\\TableCell' => new TableCellRenderer(), diff --git a/src/TableParser.php b/src/TableParser.php index 6499501a49..743c61c3d0 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -22,6 +22,7 @@ class TableParser extends AbstractBlockParser { const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\\\\|\\\\\||[^|`\\\\]+)+(?=\||$)/'; + const REGEXP_CAPTION = '/^\[(.+?)\](?:\[(.+)\])?\s*$/'; public function parse(ContextInterface $context, Cursor $cursor) { @@ -42,14 +43,24 @@ public function parse(ContextInterface $context, Cursor $cursor) } $columns = $this->parseColumns($match); - $row = $this->parseRow(trim(array_pop($lines)), $columns, TableCell::TYPE_HEAD); - if (null === $row) { + $head = $this->parseRow(trim(array_pop($lines)), $columns, TableCell::TYPE_HEAD); + if (null === $head) { return false; } $table = new Table(function (Cursor $cursor) use (&$table, $columns) { $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; } @@ -58,7 +69,7 @@ public function parse(ContextInterface $context, Cursor $cursor) return true; }); - $table->getHead()->appendChild($row); + $table->getHead()->appendChild($head); if (count($lines) >= 1) { $paragraph = new Paragraph(); @@ -111,4 +122,15 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) return $row; } + + private function parseCaption($line) + { + $caption = RegexHelper::matchAll(self::REGEXP_CAPTION, $line); + + if (null === $caption) { + return; + } + + return new TableCaption($caption[1], $caption[2]); + } } diff --git a/tests/functional/data/table-caption.html b/tests/functional/data/table-caption.html new file mode 100644 index 0000000000..94970e7e64 --- /dev/null +++ b/tests/functional/data/table-caption.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + +
Simple table
header 1header 2
cell 1.1cell 1.2
cell 2.1cell 2.2
+ + + + + + + + + + + + + + + + + + + + + +
Prototype table
First HeaderSecond HeaderThird Header
First rowDataVery long data entry
Second rowCellCell
diff --git a/tests/functional/data/table-caption.md b/tests/functional/data/table-caption.md new file mode 100644 index 0000000000..2c8a05bf58 --- /dev/null +++ b/tests/functional/data/table-caption.md @@ -0,0 +1,11 @@ +header 1 | header 2 +-------- | -------- +cell 1.1 | cell 1.2 +cell 2.1 | cell 2.2 +[Simple table] + +| First Header | Second Header | Third Header | +| :----------- | :-----------: | -------------------: | +| First row | Data | Very long data entry | +| Second row | **Cell** | *Cell* | +[*Prototype* table][reference_table] From 2807fe2f4c8ebf039a4f155550b8696ad03e1162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Sat, 24 Sep 2016 03:33:43 +0200 Subject: [PATCH 024/231] Fix tests namespace --- tests/{functional => Functional}/LocalDataTest.php | 2 +- tests/{functional => Functional}/data/aesthetic_table.html | 0 tests/{functional => Functional}/data/aesthetic_table.md | 0 tests/{functional => Functional}/data/aligned_table.html | 0 tests/{functional => Functional}/data/aligned_table.md | 0 tests/{functional => Functional}/data/simple_table.html | 0 tests/{functional => Functional}/data/simple_table.md | 0 tests/{functional => Functional}/data/table-aligned.html | 0 tests/{functional => Functional}/data/table-aligned.md | 0 .../data/table-and-block-elements.html | 0 .../{functional => Functional}/data/table-and-block-elements.md | 0 tests/{functional => Functional}/data/table-caption.html | 0 tests/{functional => Functional}/data/table-caption.md | 0 .../data/table-inline-styles-in-cell.html | 0 .../data/table-inline-styles-in-cell.md | 0 tests/{functional => Functional}/data/table-invalid-body.html | 0 tests/{functional => Functional}/data/table-invalid-body.md | 0 tests/{functional => Functional}/data/table-outer-pipe.html | 0 tests/{functional => Functional}/data/table-outer-pipe.md | 0 tests/{functional => Functional}/data/table-pipe-in-cell.html | 0 tests/{functional => Functional}/data/table-pipe-in-cell.md | 0 tests/{functional => Functional}/data/table-zero.html | 0 tests/{functional => Functional}/data/table-zero.md | 0 .../{functional => Functional}/data/table_inline_markdown.html | 0 tests/{functional => Functional}/data/table_inline_markdown.md | 0 tests/{functional => Functional}/data/untidy_table.html | 0 tests/{functional => Functional}/data/untidy_table.md | 0 tests/{functional => Functional}/template.html.twig | 0 28 files changed, 1 insertion(+), 1 deletion(-) rename tests/{functional => Functional}/LocalDataTest.php (98%) rename tests/{functional => Functional}/data/aesthetic_table.html (100%) rename tests/{functional => Functional}/data/aesthetic_table.md (100%) rename tests/{functional => Functional}/data/aligned_table.html (100%) rename tests/{functional => Functional}/data/aligned_table.md (100%) rename tests/{functional => Functional}/data/simple_table.html (100%) rename tests/{functional => Functional}/data/simple_table.md (100%) rename tests/{functional => Functional}/data/table-aligned.html (100%) rename tests/{functional => Functional}/data/table-aligned.md (100%) rename tests/{functional => Functional}/data/table-and-block-elements.html (100%) rename tests/{functional => Functional}/data/table-and-block-elements.md (100%) rename tests/{functional => Functional}/data/table-caption.html (100%) rename tests/{functional => Functional}/data/table-caption.md (100%) rename tests/{functional => Functional}/data/table-inline-styles-in-cell.html (100%) rename tests/{functional => Functional}/data/table-inline-styles-in-cell.md (100%) rename tests/{functional => Functional}/data/table-invalid-body.html (100%) rename tests/{functional => Functional}/data/table-invalid-body.md (100%) rename tests/{functional => Functional}/data/table-outer-pipe.html (100%) rename tests/{functional => Functional}/data/table-outer-pipe.md (100%) rename tests/{functional => Functional}/data/table-pipe-in-cell.html (100%) rename tests/{functional => Functional}/data/table-pipe-in-cell.md (100%) rename tests/{functional => Functional}/data/table-zero.html (100%) rename tests/{functional => Functional}/data/table-zero.md (100%) rename tests/{functional => Functional}/data/table_inline_markdown.html (100%) rename tests/{functional => Functional}/data/table_inline_markdown.md (100%) rename tests/{functional => Functional}/data/untidy_table.html (100%) rename tests/{functional => Functional}/data/untidy_table.md (100%) rename tests/{functional => Functional}/template.html.twig (100%) diff --git a/tests/functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php similarity index 98% rename from tests/functional/LocalDataTest.php rename to tests/Functional/LocalDataTest.php index 5ca4d6419a..b57c367e85 100644 --- a/tests/functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -10,7 +10,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension\tests\functional; +namespace Webuni\CommonMark\TableExtension\Tests\Functional; use League\CommonMark\DocParser; use League\CommonMark\ElementRendererInterface; diff --git a/tests/functional/data/aesthetic_table.html b/tests/Functional/data/aesthetic_table.html similarity index 100% rename from tests/functional/data/aesthetic_table.html rename to tests/Functional/data/aesthetic_table.html diff --git a/tests/functional/data/aesthetic_table.md b/tests/Functional/data/aesthetic_table.md similarity index 100% rename from tests/functional/data/aesthetic_table.md rename to tests/Functional/data/aesthetic_table.md diff --git a/tests/functional/data/aligned_table.html b/tests/Functional/data/aligned_table.html similarity index 100% rename from tests/functional/data/aligned_table.html rename to tests/Functional/data/aligned_table.html diff --git a/tests/functional/data/aligned_table.md b/tests/Functional/data/aligned_table.md similarity index 100% rename from tests/functional/data/aligned_table.md rename to tests/Functional/data/aligned_table.md diff --git a/tests/functional/data/simple_table.html b/tests/Functional/data/simple_table.html similarity index 100% rename from tests/functional/data/simple_table.html rename to tests/Functional/data/simple_table.html diff --git a/tests/functional/data/simple_table.md b/tests/Functional/data/simple_table.md similarity index 100% rename from tests/functional/data/simple_table.md rename to tests/Functional/data/simple_table.md diff --git a/tests/functional/data/table-aligned.html b/tests/Functional/data/table-aligned.html similarity index 100% rename from tests/functional/data/table-aligned.html rename to tests/Functional/data/table-aligned.html diff --git a/tests/functional/data/table-aligned.md b/tests/Functional/data/table-aligned.md similarity index 100% rename from tests/functional/data/table-aligned.md rename to tests/Functional/data/table-aligned.md diff --git a/tests/functional/data/table-and-block-elements.html b/tests/Functional/data/table-and-block-elements.html similarity index 100% rename from tests/functional/data/table-and-block-elements.html rename to tests/Functional/data/table-and-block-elements.html diff --git a/tests/functional/data/table-and-block-elements.md b/tests/Functional/data/table-and-block-elements.md similarity index 100% rename from tests/functional/data/table-and-block-elements.md rename to tests/Functional/data/table-and-block-elements.md diff --git a/tests/functional/data/table-caption.html b/tests/Functional/data/table-caption.html similarity index 100% rename from tests/functional/data/table-caption.html rename to tests/Functional/data/table-caption.html diff --git a/tests/functional/data/table-caption.md b/tests/Functional/data/table-caption.md similarity index 100% rename from tests/functional/data/table-caption.md rename to tests/Functional/data/table-caption.md diff --git a/tests/functional/data/table-inline-styles-in-cell.html b/tests/Functional/data/table-inline-styles-in-cell.html similarity index 100% rename from tests/functional/data/table-inline-styles-in-cell.html rename to tests/Functional/data/table-inline-styles-in-cell.html diff --git a/tests/functional/data/table-inline-styles-in-cell.md b/tests/Functional/data/table-inline-styles-in-cell.md similarity index 100% rename from tests/functional/data/table-inline-styles-in-cell.md rename to tests/Functional/data/table-inline-styles-in-cell.md diff --git a/tests/functional/data/table-invalid-body.html b/tests/Functional/data/table-invalid-body.html similarity index 100% rename from tests/functional/data/table-invalid-body.html rename to tests/Functional/data/table-invalid-body.html diff --git a/tests/functional/data/table-invalid-body.md b/tests/Functional/data/table-invalid-body.md similarity index 100% rename from tests/functional/data/table-invalid-body.md rename to tests/Functional/data/table-invalid-body.md diff --git a/tests/functional/data/table-outer-pipe.html b/tests/Functional/data/table-outer-pipe.html similarity index 100% rename from tests/functional/data/table-outer-pipe.html rename to tests/Functional/data/table-outer-pipe.html diff --git a/tests/functional/data/table-outer-pipe.md b/tests/Functional/data/table-outer-pipe.md similarity index 100% rename from tests/functional/data/table-outer-pipe.md rename to tests/Functional/data/table-outer-pipe.md diff --git a/tests/functional/data/table-pipe-in-cell.html b/tests/Functional/data/table-pipe-in-cell.html similarity index 100% rename from tests/functional/data/table-pipe-in-cell.html rename to tests/Functional/data/table-pipe-in-cell.html diff --git a/tests/functional/data/table-pipe-in-cell.md b/tests/Functional/data/table-pipe-in-cell.md similarity index 100% rename from tests/functional/data/table-pipe-in-cell.md rename to tests/Functional/data/table-pipe-in-cell.md diff --git a/tests/functional/data/table-zero.html b/tests/Functional/data/table-zero.html similarity index 100% rename from tests/functional/data/table-zero.html rename to tests/Functional/data/table-zero.html diff --git a/tests/functional/data/table-zero.md b/tests/Functional/data/table-zero.md similarity index 100% rename from tests/functional/data/table-zero.md rename to tests/Functional/data/table-zero.md diff --git a/tests/functional/data/table_inline_markdown.html b/tests/Functional/data/table_inline_markdown.html similarity index 100% rename from tests/functional/data/table_inline_markdown.html rename to tests/Functional/data/table_inline_markdown.html diff --git a/tests/functional/data/table_inline_markdown.md b/tests/Functional/data/table_inline_markdown.md similarity index 100% rename from tests/functional/data/table_inline_markdown.md rename to tests/Functional/data/table_inline_markdown.md diff --git a/tests/functional/data/untidy_table.html b/tests/Functional/data/untidy_table.html similarity index 100% rename from tests/functional/data/untidy_table.html rename to tests/Functional/data/untidy_table.html diff --git a/tests/functional/data/untidy_table.md b/tests/Functional/data/untidy_table.md similarity index 100% rename from tests/functional/data/untidy_table.md rename to tests/Functional/data/untidy_table.md diff --git a/tests/functional/template.html.twig b/tests/Functional/template.html.twig similarity index 100% rename from tests/functional/template.html.twig rename to tests/Functional/template.html.twig From 6a83cf94ea96cf4060d2ba66f78de07b307e8ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Sat, 24 Sep 2016 03:36:28 +0200 Subject: [PATCH 025/231] Move support for twig renderer to another repository --- composer.json | 1 - src/Resources/commonmark-table.html.twig | 36 ------------------------ tests/Functional/LocalDataTest.php | 28 ++---------------- tests/Functional/template.html.twig | 2 -- 4 files changed, 2 insertions(+), 65 deletions(-) delete mode 100644 src/Resources/commonmark-table.html.twig delete mode 100644 tests/Functional/template.html.twig diff --git a/composer.json b/composer.json index 7f6d4762ce..2b0f318949 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,6 @@ "league/commonmark": "^0.11|^0.12|^0.13|^0.14" }, "require-dev": { - "webuni/commonmark-twig-renderer": "dev-master", "phpunit/phpunit": "^4.3|^5.0", "friendsofphp/php-cs-fixer": "^1.9", "sllh/php-cs-fixer-styleci-bridge": "^2.0", diff --git a/src/Resources/commonmark-table.html.twig b/src/Resources/commonmark-table.html.twig deleted file mode 100644 index 88adcefcd5..0000000000 --- a/src/Resources/commonmark-table.html.twig +++ /dev/null @@ -1,36 +0,0 @@ -{% block table -%} - - {{- options.inner_separator|default("\n") -}} - {{- block('_children') -}} - {{- options.inner_separator|default("\n") -}} - -{%- endblock %} - -{% block table_caption -%} - {% if node.id -%} - {% set attributes = { id: node.id } -%} - {% endif -%} - {% set attributes = none %}{{- block('_inline_children') -}} -{%- endblock %} - -{% block table_rows -%} - <{{node.type}}{{ block('_attributes') }}> - {{- options.inner_separator|default("\n") -}} - {{- block('_children') -}} - {{- options.inner_separator|default("\n") -}} - -{%- endblock %} - -{% block table_row -%} - - {{- options.inner_separator|default("\n") -}} - {{- block('_children') -}} - {{- options.inner_separator|default("\n") -}} - -{%- endblock %} - -{% block table_cell -%} - <{{ node.type }}{{ block('_attributes') }}{% if node.align %} align="{{ node.align }}"{% endif %}> - {{- block('_inline_children') -}} - -{%- endblock %} diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index b57c367e85..8aaabcedae 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -17,8 +17,6 @@ use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; use Webuni\CommonMark\TableExtension\TableExtension; -use Webuni\CommonMark\TwigRenderer\CommonMarkTwigExtension; -use Webuni\CommonMark\TwigRenderer\TwigRenderer; class LocalDataTest extends \PHPUnit_Framework_TestCase { @@ -37,34 +35,12 @@ protected function setUp() /** * @dataProvider dataProvider */ - public function testHtmlRenderer($markdown, $html, $testName) + public function testRenderer($markdown, $html, $testName) { $renderer = new HtmlRenderer($this->environment); $this->assertCommonMark($renderer, $markdown, $html, $testName); } - /** - * @dataProvider dataProvider - */ - public function testTwigRenderer($markdown, $html, $testName) - { - $loader = CommonMarkTwigExtension::createTwigLoader(); - - $ref = new \ReflectionClass('Webuni\CommonMark\TableExtension\TableExtension'); - $loader->addPath(dirname($ref->getFileName()).'/Resources'); - $loader->addPath(__DIR__); - - $twig = new \Twig_Environment($loader, [ - 'strict_variables' => true, - ]); - $twig->addExtension(new CommonMarkTwigExtension()); - - $this->environment->mergeConfig(['renderer' => ['twig_template' => 'template.html.twig']]); - $renderer = new TwigRenderer($this->environment, $twig); - - $this->assertCommonMark($renderer, $markdown, $html, $testName); - } - /** * @return array */ @@ -82,7 +58,7 @@ public function dataProvider() return $ret; } - private function assertCommonMark(ElementRendererInterface $renderer, $markdown, $html, $testName) + protected function assertCommonMark(ElementRendererInterface $renderer, $markdown, $html, $testName) { $documentAST = $this->parser->parse($markdown); $actualResult = $renderer->renderBlock($documentAST); diff --git a/tests/Functional/template.html.twig b/tests/Functional/template.html.twig deleted file mode 100644 index 856e46d65d..0000000000 --- a/tests/Functional/template.html.twig +++ /dev/null @@ -1,2 +0,0 @@ -{% extends 'commonmark.html.twig' %} -{% use 'commonmark-table.html.twig' %} From 96df6e4631224a401d1382252f246c858eb48684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Goetz?= Date: Thu, 22 Sep 2016 22:32:00 +0200 Subject: [PATCH 026/231] Add support for commonmark 0.15 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2b0f318949..5018a7761b 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": "^5.5|^7.0", - "league/commonmark": "^0.11|^0.12|^0.13|^0.14" + "league/commonmark": "^0.11|^0.12|^0.13|^0.14|^0.15" }, "require-dev": { "phpunit/phpunit": "^4.3|^5.0", From b11075791819972687096479a513e265d0709a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Goetz?= Date: Thu, 22 Sep 2016 22:41:30 +0200 Subject: [PATCH 027/231] Improve test matrix --- .travis.yml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index d1f59313b4..71314f5ba4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,17 +6,24 @@ cache: directories: - $HOME/.composer/cache -matrix: - include: - - php: 5.5 - env: COMPOSER_FLAGS="--prefer-lowest" - - php: 5.6 - - php: 7.0 - env: PHPUNIT_COVERAGE="--coverage-clover coverage.clover" - - php: hhvm +php: + - 5.5 + - 5.6 + - 7.0 + - hhvm + +env: + - COMMONMARK_VERSION=0.11.* + - COMMONMARK_VERSION=0.12.* + - COMMONMARK_VERSION=0.13.* + - COMMONMARK_VERSION=0.14.* + - COMMONMARK_VERSION=0.15.* before_script: + - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi + - if [ $TRAVIS_PHP_VERSION = '5.5' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi - composer self-update + - if [ "$COMMONMARK_VERSION" != "" ]; then composer require "league/commonmark:${COMMONMARK_VERSION}" --no-update; fi - composer update --prefer-dist --no-interaction $COMPOSER_FLAGS script: From 256f250f62150219b57ebd4b34c38466a0f5f4cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Sat, 24 Sep 2016 04:08:51 +0200 Subject: [PATCH 028/231] Support only two latest versions of commonmark --- .travis.yml | 6 +----- composer.json | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 71314f5ba4..ff0ca8a72b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,9 +13,6 @@ php: - hhvm env: - - COMMONMARK_VERSION=0.11.* - - COMMONMARK_VERSION=0.12.* - - COMMONMARK_VERSION=0.13.* - COMMONMARK_VERSION=0.14.* - COMMONMARK_VERSION=0.15.* @@ -23,8 +20,7 @@ before_script: - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi - if [ $TRAVIS_PHP_VERSION = '5.5' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi - composer self-update - - if [ "$COMMONMARK_VERSION" != "" ]; then composer require "league/commonmark:${COMMONMARK_VERSION}" --no-update; fi - - composer update --prefer-dist --no-interaction $COMPOSER_FLAGS + - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS script: - vendor/bin/phpunit $PHPUNIT_COVERAGE diff --git a/composer.json b/composer.json index 5018a7761b..b0c3190fea 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": "^5.5|^7.0", - "league/commonmark": "^0.11|^0.12|^0.13|^0.14|^0.15" + "league/commonmark": "^0.14|^0.15" }, "require-dev": { "phpunit/phpunit": "^4.3|^5.0", From cd4e3753a2693235f67493c0c2a2b8e4434dc6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Mon, 26 Sep 2016 09:40:08 +0200 Subject: [PATCH 029/231] Update Readme and Changelog --- CHANGELOG.md | 6 +++++ README.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++--- composer.json | 2 +- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d379bb58eb..2ddbb41c73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +0.6.0 (2016-09-26) +------------------ + + * 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) ------------------ diff --git a/README.md b/README.md index ec6cb73075..d924716e89 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ CommonMark Table Extension ========================== -[![Packagist](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg?style=flat-square)](https://packagist.org/packages/webuni/commonmark-table-extension) +[![Latest Version](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg?style=flat-square)](https://packagist.org/packages/webuni/commonmark-table-extension) [![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) [![StyleCI](https://styleci.io/repos/36301048/shield)](https://styleci.io/repos/36301048) -[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) +[![Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension/code-structure) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) [![SensioLabsInsight](https://img.shields.io/sensiolabs/i/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b.svg?style=flat-square)](https://insight.sensiolabs.com/projects/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b) The Table extension adds the ability to create tables in CommonMark documents. @@ -37,12 +38,37 @@ echo $converter->convertToHtml('# Hello World!'); Syntax ------ +### Simple + +Code: ```markdown th | th(center) | th(right) ---|:----------:|----------: -td | td | td +td | td | td +``` + +Result: +```html + + + + + + + + + + + + + + +
thth(center)th(right<)/th> +
tdtdtd
``` +### Advanced + ```markdown | header 1 | header 2 | header 2 | | :------- | :------: | -------: | @@ -50,3 +76,39 @@ td | td | td | 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 + + + + + + + + + + + + + + +
Prototype table
header 1header 2
cell 1.1cell 1.2
+ +``` diff --git a/composer.json b/composer.json index b0c3190fea..010716e789 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.5-dev" + "dev-master": "0.7-dev" } } } From 95fb184b72b4ea2176208c9352617d7d4c5899a9 Mon Sep 17 00:00:00 2001 From: Walther Lalk Date: Fri, 30 Sep 2016 13:10:58 +0200 Subject: [PATCH 030/231] Allow any phpunit --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f7b7989ec0..9cecdd56a4 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "league/commonmark": "^0.10.0" }, "require-dev": { - "phpunit/phpunit": "^4.7" + "phpunit/phpunit": "*" }, "license": "MIT", "authors": [ From 23c598ba75f4df6dceb9c51f533ce0aaf98f73b1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 5 Jan 2017 19:54:59 +1030 Subject: [PATCH 031/231] Fix single-column tables not rendering. --- src/TableParser.php | 14 ++++++++- .../Functional/data/single_column_table.html | 12 ++++++++ tests/Functional/data/single_column_table.md | 3 ++ ...ingle_column_table_and_block_elements.html | 14 +++++++++ .../single_column_table_and_block_elements.md | 5 ++++ .../data/single_column_table_caption.html | 29 +++++++++++++++++++ .../data/single_column_table_caption.md | 10 +++++++ 7 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/Functional/data/single_column_table.html create mode 100644 tests/Functional/data/single_column_table.md create mode 100644 tests/Functional/data/single_column_table_and_block_elements.html create mode 100644 tests/Functional/data/single_column_table_and_block_elements.md create mode 100644 tests/Functional/data/single_column_table_caption.html create mode 100644 tests/Functional/data/single_column_table_caption.md diff --git a/src/TableParser.php b/src/TableParser.php index 743c61c3d0..bbca84148a 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -107,10 +107,22 @@ private function parseColumns(array $match) private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) { $cells = RegexHelper::matchAll(self::REGEXP_CELLS, $line); - if (null === $cells || !is_array($cells[0])) { + + if (null === $cells) { return; } + // If we have a single match we might be using a single-column table + if (!is_array($cells[0])) { + // If no indication of the existence of a cell, it's not a valid row + if (strpos($line, '|') === false) { + return; + } + + // Fake single match as array of matches for the code below + $cells = [$cells]; + } + $row = new TableRow(); foreach ($cells[0] as $i => $cell) { $row->appendChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); diff --git a/tests/Functional/data/single_column_table.html b/tests/Functional/data/single_column_table.html new file mode 100644 index 0000000000..19020573bf --- /dev/null +++ b/tests/Functional/data/single_column_table.html @@ -0,0 +1,12 @@ +
+ + + + + + + + + + +
header 1
cell 1.1
diff --git a/tests/Functional/data/single_column_table.md b/tests/Functional/data/single_column_table.md new file mode 100644 index 0000000000..03c208f78f --- /dev/null +++ b/tests/Functional/data/single_column_table.md @@ -0,0 +1,3 @@ +| header 1 | +| -------- | +| cell 1.1 | \ No newline at end of file diff --git a/tests/Functional/data/single_column_table_and_block_elements.html b/tests/Functional/data/single_column_table_and_block_elements.html new file mode 100644 index 0000000000..28a3633304 --- /dev/null +++ b/tests/Functional/data/single_column_table_and_block_elements.html @@ -0,0 +1,14 @@ +

Paragraph

+ + + + + + + + + + + +
header 1
cell 1.1
+

Paragraph

diff --git a/tests/Functional/data/single_column_table_and_block_elements.md b/tests/Functional/data/single_column_table_and_block_elements.md new file mode 100644 index 0000000000..22bdf3ebaa --- /dev/null +++ b/tests/Functional/data/single_column_table_and_block_elements.md @@ -0,0 +1,5 @@ +Paragraph +| header 1 | +| -------- | +| cell 1.1 | +Paragraph \ No newline at end of file diff --git a/tests/Functional/data/single_column_table_caption.html b/tests/Functional/data/single_column_table_caption.html new file mode 100644 index 0000000000..1d93e6af83 --- /dev/null +++ b/tests/Functional/data/single_column_table_caption.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + +
Simple table
header 1
cell 1.1
+ + + + + + + + + + + + + + + +
Simple table 2
header 1
cell 1.1
[Not a caption]
diff --git a/tests/Functional/data/single_column_table_caption.md b/tests/Functional/data/single_column_table_caption.md new file mode 100644 index 0000000000..3dda10050d --- /dev/null +++ b/tests/Functional/data/single_column_table_caption.md @@ -0,0 +1,10 @@ +| header 1 | +| -------- | +| cell 1.1 | +[Simple table] + +| header 1 | +| -------- | +| cell 1.1 | +| [Not a caption] +[Simple table 2] \ No newline at end of file From 55a26edf951d4fc30575673421b8d60b057e5a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 11 Jan 2017 15:38:39 +0100 Subject: [PATCH 032/231] Correct implementation for single column tables --- src/TableParser.php | 15 ++--------- .../Functional/data/single_column_table.html | 26 +++++++++++++++++++ tests/Functional/data/single_column_table.md | 12 ++++++++- .../single_column_table_and_block_elements.md | 2 +- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/TableParser.php b/src/TableParser.php index bbca84148a..1391ceeca3 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -108,23 +108,12 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) { $cells = RegexHelper::matchAll(self::REGEXP_CELLS, $line); - if (null === $cells) { + if (null === $cells || $line === $cells[0]) { return; } - // If we have a single match we might be using a single-column table - if (!is_array($cells[0])) { - // If no indication of the existence of a cell, it's not a valid row - if (strpos($line, '|') === false) { - return; - } - - // Fake single match as array of matches for the code below - $cells = [$cells]; - } - $row = new TableRow(); - foreach ($cells[0] as $i => $cell) { + foreach ((array) $cells[0] as $i => $cell) { $row->appendChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); } diff --git a/tests/Functional/data/single_column_table.html b/tests/Functional/data/single_column_table.html index 19020573bf..19674224df 100644 --- a/tests/Functional/data/single_column_table.html +++ b/tests/Functional/data/single_column_table.html @@ -10,3 +10,29 @@ + + + + + + + + + + + +
header 1
cell 1.1
+

| not a cell |

+ + + + + + + + + + + +
header 1
cell 1.1
+

| not a cell |

diff --git a/tests/Functional/data/single_column_table.md b/tests/Functional/data/single_column_table.md index 03c208f78f..000524ff6e 100644 --- a/tests/Functional/data/single_column_table.md +++ b/tests/Functional/data/single_column_table.md @@ -1,3 +1,13 @@ | header 1 | | -------- | -| cell 1.1 | \ No newline at end of file +| cell 1.1 | + +| header 1 | +| -------- | +| cell 1.1 | +`| not a cell |` + +| header 1 | +| -------- | +| cell 1.1 | +\| not a cell \| diff --git a/tests/Functional/data/single_column_table_and_block_elements.md b/tests/Functional/data/single_column_table_and_block_elements.md index 22bdf3ebaa..9736af7c7f 100644 --- a/tests/Functional/data/single_column_table_and_block_elements.md +++ b/tests/Functional/data/single_column_table_and_block_elements.md @@ -2,4 +2,4 @@ Paragraph | header 1 | | -------- | | cell 1.1 | -Paragraph \ No newline at end of file +Paragraph From df490a8e8b04555b33021d867c4545a39130cfb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 11 Jan 2017 14:32:21 +0100 Subject: [PATCH 033/231] Add webuni as author to composer.json --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index 010716e789..155a21edb5 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,10 @@ "name": "Martin Hasoň", "email": "martin.hason@gmail.com", "role": "Lead Developer" + }, + { + "name": "Webuni s.r.o.", + "homepage": "https://www.webuni.cz" } ], "require": { From ebbd69b63436283ec726658835b213ec634485e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 11 Jan 2017 15:52:17 +0100 Subject: [PATCH 034/231] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ddbb41c73..2cd7a7051b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +0.6.1 (2017-01-11) +------------------ + + * Fixed parsing of one column tables + 0.6.0 (2016-09-26) ------------------ From 70259aa9688baca75b7154793b22f8f58d66e83e Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 27 Feb 2017 15:40:41 +0900 Subject: [PATCH 035/231] Better parsing of escapes in cell --- src/TableParser.php | 2 +- tests/Functional/data/table_inline_markdown.html | 4 ++++ tests/Functional/data/table_inline_markdown.md | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/TableParser.php b/src/TableParser.php index 1391ceeca3..1c399e665a 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -21,7 +21,7 @@ class TableParser extends AbstractBlockParser { const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; - const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\\\\|\\\\\||[^|`\\\\]+)+(?=\||$)/'; + const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\||\\\\|[^|`\\\\]+)+(?=\||$)/'; const REGEXP_CAPTION = '/^\[(.+?)\](?:\[(.+)\])?\s*$/'; public function parse(ContextInterface $context, Cursor $cursor) diff --git a/tests/Functional/data/table_inline_markdown.html b/tests/Functional/data/table_inline_markdown.html index ac6b59796c..b294088941 100644 --- a/tests/Functional/data/table_inline_markdown.html +++ b/tests/Functional/data/table_inline_markdown.html @@ -18,5 +18,9 @@ \| 2.1 link + +_cell_ 4.1 + + diff --git a/tests/Functional/data/table_inline_markdown.md b/tests/Functional/data/table_inline_markdown.md index 47d62ff8d7..e9f6adcfaa 100644 --- a/tests/Functional/data/table_inline_markdown.md +++ b/tests/Functional/data/table_inline_markdown.md @@ -3,3 +3,4 @@ | _cell_ 1.1 | **cell** 1.2 | | `|` 2.1 | \| 2.2 | | `\|` 2.1 | [link](/) | +| \_cell\_ 4.1 | | From dc86cb1a8f289b172c741eed65428a622893166b Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 1 Nov 2017 07:43:48 +0000 Subject: [PATCH 036/231] Added support for league/commonmark 0.16 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 155a21edb5..15bd3e3914 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ ], "require": { "php": "^5.5|^7.0", - "league/commonmark": "^0.14|^0.15" + "league/commonmark": "^0.14|^0.15|^0.16" }, "require-dev": { "phpunit/phpunit": "^4.3|^5.0", From a610130640e96e5b948785b0e1ab67d1e205d99e Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 1 Nov 2017 07:46:21 +0000 Subject: [PATCH 037/231] Added commonmark v0.16 to Travis CI config --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ff0ca8a72b..9f391fe161 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ php: env: - COMMONMARK_VERSION=0.14.* - COMMONMARK_VERSION=0.15.* + - COMMONMARK_VERSION=0.16.* before_script: - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi From 8ef65ceda73c21dd27491e421ea238670b2a96e2 Mon Sep 17 00:00:00 2001 From: webimpress Date: Wed, 1 Nov 2017 07:46:33 +0000 Subject: [PATCH 038/231] Added PHP 7.1 and PHP 7.2 in Travis CI config --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9f391fe161..88a5e48896 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,8 @@ php: - 5.5 - 5.6 - 7.0 + - 7.1 + - 7.2 - hhvm env: From ca3e56c524ada9ba4a88ac9eaae3916a6fdfd5ca Mon Sep 17 00:00:00 2001 From: Tony Lemke Date: Tue, 14 Nov 2017 10:38:00 +0100 Subject: [PATCH 039/231] In league/commonmark:0.15, Cursor::getFirstNonSpacePosition() is deprecated and Cursor::getNextNonSpacePosition() can instead be used. --- src/TableParser.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/TableParser.php b/src/TableParser.php index 1391ceeca3..6e38db51e5 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -37,7 +37,13 @@ public function parse(ContextInterface $context, Cursor $cursor) return false; } - $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $cursor->getFirstNonSpacePosition()); + if (method_exists($cursor, 'getNextNonSpacePosition')) { + $expressionOffset = $cursor->getNextNonSpacePosition(); + } else { + $expressionOffset = $cursor->getFirstNonSpacePosition(); + } + + $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $expressionOffset); if (null === $match) { return false; } From f3b4e1886e795b8391f8b975921925cdbda972ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jan 2018 10:44:06 +0100 Subject: [PATCH 040/231] Fix parsing whitespaces at the end of line --- src/TableParser.php | 6 +++++- tests/Functional/data/end_whitespaces.html | 18 ++++++++++++++++++ tests/Functional/data/end_whitespaces.md | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/Functional/data/end_whitespaces.html create mode 100644 tests/Functional/data/end_whitespaces.md diff --git a/src/TableParser.php b/src/TableParser.php index 94bc6c686a..d32795958b 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -103,7 +103,7 @@ private function parseColumns(array $match) } elseif (isset($match[2][$i]) && $match[2][$i]) { $columns[] = TableCell::ALIGN_RIGHT; } else { - $columns[] = null; + $columns[] = ''; } } @@ -120,6 +120,10 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) $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)); } diff --git a/tests/Functional/data/end_whitespaces.html b/tests/Functional/data/end_whitespaces.html new file mode 100644 index 0000000000..9b4f4463d5 --- /dev/null +++ b/tests/Functional/data/end_whitespaces.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +
Th 1Th 2Th 3
td1td2td3td4
diff --git a/tests/Functional/data/end_whitespaces.md b/tests/Functional/data/end_whitespaces.md new file mode 100644 index 0000000000..2a84524fa1 --- /dev/null +++ b/tests/Functional/data/end_whitespaces.md @@ -0,0 +1,3 @@ +| Th 1 | Th 2 | Th 3 | | +|------|------|------|-----| +| td1 | td2 | td3 | td4 | From 0273ce0e051a87ba7cfbec3573be7c7a375edd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jan 2018 11:16:34 +0100 Subject: [PATCH 041/231] Tag 0.7.0 version --- .gitattributes | 1 - .php_cs | 23 +++++++++++++---------- .styleci.yml | 6 ------ .travis.yml | 8 ++++---- CHANGELOG.md | 8 ++++++++ composer.json | 14 ++++++-------- src/TableParser.php | 6 +----- tests/Functional/LocalDataTest.php | 13 ++++++++++++- 8 files changed, 44 insertions(+), 35 deletions(-) delete mode 100644 .styleci.yml diff --git a/.gitattributes b/.gitattributes index 7bdf2e0b8a..6b73a2a7c7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,7 +2,6 @@ /.gitignore export-ignore /.php_cs export-ignore /.scrutinizer.yml export-ignore -/.styleci.yml export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore /tests export-ignore diff --git a/.php_cs b/.php_cs index 99ca0bf476..ad7c679cde 100644 --- a/.php_cs +++ b/.php_cs @@ -1,10 +1,5 @@ setRules(array( + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'header_comment' => [ + 'header' => $header, + ], + 'ordered_imports' => true, + )) + ->setLineEnding("\n") + ->setUsingCache(false) + ->setFinder(PhpCsFixer\Finder::create()->in([__DIR__.'/src', __DIR__.'/tests'])) +; diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index b015c73cfb..0000000000 --- a/.styleci.yml +++ /dev/null @@ -1,6 +0,0 @@ -preset: symfony - -enabled: - - newline_after_open_tag - - ordered_use - - short_array_syntax diff --git a/.travis.yml b/.travis.yml index 88a5e48896..89ea0e7ce5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ cache: - $HOME/.composer/cache php: - - 5.5 - 5.6 - 7.0 - 7.1 @@ -18,15 +17,16 @@ env: - COMMONMARK_VERSION=0.14.* - COMMONMARK_VERSION=0.15.* - COMMONMARK_VERSION=0.16.* + - COMMONMARK_VERSION=0.17.* before_script: - - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi - - if [ $TRAVIS_PHP_VERSION = '5.5' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi + - if [ $TRAVIS_PHP_VERSION = '7.2' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi + - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi - composer self-update - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS script: - - vendor/bin/phpunit $PHPUNIT_COVERAGE + - phpunit $PHPUNIT_COVERAGE after_script: - if [[ "$PHPUNIT_COVERAGE" != "" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cd7a7051b..a011863e7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +0.7.0 (2018-01-09) +------------------ + + * Increased minimum PHP version to 5.6 + * Removed support for commonmark 0.14 and 0.15 API + * Updated to the commonmark 0.16 and 0.17 API + * Fix a problem with parsing whitespaces at the end of line + 0.6.1 (2017-01-11) ------------------ diff --git a/composer.json b/composer.json index 15bd3e3914..3c5814526c 100644 --- a/composer.json +++ b/composer.json @@ -8,8 +8,7 @@ "authors": [ { "name": "Martin Hasoň", - "email": "martin.hason@gmail.com", - "role": "Lead Developer" + "email": "martin.hason@gmail.com" }, { "name": "Webuni s.r.o.", @@ -17,14 +16,13 @@ } ], "require": { - "php": "^5.5|^7.0", - "league/commonmark": "^0.14|^0.15|^0.16" + "php": "^5.6|^7.0", + "league/commonmark": "^0.16|^0.17" }, "require-dev": { - "phpunit/phpunit": "^4.3|^5.0", - "friendsofphp/php-cs-fixer": "^1.9", - "sllh/php-cs-fixer-styleci-bridge": "^2.0", - "symfony/var-dumper": "^2.7|^3.0" + "phpunit/phpunit": "^5.4|^6.0", + "friendsofphp/php-cs-fixer": "^2.9", + "symfony/var-dumper": "^3.0|^4.0" }, "autoload": { "psr-4": { diff --git a/src/TableParser.php b/src/TableParser.php index d32795958b..9519a638a9 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -37,11 +37,7 @@ public function parse(ContextInterface $context, Cursor $cursor) return false; } - if (method_exists($cursor, 'getNextNonSpacePosition')) { - $expressionOffset = $cursor->getNextNonSpacePosition(); - } else { - $expressionOffset = $cursor->getFirstNonSpacePosition(); - } + $expressionOffset = $cursor->getNextNonSpacePosition(); $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $expressionOffset); if (null === $match) { diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index 8aaabcedae..722e189c0b 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -16,9 +16,20 @@ use League\CommonMark\ElementRendererInterface; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; +use PHPUnit\Framework\TestCase; use Webuni\CommonMark\TableExtension\TableExtension; -class LocalDataTest extends \PHPUnit_Framework_TestCase +if (class_exists(TestCase::class)) { + class CompatibleTestsCase extends TestCase + { + } +} else { + class CompatibleTestsCase extends \PHPUnit_Framework_TestCase + { + } +} + +class LocalDataTest extends CompatibleTestsCase { /* @var Environment */ private $environment; From 6326245c1e198cc839ef4f6dc070cf99cffb1a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jan 2018 12:05:15 +0100 Subject: [PATCH 042/231] Fix travis configuration --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 89ea0e7ce5..a0df9346d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,11 +11,8 @@ php: - 7.0 - 7.1 - 7.2 - - hhvm env: - - COMMONMARK_VERSION=0.14.* - - COMMONMARK_VERSION=0.15.* - COMMONMARK_VERSION=0.16.* - COMMONMARK_VERSION=0.17.* From 24845f086279f1a81a84e054c7d40a5ec1625782 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 15 Jan 2018 20:59:50 +0900 Subject: [PATCH 043/231] Update escape to use the new helper method --- src/TableCaptionRenderer.php | 3 ++- src/TableCellRenderer.php | 3 ++- src/TableRenderer.php | 3 ++- src/TableRowRenderer.php | 3 ++- src/TableRowsRenderer.php | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index f845fccfd2..e92a68503c 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -16,6 +16,7 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; +use League\CommonMark\Util\Xml; class TableCaptionRenderer implements BlockRendererInterface { @@ -27,7 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = $htmlRenderer->escape($value, true); + $attrs[$key] = Xml::escape($value, true); } if ($block->id) { diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index f88443e873..505b7cb3d8 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -16,6 +16,7 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; +use League\CommonMark\Util\Xml; class TableCellRenderer implements BlockRendererInterface { @@ -27,7 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = $htmlRenderer->escape($value, true); + $attrs[$key] = Xml::escape($value, true); } if ($block->align) { diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 78356955fa..20a0481725 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -16,6 +16,7 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; +use League\CommonMark\Util\Xml; class TableRenderer implements BlockRendererInterface { @@ -27,7 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = $htmlRenderer->escape($value, true); + $attrs[$key] = Xml::escape($value, true); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index ca2aae8984..ab4bbfb7d2 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -16,6 +16,7 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; +use League\CommonMark\Util\Xml; class TableRowRenderer implements BlockRendererInterface { @@ -27,7 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = $htmlRenderer->escape($value, true); + $attrs[$key] = Xml::escape($value, true); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 0f6a885c30..9aecb4cd77 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -16,6 +16,7 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; +use League\CommonMark\Util\Xml; class TableRowsRenderer implements BlockRendererInterface { @@ -31,7 +32,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = $htmlRenderer->escape($value, true); + $attrs[$key] = Xml::escape($value, true); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); From de50839663ad4a03f049724a14d7405f60477657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 23 Jan 2018 12:30:25 +0100 Subject: [PATCH 044/231] Add Psalm static analysis tool --- .travis.yml | 1 + CHANGELOG.md | 5 +++++ composer.json | 3 ++- psalm.xml | 32 ++++++++++++++++++++++++++++++++ src/TableCaptionRenderer.php | 2 +- src/TableCellRenderer.php | 2 +- src/TableParser.php | 1 + src/TableRenderer.php | 2 +- src/TableRowRenderer.php | 2 +- src/TableRowsRenderer.php | 2 +- 10 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 psalm.xml diff --git a/.travis.yml b/.travis.yml index a0df9346d9..2416701467 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ before_script: - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS script: + - vendor/bin/psalm - phpunit $PHPUNIT_COVERAGE after_script: diff --git a/CHANGELOG.md b/CHANGELOG.md index a011863e7d..742892200d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +0.7.1 (2018-01-23) +------------------ + + * Fix undefined method in commonmark 0.17 + 0.7.0 (2018-01-09) ------------------ diff --git a/composer.json b/composer.json index 3c5814526c..32493e0fe4 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ }, "require-dev": { "phpunit/phpunit": "^5.4|^6.0", + "vimeo/psalm": "~0.3", "friendsofphp/php-cs-fixer": "^2.9", "symfony/var-dumper": "^3.0|^4.0" }, @@ -31,7 +32,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.7-dev" + "dev-master": "0.8-dev" } } } diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000000..93a850ec8f --- /dev/null +++ b/psalm.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index e92a68503c..fd02f2d0fc 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -22,7 +22,7 @@ class TableCaptionRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { - if (!($block instanceof TableCaption)) { + if (!$block instanceof TableCaption) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 505b7cb3d8..226b0ec9e6 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -22,7 +22,7 @@ class TableCellRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { - if (!($block instanceof TableCell)) { + if (!$block instanceof TableCell) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } diff --git a/src/TableParser.php b/src/TableParser.php index 9519a638a9..4257787432 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -114,6 +114,7 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) return; } + $i = 0; $row = new TableRow(); foreach ((array) $cells[0] as $i => $cell) { if (!isset($columns[$i])) { diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 20a0481725..30f666b01a 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -22,7 +22,7 @@ class TableRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { - if (!($block instanceof Table)) { + if (!$block instanceof Table) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index ab4bbfb7d2..337a9f015c 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -22,7 +22,7 @@ class TableRowRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { - if (!($block instanceof TableRow)) { + if (!$block instanceof TableRow) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 9aecb4cd77..dd343f04c9 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -22,7 +22,7 @@ class TableRowsRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) { - if (!($block instanceof TableRows)) { + if (!$block instanceof TableRows) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } From d66b3e51705967442c774ffe1248dc2e5f52c8b6 Mon Sep 17 00:00:00 2001 From: Ryan Cole Date: Wed, 24 Jan 2018 22:13:03 +1000 Subject: [PATCH 045/231] Feature/html5 head align (#11) * Update th align to html5 th align was removed in html 5. Replaced with * Removed debug line * Updated readme Updated readme to display HTML5 th align. --- README.md | 6 +++--- src/TableCellRenderer.php | 6 +++++- tests/Functional/data/aligned_table.html | 6 +++--- tests/Functional/data/simple_table.html | 2 +- tests/Functional/data/table-aligned.html | 4 ++-- tests/Functional/data/table-caption.html | 6 +++--- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d924716e89..eeac945958 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,9 @@ Result: - - - + + diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 226b0ec9e6..bcff4d510d 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -32,7 +32,11 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende } if ($block->align) { - $attrs['align'] = $block->align; + if ($block->type == TableCell::TYPE_HEAD) { + $attrs['style'] = "text-align: $block->align"; + } else { + $attrs['align'] = $block->align; + } } return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children())); diff --git a/tests/Functional/data/aligned_table.html b/tests/Functional/data/aligned_table.html index 4c1d319c57..79ee8c3813 100644 --- a/tests/Functional/data/aligned_table.html +++ b/tests/Functional/data/aligned_table.html @@ -1,9 +1,9 @@
thth(center)th(right<)/th> +thth(center)th(right<)/th>
- - - + + + diff --git a/tests/Functional/data/simple_table.html b/tests/Functional/data/simple_table.html index d38b1df177..415602ae4c 100644 --- a/tests/Functional/data/simple_table.html +++ b/tests/Functional/data/simple_table.html @@ -20,7 +20,7 @@
header 1header 2header 2header 1header 2header 2
- + diff --git a/tests/Functional/data/table-aligned.html b/tests/Functional/data/table-aligned.html index 2fc996c9a8..7f94ab1c63 100644 --- a/tests/Functional/data/table-aligned.html +++ b/tests/Functional/data/table-aligned.html @@ -2,8 +2,8 @@ - - + + diff --git a/tests/Functional/data/table-caption.html b/tests/Functional/data/table-caption.html index 94970e7e64..93a423b5aa 100644 --- a/tests/Functional/data/table-caption.html +++ b/tests/Functional/data/table-caption.html @@ -21,9 +21,9 @@ - - - + + + From 4304b1f56b26e5213a4a781b654f62ef5ed8fbe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 24 Jan 2018 13:30:02 +0100 Subject: [PATCH 046/231] Replace align attribute with text-align style --- CHANGELOG.md | 5 +++++ README.md | 8 +++----- src/TableCellRenderer.php | 6 +----- tests/Functional/data/aligned_table.html | 12 ++++++------ tests/Functional/data/simple_table.html | 4 ++-- tests/Functional/data/table-aligned.html | 4 ++-- tests/Functional/data/table-caption.html | 12 ++++++------ 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 742892200d..3980ca02e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +0.8.0 (2018-01-24) +------------------ + + * Replace align attribute with text-align style + 0.7.1 (2018-01-23) ------------------ diff --git a/README.md b/README.md index eeac945958..05f7359ec8 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,8 @@ CommonMark Table Extension [![Latest Version](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg?style=flat-square)](https://packagist.org/packages/webuni/commonmark-table-extension) [![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) -[![StyleCI](https://styleci.io/repos/36301048/shield)](https://styleci.io/repos/36301048) [![Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension/code-structure) [![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) -[![SensioLabsInsight](https://img.shields.io/sensiolabs/i/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b.svg?style=flat-square)](https://insight.sensiolabs.com/projects/d7a0bce6-6a3a-4b3c-abb1-0b69ad10513b) The Table extension adds the ability to create tables in CommonMark documents. @@ -59,9 +57,9 @@ Result: - - - + + +
header 1header 1 header 2
thth(center)th(right)th(center)th(right)
Prototype table
First HeaderSecond HeaderThird HeaderFirst HeaderSecond HeaderThird Header
tdtdtdtdtdtd
diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index bcff4d510d..d9902a0210 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -32,11 +32,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende } if ($block->align) { - if ($block->type == TableCell::TYPE_HEAD) { - $attrs['style'] = "text-align: $block->align"; - } else { - $attrs['align'] = $block->align; - } + $attrs['style'] = (isset($attrs['style']) ? $attrs['style'] . ' ' : '') . 'text-align: ' . $block->align; } return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children())); diff --git a/tests/Functional/data/aligned_table.html b/tests/Functional/data/aligned_table.html index 79ee8c3813..f983f54efd 100644 --- a/tests/Functional/data/aligned_table.html +++ b/tests/Functional/data/aligned_table.html @@ -8,14 +8,14 @@ -cell 1.1 -cell 1.2 -cell 1.3 +cell 1.1 +cell 1.2 +cell 1.3 -cell 2.1 -cell 2.2 -cell 2.3 +cell 2.1 +cell 2.2 +cell 2.3 diff --git a/tests/Functional/data/simple_table.html b/tests/Functional/data/simple_table.html index 415602ae4c..5b381589fd 100644 --- a/tests/Functional/data/simple_table.html +++ b/tests/Functional/data/simple_table.html @@ -26,11 +26,11 @@ -cell 1.1 +cell 1.1 cell 1.2 -cell 2.1 +cell 2.1 cell 2.2 diff --git a/tests/Functional/data/table-aligned.html b/tests/Functional/data/table-aligned.html index 7f94ab1c63..d9076608b4 100644 --- a/tests/Functional/data/table-aligned.html +++ b/tests/Functional/data/table-aligned.html @@ -9,8 +9,8 @@ td -td -td +td +td diff --git a/tests/Functional/data/table-caption.html b/tests/Functional/data/table-caption.html index 93a423b5aa..7e032428c7 100644 --- a/tests/Functional/data/table-caption.html +++ b/tests/Functional/data/table-caption.html @@ -28,14 +28,14 @@ -First row -Data -Very long data entry +First row +Data +Very long data entry -Second row -Cell -Cell +Second row +Cell +Cell From 8c75eb04cee8adfd4a29a4434cfd37fceb6c9568 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sat, 12 May 2018 10:27:17 -0400 Subject: [PATCH 047/231] Update to league/commonmark 0.17 --- composer.json | 4 +-- src/Strikethrough/StrikethroughParser.php | 12 +++------ src/Strikethrough/StrikethroughRenderer.php | 3 ++- .../StrikethroughParserTest.php | 25 +++++++++++-------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index 9cecdd56a4..7fede6ee38 100644 --- a/composer.json +++ b/composer.json @@ -3,10 +3,10 @@ "description": "Extended parsers and renderers for The PHP League CommonMark parser", "keywords": ["markdown", "strikethrough", "strikeout", "commonmark"], "require": { - "league/commonmark": "^0.10.0" + "league/commonmark": "^0.17" }, "require-dev": { - "phpunit/phpunit": "*" + "phpunit/phpunit": "5" }, "license": "MIT", "authors": [ diff --git a/src/Strikethrough/StrikethroughParser.php b/src/Strikethrough/StrikethroughParser.php index 98b866eab7..b7edba552e 100644 --- a/src/Strikethrough/StrikethroughParser.php +++ b/src/Strikethrough/StrikethroughParser.php @@ -22,7 +22,7 @@ public function getCharacters() * * @return bool */ - public function parse(ContextInterface $context, InlineParserContext $inline_context) + public function parse(InlineParserContext $inline_context) { $cursor = $inline_context->getCursor(); $character = $cursor->getCharacter(); @@ -37,19 +37,15 @@ public function parse(ContextInterface $context, InlineParserContext $inline_con $previous_state = $cursor->saveState(); while ($matching_tildes = $cursor->match('/~~+/m')) { if ($matching_tildes === $tildes) { - $text = mb_substr($cursor->getLine(), $previous_state->getCurrentPosition(), - $cursor->getPosition() - $previous_state->getCurrentPosition() - strlen($tildes), 'utf-8'); + $text = mb_substr( $cursor->getPreviousText(), 0, -mb_strlen($tildes) ); $text = preg_replace('/[ \n]+/', ' ', $text); - $inline_context->getInlines() - ->add(new Strikethrough(trim($text))); + $inline_context->getContainer()->appendChild(new Strikethrough(trim($text))); return true; } } // If we got here, we didn't match a closing tilde pair sequence $cursor->restoreState($previous_state); - $inline_context->getInlines() - ->add(new Text($tildes)); - + $inline_context->getContainer()->appendChild(new Text($tildes)); return true; } } diff --git a/src/Strikethrough/StrikethroughRenderer.php b/src/Strikethrough/StrikethroughRenderer.php index b27ab44aff..eb6c882784 100644 --- a/src/Strikethrough/StrikethroughRenderer.php +++ b/src/Strikethrough/StrikethroughRenderer.php @@ -5,6 +5,7 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Inline\Renderer\InlineRendererInterface; +use League\CommonMark\Util\Xml; class StrikethroughRenderer implements InlineRendererInterface { @@ -24,6 +25,6 @@ public function render(AbstractInline $inline, ElementRendererInterface $htmlRen $attrs[$key] = $htmlRenderer->escape($value, true); } - return new HtmlElement('del', $attrs, $htmlRenderer->escape($inline->getContent())); + return new HtmlElement('del', $attrs, Xml::escape($inline->getContent())); } } diff --git a/tests/StrikethroughTests/StrikethroughParserTest.php b/tests/StrikethroughTests/StrikethroughParserTest.php index 32b7366613..1cefc55f6a 100644 --- a/tests/StrikethroughTests/StrikethroughParserTest.php +++ b/tests/StrikethroughTests/StrikethroughParserTest.php @@ -5,6 +5,7 @@ use CommonMarkExt\Strikethrough\StrikethroughParser; use League\CommonMark\Cursor; use League\CommonMark\InlineParserContext; +use League\CommonMark\Reference\ReferenceMap; class StrikethroughParserTest extends \PHPUnit_Framework_TestCase { @@ -16,20 +17,22 @@ class StrikethroughParserTest extends \PHPUnit_Framework_TestCase */ public function testParse($string, $expected) { - $cursor = new Cursor($string); + $nodeStub = $this->getMock('League\CommonMark\Block\Element\AbstractBlock'); + $nodeStub->expects($this->any())->method('getStringContent')->willReturn($string); + $nodeStub + ->expects($this->once()) + ->method('appendChild') + ->with($this->callback(function (Strikethrough $s) use ($expected) { + return $s instanceof Strikethrough && $expected === $s->getContent(); + })); + $inline_context = new InlineParserContext($nodeStub, new ReferenceMap()); + // Move to just before the first tilde pair $first_tilde_pos = mb_strpos($string, '~~', null, 'utf-8'); - $cursor->advanceBy($first_tilde_pos); - $inline_context = new InlineParserContext($cursor); - $context_stub = $this->getMock('League\CommonMark\ContextInterface'); + $inline_context->getCursor()->advanceBy($first_tilde_pos); + $parser = new StrikethroughParser(); - $parser->parse($context_stub, $inline_context); - $inlines = $inline_context->getInlines(); - $this->assertCount(1, $inlines); - $this->assertTrue($inlines->first() instanceof Strikethrough); - /** @var Strikethrough $text */ - $text = $inlines->first(); - $this->assertEquals($expected, $text->getContent()); + $parser->parse($inline_context); } /** From 3db4e01d34287fbc8fd9a5ad54cb6cd0313cef80 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sat, 12 May 2018 10:39:15 -0400 Subject: [PATCH 048/231] Add a StrikethroughExtension for ease of use --- src/Strikethrough/StrikethroughExtension.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/Strikethrough/StrikethroughExtension.php diff --git a/src/Strikethrough/StrikethroughExtension.php b/src/Strikethrough/StrikethroughExtension.php new file mode 100644 index 0000000000..e471049f8c --- /dev/null +++ b/src/Strikethrough/StrikethroughExtension.php @@ -0,0 +1,16 @@ + new StrikethroughRenderer() ]; } +} + From 9046e7e8f2ac915b69fbf9eab38ebc9d6af5b82c Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Sat, 12 May 2018 10:44:39 -0400 Subject: [PATCH 049/231] Document use of StrikethroughExtension --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 85c94b9e68..bc9e19c06c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ parsing engine, which itself is based on the CommonMark spec. ## Current Custom Parsers and Renderers -* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. +* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \CommonmarkExt\Strikethrough\StrikethroughExtension())`. ## Installation From 6d10f45c9ab60c8acf2a56f87c2cf8342a5c048e Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 14 May 2018 09:09:54 +0200 Subject: [PATCH 050/231] Adding .stickler.yml --- .stickler.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .stickler.yml diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 0000000000..2792063958 --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,9 @@ +linters: + phpcs: + standard: PSR2 + fixer: true +files: + ignore: + - 'vendor/*' +fixers: + enable: true From d347b1d42ba6c8f0f72e9b3af9117c9119be40e0 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Mon, 14 May 2018 04:04:19 -0400 Subject: [PATCH 051/231] Requested change --- tests/StrikethroughTests/StrikethroughParserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/StrikethroughTests/StrikethroughParserTest.php b/tests/StrikethroughTests/StrikethroughParserTest.php index 1cefc55f6a..8acd4c8ab4 100644 --- a/tests/StrikethroughTests/StrikethroughParserTest.php +++ b/tests/StrikethroughTests/StrikethroughParserTest.php @@ -17,7 +17,7 @@ class StrikethroughParserTest extends \PHPUnit_Framework_TestCase */ public function testParse($string, $expected) { - $nodeStub = $this->getMock('League\CommonMark\Block\Element\AbstractBlock'); + $nodeStub = $this->getMock(\League\CommonMark\Block\Element\AbstractBlock::class); $nodeStub->expects($this->any())->method('getStringContent')->willReturn($string); $nodeStub ->expects($this->once()) From cfa6dbd52faae4fa917b958762830c7d93c21f83 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Mon, 14 May 2018 04:04:34 -0400 Subject: [PATCH 052/231] Remove use of removed escape() method on renderers --- src/Strikethrough/StrikethroughRenderer.php | 2 +- tests/StrikethroughTests/StrikethroughRendererTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Strikethrough/StrikethroughRenderer.php b/src/Strikethrough/StrikethroughRenderer.php index eb6c882784..54c0e77f21 100644 --- a/src/Strikethrough/StrikethroughRenderer.php +++ b/src/Strikethrough/StrikethroughRenderer.php @@ -22,7 +22,7 @@ public function render(AbstractInline $inline, ElementRendererInterface $htmlRen } $attrs = []; foreach ($inline->getData('attributes', []) as $key => $value) { - $attrs[$key] = $htmlRenderer->escape($value, true); + $attrs[$key] = Xml::escape($value, true); } return new HtmlElement('del', $attrs, Xml::escape($inline->getContent())); diff --git a/tests/StrikethroughTests/StrikethroughRendererTest.php b/tests/StrikethroughTests/StrikethroughRendererTest.php index b6f635baeb..f872c2f9a7 100644 --- a/tests/StrikethroughTests/StrikethroughRendererTest.php +++ b/tests/StrikethroughTests/StrikethroughRendererTest.php @@ -22,13 +22,13 @@ protected function setUp() public function testRender() { $inline = new Strikethrough('reviewed text'); - $inline->data['attributes'] = ['id' => 'id']; + $inline->data['attributes'] = ['id' => 'some"&id']; $fake_renderer = new FakeHtmlRenderer(); $result = $this->renderer->render($inline, $fake_renderer); $this->assertTrue($result instanceof HtmlElement); $this->assertEquals('del', $result->getTagName()); $this->assertContains('reviewed text', $result->getContents(true)); - $this->assertEquals(['id' => '::escape::id'], $result->getAllAttributes()); + $this->assertEquals(['id' => 'some"&id'], $result->getAllAttributes()); } /** From 607c9a8c34b09d4f266608b847439e3c4b3f8800 Mon Sep 17 00:00:00 2001 From: Johan Meiring Date: Sun, 3 Jun 2018 09:55:39 +0200 Subject: [PATCH 053/231] Indicate correct namespace --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc9e19c06c..e50d649c1f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ parsing engine, which itself is based on the CommonMark spec. ## Current Custom Parsers and Renderers -* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \CommonmarkExt\Strikethrough\StrikethroughExtension())`. +* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \CommonMarkExt\Strikethrough\StrikethroughExtension())`. ## Installation From ff065cfc9d302e5004c08a5fd64df5d2eecb4894 Mon Sep 17 00:00:00 2001 From: Johan Meiring Date: Sun, 3 Jun 2018 09:56:07 +0200 Subject: [PATCH 054/231] De-lint README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e50d649c1f..1b18989d54 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ parsing engine, which itself is based on the CommonMark spec. ## Current Custom Parsers and Renderers + * **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \CommonMarkExt\Strikethrough\StrikethroughExtension())`. ## Installation @@ -15,12 +16,14 @@ This project can be installed via [Composer]: ``` bash $ composer require uafrica/commonmark-ext +... ``` ## Testing ``` bash $ ./vendor/bin/phpunit +... ``` ## License From 79ced508cb10877ff3163c976460e15bcbca4ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20HULARD?= Date: Mon, 8 Oct 2018 16:07:06 +0200 Subject: [PATCH 055/231] Allow to use the library with CommonMark v0.18. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 32493e0fe4..341a42f40c 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^5.6|^7.0", - "league/commonmark": "^0.16|^0.17" + "league/commonmark": "^0.16|^0.17|^0.18" }, "require-dev": { "phpunit/phpunit": "^5.4|^6.0", From 94bc98d802d0b706e748716854e5fa0bd3644df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 28 Nov 2018 12:29:11 +0100 Subject: [PATCH 056/231] Bump version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 341a42f40c..bd22350961 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.8-dev" + "dev-master": "0.9-dev" } } } From b64f0f02110feca4c9cae74ea4bb6b2287593a6a Mon Sep 17 00:00:00 2001 From: Laurent Bardin Date: Thu, 3 Jan 2019 18:49:14 +0100 Subject: [PATCH 057/231] Update to league/commonmark 0.18 Composer installed v0.18.1 and all tests ran fine. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7fede6ee38..d95787f53c 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Extended parsers and renderers for The PHP League CommonMark parser", "keywords": ["markdown", "strikethrough", "strikeout", "commonmark"], "require": { - "league/commonmark": "^0.17" + "league/commonmark": "^0.18" }, "require-dev": { "phpunit/phpunit": "5" From 0f927fd2bf8f65c7c9b54924c1faccab839aaa5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 15:18:33 +0100 Subject: [PATCH 058/231] Update dependencies --- .gitignore | 2 ++ .php_cs | 3 +++ .travis.yml | 9 ++++--- composer.json | 15 +++++------ phpunit.xml.dist | 1 - psalm.xml | 40 ++++++++++++++++++++++-------- tests/Functional/LocalDataTest.php | 18 +++++--------- 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index ca07b308b8..2d7ab77d69 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /.php_cs.cache +/.phpunit.result.cache +/.runner /composer.lock /phpunit.xml /vendor/ diff --git a/.php_cs b/.php_cs index ad7c679cde..9f00fefcc3 100644 --- a/.php_cs +++ b/.php_cs @@ -13,6 +13,9 @@ EOF; return PhpCsFixer\Config::create() ->setRules(array( '@PSR2' => true, + '@PHP71Migration:risky' => true, + '@Symfony' => true, + '@PhpCsFixer' => true, 'array_syntax' => ['syntax' => 'short'], 'header_comment' => [ 'header' => $header, diff --git a/.travis.yml b/.travis.yml index 2416701467..dfd33e7952 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,18 +7,19 @@ cache: - $HOME/.composer/cache php: - - 5.6 - - 7.0 - 7.1 - 7.2 + - 7.3 env: - COMMONMARK_VERSION=0.16.* - COMMONMARK_VERSION=0.17.* + - COMMONMARK_VERSION=0.18.* + - COMMONMARK_VERSION=0.19.*@dev before_script: - - if [ $TRAVIS_PHP_VERSION = '7.2' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi - - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi + - if [ $TRAVIS_PHP_VERSION = '7.3' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi + - if [ $TRAVIS_PHP_VERSION = '7.1' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi - composer self-update - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS diff --git a/composer.json b/composer.json index bd22350961..10c93b3a4c 100644 --- a/composer.json +++ b/composer.json @@ -16,14 +16,15 @@ } ], "require": { - "php": "^5.6|^7.0", - "league/commonmark": "^0.16|^0.17|^0.18" + "php": "^7.1", + "league/commonmark": "^0.17|^0.18|^0.19@dev" }, "require-dev": { - "phpunit/phpunit": "^5.4|^6.0", - "vimeo/psalm": "~0.3", - "friendsofphp/php-cs-fixer": "^2.9", - "symfony/var-dumper": "^3.0|^4.0" + "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": { @@ -32,7 +33,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.9-dev" + "dev-master": "0.10-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 24053be817..e8cc856d1b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,7 +8,6 @@ convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" - syntaxCheck="false" bootstrap="vendor/autoload.php" > diff --git a/psalm.xml b/psalm.xml index 93a850ec8f..30867b9b11 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,32 +1,50 @@ + + + - + + - - - - - + + + + + + + + + - + + + + + + + + + + + - + diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index 722e189c0b..67ac821d66 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -19,19 +19,13 @@ use PHPUnit\Framework\TestCase; use Webuni\CommonMark\TableExtension\TableExtension; -if (class_exists(TestCase::class)) { - class CompatibleTestsCase extends TestCase - { - } -} else { - class CompatibleTestsCase extends \PHPUnit_Framework_TestCase - { - } -} - -class LocalDataTest extends CompatibleTestsCase +/** + * @internal + * @coversNothing + */ +class LocalDataTest extends TestCase { - /* @var Environment */ + // @var Environment private $environment; private $parser; From 2540c85e98be654574d709803ccadddba0be9941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 15:22:12 +0100 Subject: [PATCH 059/231] Fix cs --- src/Table.php | 14 ++++++++------ src/TableCaption.php | 18 +++++++++++------- src/TableCaptionRenderer.php | 2 ++ src/TableCell.php | 20 ++++++++++++-------- src/TableCellRenderer.php | 4 +++- src/TableExtension.php | 8 +++++--- src/TableParser.php | 16 +++++++++------- src/TableRenderer.php | 2 ++ src/TableRow.php | 13 ++++++++----- src/TableRowRenderer.php | 2 ++ src/TableRows.php | 19 +++++++++++-------- src/TableRowsRenderer.php | 4 +++- tests/Functional/LocalDataTest.php | 9 +++++---- 13 files changed, 81 insertions(+), 50 deletions(-) diff --git a/src/Table.php b/src/Table.php index b7dac6a7d6..5ffe1a0883 100644 --- a/src/Table.php +++ b/src/Table.php @@ -1,5 +1,7 @@ parser = $parser; } - public function canContain(AbstractBlock $block) + public function canContain(AbstractBlock $block): bool { return $block instanceof TableRows || $block instanceof TableCaption; } - public function acceptsLines() + public function acceptsLines(): bool { return true; } - public function isCode() + public function isCode(): bool { return false; } - public function setCaption(TableCaption $caption = null) + public function setCaption(TableCaption $caption = null): void { $node = $this->getCaption(); if ($node instanceof TableCaption) { @@ -82,9 +85,8 @@ public function getBody() } } - public function matchesNextLine(Cursor $cursor) + public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { - return call_user_func($this->parser, $cursor); } public function handleRemainingContents(ContextInterface $context, Cursor $cursor) diff --git a/src/TableCaption.php b/src/TableCaption.php index be4413fb1c..d48282882a 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -1,5 +1,7 @@ finalStringContents = $caption; $this->id = $id; } - public function canContain(AbstractBlock $block) + public function canContain(AbstractBlock $block): bool { return false; } - public function acceptsLines() + public function acceptsLines(): bool { return false; } - public function isCode() + public function isCode(): bool { return false; } - public function matchesNextLine(Cursor $cursor) + public function matchesNextLine(Cursor $cursor): bool { return false; } diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index fd02f2d0fc..87efbf64f6 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -1,5 +1,7 @@ finalStringContents = $string; @@ -37,27 +41,27 @@ public function __construct($string = '', $type = self::TYPE_BODY, $align = null $this->align = $align; } - public function canContain(AbstractBlock $block) + public function canContain(AbstractBlock $block): bool { return false; } - public function acceptsLines() + public function acceptsLines(): bool { return false; } - public function isCode() + public function isCode(): bool { return false; } - public function matchesNextLine(Cursor $cursor) + public function matchesNextLine(Cursor $cursor): bool { return false; } - public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } } diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index d9902a0210..9f99d89120 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -1,5 +1,7 @@ align) { - $attrs['style'] = (isset($attrs['style']) ? $attrs['style'] . ' ' : '') . 'text-align: ' . $block->align; + $attrs['style'] = (isset($attrs['style']) ? $attrs['style'].' ' : '').'text-align: '.$block->align; } return new HtmlElement($block->type, $attrs, $htmlRenderer->renderInlines($block->children())); diff --git a/src/TableExtension.php b/src/TableExtension.php index 30eb492793..1b4621bfd1 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -1,5 +1,7 @@ new TableRenderer(), @@ -34,7 +36,7 @@ public function getBlockRenderers() ]; } - public function getName() + public function getName(): string { return 'table'; } diff --git a/src/TableParser.php b/src/TableParser.php index 4257787432..4c7870e638 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -1,5 +1,7 @@ getContainer(); @@ -45,7 +47,7 @@ public function parse(ContextInterface $context, Cursor $cursor) } $columns = $this->parseColumns($match); - $head = $this->parseRow(trim(array_pop($lines)), $columns, TableCell::TYPE_HEAD); + $head = $this->parseRow(trim((string) array_pop($lines)), $columns, TableCell::TYPE_HEAD); if (null === $head) { return false; } @@ -88,7 +90,7 @@ public function parse(ContextInterface $context, Cursor $cursor) return true; } - private function parseColumns(array $match) + private function parseColumns(array $match): array { $columns = []; foreach ((array) $match[0] as $i => $column) { @@ -106,12 +108,12 @@ private function parseColumns(array $match) return $columns; } - private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) + 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; + return null; } $i = 0; @@ -131,12 +133,12 @@ private function parseRow($line, array $columns, $type = TableCell::TYPE_BODY) return $row; } - private function parseCaption($line) + private function parseCaption(string $line): ?TableCaption { $caption = RegexHelper::matchAll(self::REGEXP_CAPTION, $line); if (null === $caption) { - return; + return null; } return new TableCaption($caption[1], $caption[2]); diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 30f666b01a..8ec9a5dabd 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -1,5 +1,7 @@ type = $type; } - public function isHead() + public function isHead(): bool { return self::TYPE_HEAD === $this->type; } - public function isBody() + public function isBody(): bool { return self::TYPE_BODY === $this->type; } - public function canContain(AbstractBlock $block) + public function canContain(AbstractBlock $block): bool { return $block instanceof TableRow; } - public function acceptsLines() + public function acceptsLines(): bool { return false; } - public function isCode() + public function isCode(): bool { return false; } - public function matchesNextLine(Cursor $cursor) + public function matchesNextLine(Cursor $cursor): bool { return false; } - public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } } diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index dd343f04c9..87360e41a0 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -1,5 +1,7 @@ hasChildren()) { - return; + return ''; } $attrs = []; diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index 67ac821d66..8f903f4e72 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -1,5 +1,7 @@ environment = Environment::createCommonMarkEnvironment(); $this->environment->addExtension(new TableExtension()); @@ -40,7 +41,7 @@ protected function setUp() /** * @dataProvider dataProvider */ - public function testRenderer($markdown, $html, $testName) + public function testRenderer(string $markdown, string $html, string $testName): void { $renderer = new HtmlRenderer($this->environment); $this->assertCommonMark($renderer, $markdown, $html, $testName); @@ -63,7 +64,7 @@ public function dataProvider() return $ret; } - protected function assertCommonMark(ElementRendererInterface $renderer, $markdown, $html, $testName) + protected function assertCommonMark(ElementRendererInterface $renderer, $markdown, $html, $testName): void { $documentAST = $this->parser->parse($markdown); $actualResult = $renderer->renderBlock($documentAST); From 18b2727027c0ae7647740ce60658d957082e9457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 15:23:20 +0100 Subject: [PATCH 060/231] Fix errors from static analyse --- src/Table.php | 6 +++++- src/TableCaption.php | 8 ++++++++ src/TableCell.php | 8 ++++++++ src/TableRow.php | 8 ++++++++ src/TableRows.php | 8 ++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/Table.php b/src/Table.php index 5ffe1a0883..5fced7717c 100644 --- a/src/Table.php +++ b/src/Table.php @@ -89,7 +89,11 @@ public function handleRemainingContents(ContextInterface $context, Cursor $curso { } - public function handleRemainingContents(ContextInterface $context, Cursor $cursor) + /** + * @return AbstractBlock[] + */ + public function children(): array { + return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractBlock; }); } } diff --git a/src/TableCaption.php b/src/TableCaption.php index d48282882a..b4945ddc8f 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -50,4 +50,12 @@ public function matchesNextLine(Cursor $cursor): bool { return false; } + + /** + * @return AbstractInline[] + */ + public function children(): array + { + return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractInline; }); + } } diff --git a/src/TableCell.php b/src/TableCell.php index 23cd089f83..9d937cee57 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -64,4 +64,12 @@ public function matchesNextLine(Cursor $cursor): bool public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } + + /** + * @return AbstractInline[] + */ + public function children(): array + { + return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractInline; }); + } } diff --git a/src/TableRow.php b/src/TableRow.php index c5aaea81ba..03ab1f2070 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -44,4 +44,12 @@ public function matchesNextLine(Cursor $cursor): bool public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } + + /** + * @return AbstractBlock[] + */ + public function children(): array + { + return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractBlock; }); + } } diff --git a/src/TableRows.php b/src/TableRows.php index b9534a35d6..48bbf92d92 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -65,4 +65,12 @@ public function matchesNextLine(Cursor $cursor): bool public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } + + /** + * @return AbstractBlock[] + */ + public function children(): array + { + return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractBlock; }); + } } From 44ffaba13ff88d51e7246232bce5bd3211a7798c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 15:26:31 +0100 Subject: [PATCH 061/231] Fix implementation of Table --- src/Table.php | 39 ++++++++++++++++++--------------------- src/TableParser.php | 2 +- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/Table.php b/src/Table.php index 5fced7717c..7858a75d8a 100644 --- a/src/Table.php +++ b/src/Table.php @@ -21,13 +21,16 @@ class Table extends AbstractBlock { + private $caption; + private $head; + private $body; private $parser; public function __construct(\Closure $parser) { parent::__construct(); - $this->appendChild(new TableRows(TableRows::TYPE_HEAD)); - $this->appendChild(new TableRows(TableRows::TYPE_BODY)); + $this->appendChild($this->head = new TableRows(TableRows::TYPE_HEAD)); + $this->appendChild($this->body = new TableRows(TableRows::TYPE_BODY)); $this->parser = $parser; } @@ -53,36 +56,30 @@ public function setCaption(TableCaption $caption = null): void $node->detach(); } - if ($caption instanceof TableCaption) { + $this->caption = $caption; + if (null !== $caption) { $this->prependChild($caption); } } - public function getCaption() + public function getCaption(): ?TableCaption { - foreach ($this->children() as $child) { - if ($child instanceof TableCaption) { - return $child; - } - } + return $this->caption; } - public function getHead() + public function getHead(): TableRows { - foreach ($this->children() as $child) { - if ($child instanceof TableRows && $child->isHead()) { - return $child; - } - } + return $this->head; } - public function getBody() + public function getBody(): TableRows { - foreach ($this->children() as $child) { - if ($child instanceof TableRows && $child->isBody()) { - return $child; - } - } + return $this->body; + } + + public function matchesNextLine(Cursor $cursor): bool + { + return call_user_func($this->parser, $cursor, $this); } public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void diff --git a/src/TableParser.php b/src/TableParser.php index 4c7870e638..2daeb24f62 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -52,7 +52,7 @@ public function parse(ContextInterface $context, Cursor $cursor): bool return false; } - $table = new Table(function (Cursor $cursor) use (&$table, $columns) { + $table = new Table(function (Cursor $cursor, Table $table) use ($columns): bool { $row = $this->parseRow($cursor->getLine(), $columns); if (null === $row) { if (null !== $table->getCaption()) { From 2d90236cf3e02c1f11a9518883907d52e20cdc52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 15:26:47 +0100 Subject: [PATCH 062/231] Update changelog --- .gitattributes | 1 + CHANGELOG.md | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.gitattributes b/.gitattributes index 6b73a2a7c7..8c7e284d18 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,4 +4,5 @@ /.scrutinizer.yml export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore +/psalm.xml /tests export-ignore diff --git a/CHANGELOG.md b/CHANGELOG.md index 3980ca02e4..75d46be1c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,26 @@ CHANGELOG ========= +0.10.0 (2019-xx-xx) +------------------- + + * Increased minimum PHP version to 7.1 + * Removed support for commonmark 0.16 + +0.9.0 (2018-11-28) +------------------ + + * Allowed the commonmark 0.18 + 0.8.0 (2018-01-24) ------------------ - * Replace align attribute with text-align style + * Replaced align attribute with text-align style 0.7.1 (2018-01-23) ------------------ - * Fix undefined method in commonmark 0.17 + * Fixed undefined method in commonmark 0.17 0.7.0 (2018-01-09) ------------------ @@ -17,7 +28,7 @@ CHANGELOG * Increased minimum PHP version to 5.6 * Removed support for commonmark 0.14 and 0.15 API * Updated to the commonmark 0.16 and 0.17 API - * Fix a problem with parsing whitespaces at the end of line + * Fixed a problem with parsing whitespaces at the end of line 0.6.1 (2017-01-11) ------------------ From 25838c21c5642cebe42cb9ec3517329b237cbe2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 22:45:36 +0100 Subject: [PATCH 063/231] Fix travis build --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dfd33e7952..6e627cb029 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,6 @@ php: - 7.3 env: - - COMMONMARK_VERSION=0.16.* - COMMONMARK_VERSION=0.17.* - COMMONMARK_VERSION=0.18.* - COMMONMARK_VERSION=0.19.*@dev From cdb21c2d8c01756a9288601ef962e87de982b8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Thu, 14 Feb 2019 22:47:30 +0100 Subject: [PATCH 064/231] Add run script --- .gitignore | 1 + run | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 run diff --git a/.gitignore b/.gitignore index 2d7ab77d69..a12fada64e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.idea /.php_cs.cache /.phpunit.result.cache /.runner diff --git a/run b/run new file mode 100755 index 0000000000..fbd673c469 --- /dev/null +++ b/run @@ -0,0 +1,22 @@ +#!/usr/bin/env sh +set -e + +# Static analyse +task_analyse()( + ./vendor/bin/phpstan analyse -l7 src "$@" + ./vendor/bin/psalm +) + +# Fix code style +task_cs_fix()( + ./vendor/bin/php-cs-fixer fix --allow-risky=yes "$@" +) + +# Run tests +task_tests()( + ./vendor/bin/phpunit "$@" +) + +url="https://raw.githubusercontent.com/webuni/shell-task-runner/master/runner" +! if [ -n "$(command -v 'wget')" ]; then r="$(wget -qT 1 "$url" -O-)" && echo "$r" > .runner; else curl --connect-timeout 1 -fso .runner "$url"; fi +. ./.runner From 83af2039a20a35e2a9b5edd57ca4539731fdb3ba Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 10 Mar 2019 21:24:04 -0400 Subject: [PATCH 065/231] Initial commit --- .editorconfig | 15 ++++ .gitattributes | 11 +++ .gitignore | 4 ++ .scrutinizer.yml | 39 ++++++++++ .styleci.yml | 9 +++ .travis.yml | 26 +++++++ CHANGELOG.md | 11 +++ CONDUCT.md | 22 ++++++ CONTRIBUTING.md | 51 +++++++++++++ LICENSE.md | 32 +++++++++ README.md | 91 ++++++++++++++++++++++++ composer.json | 55 +++++++++++++++ phpunit.xml.dist | 29 ++++++++ src/PunctuationParser.php | 75 ++++++++++++++++++++ src/QuoteParser.php | 110 +++++++++++++++++++++++++++++ src/QuoteProcessor.php | 44 ++++++++++++ src/SmartPunctExtension.php | 67 ++++++++++++++++++ tests/SmartPunctFunctionalTest.php | 105 +++++++++++++++++++++++++++ 18 files changed, 796 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/PunctuationParser.php create mode 100644 src/QuoteParser.php create mode 100644 src/QuoteProcessor.php create mode 100644 src/SmartPunctExtension.php create mode 100644 tests/SmartPunctFunctionalTest.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..43590ddcff --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/scrutinizer.yml export-ignore +/tests export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7aa851fa06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/build/ +/composer.lock +/vendor/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..a2baf35af7 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: + enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..bc9a4c815b --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,9 @@ +preset: recommended + +enabled: + - concat_with_spaces + - strict + +disabled: + - concat_without_spaces + - phpdoc_summary diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..accc57e21e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: php + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - 7.3 + +env: + matrix: + - COMPOSER_FLAGS="" + - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + +sudo: false + +before_script: + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + +after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..4af8753a97 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes will be documented in this file. + +## [Unreleased][unreleased] + +## 0.1.0 - 2019-03-10 + +Forked this extension out of the old `league/commonmark-extras` library. + +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/0.1.0...HEAD diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000000..6ff94ca3a4 --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..9808afa00d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-extras). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +- **Docblocks** - All files should start with the following docblock: + +~~~ +/* + * This file is part of the league/commonmark-extras package. + * + * (c) Colin O'Dell + * + * Authored by Your Name + * + * 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. + */ +~~~ + +The "Authored by" line is optional. + + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000..ce4d2078c5 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,32 @@ +Copyright (c) 2014-2019, Colin O'Dell + +Portions of this code based on commonmark.js: Copyright (c) 2014-2016, John MacFarlane + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Colin O'Dell nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..921b3d7022 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# Smart Punctuation for `league/commonmark` + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-travis]][link-travis] +[![Coverage Status][ico-scrutinizer]][link-scrutinizer] +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] + +Intelligently converts ASCII quotes, dashes, and ellipses to their Unicode equivalents. + +For example, this Markdown... + +```md +"CommonMark is the PHP League's Markdown parser," she said. "It's super-configurable... you can even use additional extensions to expand its capabilities -- just like this one!" +``` + +Will result in this HTML: + +```html +

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

+``` + +## Install + +Via Composer + +``` bash +$ composer require league/commonmark-ext-smartpunct +``` + +## Usage + +Extensions can be added to any new `Environment`: + +``` php +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\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()); + +// Instantiate the converter engine and start converting some Markdown! +$converter = new CommonMarkConverter($config, $environment); +echo $converter->convertToHtml('# Hello World!'); +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + +## Testing + +``` bash +$ composer test +``` + +## Security + +If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. + +## Credits + +- [Colin O'Dell][link-author] +- [John MacFarlane][link-jgm] +- [All Contributors][link-contributors] + +## License + +This library is licensed under the BSD-3 license. See the [License File](LICENSE.md) for more information. + +[ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-smartpunct.svg?style=flat-square +[ico-license]: http://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/thephpleague/commonmark-ext-smartpunct/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-smartpunct.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-smartpunct.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/league/commonmark-ext-smartpunct.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/league/commonmark-ext-smartpunct +[link-travis]: https://travis-ci.org/thephpleague/commonmark-ext-smartpunct +[link-scrutinizer]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-smartpunct/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-smartpunct +[link-downloads]: https://packagist.org/packages/league/commonmark-ext-smartpunct +[link-author]: https://github.com/colinodell +[link-contributors]: ../../contributors +[link-league-commonmark]: https://github.com/thephpleague/commonmark +[link-jgm]: https://github.com/jgm diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..0ecceeeffa --- /dev/null +++ b/composer.json @@ -0,0 +1,55 @@ +{ + "name": "league/commonmark-ext-smartpunct", + "type": "commonmark-extension", + "description": "Intelligently converts ASCII quotes, dashes, and ellipses to their Unicode equivalents", + "keywords": ["markdown", "commonmark", "extension", "punctuation"], + "homepage": "https://github.com/thephpleague/commonmark-ext-smartpunct", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "require": { + "php" : ">=5.6", + "league/commonmark": "^0.13|^0.14|^0.15|^0.16|^0.17|^0.18" + }, + "require-dev": { + "jgm/smartpunct": "0.28", + "phpunit/phpunit": "^5.7" + }, + "repositories": [ + { + "type": "package", + "package": { + "name": "jgm/smartpunct", + "version": "0.28", + "dist": { + "url": "https://raw.githubusercontent.com/jgm/commonmark.js/0.28.0/test/smart_punct.txt", + "type": "file" + } + } + } + ], + "autoload": { + "psr-4": { + "League\\CommonMark\\Ext\\SmartPunct\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "league\\CommonMark\\Ext\\SmartPunct\\Test\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..c90fd7e546 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + tests + + + + + src/ + + + + + + + + + + diff --git a/src/PunctuationParser.php b/src/PunctuationParser.php new file mode 100644 index 0000000000..20214528d6 --- /dev/null +++ b/src/PunctuationParser.php @@ -0,0 +1,75 @@ + + * + * 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\Ext\SmartPunct; + +use League\CommonMark\Inline\Element\Text; +use League\CommonMark\Inline\Parser\AbstractInlineParser; +use League\CommonMark\InlineParserContext; + +class PunctuationParser extends AbstractInlineParser +{ + /** + * @return string[] + */ + public function getCharacters() + { + return ['-', '.']; + } + + /** + * @param InlineParserContext $inlineContext + * + * @return bool + */ + public function parse(InlineParserContext $inlineContext) + { + $cursor = $inlineContext->getCursor(); + $ch = $cursor->getCharacter(); + + // Ellipses + if ($ch === '.' && $matched = $cursor->match('/^\\.( ?\\.)\\1/')) { + $inlineContext->getContainer()->appendChild(new Text('…')); + + return true; + } + + // Em/En-dashes + elseif ($ch === '-' && $matched = $cursor->match('/^(?getContainer()->appendChild(new Text( + str_repeat($em_dash, $em_count) . str_repeat($en_dash, $en_count) + )); + + return true; + } + + return false; + } +} diff --git a/src/QuoteParser.php b/src/QuoteParser.php new file mode 100644 index 0000000000..84623f946e --- /dev/null +++ b/src/QuoteParser.php @@ -0,0 +1,110 @@ + + * + * 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\Ext\SmartPunct; + +use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Inline\Element\Text; +use League\CommonMark\Inline\Parser\AbstractInlineParser; +use League\CommonMark\InlineParserContext; +use League\CommonMark\Util\RegexHelper; + +class QuoteParser extends AbstractInlineParser +{ + protected $double = ['"', '“', '”']; + protected $single = ["'", '‘', '’']; + + /** + * @return string[] + */ + public function getCharacters() + { + return array_merge($this->double, $this->single); + } + + /** + * @param InlineParserContext $inlineContext + * + * @return bool + */ + public function parse(InlineParserContext $inlineContext) + { + $cursor = $inlineContext->getCursor(); + $character = $this->getCharacterType($cursor->getCharacter()); + + $charBefore = $cursor->peek(-1); + if ($charBefore === null) { + $charBefore = "\n"; + } + + $cursor->advance(); + + $charAfter = $cursor->getCharacter(); + if ($charAfter === null) { + $charAfter = "\n"; + } + + list($leftFlanking, $rightFlanking) = $this->determineFlanking($charBefore, $charAfter); + $canOpen = $leftFlanking && !$rightFlanking; + $canClose = $rightFlanking; + + $node = new Text($character, ['delim' => true]); + $inlineContext->getContainer()->appendChild($node); + + // Add entry to stack to this opener + $inlineContext->getDelimiterStack()->push(new Delimiter($character, 1, $node, $canOpen, $canClose)); + + return true; + } + + /** + * @param string $character + * + * @return string|null + */ + private function getCharacterType($character) + { + if (in_array($character, $this->double)) { + return '“'; + } elseif (in_array($character, $this->single)) { + return '’'; + } + } + + /** + * @param string $charBefore + * @param string $charAfter + * + * @return string[] + */ + 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/src/QuoteProcessor.php b/src/QuoteProcessor.php new file mode 100644 index 0000000000..6b3f57fd41 --- /dev/null +++ b/src/QuoteProcessor.php @@ -0,0 +1,44 @@ + + * + * 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\Ext\SmartPunct; + +use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Delimiter\DelimiterStack; +use League\CommonMark\Inline\Processor\InlineProcessorInterface; + +class QuoteProcessor implements InlineProcessorInterface +{ + public function processInlines(DelimiterStack $delimiterStack, Delimiter $stackBottom = null) + { + $callback = function (Delimiter $opener, Delimiter $closer) { + // Open quote + $openerInline = $opener->getInlineNode(); + $openerInline->setContent( + $openerInline->getContent() === '“' ? '“' : '‘' + ); + + // Close quote + $closerInline = $closer->getInlineNode(); + $closerInline->setContent( + $closerInline->getContent() === '“' ? '”' : '’' + ); + + return $closer->getNext(); + }; + + // Process the emphasis characters + $delimiterStack->iterateByCharacters(['“', '’'], $callback, $stackBottom); + } +} diff --git a/src/SmartPunctExtension.php b/src/SmartPunctExtension.php new file mode 100644 index 0000000000..09d9153efd --- /dev/null +++ b/src/SmartPunctExtension.php @@ -0,0 +1,67 @@ + + * + * 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\Ext\SmartPunct; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\Block\Element\Paragraph; +use League\CommonMark\Block\Renderer as CoreBlockRenderer; +use League\CommonMark\Extension\Extension; +use League\CommonMark\Inline\Element\Text; +use League\CommonMark\Inline\Renderer as CoreInlineRenderer; + +class SmartPunctExtension extends Extension +{ + /** + * {@inheritdoc} + */ + public function getInlineParsers() + { + return [ + new QuoteParser(), + new PunctuationParser(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getInlineProcessors() + { + return [ + new QuoteProcessor(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getBlockRenderers() + { + return [ + Document::class => new CoreBlockRenderer\DocumentRenderer(), + Paragraph::class => new CoreBlockRenderer\ParagraphRenderer(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getInlineRenderers() + { + return [ + Text::class => new CoreInlineRenderer\TextRenderer(), + ]; + } +} diff --git a/tests/SmartPunctFunctionalTest.php b/tests/SmartPunctFunctionalTest.php new file mode 100644 index 0000000000..2e7e07ade5 --- /dev/null +++ b/tests/SmartPunctFunctionalTest.php @@ -0,0 +1,105 @@ + + * + * 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\Ext\Tests\SmartPunct; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Converter; +use League\CommonMark\DocParser; +use League\CommonMark\Environment; +use League\CommonMark\Ext\SmartPunct\SmartPunctExtension; +use League\CommonMark\HtmlRenderer; +use PHPUnit\Framework\TestCase; + +/** + * Tests the parser against the CommonMark spec + */ +class SmartPunctFunctionalTest extends TestCase +{ + /** + * @var CommonMarkConverter + */ + protected $converter; + + protected function setUp() + { + $environment = Environment::createCommonMarkEnvironment(); + $environment->addExtension(new SmartPunctExtension()); + $this->converter = new Converter( + new DocParser($environment), + new HtmlRenderer($environment) + ); + } + + /** + * @param string $markdown Markdown to parse + * @param string $html Expected result + * @param string $section Section of the spec + * @param int $number Example number + * + * @dataProvider dataProvider + */ + public function testExample($markdown, $html, $section, $number) + { + $actualResult = $this->converter->convertToHtml($markdown); + + $failureMessage = sprintf('Unexpected result ("%s" section, example #%d)', $section, $number); + $failureMessage .= "\n=== markdown ===============\n" . $markdown; + $failureMessage .= "\n=== expected ===============\n" . $html; + $failureMessage .= "\n=== got ====================\n" . $actualResult; + + $this->assertEquals($html, $actualResult, $failureMessage); + } + + /** + * @return array + */ + public function dataProvider() + { + $filename = __DIR__ . '/../vendor/jgm/smartpunct/smart_punct.txt'; + if (($data = file_get_contents($filename)) === false) { + $this->fail(sprintf('Failed to load spec from %s', $filename)); + } + + $matches = []; + // Normalize newlines for platform independence + $data = preg_replace('/\r\n?/', "\n", $data); + $data = preg_replace('/.*$/', '', $data); + preg_match_all('/^`{32} example\n([\s\S]*?)^\.\n([\s\S]*?)^`{32}$|^#{1,6} *(.*)$/m', $data, $matches, PREG_SET_ORDER); + + $examples = []; + $currentSection = ''; + $exampleNumber = 0; + + foreach ($matches as $match) { + if (isset($match[3])) { + $currentSection = $match[3]; + } else { + $exampleNumber++; + + $markdown = $match[1]; + $markdown = str_replace('→', "\t", $markdown); + + $examples[] = [ + 'markdown' => $markdown, + 'html' => $match[2], + 'section' => $currentSection, + 'number' => $exampleNumber, + ]; + } + } + + return $examples; + } +} From 2d04acd7a6a72e916c1ee365f587540cff53b028 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 10 Mar 2019 21:35:26 -0400 Subject: [PATCH 066/231] Update description and keywords --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0ecceeeffa..823674797b 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { "name": "league/commonmark-ext-smartpunct", "type": "commonmark-extension", - "description": "Intelligently converts ASCII quotes, dashes, and ellipses to their Unicode equivalents", - "keywords": ["markdown", "commonmark", "extension", "punctuation"], + "description": "Intelligently converts ASCII quotes, dashes, and ellipses in Markdown to their Unicode equivalents", + "keywords": ["markdown", "commonmark", "extension", "punctuation", "smartpunct"], "homepage": "https://github.com/thephpleague/commonmark-ext-smartpunct", "license": "BSD-3-Clause", "authors": [ From aece89338949e86cddedd847a466d96d3a019f8e Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 10 Mar 2019 21:37:56 -0400 Subject: [PATCH 067/231] Fix StyleCI violations --- src/SmartPunctExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SmartPunctExtension.php b/src/SmartPunctExtension.php index 09d9153efd..9d41ab082a 100644 --- a/src/SmartPunctExtension.php +++ b/src/SmartPunctExtension.php @@ -50,7 +50,7 @@ public function getInlineProcessors() public function getBlockRenderers() { return [ - Document::class => new CoreBlockRenderer\DocumentRenderer(), + Document::class => new CoreBlockRenderer\DocumentRenderer(), Paragraph::class => new CoreBlockRenderer\ParagraphRenderer(), ]; } From 2fa7239462d6ffc96f6b1e3a952a2d94894d9e9d Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 10 Mar 2019 21:40:23 -0400 Subject: [PATCH 068/231] Add link to league/commonmark project --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 921b3d7022..ca52bdcec1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Quality Score][ico-code-quality]][link-code-quality] [![Total Downloads][ico-downloads]][link-downloads] -Intelligently converts ASCII quotes, dashes, and ellipses to their Unicode equivalents. +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... From c1dc244a821a4901565e9f10545f0ab309391ac3 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 11 Mar 2019 10:14:08 -0400 Subject: [PATCH 069/231] Fix project name and namespace --- CHANGELOG.md | 4 ++-- CONTRIBUTING.md | 4 ++-- phpunit.xml.dist | 2 +- src/PunctuationParser.php | 2 +- src/QuoteParser.php | 2 +- src/QuoteProcessor.php | 2 +- src/SmartPunctExtension.php | 2 +- tests/SmartPunctFunctionalTest.php | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4af8753a97..c39e2c7b8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ All notable changes will be documented in this file. ## [Unreleased][unreleased] -## 0.1.0 - 2019-03-10 +## 0.1.0 - 2019-03-11 -Forked this extension out of the old `league/commonmark-extras` library. +Forked this extension out of the old `league/commonmark-ext-smartpunct` library. [unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/0.1.0...HEAD diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9808afa00d..fed84253b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contributions are **welcome** and will be fully **credited**. -We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-extras). +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-ext-smartpunct). ## Pull Requests @@ -24,7 +24,7 @@ We accept contributions via Pull Requests on [Github](https://github.com/thephpl ~~~ /* - * This file is part of the league/commonmark-extras package. + * This file is part of the league/commonmark-ext-smartpunct package. * * (c) Colin O'Dell * diff --git a/phpunit.xml.dist b/phpunit.xml.dist index c90fd7e546..470e2aff35 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ processIsolation="false" stopOnFailure="false"> - + tests diff --git a/src/PunctuationParser.php b/src/PunctuationParser.php index 20214528d6..173c57ed53 100644 --- a/src/PunctuationParser.php +++ b/src/PunctuationParser.php @@ -1,7 +1,7 @@ * diff --git a/src/QuoteParser.php b/src/QuoteParser.php index 84623f946e..9f1b7e719b 100644 --- a/src/QuoteParser.php +++ b/src/QuoteParser.php @@ -1,7 +1,7 @@ * diff --git a/src/QuoteProcessor.php b/src/QuoteProcessor.php index 6b3f57fd41..03e031e3f6 100644 --- a/src/QuoteProcessor.php +++ b/src/QuoteProcessor.php @@ -1,7 +1,7 @@ * diff --git a/src/SmartPunctExtension.php b/src/SmartPunctExtension.php index 9d41ab082a..83d2e451e9 100644 --- a/src/SmartPunctExtension.php +++ b/src/SmartPunctExtension.php @@ -1,7 +1,7 @@ * diff --git a/tests/SmartPunctFunctionalTest.php b/tests/SmartPunctFunctionalTest.php index 2e7e07ade5..76fbb7caf2 100644 --- a/tests/SmartPunctFunctionalTest.php +++ b/tests/SmartPunctFunctionalTest.php @@ -1,7 +1,7 @@ * @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace League\CommonMark\Ext\Tests\SmartPunct; +namespace League\CommonMark\Ext\SmartPunct\Tests; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Converter; From f910a117a4f6b12d87de2737cbe252a34ad37748 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 11 Mar 2019 10:08:21 -0400 Subject: [PATCH 070/231] Initial commit --- .editorconfig | 15 +++++ .gitattributes | 11 ++++ .gitignore | 4 ++ .scrutinizer.yml | 39 ++++++++++++ .styleci.yml | 9 +++ .travis.yml | 26 ++++++++ CHANGELOG.md | 11 ++++ CONDUCT.md | 22 +++++++ CONTRIBUTING.md | 51 +++++++++++++++ LICENSE.md | 32 ++++++++++ README.md | 79 ++++++++++++++++++++++++ composer.json | 41 ++++++++++++ phpunit.xml.dist | 29 +++++++++ src/ChildRenderer.php | 47 ++++++++++++++ src/InlinesOnlyExtension.php | 96 +++++++++++++++++++++++++++++ tests/InlinesOnlyFunctionalTest.php | 75 ++++++++++++++++++++++ tests/inlines.html | 8 +++ tests/inlines.md | 9 +++ 18 files changed, 604 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/ChildRenderer.php create mode 100644 src/InlinesOnlyExtension.php create mode 100644 tests/InlinesOnlyFunctionalTest.php create mode 100644 tests/inlines.html create mode 100644 tests/inlines.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..43590ddcff --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/scrutinizer.yml export-ignore +/tests export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7aa851fa06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/build/ +/composer.lock +/vendor/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..a2baf35af7 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: + enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..bc9a4c815b --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,9 @@ +preset: recommended + +enabled: + - concat_with_spaces + - strict + +disabled: + - concat_without_spaces + - phpdoc_summary diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..accc57e21e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: php + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - 7.3 + +env: + matrix: + - COMPOSER_FLAGS="" + - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + +sudo: false + +before_script: + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + +after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..d3dc3f165d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes will be documented in this file. + +## [Unreleased][unreleased] + +## 0.1.0 - 2019-03-11 + +Initial release! + +[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/0.1.0...HEAD diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000000..6ff94ca3a4 --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..4d9c7bde9e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-ext-inlines-only). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +- **Docblocks** - All files should start with the following docblock: + +~~~ +/* + * This file is part of the league/commonmark-ext-inlines-only package. + * + * (c) Colin O'Dell + * + * Authored by Your Name + * + * 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. + */ +~~~ + +The "Authored by" line is optional. + + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000..ce4d2078c5 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,32 @@ +Copyright (c) 2014-2019, Colin O'Dell + +Portions of this code based on commonmark.js: Copyright (c) 2014-2016, John MacFarlane + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Colin O'Dell nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..fc55cbd4db --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# Inline-only extension for `league/commonmark` + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-travis]][link-travis] +[![Coverage Status][ico-scrutinizer]][link-scrutinizer] +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] + +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. + +## Install + +Via Composer + +``` bash +$ composer require league/commonmark-ext-inlines-only +``` + +## 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\Ext\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!**'); +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + +## Testing + +``` bash +$ composer test +``` + +## Security + +If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. + +## Credits + +- [Colin O'Dell][link-author] +- [John MacFarlane][link-jgm] +- [All Contributors][link-contributors] + +## License + +This library is licensed under the BSD-3 license. See the [License File](LICENSE.md) for more information. + +[ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-inlines-only.svg?style=flat-square +[ico-license]: http://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/thephpleague/commonmark-ext-inlines-only/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-inlines-only.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-inlines-only.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/league/commonmark-ext-inlines-only.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/league/commonmark-ext-inlines-only +[link-travis]: https://travis-ci.org/thephpleague/commonmark-ext-inlines-only +[link-scrutinizer]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-inlines-only/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-inlines-only +[link-downloads]: https://packagist.org/packages/league/commonmark-ext-inlines-only +[link-author]: https://github.com/colinodell +[link-contributors]: ../../contributors +[link-league-commonmark]: https://github.com/thephpleague/commonmark +[link-jgm]: https://github.com/jgm diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..0e3045fef1 --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "league/commonmark-ext-inlines-only", + "type": "commonmark-extension", + "description": "Extension for league/commonmark which only renders inline text", + "keywords": ["markdown", "commonmark", "extension", "inline"], + "homepage": "https://github.com/thephpleague/commonmark-ext-inlines-only", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "require": { + "php" : ">=5.6", + "league/commonmark": "^0.18.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\Ext\\InlinesOnly\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "league\\CommonMark\\Ext\\InlinesOnly\\Test\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..d5f268e8bb --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + tests + + + + + src/ + + + + + + + + + + diff --git a/src/ChildRenderer.php b/src/ChildRenderer.php new file mode 100644 index 0000000000..621b4eb010 --- /dev/null +++ b/src/ChildRenderer.php @@ -0,0 +1,47 @@ + + * + * 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\Ext\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; + +/** + * Simply renders child elements as-is, adding newlines as needed. + */ +final class ChildRenderer implements BlockRendererInterface +{ + /** + * {@inheritdoc} + */ + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + { + $out = ''; + + if ($block instanceof InlineContainerInterface) { + $out .= $htmlRenderer->renderInlines($block->children()); + } else { + $out .= $htmlRenderer->renderBlocks($block->children()); + } + + if (!($block instanceof Document)) { + $out .= "\n"; + } + + return $out; + } +} diff --git a/src/InlinesOnlyExtension.php b/src/InlinesOnlyExtension.php new file mode 100644 index 0000000000..266593ea5c --- /dev/null +++ b/src/InlinesOnlyExtension.php @@ -0,0 +1,96 @@ + + * + * 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\Ext\InlinesOnly; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\Block\Element\Paragraph; +use League\CommonMark\Block\Parser as BlockParser; +use League\CommonMark\Extension\Extension; +use League\CommonMark\Inline\Element as InlineElement; +use League\CommonMark\Inline\Parser as InlineParser; +use League\CommonMark\Inline\Processor as InlineProcessor; +use League\CommonMark\Inline\Renderer as InlineRenderer; + +final class InlinesOnlyExtension extends Extension +{ + /** + * {@inheritdoc} + */ + public function getBlockParsers() + { + return [ + new BlockParser\LazyParagraphParser(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getInlineParsers() + { + return [ + new InlineParser\NewlineParser(), + new InlineParser\BacktickParser(), + new InlineParser\EscapableParser(), + new InlineParser\EntityParser(), + new InlineParser\EmphasisParser(), + new InlineParser\AutolinkParser(), + new InlineParser\HtmlInlineParser(), + new InlineParser\CloseBracketParser(), + new InlineParser\OpenBracketParser(), + new InlineParser\BangParser(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getInlineProcessors() + { + return [ + new InlineProcessor\EmphasisProcessor(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getBlockRenderers() + { + $renderer = new ChildRenderer(); + + return [ + Document::class => $renderer, + Paragraph::class => $renderer, + ]; + } + + /** + * {@inheritdoc} + */ + public function getInlineRenderers() + { + return [ + InlineElement\Code::class => new InlineRenderer\CodeRenderer(), + InlineElement\Emphasis::class => new InlineRenderer\EmphasisRenderer(), + InlineElement\HtmlInline::class => new InlineRenderer\HtmlInlineRenderer(), + InlineElement\Image::class => new InlineRenderer\ImageRenderer(), + InlineElement\Link::class => new InlineRenderer\LinkRenderer(), + InlineElement\Newline::class => new InlineRenderer\NewlineRenderer(), + InlineElement\Strong::class => new InlineRenderer\StrongRenderer(), + InlineElement\Text::class => new InlineRenderer\TextRenderer(), + ]; + } +} diff --git a/tests/InlinesOnlyFunctionalTest.php b/tests/InlinesOnlyFunctionalTest.php new file mode 100644 index 0000000000..fe0fb419de --- /dev/null +++ b/tests/InlinesOnlyFunctionalTest.php @@ -0,0 +1,75 @@ + + * + * 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\Ext\InlinesOnly\Tests; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Converter; +use League\CommonMark\DocParser; +use League\CommonMark\Environment; +use League\CommonMark\Ext\InlinesOnly\InlinesOnlyExtension; +use League\CommonMark\HtmlRenderer; +use PHPUnit\Framework\TestCase; + +/** + * Tests the extension against sample files + */ +class InlinesOnlyFunctionalTest extends TestCase +{ + /** + * @var CommonMarkConverter + */ + protected $converter; + + protected function setUp() + { + $environment = new Environment(); + $environment->addExtension(new InlinesOnlyExtension()); + $this->converter = new Converter( + new DocParser($environment), + new HtmlRenderer($environment) + ); + } + + /** + * @param string $markdown Markdown to parse + * @param string $html Expected result + * + * @dataProvider dataProvider + */ + public function testExample($markdown, $html) + { + $actualResult = $this->converter->convertToHtml($markdown); + + $failureMessage = 'Unexpected result'; + $failureMessage .= "\n=== markdown ===============\n" . $markdown; + $failureMessage .= "\n=== expected ===============\n" . $html; + $failureMessage .= "\n=== got ====================\n" . $actualResult; + + $this->assertEquals($html, $actualResult, $failureMessage); + } + + /** + * @return array + */ + public function dataProvider() + { + $markdown = file_get_contents(__DIR__ . '/inlines.md'); + $html = file_get_contents(__DIR__ . '/inlines.html'); + + return [ + [$markdown, $html], + ]; + } +} diff --git a/tests/inlines.html b/tests/inlines.html new file mode 100644 index 0000000000..f0c799b87f --- /dev/null +++ b/tests/inlines.html @@ -0,0 +1,8 @@ +Bold text normal text +Normal text and italics text too. + +Documentation is at https://commonmark.thephpleague.com. + +# This header will NOT be rendered in an h1 tag + +Two line breaks above diff --git a/tests/inlines.md b/tests/inlines.md new file mode 100644 index 0000000000..b5b883c728 --- /dev/null +++ b/tests/inlines.md @@ -0,0 +1,9 @@ +**Bold text** normal text +Normal text and _italics text_ too. + +Documentation is at . + +# This header will NOT be rendered in an h1 tag + + +Two line breaks above From 0fe08a221efbcf5ef4bfb9447b48384c3e6fab26 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 11 Mar 2019 10:24:52 -0400 Subject: [PATCH 071/231] Fix package reference This is what I get for doing a find-and-replace and not triple-checking the results --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c39e2c7b8b..52e2695b47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,6 @@ All notable changes will be documented in this file. ## 0.1.0 - 2019-03-11 -Forked this extension out of the old `league/commonmark-ext-smartpunct` library. +Forked this extension out of the old `league/commonmark-extras` library. [unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/0.1.0...HEAD From 12af0f182a1bd20efa97395259e4261c4cd3e366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 12 Mar 2019 00:00:11 +0200 Subject: [PATCH 072/231] composer: fix autoload-dev for tests looks like this problem has spewed over multiple repositories --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0e3045fef1..c28009f5c7 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "autoload-dev": { "psr-4": { - "league\\CommonMark\\Ext\\InlinesOnly\\Test\\": "tests" + "League\\CommonMark\\Ext\\InlinesOnly\\Tests\\": "tests" } }, "scripts": { From 51cd6fa1f9b88edcf352510eee262c55d6c736e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 12 Mar 2019 00:12:36 +0200 Subject: [PATCH 073/231] composer: fix autoload-dev for tests looks like this problem has spewed over multiple repositories --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 823674797b..93a6b2db41 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ }, "autoload-dev": { "psr-4": { - "league\\CommonMark\\Ext\\SmartPunct\\Test\\": "tests" + "League\\CommonMark\\Ext\\SmartPunct\\Tests\\": "tests" } }, "scripts": { From d516b52a5ccc6a173110331ab0b378f3158d2296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 12 Mar 2019 00:16:25 +0200 Subject: [PATCH 074/231] changelog: reformat and fix changelog links --- CHANGELOG.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e2695b47..f255420942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ # Changelog -All notable changes will be documented in this file. +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] -## 0.1.0 - 2019-03-11 +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.1.0...HEAD + +## [0.1.0] - 2019-03-11 -Forked this extension out of the old `league/commonmark-extras` library. +Split this extension out of the old `league/commonmark-extras` library. -[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/0.1.0...HEAD +[0.1.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/commits/v0.1.0 From 721a1ecd27ebf10ac892887f7ef02e56058c882e Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 14 Mar 2019 21:38:10 -0400 Subject: [PATCH 075/231] Initial release --- .editorconfig | 15 ++++ .gitattributes | 11 +++ .gitignore | 4 + .scrutinizer.yml | 39 +++++++++ .styleci.yml | 13 +++ .travis.yml | 26 ++++++ CHANGELOG.md | 11 +++ CONDUCT.md | 22 +++++ CONTRIBUTING.md | 46 ++++++++++ LICENSE.md | 30 +++++++ README.md | 124 +++++++++++++++++++++++++++ composer.json | 41 +++++++++ phpunit.xml.dist | 29 +++++++ src/AutolinkExtension.php | 25 ++++++ src/EmailAutolinkProcessor.php | 51 +++++++++++ src/InlineMentionParser.php | 98 +++++++++++++++++++++ src/UrlAutolinkProcessor.php | 89 +++++++++++++++++++ tests/EmailAutolinkProcessorTest.php | 64 ++++++++++++++ tests/InlineMentionParserTest.php | 58 +++++++++++++ tests/UrlAutolinkProcessorTest.php | 42 +++++++++ 20 files changed, 838 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/AutolinkExtension.php create mode 100644 src/EmailAutolinkProcessor.php create mode 100644 src/InlineMentionParser.php create mode 100644 src/UrlAutolinkProcessor.php create mode 100644 tests/EmailAutolinkProcessorTest.php create mode 100644 tests/InlineMentionParserTest.php create mode 100644 tests/UrlAutolinkProcessorTest.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..43590ddcff --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/scrutinizer.yml export-ignore +/tests export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7aa851fa06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/build/ +/composer.lock +/vendor/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..a2baf35af7 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: + enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..af9054cd43 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,13 @@ +preset: recommended + +enabled: + - concat_with_spaces + - no_useless_else + - strict + +disabled: + - concat_without_spaces + - no_trailing_comma_in_list_call + - phpdoc_summary + - post_increment + - self_accessor diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..accc57e21e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: php + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + - 7.3 + +env: + matrix: + - COMPOSER_FLAGS="" + - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + +sudo: false + +before_script: + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + +after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..46ce01cd07 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes will be documented in this file. + +## [Unreleased][unreleased] + +## 0.1.0 - 2019-03-14 + +Initial release! + +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/0.1.0...HEAD diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000000..6ff94ca3a4 --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..da581cb194 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-ext-autolink). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +- **Docblocks** - All files should start with the following docblock: + +~~~ +/* + * This file is part of the league/commonmark-ext-autolink package. + * + * (c) Colin O'Dell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +~~~ + +The "Authored by" line is optional. + + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000..42bf99e480 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,30 @@ +Copyright (c) 2019, Colin O'Dell + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Colin O'Dell nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..970e052692 --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# URL and email autolinking extension for `league/commonmark` + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-travis]][link-travis] +[![Coverage Status][ico-scrutinizer]][link-scrutinizer] +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] + +This extension configures the [`league/commonmark` Markdown parser for PHP][link-league-commonmark] to automatically link URLs and email addresses even if the CommonMark `<...>` autolink syntax is not used. + +It also provides a parser to autolink `@mentions` and configure your own custom ones, though this is disabled by default. + +## Install + +Via Composer + +``` bash +$ composer require league/commonmark-ext-autolink +``` + +## 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\Ext\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($config, $environment); +echo $converter->convertToHtml('I successfully instead the https://github.com/thephpleague/commonmark-ext-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\Ext\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\Ext\Autolink\InlineMentionParser; + +$environment = Environment::createCommonMarkEnvironment(); +$environment->addInlineParser(InlineMentionParser::createTwitterHandleParser()); + +// TODO: Instantiate your converter and convert some Markdown +``` + +Or configure your own custom one: + +```php +use League\CommonMark\Environment; +use League\CommonMark\Ext\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)/'`) + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + +## Testing + +``` bash +$ composer test +``` + +## Security + +If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. + +## Credits + +- [Colin O'Dell][link-author] +- [All Contributors][link-contributors] + +## License + +This library is licensed under the BSD-3 license. See the [License File](LICENSE.md) for more information. + +[ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-autolink.svg?style=flat-square +[ico-license]: http://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/thephpleague/commonmark-ext-autolink/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-autolink.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-autolink.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/league/commonmark-ext-autolink.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/league/commonmark-ext-autolink +[link-travis]: https://travis-ci.org/thephpleague/commonmark-ext-autolink +[link-scrutinizer]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-autolink/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-autolink +[link-downloads]: https://packagist.org/packages/league/commonmark-ext-autolink +[link-author]: https://github.com/colinodell +[link-contributors]: ../../contributors +[link-league-commonmark]: https://github.com/thephpleague/commonmark diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..b3bd9222a0 --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "league/commonmark-ext-autolink", + "type": "commonmark-extension", + "description": "Extension for league/commonmark which autolinks URLs, emails, and @-mentions", + "keywords": ["markdown", "commonmark", "extension", "autolink", "twitter", "github"], + "homepage": "https://github.com/thephpleague/commonmark-ext-autolink", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "require": { + "php" : ">=5.6", + "league/commonmark": "^0.18.1" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\Ext\\Autolink\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "League\\CommonMark\\Ext\\Autolink\\Test\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..ef120d6ec6 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + tests + + + + + src/ + + + + + + + + + + diff --git a/src/AutolinkExtension.php b/src/AutolinkExtension.php new file mode 100644 index 0000000000..f4dc4b7878 --- /dev/null +++ b/src/AutolinkExtension.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\Autolink; + +use League\CommonMark\Extension\Extension; + +final class AutolinkExtension extends Extension +{ + public function getDocumentProcessors() + { + return [ + new EmailAutolinkProcessor(), + new UrlAutolinkProcessor(), + ]; + } +} diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php new file mode 100644 index 0000000000..c8859ebb60 --- /dev/null +++ b/src/EmailAutolinkProcessor.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\Autolink; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\DocumentProcessorInterface; +use League\CommonMark\Inline\Element\Link; +use League\CommonMark\Inline\Element\Text; + +final class EmailAutolinkProcessor implements DocumentProcessorInterface +{ + // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/EmailValidator.php + const REGEX = '/([a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)/'; + + /** + * @param Document $document + * + * @return void + */ + public function processDocument(Document $document) + { + $walker = $document->walker(); + + while ($event = $walker->next()) { + if ($event->isEntering() && $event->getNode() instanceof Text) { + /** @var Text $node */ + $node = $event->getNode(); + + $contents = preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + foreach ($contents as $i => $content) { + if ($i % 2 === 0) { + $node->insertBefore(new Text($content)); + } else { + $node->insertBefore(new Link('mailto:'.$content, $content)); + } + } + + $node->detach(); + } + } + } +} diff --git a/src/InlineMentionParser.php b/src/InlineMentionParser.php new file mode 100644 index 0000000000..0003f75f0e --- /dev/null +++ b/src/InlineMentionParser.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\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 getName() + { + return 'mention'; + } + + /** + * {@inheritdoc} + */ + public function getCharacters() + { + return ['@']; + } + + /** + * {@inheritdoc} + */ + public function parse(InlineParserContext $inlineContext) + { + $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/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php new file mode 100644 index 0000000000..6191bebad5 --- /dev/null +++ b/src/UrlAutolinkProcessor.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\Autolink; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\DocumentProcessorInterface; +use League\CommonMark\Inline\Element\Link; +use League\CommonMark\Inline\Element\Text; + +final class UrlAutolinkProcessor implements DocumentProcessorInterface +{ + // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php + const REGEX = '~( + (?:%s):// # protocol + (?:([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth + (?: + (?:[\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 $allowedProtocols; + + public function __construct(array $allowedProtocols = ['http', 'https']) + { + $this->allowedProtocols = $allowedProtocols; + } + + /** + * @param Document $document + * + * @return void + */ + public function processDocument(Document $document) + { + $regex = sprintf(self::REGEX, implode('|', $this->allowedProtocols)); + + $walker = $document->walker(); + + while ($event = $walker->next()) { + if ($event->isEntering() && $event->getNode() instanceof Text) { + /** @var Text $node */ + $node = $event->getNode(); + + $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + $leftovers = ''; + foreach ($contents as $i => $content) { + if ($i % 2 === 0) { + $node->insertBefore(new Text($leftovers.$content)); + $leftovers = ''; + } else { + // 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]; + } + $node->insertBefore(new Link($content, $content)); + } + } + + if ($leftovers !== '') { + $node->insertBefore(new Text($leftovers)); + } + + $node->detach(); + } + } + } +} diff --git a/tests/EmailAutolinkProcessorTest.php b/tests/EmailAutolinkProcessorTest.php new file mode 100644 index 0000000000..c7e954f359 --- /dev/null +++ b/tests/EmailAutolinkProcessorTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace league\CommonMark\Ext\Autolink\Test\Email; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\Autolink\AutolinkExtension; +use PHPUnit\Framework\TestCase; + +final class EmailAutolinkProcessorTest extends TestCase +{ + public function testEmailAutolinks() + { + $input = << This processor can even handle email addresses like foo@example.com inside of blockquotes! + +More fake emails: + + - foo@example.com + - bar@example.com + +However, @foo is not an email address and should be left as-is. +EOT; + + $expected = <<This is some test content.

+

You can try emailing foo@example.com but that inbox doesn't actually exist.

+
+

This processor can even handle email addresses like foo@example.com inside of blockquotes!

+
+

More fake emails:

+ +

However, @foo is not an email address and should be left as-is.

+ +EOT; + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addExtension(new AutolinkExtension()); + + $converter = new CommonMarkConverter([], $environment); + + $this->assertEquals($expected, $converter->convertToHtml($input)); + } +} diff --git a/tests/InlineMentionParserTest.php b/tests/InlineMentionParserTest.php new file mode 100644 index 0000000000..ca0740a977 --- /dev/null +++ b/tests/InlineMentionParserTest.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace league\CommonMark\Ext\Autolink\Test; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\Autolink\InlineMentionParser; +use PHPUnit\Framework\TestCase; + +final class InlineMentionParserTest extends TestCase +{ + public function testTwitterMentionParser() + { + $input = <<You can follow the author of this library on Twitter - he's @colinodell!

+ +EOT; + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addInlineParser(InlineMentionParser::createTwitterHandleParser()); + + $converter = new CommonMarkConverter([], $environment); + + $this->assertEquals($expected, $converter->convertToHtml($input)); + } + + public function testGithubMentionParser() + { + $input = <<You can follow the author of this library on Github - he's @colinodell!

+ +EOT; + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addInlineParser(InlineMentionParser::createGithubHandleParser()); + + $converter = new CommonMarkConverter([], $environment); + + $this->assertEquals($expected, $converter->convertToHtml($input)); + } +} diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php new file mode 100644 index 0000000000..e1ec3c9a47 --- /dev/null +++ b/tests/UrlAutolinkProcessorTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace league\CommonMark\Ext\Autolink\Test\Url; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\Autolink\AutolinkExtension; +use PHPUnit\Framework\TestCase; + +final class UrlAutolinkProcessorTest extends TestCase +{ + public function testEmUrlAutolinks() + { + $input = <<You can search on http://google.com for stuff. For example, maybe you're interested in https://www.google.com/search?q=php+commonmark! Or perhaps you're looking for my personal website https://www.colinodell.com...?

+

All of those links above should be auto-converted. However, invalid or incomplete URLs like google.com and http:/google.com won't be converted. Also, javascript:alert(0); won't be converted because we never whitelisted that protocol.

+ +EOT; + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addExtension(new AutolinkExtension()); + + $converter = new CommonMarkConverter([], $environment); + + $this->assertEquals($expected, $converter->convertToHtml($input)); + } +} From 76b29bc6c9fea27a6c5474c6cedc72062709a933 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 14 Mar 2019 21:42:13 -0400 Subject: [PATCH 076/231] Fix broken example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 970e052692..9eca57f2f5 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new AutolinkExtension()); // Instantiate the converter engine and start converting some Markdown! -$converter = new CommonMarkConverter($config, $environment); +$converter = new CommonMarkConverter([], $environment); echo $converter->convertToHtml('I successfully instead the https://github.com/thephpleague/commonmark-ext-autolink extension!'); ``` From 520e2568717aeca40ff5a03c482ac1d32b7d32ff Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 14 Mar 2019 21:55:19 -0400 Subject: [PATCH 077/231] Expand Twitter test suite --- tests/InlineMentionParserTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/InlineMentionParserTest.php b/tests/InlineMentionParserTest.php index ca0740a977..8811ab4249 100644 --- a/tests/InlineMentionParserTest.php +++ b/tests/InlineMentionParserTest.php @@ -22,10 +22,16 @@ public function testTwitterMentionParser() { $input = <<You can follow the author of this library on Twitter - he's @colinodell!

+

Usernames like @commonmarkisthebestmarkdownspec are too long.

+

Security issues should be emailed to colinodell@gmail.com

EOT; From 1e446cd6dfe586aa8a7f7998aa062f7829feee2c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 14 Mar 2019 22:41:51 -0400 Subject: [PATCH 078/231] Use the new "commonmark-extension" package type This makes it easier for people to find extensions on Packagist: https://packagist.org/packages/league/commonmark-ext-autolink?type=commonmark-extension --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index d95787f53c..d838c18def 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "uafrica/commonmark-ext", + "type": "commonmark-extension", "description": "Extended parsers and renderers for The PHP League CommonMark parser", "keywords": ["markdown", "strikethrough", "strikeout", "commonmark"], "require": { From 9cd798ed1dd2ffbc10aa716d01dc0a2b466e3bac Mon Sep 17 00:00:00 2001 From: Sven Luijten <11269635+svenluijten@users.noreply.github.com> Date: Fri, 15 Mar 2019 14:10:19 +0100 Subject: [PATCH 079/231] Fix typos in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9eca57f2f5..f5619e0538 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ $environment->addExtension(new AutolinkExtension()); // Instantiate the converter engine and start converting some Markdown! $converter = new CommonMarkConverter([], $environment); -echo $converter->convertToHtml('I successfully instead the https://github.com/thephpleague/commonmark-ext-autolink extension!'); +echo $converter->convertToHtml('I successfully installed the https://github.com/thephpleague/commonmark-ext-autolink extension!'); ``` ## `@mention` Autolinking @@ -55,14 +55,14 @@ $environment->addInlineParser(InlineMentionParser::createTwitterHandleParser()); // TODO: Instantiate your converter and convert some Markdown ``` -For Github: +For GitHub: ```php use League\CommonMark\Environment; use League\CommonMark\Ext\Autolink\InlineMentionParser; $environment = Environment::createCommonMarkEnvironment(); -$environment->addInlineParser(InlineMentionParser::createTwitterHandleParser()); +$environment->addInlineParser(InlineMentionParser::createGithubHandleParser()); // TODO: Instantiate your converter and convert some Markdown ``` From 054450b19349fff03ede4ae19e28ae247f614f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sat, 16 Mar 2019 20:30:09 +0200 Subject: [PATCH 080/231] exclude editorconfig and styleci from git export --- .gitattributes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 43590ddcff..42120e234c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,10 +2,12 @@ # https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html # Ignore all test and documentation with "export-ignore". +/.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore /.scrutinizer.yml export-ignore +/.styleci.yml export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore /scrutinizer.yml export-ignore -/tests export-ignore +/tests/ export-ignore From 11c934c8680c85a5d10be7277322daa19904326e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sat, 16 Mar 2019 20:46:03 +0200 Subject: [PATCH 081/231] tests: fix namespace capitalization --- tests/EmailAutolinkProcessorTest.php | 2 +- tests/InlineMentionParserTest.php | 2 +- tests/UrlAutolinkProcessorTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/EmailAutolinkProcessorTest.php b/tests/EmailAutolinkProcessorTest.php index c7e954f359..a4a283d81d 100644 --- a/tests/EmailAutolinkProcessorTest.php +++ b/tests/EmailAutolinkProcessorTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace league\CommonMark\Ext\Autolink\Test\Email; +namespace League\CommonMark\Ext\Autolink\Test\Email; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; diff --git a/tests/InlineMentionParserTest.php b/tests/InlineMentionParserTest.php index 8811ab4249..089ad3e7db 100644 --- a/tests/InlineMentionParserTest.php +++ b/tests/InlineMentionParserTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace league\CommonMark\Ext\Autolink\Test; +namespace League\CommonMark\Ext\Autolink\Test; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index e1ec3c9a47..4b97ef237a 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace league\CommonMark\Ext\Autolink\Test\Url; +namespace League\CommonMark\Ext\Autolink\Test\Url; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; From a0cb79d0d4ea042cc0a7ef9f278f71720179a503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sat, 16 Mar 2019 20:46:24 +0200 Subject: [PATCH 082/231] composer: use semver construct for php version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b3bd9222a0..054fd89f58 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php" : ">=5.6", + "php" : "^5.6||^7.0", "league/commonmark": "^0.18.1" }, "require-dev": { From 4f4d3a8af26f6f3f997551ac10a268e4d2ef0ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sat, 16 Mar 2019 20:47:56 +0200 Subject: [PATCH 083/231] changelog: add 0.1.0 section, fix linking --- CHANGELOG.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ce01cd07..07e042ed45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ # Changelog -All notable changes will be documented in this file. +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] -## 0.1.0 - 2019-03-14 +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...HEAD + +## [0.1.0] - 2019-03-14 Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/0.1.0...HEAD +[0.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/commits/v0.1.0 \ No newline at end of file From 5623c32be583bd4c104c1a4e6de067b9e282206d Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 18:09:05 -0400 Subject: [PATCH 084/231] Update CHANGELOG.md --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07e042ed45..bedabf79ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...HEAD - ## [0.1.0] - 2019-03-14 Initial release! -[0.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/commits/v0.1.0 \ No newline at end of file +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/commits/v0.1.0 From 84a5e1015d42633e55d24114db87252b1fdad990 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 19:11:59 -0400 Subject: [PATCH 085/231] Refactor tests to use a data provider --- tests/EmailAutolinkProcessorTest.php | 51 ++++++++-------------------- tests/UrlAutolinkProcessorTest.php | 36 ++++++++++++-------- 2 files changed, 37 insertions(+), 50 deletions(-) diff --git a/tests/EmailAutolinkProcessorTest.php b/tests/EmailAutolinkProcessorTest.php index a4a283d81d..2d54cca9bd 100644 --- a/tests/EmailAutolinkProcessorTest.php +++ b/tests/EmailAutolinkProcessorTest.php @@ -18,47 +18,26 @@ final class EmailAutolinkProcessorTest extends TestCase { - public function testEmailAutolinks() + /** + * @param string $input + * @param string $expected + * + * @dataProvider dataProviderForEmailAutolinks + */ + public function testEmailAutolinks($input, $expected) { - $input = << This processor can even handle email addresses like foo@example.com inside of blockquotes! - -More fake emails: - - - foo@example.com - - bar@example.com - -However, @foo is not an email address and should be left as-is. -EOT; - - $expected = <<This is some test content.

-

You can try emailing foo@example.com but that inbox doesn't actually exist.

-
-

This processor can even handle email addresses like foo@example.com inside of blockquotes!

-
-

More fake emails:

- -

However, @foo is not an email address and should be left as-is.

- -EOT; - $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new AutolinkExtension()); $converter = new CommonMarkConverter([], $environment); - $this->assertEquals($expected, $converter->convertToHtml($input)); + $this->assertEquals($expected, \trim($converter->convertToHtml($input))); + } + + public function dataProviderForEmailAutolinks() + { + yield ['You can try emailing foo@example.com but that inbox doesn\'t actually exist.', '

You can try emailing foo@example.com but that inbox doesn\'t actually exist.

']; + yield ['> This processor can even handle email addresses like foo@example.com inside of blockquotes!', "
\n

This processor can even handle email addresses like foo@example.com inside of blockquotes!

\n
"]; + yield ['@invalid', '

@invalid

']; } } diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 4b97ef237a..174f2afcd5 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -18,25 +18,33 @@ final class UrlAutolinkProcessorTest extends TestCase { - public function testEmUrlAutolinks() + /** + * @param string $input + * @param string $expected + * + * @dataProvider dataProviderForAutolinkTests + */ + public function testUrlAutolinks($input, $expected) { - $input = <<You can search on http://google.com for stuff. For example, maybe you're interested in https://www.google.com/search?q=php+commonmark! Or perhaps you're looking for my personal website https://www.colinodell.com...?

-

All of those links above should be auto-converted. However, invalid or incomplete URLs like google.com and http:/google.com won't be converted. Also, javascript:alert(0); won't be converted because we never whitelisted that protocol.

- -EOT; - $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new AutolinkExtension()); $converter = new CommonMarkConverter([], $environment); - $this->assertEquals($expected, $converter->convertToHtml($input)); + $this->assertEquals($expected, trim($converter->convertToHtml($input))); + } + + public function dataProviderForAutolinkTests() + { + yield ['You can search on http://google.com for stuff.', '

You can search on http://google.com for stuff.

']; + + // Tests of "incomplete" URLs + yield ['google.com is missing www and/or a protocol', '

google.com is missing www and/or a protocol

']; + yield ['http:/google.com is missing a slash', '

http:/google.com is missing a slash

']; + yield ['javascript:alert(0); doesn\'t match the supported protocols', '

javascript:alert(0); doesn\'t match the supported protocols

']; + + // Tests involving trailing characters + yield ['Maybe you\'re interested in https://www.google.com/search?q=php+commonmark!', '

Maybe you\'re interested in https://www.google.com/search?q=php+commonmark!

']; + yield ['Or perhaps you\'re looking for my personal website https://www.colinodell.com...?', '

Or perhaps you\'re looking for my personal website https://www.colinodell.com...?

']; } } From 3dc749f9287d35f887527538632a83278acba069 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 19:31:39 -0400 Subject: [PATCH 086/231] Fix issues with start/end matching; add more tests --- src/UrlAutolinkProcessor.php | 17 +++++++++-------- tests/UrlAutolinkProcessorTest.php | 8 ++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 6191bebad5..a5fb63db79 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -19,7 +19,9 @@ final class UrlAutolinkProcessor implements DocumentProcessorInterface { // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php - const REGEX = '~( + const REGEX = '~ + (?<=^|[ \\t\\n\\x0b\\x0c\\x0d*_\\~\\(]) # Can only come at the beginning of a line, after whitespace, or certain delimiting characters + ( (?:%s):// # protocol (?:([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth (?: @@ -60,16 +62,19 @@ public function processDocument(Document $document) /** @var Text $node */ $node = $event->getNode(); - $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); $leftovers = ''; foreach ($contents as $i => $content) { if ($i % 2 === 0) { - $node->insertBefore(new Text($leftovers.$content)); + $text = $leftovers.$content; + if ($text !== '') { + $node->insertBefore(new Text($leftovers . $content)); + } $leftovers = ''; } else { // Does the URL end with punctuation that should be stripped? - if (preg_match('/(.+)([,.?!])+$/', $content, $matches)) { + if (preg_match('/(.+)([?!.,:*_~]+)$/', $content, $matches)) { // Add the punctuation later $content = $matches[1]; $leftovers = $matches[2]; @@ -78,10 +83,6 @@ public function processDocument(Document $document) } } - if ($leftovers !== '') { - $node->insertBefore(new Text($leftovers)); - } - $node->detach(); } } diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 174f2afcd5..7001742856 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -36,7 +36,13 @@ public function testUrlAutolinks($input, $expected) public function dataProviderForAutolinkTests() { + // Basic examples yield ['You can search on http://google.com for stuff.', '

You can search on http://google.com for stuff.

']; + yield ['https://google.com', '

https://google.com

']; + yield [' http://leadingwhitespace.example.com', '

http://leadingwhitespace.example.com

']; + yield ['http://trailingwhitespace.example.com ', '

http://trailingwhitespace.example.com

']; + yield ['- https://example.com/list-item', ""]; + // Tests of "incomplete" URLs yield ['google.com is missing www and/or a protocol', '

google.com is missing www and/or a protocol

']; @@ -46,5 +52,7 @@ public function dataProviderForAutolinkTests() // Tests involving trailing characters yield ['Maybe you\'re interested in https://www.google.com/search?q=php+commonmark!', '

Maybe you\'re interested in https://www.google.com/search?q=php+commonmark!

']; yield ['Or perhaps you\'re looking for my personal website https://www.colinodell.com...?', '

Or perhaps you\'re looking for my personal website https://www.colinodell.com...?

']; + yield ['Check https://www.stackoverflow.com: they have all the answers', '

Check https://www.stackoverflow.com: they have all the answers

']; + yield ['- https://example.com/list-item-with-trailing-colon:', ""]; } } From a0e08748c32619993354bbbedca7be019968cd2c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 19:37:11 -0400 Subject: [PATCH 087/231] Add support for autolinking 'www' URLs per GFM --- src/UrlAutolinkProcessor.php | 14 +++++++++++--- tests/UrlAutolinkProcessorTest.php | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index a5fb63db79..a571ed7e9d 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -22,8 +22,11 @@ final class UrlAutolinkProcessor implements DocumentProcessorInterface const REGEX = '~ (?<=^|[ \\t\\n\\x0b\\x0c\\x0d*_\\~\\(]) # Can only come at the beginning of a line, after whitespace, or certain delimiting characters ( - (?:%s):// # protocol - (?:([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth + # 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 @@ -78,8 +81,13 @@ public function processDocument(Document $document) // Add the punctuation later $content = $matches[1]; $leftovers = $matches[2]; + + // Auto-prefix 'http://' onto 'www' URLs + if (substr($content, 0, 4) === 'www.') { + $node->insertBefore(new Link('http://'.$content, $content)); + } else { + $node->insertBefore(new Link($content, $content)); } - $node->insertBefore(new Link($content, $content)); } } diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 7001742856..236c45a02b 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -39,6 +39,7 @@ public function dataProviderForAutolinkTests() // Basic examples yield ['You can search on http://google.com for stuff.', '

You can search on http://google.com for stuff.

']; yield ['https://google.com', '

https://google.com

']; + yield ['www.google.com', '

www.google.com

']; yield [' http://leadingwhitespace.example.com', '

http://leadingwhitespace.example.com

']; yield ['http://trailingwhitespace.example.com ', '

http://trailingwhitespace.example.com

']; yield ['- https://example.com/list-item', ""]; From cd21b114acc97964558c6caee7db0eff864b429c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 19:53:31 -0400 Subject: [PATCH 088/231] Implement trailing paren handling per the GFM spec --- src/UrlAutolinkProcessor.php | 28 ++++++++++++++++++++++++++++ tests/UrlAutolinkProcessorTest.php | 8 +++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index a571ed7e9d..87d46e9082 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -81,6 +81,13 @@ public function processDocument(Document $document) // Add the punctuation later $content = $matches[1]; $leftovers = $matches[2]; + } + + // Does the URL need its closing paren chopped off? + if (substr($content, -1) === ')' && self::hasMoreCloserParensThanOpeners($content)) { + $content = substr($content, 0, -1); + $leftovers .= ')'; + } // Auto-prefix 'http://' onto 'www' URLs if (substr($content, 0, 4) === 'www.') { @@ -95,4 +102,25 @@ public function processDocument(Document $document) } } } + + /** + * @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/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 236c45a02b..18a85ec6f1 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -44,7 +44,6 @@ public function dataProviderForAutolinkTests() yield ['http://trailingwhitespace.example.com ', '

http://trailingwhitespace.example.com

']; yield ['- https://example.com/list-item', ""]; - // Tests of "incomplete" URLs yield ['google.com is missing www and/or a protocol', '

google.com is missing www and/or a protocol

']; yield ['http:/google.com is missing a slash', '

http:/google.com is missing a slash

']; @@ -55,5 +54,12 @@ public function dataProviderForAutolinkTests() yield ['Or perhaps you\'re looking for my personal website https://www.colinodell.com...?', '

Or perhaps you\'re looking for my personal website https://www.colinodell.com...?

']; yield ['Check https://www.stackoverflow.com: they have all the answers', '

Check https://www.stackoverflow.com: they have all the answers

']; yield ['- https://example.com/list-item-with-trailing-colon:', ""]; + yield ['Visit www.commonmark.org.', '

Visit www.commonmark.org.

']; + yield ['Visit www.commonmark.org/a.b.', '

Visit www.commonmark.org/a.b.

']; + + // Tests involving parentheses + yield ['www.google.com/search?q=Markup+(business)', '

www.google.com/search?q=Markup+(business)

']; + yield ['(www.google.com/search?q=Markup+(business))', '

(www.google.com/search?q=Markup+(business))

']; + yield ['www.google.com/search?q=(business))+ok', '

www.google.com/search?q=(business))+ok

']; } } From 90b65ff57ef794f05326b93b7a27ac32fcfca1b8 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 19:57:07 -0400 Subject: [PATCH 089/231] Add more GFM spec tests --- tests/UrlAutolinkProcessorTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 18a85ec6f1..42e48d32be 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -61,5 +61,12 @@ public function dataProviderForAutolinkTests() yield ['www.google.com/search?q=Markup+(business)', '

www.google.com/search?q=Markup+(business)

']; yield ['(www.google.com/search?q=Markup+(business))', '

(www.google.com/search?q=Markup+(business))

']; yield ['www.google.com/search?q=(business))+ok', '

www.google.com/search?q=(business))+ok

']; + + // Tests involving semi-colon endings + yield ['www.google.com/search?q=commonmark&hl=en', '

www.google.com/search?q=commonmark&hl=en

']; + yield ['www.google.com/search?q=commonmark&hl;', '

www.google.com/search?q=commonmark&hl;

']; + + // Test that < immediately terminates an autolink + yield ['www.commonmark.org/hewww.commonmark.org/he<lp

']; } } From 15c97b66896eba2354fb571787d1f39aaa53d39b Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 19:58:33 -0400 Subject: [PATCH 090/231] Add ftp as a default protocol per GFM --- src/UrlAutolinkProcessor.php | 2 +- tests/UrlAutolinkProcessorTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 87d46e9082..63a18c176c 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -44,7 +44,7 @@ final class UrlAutolinkProcessor implements DocumentProcessorInterface private $allowedProtocols; - public function __construct(array $allowedProtocols = ['http', 'https']) + public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) { $this->allowedProtocols = $allowedProtocols; } diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 42e48d32be..a3a0a21223 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -39,6 +39,7 @@ public function dataProviderForAutolinkTests() // Basic examples yield ['You can search on http://google.com for stuff.', '

You can search on http://google.com for stuff.

']; yield ['https://google.com', '

https://google.com

']; + yield ['ftp://example.com', '

ftp://example.com

']; yield ['www.google.com', '

www.google.com

']; yield [' http://leadingwhitespace.example.com', '

http://leadingwhitespace.example.com

']; yield ['http://trailingwhitespace.example.com ', '

http://trailingwhitespace.example.com

']; From 925a532fdd9bb09b54a1aac0bc316e866da7c33d Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 21:48:10 -0400 Subject: [PATCH 091/231] Fix GFM entity reference handling --- src/UrlAutolinkProcessor.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 63a18c176c..31d9ffba95 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -76,6 +76,8 @@ public function processDocument(Document $document) } $leftovers = ''; } else { + $leftovers = ''; + // Does the URL end with punctuation that should be stripped? if (preg_match('/(.+)([?!.,:*_~]+)$/', $content, $matches)) { // Add the punctuation later @@ -83,6 +85,12 @@ public function processDocument(Document $document) $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); From 804b584afa206342c5c29ea66f773c5b48d5933a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 21:58:18 -0400 Subject: [PATCH 092/231] Make StyleCI happy --- src/EmailAutolinkProcessor.php | 2 +- src/UrlAutolinkProcessor.php | 4 ++-- tests/InlineMentionParserTest.php | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index c8859ebb60..b5b1a0bf54 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -40,7 +40,7 @@ public function processDocument(Document $document) if ($i % 2 === 0) { $node->insertBefore(new Text($content)); } else { - $node->insertBefore(new Link('mailto:'.$content, $content)); + $node->insertBefore(new Link('mailto:' . $content, $content)); } } diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 31d9ffba95..c65ae49d10 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -70,7 +70,7 @@ public function processDocument(Document $document) $leftovers = ''; foreach ($contents as $i => $content) { if ($i % 2 === 0) { - $text = $leftovers.$content; + $text = $leftovers . $content; if ($text !== '') { $node->insertBefore(new Text($leftovers . $content)); } @@ -99,7 +99,7 @@ public function processDocument(Document $document) // Auto-prefix 'http://' onto 'www' URLs if (substr($content, 0, 4) === 'www.') { - $node->insertBefore(new Link('http://'.$content, $content)); + $node->insertBefore(new Link('http://' . $content, $content)); } else { $node->insertBefore(new Link($content, $content)); } diff --git a/tests/InlineMentionParserTest.php b/tests/InlineMentionParserTest.php index 089ad3e7db..10a69602b5 100644 --- a/tests/InlineMentionParserTest.php +++ b/tests/InlineMentionParserTest.php @@ -20,7 +20,7 @@ final class InlineMentionParserTest extends TestCase { public function testTwitterMentionParser() { - $input = <<You can follow the author of this library on Twitter - he's @colinodell!

Usernames like @commonmarkisthebestmarkdownspec are too long.

Security issues should be emailed to colinodell@gmail.com

@@ -45,11 +45,11 @@ public function testTwitterMentionParser() public function testGithubMentionParser() { - $input = <<You can follow the author of this library on Github - he's @colinodell!

EOT; From 93fac926dd1c82a68b8c8815e1b6536d167a97ce Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 22:11:05 -0400 Subject: [PATCH 093/231] Fix bad minimum version of PHPUnit --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 054fd89f58..5e4e791924 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "league/commonmark": "^0.18.1" }, "require-dev": { - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^5.7.27" }, "autoload": { "psr-4": { From 438a90365eb3c42018861aef6b9bdf460fe94a48 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 20:50:01 -0400 Subject: [PATCH 094/231] Fix GFM spec compatibility for email autolinks --- composer.json | 2 +- src/EmailAutolinkProcessor.php | 26 ++++++++++++++++++++++---- tests/EmailAutolinkProcessorTest.php | 8 ++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 5e4e791924..4030e3e4c8 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^5.6||^7.0", - "league/commonmark": "^0.18.1" + "league/commonmark": "^0.18.2" }, "require-dev": { "phpunit/phpunit": "^5.7.27" diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index b5b1a0bf54..18b8bb0ad2 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -18,8 +18,7 @@ final class EmailAutolinkProcessor implements DocumentProcessorInterface { - // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/EmailValidator.php - const REGEX = '/([a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)/'; + const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/'; /** * @param Document $document @@ -36,11 +35,30 @@ public function processDocument(Document $document) $node = $event->getNode(); $contents = preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + + $leftovers = ''; foreach ($contents as $i => $content) { if ($i % 2 === 0) { - $node->insertBefore(new Text($content)); + $text = $leftovers.$content; + if ($text !== '') { + $node->insertBefore(new Text($leftovers . $content)); + } + $leftovers = ''; } else { - $node->insertBefore(new Link('mailto:' . $content, $content)); + // 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 = ''; + } else { + $node->insertBefore(new Link('mailto:' . $content, $content)); + } } } diff --git a/tests/EmailAutolinkProcessorTest.php b/tests/EmailAutolinkProcessorTest.php index 2d54cca9bd..6ccb1e3088 100644 --- a/tests/EmailAutolinkProcessorTest.php +++ b/tests/EmailAutolinkProcessorTest.php @@ -39,5 +39,13 @@ public function dataProviderForEmailAutolinks() yield ['You can try emailing foo@example.com but that inbox doesn\'t actually exist.', '

You can try emailing foo@example.com but that inbox doesn\'t actually exist.

']; yield ['> This processor can even handle email addresses like foo@example.com inside of blockquotes!', "
\n

This processor can even handle email addresses like foo@example.com inside of blockquotes!

\n
"]; yield ['@invalid', '

@invalid

']; + + // GFM spec tests + yield ['foo@bar.baz', '

foo@bar.baz

']; + yield ['hello@mail+xyz.example isn\'t valid, but hello+xyz@mail.example is.', '

hello@mail+xyz.example isn\'t valid, but hello+xyz@mail.example is.

']; + yield ['a.b-c_d@a.b', '

a.b-c_d@a.b

']; + yield ['a.b-c_d@a.b.', '

a.b-c_d@a.b.

']; + yield ['a.b-c_d@a.b-', '

a.b-c_d@a.b-

']; + yield ['a.b-c_d@a.b_', '

a.b-c_d@a.b_

']; } } From 69ec16f8fec8cf38aa34578121cff6def1c98dd9 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 22:24:23 -0400 Subject: [PATCH 095/231] Break processor into smaller chunks --- src/EmailAutolinkProcessor.php | 61 ++++++++++--------- src/UrlAutolinkProcessor.php | 103 ++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 74 deletions(-) diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index 18b8bb0ad2..76678fb776 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -30,40 +30,45 @@ public function processDocument(Document $document) $walker = $document->walker(); while ($event = $walker->next()) { - if ($event->isEntering() && $event->getNode() instanceof Text) { - /** @var Text $node */ - $node = $event->getNode(); + if ($event->getNode() instanceof Text) { + self::processAutolinks($event->getNode()); + } + } + } - $contents = preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + private static function processAutolinks(Text $node) + { + $contents = preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + + $leftovers = ''; + foreach ($contents as $i => $content) { + if ($i % 2 === 0) { + $text = $leftovers . $content; + if ($text !== '') { + $node->insertBefore(new Text($leftovers . $content)); + } $leftovers = ''; - foreach ($contents as $i => $content) { - if ($i % 2 === 0) { - $text = $leftovers.$content; - if ($text !== '') { - $node->insertBefore(new Text($leftovers . $content)); - } - $leftovers = ''; - } else { - // Does the URL end with punctuation that should be stripped? - if (substr($content, -1) === '.') { - // Add the punctuation later - $content = substr($content, 0, -1); - $leftovers = '.'; - } + continue; + } - // The last character cannot be - or _ - if (in_array(substr($content, -1), ['-', '_'])) { - $node->insertBefore(new Text($content . $leftovers)); - $leftovers = ''; - } else { - $node->insertBefore(new Link('mailto:' . $content, $content)); - } - } - } + // Does the URL end with punctuation that should be stripped? + if (substr($content, -1) === '.') { + // Add the punctuation later + $content = substr($content, 0, -1); + $leftovers = '.'; + } - $node->detach(); + // 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/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index c65ae49d10..589361d65c 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -42,11 +42,11 @@ final class UrlAutolinkProcessor implements DocumentProcessorInterface (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional) )~ixu'; - private $allowedProtocols; + private $finalRegex; public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) { - $this->allowedProtocols = $allowedProtocols; + $this->finalRegex = sprintf(self::REGEX, implode('|', $allowedProtocols)); } /** @@ -56,59 +56,70 @@ public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) */ public function processDocument(Document $document) { - $regex = sprintf(self::REGEX, implode('|', $this->allowedProtocols)); - $walker = $document->walker(); while ($event = $walker->next()) { - if ($event->isEntering() && $event->getNode() instanceof Text) { - /** @var Text $node */ - $node = $event->getNode(); + if ($event->getNode() instanceof Text) { + self::processAutolinks($event->getNode(), $this->finalRegex); + } + } + } - $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + private static function processAutolinks(Text $node, $regex) + { + $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + + $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 = ''; - foreach ($contents as $i => $content) { - if ($i % 2 === 0) { - $text = $leftovers . $content; - if ($text !== '') { - $node->insertBefore(new Text($leftovers . $content)); - } - $leftovers = ''; - } else { - $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 .= ')'; - } - - // Auto-prefix 'http://' onto 'www' URLs - if (substr($content, 0, 4) === 'www.') { - $node->insertBefore(new Link('http://' . $content, $content)); - } else { - $node->insertBefore(new Link($content, $content)); - } - } - } + 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]; + } - $node->detach(); + // 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 .= ')'; + } + + 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)); } /** From f78d4c5e3ba08e037882112e12e0a55c0d3d037e Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 22:25:00 -0400 Subject: [PATCH 096/231] Skip nodes with no autolinks --- src/EmailAutolinkProcessor.php | 4 ++++ src/UrlAutolinkProcessor.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index 76678fb776..1facef54d7 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -40,6 +40,10 @@ private static function processAutolinks(Text $node) { $contents = preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + if (count($contents) === 1) { + return; + } + $leftovers = ''; foreach ($contents as $i => $content) { if ($i % 2 === 0) { diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 589361d65c..63228d5d88 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -69,6 +69,10 @@ private static function processAutolinks(Text $node, $regex) { $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + if (count($contents) === 1) { + return; + } + $leftovers = ''; foreach ($contents as $i => $content) { // Even-indexed elements are things before/after the URLs From 5d950be6579ac0b52d5bb057f3e6f41ae6c284ef Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 22:31:38 -0400 Subject: [PATCH 097/231] Optimize calls to internal PHP functions --- src/EmailAutolinkProcessor.php | 10 +++++----- src/InlineMentionParser.php | 2 +- src/UrlAutolinkProcessor.php | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index 1facef54d7..f4d436c8a5 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -38,9 +38,9 @@ public function processDocument(Document $document) private static function processAutolinks(Text $node) { - $contents = preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + $contents = \preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); - if (count($contents) === 1) { + if (\count($contents) === 1) { return; } @@ -57,14 +57,14 @@ private static function processAutolinks(Text $node) } // Does the URL end with punctuation that should be stripped? - if (substr($content, -1) === '.') { + if (\substr($content, -1) === '.') { // Add the punctuation later - $content = substr($content, 0, -1); + $content = \substr($content, 0, -1); $leftovers = '.'; } // The last character cannot be - or _ - if (in_array(substr($content, -1), ['-', '_'])) { + if (\in_array(\substr($content, -1), ['-', '_'])) { $node->insertBefore(new Text($content . $leftovers)); $leftovers = ''; continue; diff --git a/src/InlineMentionParser.php b/src/InlineMentionParser.php index 0003f75f0e..b5da8b91aa 100644 --- a/src/InlineMentionParser.php +++ b/src/InlineMentionParser.php @@ -78,7 +78,7 @@ public function parse(InlineParserContext $inlineContext) return false; } - $url = sprintf($this->linkPattern, $handle); + $url = \sprintf($this->linkPattern, $handle); $inlineContext->getContainer()->appendChild(new Link($url, '@' . $handle)); diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 63228d5d88..4fb4097689 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -46,7 +46,7 @@ final class UrlAutolinkProcessor implements DocumentProcessorInterface public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) { - $this->finalRegex = sprintf(self::REGEX, implode('|', $allowedProtocols)); + $this->finalRegex = \sprintf(self::REGEX, \implode('|', $allowedProtocols)); } /** @@ -67,9 +67,9 @@ public function processDocument(Document $document) private static function processAutolinks(Text $node, $regex) { - $contents = preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); + $contents = \preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); - if (count($contents) === 1) { + if (\count($contents) === 1) { return; } @@ -90,21 +90,21 @@ private static function processAutolinks(Text $node, $regex) $leftovers = ''; // Does the URL end with punctuation that should be stripped? - if (preg_match('/(.+)([?!.,:*_~]+)$/', $content, $matches)) { + 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)) { + 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); + if (\substr($content, -1) === ')' && self::hasMoreCloserParensThanOpeners($content)) { + $content = \substr($content, 0, -1); $leftovers .= ')'; } @@ -137,7 +137,7 @@ private static function hasMoreCloserParensThanOpeners($content) // 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); + \preg_match_all('/[()]/', $content, $matches); $charCount = ['(' => 0, ')' => 0]; foreach ($matches[0] as $char) { From 8b943e8eb75ac295d81665d5a3391bb44a272572 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 22:45:41 -0400 Subject: [PATCH 098/231] Document the GFM changes and spec adherence --- CHANGELOG.md | 13 +++++++++++++ CONTRIBUTING.md | 2 ++ README.md | 5 +++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bedabf79ca..69b0275b1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.2.0] - 2019-03-16 + +This release brings the email and URL autolink processors into alignment with the official GFM spec. + +### Changed + + - Made `ftp` a default protocol + - Revised the email regex to match the GFM spec + +### Fixed + + - Fixed bug where links at the start or end of lines failed to be parsed + ## [0.1.0] - 2019-03-14 Initial release! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da581cb194..8b392a9799 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,8 @@ We accept contributions via Pull Requests on [Github](https://github.com/thephpl - **Add tests!** - Your patch won't be accepted if it doesn't have tests. +- **Adhere to the spec!** - Any changes should align with the (official GFM spec)[https://github.github.com/gfm/] + - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. diff --git a/README.md b/README.md index f5619e0538..8c5a59c99d 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ [![Quality Score][ico-code-quality]][link-code-quality] [![Total Downloads][ico-downloads]][link-downloads] -This extension configures the [`league/commonmark` Markdown parser for PHP][link-league-commonmark] to automatically link URLs and email addresses even if the CommonMark `<...>` autolink syntax is not used. +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` and configure your own custom ones, though this is disabled by default. +It also provides a parser to autolink `@mentions` to Twitter, Github, or any custom service you wish, though this is disabled by default. ## Install @@ -122,3 +122,4 @@ This library is licensed under the BSD-3 license. See the [License File](LICENS [link-author]: https://github.com/colinodell [link-contributors]: ../../contributors [link-league-commonmark]: https://github.com/thephpleague/commonmark +[link-gfm-spec-autolinking]: https://github.github.com/gfm/ From 568780535d7fd95a4b9127349e3f0b79b03284e8 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 23:01:01 -0400 Subject: [PATCH 099/231] Reformat and move the LICENSE file so Github can detect it --- LICENSE | 29 +++++++++++++++++++++++++++++ LICENSE.md | 30 ------------------------------ README.md | 2 +- 3 files changed, 30 insertions(+), 31 deletions(-) create mode 100644 LICENSE delete mode 100644 LICENSE.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..fb2c3afc49 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Colin O'Dell +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 42bf99e480..0000000000 --- a/LICENSE.md +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2019, Colin O'Dell - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * Neither the name of Colin O'Dell nor the names of other - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 8c5a59c99d..a8d85342e5 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ If you discover any security related issues, please email colinodell@gmail.com i ## License -This library is licensed under the BSD-3 license. See the [License File](LICENSE.md) for more information. +This library is licensed under the BSD-3 license. See the [License File](LICENSE) for more information. [ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-autolink.svg?style=flat-square [ico-license]: http://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square From 326c57f093b90fde5aae9486d42c3e743a5930c2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 23:04:39 -0400 Subject: [PATCH 100/231] Prepare to release v0.2.0 --- CHANGELOG.md | 8 +++++++- composer.json | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69b0275b1f..6792fdb6d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 This release brings the email and URL autolink processors into alignment with the official GFM spec. +### Added + + - Added full support for Github Flavored Markdown (GFM) autolinking + - Added some optimizations + ### Changed - Made `ftp` a default protocol @@ -24,5 +29,6 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/commits/v0.1.0 diff --git a/composer.json b/composer.json index 4030e3e4c8..dcf5d4890f 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "league/commonmark-ext-autolink", "type": "commonmark-extension", "description": "Extension for league/commonmark which autolinks URLs, emails, and @-mentions", - "keywords": ["markdown", "commonmark", "extension", "autolink", "twitter", "github"], + "keywords": ["markdown", "commonmark", "extension", "autolink", "twitter", "github", "gfm"], "homepage": "https://github.com/thephpleague/commonmark-ext-autolink", "license": "BSD-3-Clause", "authors": [ @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.3-dev" } } } From 585875f1531bbe6efd77ab480ee61ef2957137b3 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 16 Mar 2019 23:06:54 -0400 Subject: [PATCH 101/231] Fix link to GFM spec section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a8d85342e5..93e481f10c 100644 --- a/README.md +++ b/README.md @@ -122,4 +122,4 @@ This library is licensed under the BSD-3 license. See the [License File](LICENS [link-author]: https://github.com/colinodell [link-contributors]: ../../contributors [link-league-commonmark]: https://github.com/thephpleague/commonmark -[link-gfm-spec-autolinking]: https://github.github.com/gfm/ +[link-gfm-spec-autolinking]: https://github.github.com/gfm/#autolinks-extension- From 030700df86c3ffa7d1bd2e5a55bd2864000e59f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Tue, 19 Mar 2019 20:38:29 +0200 Subject: [PATCH 102/231] readme: remove empty pattern (#8) * readme: remove empty pattern empty pattern is not valid, so use the default * Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 93e481f10c..1dffa7588b 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ use League\CommonMark\Environment; use League\CommonMark\Ext\Autolink\InlineMentionParser; $environment = Environment::createCommonMarkEnvironment(); -$environment->addInlineParser(new InlineMentionParser('https://www.example.com/users/%s/profile', '')); +$environment->addInlineParser(new InlineMentionParser('https://www.example.com/users/%s/profile')); // TODO: Instantiate your converter and convert some Markdown ``` From 2f83c58214e949dc76c24c13909e4703f0e5922d Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 14 Mar 2019 22:39:09 -0400 Subject: [PATCH 103/231] Use the new "commonmark-extension" package type --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 10c93b3a4c..dd3010f4af 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "webuni/commonmark-table-extension", - "type": "library", + "type": "commonmark-extension", "description": "The table extension for CommonMark PHP implementation", "keywords": ["markdown","table","commonmark"], "homepage": "https://github.com/webuni/commonmark-table-extension", From 66ba8a93a899627ac7c1f54c0d191b3dbe309970 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 28 Mar 2019 10:03:05 -0400 Subject: [PATCH 104/231] Fix URL autolinking (fixes #10) --- CHANGELOG.md | 9 ++++++++- composer.json | 2 +- tests/UrlAutolinkProcessorTest.php | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6792fdb6d9..e4cbfa00af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.2.1] - 2019-03-28 + +### Changed + + - Increased the minimum `league/commonmark` version due to a now-fixed bug with `Text` collapsing (#10) + ## [0.2.0] - 2019-03-16 This release brings the email and URL autolink processors into alignment with the official GFM spec. @@ -29,6 +35,7 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.1...HEAD +[0.2.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/commits/v0.1.0 diff --git a/composer.json b/composer.json index dcf5d4890f..aee7f69b8f 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^5.6||^7.0", - "league/commonmark": "^0.18.2" + "league/commonmark": "^0.18.5" }, "require-dev": { "phpunit/phpunit": "^5.7.27" diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index a3a0a21223..3132fbd230 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -69,5 +69,8 @@ public function dataProviderForAutolinkTests() // Test that < immediately terminates an autolink yield ['www.commonmark.org/hewww.commonmark.org/he<lp

']; + + // Regression: two links with one underscore each + yield ["https://eventum.example.net/history.php?iss_id=107092\nhttps://gitlab.example.net/group/project/merge_requests/39#note_150630", "

https://eventum.example.net/history.php?iss_id=107092\nhttps://gitlab.example.net/group/project/merge_requests/39#note_150630

"]; } } From c35dd4a4726054ac7caffd728563b959026409cc Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 19:42:08 -0700 Subject: [PATCH 105/231] Prepare to release 0.3.0 --- CHANGELOG.md | 9 ++++++++- composer.json | 8 ++++---- phpunit.xml.dist | 5 +---- src/AutolinkExtension.php | 13 ++++++------- src/InlineMentionParser.php | 12 ++---------- 5 files changed, 21 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4cbfa00af..3bcb419456 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.3.0] - 2019-04-10 + +### Changed + + - Made extension compatible with `league/commonmark` 0.19 + ## [0.2.1] - 2019-03-28 ### Changed @@ -35,7 +41,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...HEAD +[0.3.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/thephpleague/commonmark-ext-autolink/commits/v0.1.0 diff --git a/composer.json b/composer.json index aee7f69b8f..7a9e050373 100644 --- a/composer.json +++ b/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php" : "^5.6||^7.0", - "league/commonmark": "^0.18.5" + "php" : "^7.1", + "league/commonmark": "^0.19" }, "require-dev": { - "phpunit/phpunit": "^5.7.27" + "phpunit/phpunit": "^7.5" }, "autoload": { "psr-4": { @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.3-dev" + "dev-master": "0.4-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ef120d6ec6..4cf1ef4bfd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,10 +20,7 @@ - - - + - diff --git a/src/AutolinkExtension.php b/src/AutolinkExtension.php index f4dc4b7878..e0330487fb 100644 --- a/src/AutolinkExtension.php +++ b/src/AutolinkExtension.php @@ -11,15 +11,14 @@ namespace League\CommonMark\Ext\Autolink; -use League\CommonMark\Extension\Extension; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; -final class AutolinkExtension extends Extension +final class AutolinkExtension implements ExtensionInterface { - public function getDocumentProcessors() + public function register(ConfigurableEnvironmentInterface $environment) { - return [ - new EmailAutolinkProcessor(), - new UrlAutolinkProcessor(), - ]; + $environment->addDocumentProcessor(new EmailAutolinkProcessor()); + $environment->addDocumentProcessor(new UrlAutolinkProcessor()); } } diff --git a/src/InlineMentionParser.php b/src/InlineMentionParser.php index b5da8b91aa..3f43b006f6 100644 --- a/src/InlineMentionParser.php +++ b/src/InlineMentionParser.php @@ -36,15 +36,7 @@ public function __construct($linkPattern, $handleRegex = '/^[A-Za-z0-9_]+(?!\w)/ /** * {@inheritdoc} */ - public function getName() - { - return 'mention'; - } - - /** - * {@inheritdoc} - */ - public function getCharacters() + public function getCharacters(): array { return ['@']; } @@ -52,7 +44,7 @@ public function getCharacters() /** * {@inheritdoc} */ - public function parse(InlineParserContext $inlineContext) + public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); From 12c1ec641b77eed4876d496c7ddc490a89912523 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 19:44:42 -0700 Subject: [PATCH 106/231] Prepare to release 0.2.0 --- CHANGELOG.md | 9 +++- composer.json | 8 +-- phpunit.xml.dist | 5 +- src/ChildRenderer.php | 2 +- src/InlinesOnlyExtension.php | 102 ++++++++++++----------------------- 5 files changed, 48 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3dc3f165d..1af52ae42a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,15 @@ All notable changes will be documented in this file. ## [Unreleased][unreleased] +## 0.2.0 - 2019-04-10 + +### Changed + + - Made compatible with `league/commonmark` 0.19 + ## 0.1.0 - 2019-03-11 Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/0.1.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/0.2.0...HEAD +[0.2.0]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/0.1.0...0.2.0 diff --git a/composer.json b/composer.json index c28009f5c7..d8c17a55f4 100644 --- a/composer.json +++ b/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php" : ">=5.6", - "league/commonmark": "^0.18.1" + "php" : "^7.1", + "league/commonmark": "^0.19" }, "require-dev": { - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^7.5" }, "autoload": { "psr-4": { @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.3-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d5f268e8bb..c90ad802d9 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,10 +20,7 @@ - - - + - diff --git a/src/ChildRenderer.php b/src/ChildRenderer.php index 621b4eb010..51c86f8020 100644 --- a/src/ChildRenderer.php +++ b/src/ChildRenderer.php @@ -28,7 +28,7 @@ final class ChildRenderer implements BlockRendererInterface /** * {@inheritdoc} */ - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { $out = ''; diff --git a/src/InlinesOnlyExtension.php b/src/InlinesOnlyExtension.php index 266593ea5c..9159f6e3e5 100644 --- a/src/InlinesOnlyExtension.php +++ b/src/InlinesOnlyExtension.php @@ -17,80 +17,46 @@ use League\CommonMark\Block\Element\Document; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Parser as BlockParser; -use League\CommonMark\Extension\Extension; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Inline\Element as InlineElement; use League\CommonMark\Inline\Parser as InlineParser; use League\CommonMark\Inline\Processor as InlineProcessor; use League\CommonMark\Inline\Renderer as InlineRenderer; -final class InlinesOnlyExtension extends Extension +final class InlinesOnlyExtension implements ExtensionInterface { - /** - * {@inheritdoc} - */ - public function getBlockParsers() + public function register(ConfigurableEnvironmentInterface $environment) { - return [ - new BlockParser\LazyParagraphParser(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getInlineParsers() - { - return [ - new InlineParser\NewlineParser(), - new InlineParser\BacktickParser(), - new InlineParser\EscapableParser(), - new InlineParser\EntityParser(), - new InlineParser\EmphasisParser(), - new InlineParser\AutolinkParser(), - new InlineParser\HtmlInlineParser(), - new InlineParser\CloseBracketParser(), - new InlineParser\OpenBracketParser(), - new InlineParser\BangParser(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getInlineProcessors() - { - return [ - new InlineProcessor\EmphasisProcessor(), - ]; - } - - /** - * {@inheritdoc} - */ - public function getBlockRenderers() - { - $renderer = new ChildRenderer(); - - return [ - Document::class => $renderer, - Paragraph::class => $renderer, - ]; - } - - /** - * {@inheritdoc} - */ - public function getInlineRenderers() - { - return [ - InlineElement\Code::class => new InlineRenderer\CodeRenderer(), - InlineElement\Emphasis::class => new InlineRenderer\EmphasisRenderer(), - InlineElement\HtmlInline::class => new InlineRenderer\HtmlInlineRenderer(), - InlineElement\Image::class => new InlineRenderer\ImageRenderer(), - InlineElement\Link::class => new InlineRenderer\LinkRenderer(), - InlineElement\Newline::class => new InlineRenderer\NewlineRenderer(), - InlineElement\Strong::class => new InlineRenderer\StrongRenderer(), - InlineElement\Text::class => new InlineRenderer\TextRenderer(), - ]; + $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\EmphasisParser(), 60) + ->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) + + ->addInlineProcessor(new InlineProcessor\EmphasisProcessor(), 0) + + ->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) + ; } } From a49a2d116b6211dab7e019d1c563526eefe31da6 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 19:46:12 -0700 Subject: [PATCH 107/231] Don't test on unsupported PHP versions --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index accc57e21e..35297f5ce4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: php php: - - 5.6 - - 7.0 - 7.1 - 7.2 - 7.3 From aca3fa7dd713aca762ccb471e63cc4d06123c423 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 19:47:01 -0700 Subject: [PATCH 108/231] Don't test on supported PHP versions --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index accc57e21e..35297f5ce4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: php php: - - 5.6 - - 7.0 - 7.1 - 7.2 - 7.3 From 0488f69ba7392c4dfdf6aa60013d6618f1858260 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 19:50:55 -0700 Subject: [PATCH 109/231] Fix changelog links --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1af52ae42a..5969b515ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes will be documented in this file. ## [Unreleased][unreleased] -## 0.2.0 - 2019-04-10 +## [0.2.0] - 2019-04-10 ### Changed @@ -14,5 +14,5 @@ All notable changes will be documented in this file. Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/0.2.0...HEAD -[0.2.0]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/0.1.0...0.2.0 +[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.1.0...v0.2.0 From 92806c302f39e9bb1b8fcdfb6fa7cb36de856744 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 19:47:56 -0700 Subject: [PATCH 110/231] Prepare to release 0.2.0 --- .travis.yml | 2 -- CHANGELOG.md | 8 +++++- composer.json | 14 +++++------ phpunit.xml.dist | 7 ++---- src/PunctuationParser.php | 8 +++--- src/QuoteParser.php | 8 +++--- src/SmartPunctExtension.php | 50 +++++++++---------------------------- 7 files changed, 36 insertions(+), 61 deletions(-) diff --git a/.travis.yml b/.travis.yml index accc57e21e..35297f5ce4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: php php: - - 5.6 - - 7.0 - 7.1 - 7.2 - 7.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index f255420942..77377d203e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] -[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.1.0...HEAD +## [0.2.0] - 2019-04-10 + +### Changed + + - Made extension compatible with `league/commonmark` 0.19 ## [0.1.0] - 2019-03-11 Split this extension out of the old `league/commonmark-extras` library. +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/commits/v0.1.0 diff --git a/composer.json b/composer.json index 93a6b2db41..97f9354f9a 100644 --- a/composer.json +++ b/composer.json @@ -14,21 +14,21 @@ } ], "require": { - "php" : ">=5.6", - "league/commonmark": "^0.13|^0.14|^0.15|^0.16|^0.17|^0.18" + "php" : "^7.1", + "league/commonmark": "^0.19" }, "require-dev": { - "jgm/smartpunct": "0.28", - "phpunit/phpunit": "^5.7" + "jgm/smartpunct": "0.29", + "phpunit/phpunit": "^7.5" }, "repositories": [ { "type": "package", "package": { "name": "jgm/smartpunct", - "version": "0.28", + "version": "0.29", "dist": { - "url": "https://raw.githubusercontent.com/jgm/commonmark.js/0.28.0/test/smart_punct.txt", + "url": "https://raw.githubusercontent.com/jgm/commonmark.js/0.29.0/test/smart_punct.txt", "type": "file" } } @@ -49,7 +49,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.3-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 470e2aff35..043d709461 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,14 +16,11 @@
- src/ + src - - - + - diff --git a/src/PunctuationParser.php b/src/PunctuationParser.php index 173c57ed53..d1029690f5 100644 --- a/src/PunctuationParser.php +++ b/src/PunctuationParser.php @@ -15,15 +15,15 @@ namespace League\CommonMark\Ext\SmartPunct; use League\CommonMark\Inline\Element\Text; -use League\CommonMark\Inline\Parser\AbstractInlineParser; +use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; -class PunctuationParser extends AbstractInlineParser +class PunctuationParser implements InlineParserInterface { /** * @return string[] */ - public function getCharacters() + public function getCharacters(): array { return ['-', '.']; } @@ -33,7 +33,7 @@ public function getCharacters() * * @return bool */ - public function parse(InlineParserContext $inlineContext) + public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $ch = $cursor->getCharacter(); diff --git a/src/QuoteParser.php b/src/QuoteParser.php index 9f1b7e719b..019c177720 100644 --- a/src/QuoteParser.php +++ b/src/QuoteParser.php @@ -16,11 +16,11 @@ use League\CommonMark\Delimiter\Delimiter; use League\CommonMark\Inline\Element\Text; -use League\CommonMark\Inline\Parser\AbstractInlineParser; +use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; use League\CommonMark\Util\RegexHelper; -class QuoteParser extends AbstractInlineParser +class QuoteParser implements InlineParserInterface { protected $double = ['"', '“', '”']; protected $single = ["'", '‘', '’']; @@ -28,7 +28,7 @@ class QuoteParser extends AbstractInlineParser /** * @return string[] */ - public function getCharacters() + public function getCharacters(): array { return array_merge($this->double, $this->single); } @@ -38,7 +38,7 @@ public function getCharacters() * * @return bool */ - public function parse(InlineParserContext $inlineContext) + public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $character = $this->getCharacterType($cursor->getCharacter()); diff --git a/src/SmartPunctExtension.php b/src/SmartPunctExtension.php index 83d2e451e9..a2e222181d 100644 --- a/src/SmartPunctExtension.php +++ b/src/SmartPunctExtension.php @@ -17,51 +17,25 @@ use League\CommonMark\Block\Element\Document; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Renderer as CoreBlockRenderer; -use League\CommonMark\Extension\Extension; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Inline\Element\Text; use League\CommonMark\Inline\Renderer as CoreInlineRenderer; -class SmartPunctExtension extends Extension +class SmartPunctExtension implements ExtensionInterface { - /** - * {@inheritdoc} - */ - public function getInlineParsers() + public function register(ConfigurableEnvironmentInterface $environment) { - return [ - new QuoteParser(), - new PunctuationParser(), - ]; - } + $environment + ->addInlineParser(new QuoteParser(), 10) + ->addInlineParser(new PunctuationParser(), 0) - /** - * {@inheritdoc} - */ - public function getInlineProcessors() - { - return [ - new QuoteProcessor(), - ]; - } + ->addInlineProcessor(new QuoteProcessor(), 10) - /** - * {@inheritdoc} - */ - public function getBlockRenderers() - { - return [ - Document::class => new CoreBlockRenderer\DocumentRenderer(), - Paragraph::class => new CoreBlockRenderer\ParagraphRenderer(), - ]; - } + ->addBlockRenderer(Document::class, new CoreBlockRenderer\DocumentRenderer(), 0) + ->addBlockRenderer(Paragraph::class, new CoreBlockRenderer\ParagraphRenderer(), 0) - /** - * {@inheritdoc} - */ - public function getInlineRenderers() - { - return [ - Text::class => new CoreInlineRenderer\TextRenderer(), - ]; + ->addInlineRenderer(Text::class, new CoreInlineRenderer\TextRenderer(), 0) + ; } } From ed8e604870ceeaa5f14cbfe8fd6cc84e8ea3c660 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 20:03:08 -0700 Subject: [PATCH 111/231] Make StyleCI ignore indentation --- .styleci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.styleci.yml b/.styleci.yml index bc9a4c815b..21f021b37f 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -7,3 +7,7 @@ enabled: disabled: - concat_without_spaces - phpdoc_summary + +finder: + not-name: + - "InlinesOnlyExtension.php" From fadf668c558772223e66df956ee1e166be4e1559 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Apr 2019 20:04:40 -0700 Subject: [PATCH 112/231] Make StyleCI ignore semi-colon placement --- .styleci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.styleci.yml b/.styleci.yml index bc9a4c815b..51a022fea1 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -7,3 +7,7 @@ enabled: disabled: - concat_without_spaces - phpdoc_summary + +finder: + not-name: + - "SmartPunctExtension.php" From 724a1f186e68c664ebb896b1a546900168be2f4f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 15 Mar 2019 12:53:07 -0400 Subject: [PATCH 113/231] Update namespace, copyright, composer.json, and code style --- .editorconfig | 15 ++++++ .gitattributes | 11 +++++ .gitignore | 6 +-- CONTRIBUTING.md | 43 ++++++++++++++++ LICENSE | 7 +-- README.md | 2 +- composer.json | 36 +++++++++----- phpunit.xml.dist | 2 +- src/Strikethrough.php | 18 +++++++ src/Strikethrough/Strikethrough.php | 8 --- src/Strikethrough/StrikethroughExtension.php | 16 ------ src/StrikethroughExtension.php | 49 +++++++++++++++++++ .../StrikethroughParser.php | 33 ++++++++----- .../StrikethroughRenderer.php | 20 +++++--- tests/FakeHtmlRenderer.php | 13 ++--- .../IntegrationTest.php | 29 ++++++----- .../StrikethroughParserTest.php | 20 ++++++-- .../StrikethroughRendererTest.php | 33 +++++++------ 18 files changed, 256 insertions(+), 105 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 CONTRIBUTING.md create mode 100644 src/Strikethrough.php delete mode 100644 src/Strikethrough/Strikethrough.php delete mode 100644 src/Strikethrough/StrikethroughExtension.php create mode 100644 src/StrikethroughExtension.php rename src/{Strikethrough => }/StrikethroughParser.php (58%) rename src/{Strikethrough => }/StrikethroughRenderer.php (63%) rename tests/{StrikethroughTests => }/IntegrationTest.php (58%) rename tests/{StrikethroughTests => }/StrikethroughParserTest.php (70%) rename tests/{StrikethroughTests => }/StrikethroughRendererTest.php (54%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..43590ddcff --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/scrutinizer.yml export-ignore +/tests export-ignore diff --git a/.gitignore b/.gitignore index 7b43c0b61c..7aa851fa06 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/vendor/ -/build/ /.idea/ -composer.lock \ No newline at end of file +/build/ +/composer.lock +/vendor/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..91a7cc431a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,43 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-ext-autolink). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +- **Docblocks** - All files should start with the following docblock: + +~~~ +/* + * This file is part of the league/commonmark-ext-strikethrough package. + * + * (c) Colin O'Dell 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. + */ +~~~ + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE b/LICENSE index a974ca1cd9..852c269064 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,4 @@ -The MIT License - -uAfrica.com (http://uafrica.com) -Copyright (c), uAfrica.com +Copyright (c) 2019, Colin O'Dell & uAfrica.com (http://uafrica.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -20,5 +17,3 @@ 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. - -uAfrica.com diff --git a/README.md b/README.md index 1b18989d54..9752c55b83 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ parsing engine, which itself is based on the CommonMark spec. ## Current Custom Parsers and Renderers -* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \CommonMarkExt\Strikethrough\StrikethroughExtension())`. +* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \League\CommonMark\Ext\Strikethrough\StrikethroughExtension())`. ## Installation diff --git a/composer.json b/composer.json index d838c18def..36842c3793 100644 --- a/composer.json +++ b/composer.json @@ -1,29 +1,43 @@ { - "name": "uafrica/commonmark-ext", + "name": "league/commonmark-ext-strikethrough", "type": "commonmark-extension", - "description": "Extended parsers and renderers for The PHP League CommonMark parser", - "keywords": ["markdown", "strikethrough", "strikeout", "commonmark"], - "require": { - "league/commonmark": "^0.18" - }, - "require-dev": { - "phpunit/phpunit": "5" - }, + "description": "Strikethrough support for the PHP League's CommonMark Markdown parser", + "keywords": ["markdown", "commonmark", "extension", "strikethrough", "strikeout"], + "homepage": "https://github.com/thephpleague/commonmark-ext-strikethrough", "license": "MIT", "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com" + }, { "name": "Johan Meiring", "email": "johan@uafrica.com" } ], + "require": { + "php": ">=5.6", + "league/commonmark": "^0.18" + }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, "autoload": { "psr-4": { - "CommonMarkExt\\": "src/" + "League\\CommonMark\\Ext\\Strikethrough\\": "src/" } }, "autoload-dev": { "psr-4": { - "CommonMarkExt\\Tests\\": "tests/" + "League\\CommonMark\\Ext\\Strikethrough\\Test\\": "tests/" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 3357af9425..1db9a7528d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ processIsolation="false" stopOnFailure="false"> - + tests diff --git a/src/Strikethrough.php b/src/Strikethrough.php new file mode 100644 index 0000000000..bf77e28a7f --- /dev/null +++ b/src/Strikethrough.php @@ -0,0 +1,18 @@ + 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\Ext\Strikethrough; + +use League\CommonMark\Inline\Element\AbstractStringContainer; + +class Strikethrough extends AbstractStringContainer +{ +} diff --git a/src/Strikethrough/Strikethrough.php b/src/Strikethrough/Strikethrough.php deleted file mode 100644 index 62d9ccc6ab..0000000000 --- a/src/Strikethrough/Strikethrough.php +++ /dev/null @@ -1,8 +0,0 @@ - new StrikethroughRenderer() ]; } -} - diff --git a/src/StrikethroughExtension.php b/src/StrikethroughExtension.php new file mode 100644 index 0000000000..2e3618dedd --- /dev/null +++ b/src/StrikethroughExtension.php @@ -0,0 +1,49 @@ + 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\Ext\Strikethrough; + +use League\CommonMark\Extension\Extension; +use League\CommonMark\Inline\Parser\InlineParserInterface; +use League\CommonMark\Inline\Processor\InlineProcessorInterface; +use League\CommonMark\Inline\Renderer\InlineRendererInterface; + +final class StrikethroughExtension extends Extension +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'strikethrough'; + } + + /** + * {@inheritdoc} + */ + public function getInlineParsers() + { + return [ + new StrikethroughParser(), + ]; + } + + /** + * {@inheritdoc} + */ + public function getInlineRenderers() + { + return [ + Strikethrough::class => new StrikethroughRenderer(), + ]; + } +} + diff --git a/src/Strikethrough/StrikethroughParser.php b/src/StrikethroughParser.php similarity index 58% rename from src/Strikethrough/StrikethroughParser.php rename to src/StrikethroughParser.php index b7edba552e..626198bdf0 100644 --- a/src/Strikethrough/StrikethroughParser.php +++ b/src/StrikethroughParser.php @@ -1,15 +1,24 @@ 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\Ext\Strikethrough; + use League\CommonMark\Inline\Element\Text; use League\CommonMark\Inline\Parser\AbstractInlineParser; use League\CommonMark\InlineParserContext; -class StrikethroughParser extends AbstractInlineParser +final class StrikethroughParser extends AbstractInlineParser { /** - * @return string[] + * {@inheritdoc} */ public function getCharacters() { @@ -17,14 +26,11 @@ public function getCharacters() } /** - * @param ContextInterface $context - * @param InlineParserContext $inline_context - * - * @return bool + * {@inheritdoc} */ - public function parse(InlineParserContext $inline_context) + public function parse(InlineParserContext $inlineContext) { - $cursor = $inline_context->getCursor(); + $cursor = $inlineContext->getCursor(); $character = $cursor->getCharacter(); if ($cursor->peek(1) !== $character) { return false; @@ -34,18 +40,21 @@ public function parse(InlineParserContext $inline_context) if ($tildes === '') { return false; } + $previous_state = $cursor->saveState(); while ($matching_tildes = $cursor->match('/~~+/m')) { if ($matching_tildes === $tildes) { $text = mb_substr( $cursor->getPreviousText(), 0, -mb_strlen($tildes) ); $text = preg_replace('/[ \n]+/', ' ', $text); - $inline_context->getContainer()->appendChild(new Strikethrough(trim($text))); + $inlineContext->getContainer()->appendChild(new Strikethrough(trim($text))); return true; } } + // If we got here, we didn't match a closing tilde pair sequence $cursor->restoreState($previous_state); - $inline_context->getContainer()->appendChild(new Text($tildes)); + $inlineContext->getContainer()->appendChild(new Text($tildes)); + return true; } } diff --git a/src/Strikethrough/StrikethroughRenderer.php b/src/StrikethroughRenderer.php similarity index 63% rename from src/Strikethrough/StrikethroughRenderer.php rename to src/StrikethroughRenderer.php index 54c0e77f21..988e6743e2 100644 --- a/src/Strikethrough/StrikethroughRenderer.php +++ b/src/StrikethroughRenderer.php @@ -1,5 +1,15 @@ 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\Ext\Strikethrough; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; @@ -7,19 +17,17 @@ use League\CommonMark\Inline\Renderer\InlineRendererInterface; use League\CommonMark\Util\Xml; -class StrikethroughRenderer implements InlineRendererInterface +final class StrikethroughRenderer implements InlineRendererInterface { /** - * @param AbstractInline $inline - * @param ElementRendererInterface $htmlRenderer - * - * @return HtmlElement|string + * {@inheritdoc} */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { if (!($inline instanceof Strikethrough)) { throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline)); } + $attrs = []; foreach ($inline->getData('attributes', []) as $key => $value) { $attrs[$key] = Xml::escape($value, true); diff --git a/tests/FakeHtmlRenderer.php b/tests/FakeHtmlRenderer.php index 380db6b9d4..76b26be825 100644 --- a/tests/FakeHtmlRenderer.php +++ b/tests/FakeHtmlRenderer.php @@ -1,20 +1,15 @@ - * - * Original code based on the CommonMark JS reference parser (http://bitly.com/commonmark-js) - * - (c) John MacFarlane + * (c) Colin O'Dell 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: https://github.com/thephpleague/commonmark/blob/master/LICENSE + * file that was distributed with this source code. */ -namespace CommonMarkExt\Tests; +namespace League\CommonMark\Ext\Strikethrough\Test; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\ElementRendererInterface; diff --git a/tests/StrikethroughTests/IntegrationTest.php b/tests/IntegrationTest.php similarity index 58% rename from tests/StrikethroughTests/IntegrationTest.php rename to tests/IntegrationTest.php index b39580c3e1..afe5e23237 100644 --- a/tests/StrikethroughTests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -1,9 +1,17 @@ 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\Ext\Strikethrough\Test\StrikethroughTests; + +use League\CommonMark\Ext\Strikethrough\StrikethroughExtension; use League\CommonMark\DocParser; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; @@ -13,15 +21,13 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase /** * @param string $string * @param string $expected - * @return void * * @dataProvider dataForIntegrationTest */ public function testStrikethrough($string, $expected) { $environment = Environment::createCommonMarkEnvironment(); - $environment->addInlineParser(new StrikethroughParser()); - $environment->addInlineRenderer('CommonMarkExt\Strikethrough\Strikethrough', new StrikethroughRenderer()); + $environment->addExtension(new StrikethroughExtension()); $parser = new DocParser($environment); $renderer = new HtmlRenderer($environment); @@ -29,9 +35,6 @@ public function testStrikethrough($string, $expected) $document = $parser->parse($string); $html = $renderer->renderBlock($document); -// -// $converter = new CommonMarkConverter($environment->getConfig()); -// $html = $converter->convertToHtml($string); $this->assertSame($expected, $html); } @@ -46,6 +49,10 @@ public function dataForIntegrationTest() ['This is a test without any ~valid~ strikethroughs', "

This is a test without any ~valid~ strikethroughs

\n"], ['This is a test `without` any ~valid~ strikethroughs', "

This is a test without any ~valid~ strikethroughs

\n"], ['This is a ~~unit~~ integration test', "

This is a unit integration test

\n"], + ['This ~~test has no ending match', "

This ~~test has no ending match

\n"], + ['This ~~test~~~ has mismatched tildes', "

This ~~test~~~ has mismatched tildes

\n"], + ['This ~~~test~~ also has mismatched tildes', "

This ~~~test~~ also has mismatched tildes

\n"], + ['This one has ~~~three~~~ tildes', "

This one has three tildes

\n"], ]; } -} \ No newline at end of file +} diff --git a/tests/StrikethroughTests/StrikethroughParserTest.php b/tests/StrikethroughParserTest.php similarity index 70% rename from tests/StrikethroughTests/StrikethroughParserTest.php rename to tests/StrikethroughParserTest.php index 8acd4c8ab4..4c83fa3577 100644 --- a/tests/StrikethroughTests/StrikethroughParserTest.php +++ b/tests/StrikethroughParserTest.php @@ -1,9 +1,19 @@ 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\Ext\Strikethrough\Test; + +use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Ext\Strikethrough\Strikethrough; +use League\CommonMark\Ext\Strikethrough\StrikethroughParser; use League\CommonMark\InlineParserContext; use League\CommonMark\Reference\ReferenceMap; @@ -17,7 +27,7 @@ class StrikethroughParserTest extends \PHPUnit_Framework_TestCase */ public function testParse($string, $expected) { - $nodeStub = $this->getMock(\League\CommonMark\Block\Element\AbstractBlock::class); + $nodeStub = $this->createMock(AbstractBlock::class); $nodeStub->expects($this->any())->method('getStringContent')->willReturn($string); $nodeStub ->expects($this->once()) diff --git a/tests/StrikethroughTests/StrikethroughRendererTest.php b/tests/StrikethroughRendererTest.php similarity index 54% rename from tests/StrikethroughTests/StrikethroughRendererTest.php rename to tests/StrikethroughRendererTest.php index f872c2f9a7..23d5f15d28 100644 --- a/tests/StrikethroughTests/StrikethroughRendererTest.php +++ b/tests/StrikethroughRendererTest.php @@ -1,9 +1,18 @@ 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\Ext\Strikethrough\Test; + +use League\CommonMark\Ext\Strikethrough\Strikethrough; +use League\CommonMark\Ext\Strikethrough\StrikethroughRenderer; use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Renderer\CodeRenderer; @@ -23,21 +32,13 @@ public function testRender() { $inline = new Strikethrough('reviewed text'); $inline->data['attributes'] = ['id' => 'some"&id']; - $fake_renderer = new FakeHtmlRenderer(); - $result = $this->renderer->render($inline, $fake_renderer); + $fakeRenderer = new FakeHtmlRenderer(); + + $result = $this->renderer->render($inline, $fakeRenderer); + $this->assertTrue($result instanceof HtmlElement); $this->assertEquals('del', $result->getTagName()); $this->assertContains('reviewed text', $result->getContents(true)); $this->assertEquals(['id' => 'some"&id'], $result->getAllAttributes()); } - - /** - * @expectedException \InvalidArgumentException - */ - public function testRenderWithInvalidType() - { - $inline = $this->getMockForAbstractClass('League\CommonMark\Inline\Element\AbstractInline'); - $fake_renderer = new FakeHtmlRenderer(); - $this->renderer->render($inline, $fake_renderer); - } } From 20be7eb5e0e563b94d6cddd371adb9388cee6d98 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 14 Apr 2019 13:36:39 -0400 Subject: [PATCH 114/231] Bump dependencies; make compatible with league/commonmark 0.19 --- composer.json | 6 ++--- phpunit.xml.dist | 5 +--- src/StrikethroughExtension.php | 36 +++++------------------------ src/StrikethroughParser.php | 8 +++---- src/StrikethroughRenderer.php | 7 +----- tests/FakeHtmlRenderer.php | 8 +++---- tests/IntegrationTest.php | 3 ++- tests/StrikethroughParserTest.php | 7 +++--- tests/StrikethroughRendererTest.php | 5 ++-- 9 files changed, 28 insertions(+), 57 deletions(-) diff --git a/composer.json b/composer.json index 36842c3793..247823b416 100644 --- a/composer.json +++ b/composer.json @@ -16,11 +16,11 @@ } ], "require": { - "php": ">=5.6", - "league/commonmark": "^0.18" + "php": "^7.1", + "league/commonmark": "^0.19" }, "require-dev": { - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^7.5" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 1db9a7528d..dbff6eb4f8 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,11 +20,8 @@ - - - + - diff --git a/src/StrikethroughExtension.php b/src/StrikethroughExtension.php index 2e3618dedd..4b7ac25742 100644 --- a/src/StrikethroughExtension.php +++ b/src/StrikethroughExtension.php @@ -11,39 +11,15 @@ namespace League\CommonMark\Ext\Strikethrough; -use League\CommonMark\Extension\Extension; -use League\CommonMark\Inline\Parser\InlineParserInterface; -use League\CommonMark\Inline\Processor\InlineProcessorInterface; -use League\CommonMark\Inline\Renderer\InlineRendererInterface; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; -final class StrikethroughExtension extends Extension +final class StrikethroughExtension implements ExtensionInterface { - /** - * {@inheritdoc} - */ - public function getName() - { - return 'strikethrough'; - } - - /** - * {@inheritdoc} - */ - public function getInlineParsers() - { - return [ - new StrikethroughParser(), - ]; - } - /** - * {@inheritdoc} - */ - public function getInlineRenderers() + public function register(ConfigurableEnvironmentInterface $environment) { - return [ - Strikethrough::class => new StrikethroughRenderer(), - ]; + $environment->addInlineParser(new StrikethroughParser()); + $environment->addInlineRenderer(Strikethrough::class, new StrikethroughRenderer()); } } - diff --git a/src/StrikethroughParser.php b/src/StrikethroughParser.php index 626198bdf0..8197eea632 100644 --- a/src/StrikethroughParser.php +++ b/src/StrikethroughParser.php @@ -12,15 +12,15 @@ namespace League\CommonMark\Ext\Strikethrough; use League\CommonMark\Inline\Element\Text; -use League\CommonMark\Inline\Parser\AbstractInlineParser; +use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; -final class StrikethroughParser extends AbstractInlineParser +final class StrikethroughParser implements InlineParserInterface { /** * {@inheritdoc} */ - public function getCharacters() + public function getCharacters(): array { return ['~']; } @@ -28,7 +28,7 @@ public function getCharacters() /** * {@inheritdoc} */ - public function parse(InlineParserContext $inlineContext) + public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); $character = $cursor->getCharacter(); diff --git a/src/StrikethroughRenderer.php b/src/StrikethroughRenderer.php index 988e6743e2..27cddaeb20 100644 --- a/src/StrikethroughRenderer.php +++ b/src/StrikethroughRenderer.php @@ -28,11 +28,6 @@ public function render(AbstractInline $inline, ElementRendererInterface $htmlRen throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline)); } - $attrs = []; - foreach ($inline->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value, true); - } - - return new HtmlElement('del', $attrs, Xml::escape($inline->getContent())); + return new HtmlElement('del', $inline->getData('attributes', []), Xml::escape($inline->getContent())); } } diff --git a/tests/FakeHtmlRenderer.php b/tests/FakeHtmlRenderer.php index 76b26be825..dd9fe3754e 100644 --- a/tests/FakeHtmlRenderer.php +++ b/tests/FakeHtmlRenderer.php @@ -34,7 +34,7 @@ public function setOption($option, $value) * * @return mixed|null */ - public function getOption($option, $default = null) + public function getOption(string $option, $default = null) { if (!isset($this->options[$option])) { return $default; @@ -59,7 +59,7 @@ public function escape($string, $preserveEntities = false) * * @return string */ - public function renderInlines($inlines) + public function renderInlines(iterable $inlines): string { return '::inlines::'; } @@ -72,7 +72,7 @@ public function renderInlines($inlines) * * @return string */ - public function renderBlock(AbstractBlock $block, $inTightList = false) + public function renderBlock(AbstractBlock $block, bool $inTightList = false): string { return '::block::'; } @@ -83,7 +83,7 @@ public function renderBlock(AbstractBlock $block, $inTightList = false) * * @return string */ - public function renderBlocks($blocks, $inTightList = false) + public function renderBlocks(iterable $blocks, bool $inTightList = false): string { return '::blocks::'; } diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index afe5e23237..7ef0e71108 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -15,8 +15,9 @@ use League\CommonMark\DocParser; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; +use PHPUnit\Framework\TestCase; -class IntegrationTest extends \PHPUnit_Framework_TestCase +class IntegrationTest extends TestCase { /** * @param string $string diff --git a/tests/StrikethroughParserTest.php b/tests/StrikethroughParserTest.php index 4c83fa3577..b6af5b0f4d 100644 --- a/tests/StrikethroughParserTest.php +++ b/tests/StrikethroughParserTest.php @@ -11,13 +11,14 @@ namespace League\CommonMark\Ext\Strikethrough\Test; -use League\CommonMark\Block\Element\AbstractBlock; +use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Ext\Strikethrough\Strikethrough; use League\CommonMark\Ext\Strikethrough\StrikethroughParser; use League\CommonMark\InlineParserContext; use League\CommonMark\Reference\ReferenceMap; +use PHPUnit\Framework\TestCase; -class StrikethroughParserTest extends \PHPUnit_Framework_TestCase +class StrikethroughParserTest extends TestCase { /** * @param $string @@ -27,7 +28,7 @@ class StrikethroughParserTest extends \PHPUnit_Framework_TestCase */ public function testParse($string, $expected) { - $nodeStub = $this->createMock(AbstractBlock::class); + $nodeStub = $this->createMock(Paragraph::class); $nodeStub->expects($this->any())->method('getStringContent')->willReturn($string); $nodeStub ->expects($this->once()) diff --git a/tests/StrikethroughRendererTest.php b/tests/StrikethroughRendererTest.php index 23d5f15d28..a6b3dafca2 100644 --- a/tests/StrikethroughRendererTest.php +++ b/tests/StrikethroughRendererTest.php @@ -15,8 +15,9 @@ use League\CommonMark\Ext\Strikethrough\StrikethroughRenderer; use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Renderer\CodeRenderer; +use PHPUnit\Framework\TestCase; -class StrikethroughRendererTest extends \PHPUnit_Framework_TestCase +class StrikethroughRendererTest extends TestCase { /** * @var CodeRenderer @@ -39,6 +40,6 @@ public function testRender() $this->assertTrue($result instanceof HtmlElement); $this->assertEquals('del', $result->getTagName()); $this->assertContains('reviewed text', $result->getContents(true)); - $this->assertEquals(['id' => 'some"&id'], $result->getAllAttributes()); + $this->assertEquals(['id' => 'some"&id'], $result->getAllAttributes()); } } From e69547eabb678e8a7042077cbb298f8db604fc63 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 16:52:09 -0400 Subject: [PATCH 115/231] Update the README --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9752c55b83..965b3ef088 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,81 @@ -# uafrica/commonmark-ext +# Strikethrough support for `league/commonmark` -[![Latest Version](https://img.shields.io/packagist/v/uafrica/commonmark-ext.svg?style=flat-square)](https://packagist.org/packages/uafrica/commonmark-ext) -[![Software License](http://img.shields.io/badge/License-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-travis]][link-travis] +[![Coverage Status][ico-scrutinizer]][link-scrutinizer] +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] -**uafrica/commonmark-ext** is a collection of custom parsers and renderers for the [league-commonmark] Markdown -parsing engine, which itself is based on the CommonMark spec. +This extension adds strikethrough Markdown support for the (`league/commonmark`)[link-league-commonmark] Markdown parsing engine, which itself is based on the CommonMark spec. -## Current Custom Parsers and Renderers - -* **Strikethrough:** Parser and Renderer. Allows users to use `~~` in order to indicate text that should be rendered within `` tags. To use it, add it to your environment object with `$env->addExtension(new \League\CommonMark\Ext\Strikethrough\StrikethroughExtension())`. +It allows users to use `~~` in order to indicate text that should be rendered within `` tags. ## Installation -This project can be installed via [Composer]: +This project can be installed via Composer: ``` bash -$ composer require uafrica/commonmark-ext -... +$ composer require league/commonmark-ext-strikethrough +``` + +## Usage + +Extensions can be added to any new `Environment`: + +``` php +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\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!'); ``` +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + ## Testing ``` bash -$ ./vendor/bin/phpunit -... +$ composer test ``` +## Security + +If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. + +## Credits + +- [Colin O'Dell][link-colinodell] +- [uAfrica Technologies (Pty) Ltd][link-uafrica] +- [All Contributors][link-contributors] + ## License -**uafrica/commonmark-ext** is licensed under the MIT. See the `LICENSE` file for more details. +This library is licensed under the MIT license. See the `LICENSE` file for more information. + +[ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-strikethrough.svg?style=flat-square +[ico-license]: http://img.shields.io/badge/License-MIT-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/thephpleague/commonmark-ext-strikethrough/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-strikethrough.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-strikethrough.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/league/commonmark-ext-strikethrough.svg?style=flat-square -[league-commonmark]: https://github.com/thephpleague/commonmark +[link-packagist]: https://packagist.org/packages/league/commonmark-ext-strikethrough +[link-travis]: https://travis-ci.org/thephpleague/commonmark-ext-strikethrough +[link-scrutinizer]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-strikethrough/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-strikethrough +[link-downloads]: https://packagist.org/packages/league/commonmark-ext-strikethrough +[link-uafrica]: https://github.com/uafrica +[link-colinodell]: https://github.com/colinodell +[link-contributors]: ../../contributors +[link-league-commonmark]: https://github.com/thephpleague/commonmark From 624b86be719a4110bae42206961d2b135891e47b Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 16:52:23 -0400 Subject: [PATCH 116/231] Bump the master branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 247823b416..0375133529 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "0.4-dev" } } } From 76191d4f873b57f2a20eceea63952aafa6d7fec1 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 16:54:08 -0400 Subject: [PATCH 117/231] Add CONDUCT.md --- CONDUCT.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 CONDUCT.md diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000000..6ff94ca3a4 --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) From fb9a338c6c0b66c8ee4bac162776cc98e8ad4190 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 16:57:45 -0400 Subject: [PATCH 118/231] Add a changelog --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..c73710e5cb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# 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] + +Split this extension out of the old `uafrica/commonmark-ext` library. + +## [0.3.0] - 2019-01-08 + +### Changed + + - Updated to `league/commonmark` v0.18 + +## [0.2.0] - 2018-05-14 + +### Changed + + - Updated to `league/commonmark` v0.17 + +[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.3.0...HEAD +[0.3.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.2.0...v0.3.0 +[0.2.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.1.1...v0.2.0 From e5e6a3a02ef2f3f20548ba5f2ee6b50826d1da1d Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 16:59:07 -0400 Subject: [PATCH 119/231] Configure third-party services --- .gitattributes | 2 ++ .scrutinizer.yml | 39 +++++++++++++++++++++++++++++++++++++++ .stickler.yml | 9 --------- .styleci.yml | 13 +++++++++++++ .travis.yml | 24 ++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 .scrutinizer.yml delete mode 100644 .stickler.yml create mode 100644 .styleci.yml create mode 100644 .travis.yml diff --git a/.gitattributes b/.gitattributes index 43590ddcff..803eba2766 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,9 +2,11 @@ # https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html # Ignore all test and documentation with "export-ignore". +/.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore /.scrutinizer.yml export-ignore +/.styleci.yml export-ignore /.travis.yml export-ignore /phpunit.xml.dist export-ignore /scrutinizer.yml export-ignore diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..a2baf35af7 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: + enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true diff --git a/.stickler.yml b/.stickler.yml deleted file mode 100644 index 2792063958..0000000000 --- a/.stickler.yml +++ /dev/null @@ -1,9 +0,0 @@ -linters: - phpcs: - standard: PSR2 - fixer: true -files: - ignore: - - 'vendor/*' -fixers: - enable: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..51a022fea1 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,13 @@ +preset: recommended + +enabled: + - concat_with_spaces + - strict + +disabled: + - concat_without_spaces + - phpdoc_summary + +finder: + not-name: + - "SmartPunctExtension.php" diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..35297f5ce4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: php + +php: + - 7.1 + - 7.2 + - 7.3 + +env: + matrix: + - COMPOSER_FLAGS="" + - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + +sudo: false + +before_script: + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + +after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover From 1ba496f4b9ae82b79f3508ee77082f2310b0411c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 17:00:38 -0400 Subject: [PATCH 120/231] Fix link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 965b3ef088..6ac541f513 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Quality Score][ico-code-quality]][link-code-quality] [![Total Downloads][ico-downloads]][link-downloads] -This extension adds strikethrough Markdown support for the (`league/commonmark`)[link-league-commonmark] Markdown parsing engine, which itself is based on the CommonMark spec. +This extension adds strikethrough Markdown support for the [league/commonmark](link-league-commonmark) PHP Markdown parsing engine, which itself is based on the CommonMark spec. It allows users to use `~~` in order to indicate text that should be rendered within `` tags. From 096c1a364a868b751a01e157360e7cbe5e92cf7c Mon Sep 17 00:00:00 2001 From: colinodell Date: Fri, 19 Apr 2019 21:03:50 +0000 Subject: [PATCH 121/231] Apply fixes from StyleCI --- src/StrikethroughExtension.php | 1 - src/StrikethroughParser.php | 3 ++- tests/FakeHtmlRenderer.php | 10 +++++----- tests/IntegrationTest.php | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/StrikethroughExtension.php b/src/StrikethroughExtension.php index 4b7ac25742..ca749650b7 100644 --- a/src/StrikethroughExtension.php +++ b/src/StrikethroughExtension.php @@ -16,7 +16,6 @@ final class StrikethroughExtension implements ExtensionInterface { - public function register(ConfigurableEnvironmentInterface $environment) { $environment->addInlineParser(new StrikethroughParser()); diff --git a/src/StrikethroughParser.php b/src/StrikethroughParser.php index 8197eea632..b865fd7309 100644 --- a/src/StrikethroughParser.php +++ b/src/StrikethroughParser.php @@ -44,9 +44,10 @@ public function parse(InlineParserContext $inlineContext): bool $previous_state = $cursor->saveState(); while ($matching_tildes = $cursor->match('/~~+/m')) { if ($matching_tildes === $tildes) { - $text = mb_substr( $cursor->getPreviousText(), 0, -mb_strlen($tildes) ); + $text = mb_substr($cursor->getPreviousText(), 0, -mb_strlen($tildes)); $text = preg_replace('/[ \n]+/', ' ', $text); $inlineContext->getContainer()->appendChild(new Strikethrough(trim($text))); + return true; } } diff --git a/tests/FakeHtmlRenderer.php b/tests/FakeHtmlRenderer.php index dd9fe3754e..790cf1452f 100644 --- a/tests/FakeHtmlRenderer.php +++ b/tests/FakeHtmlRenderer.php @@ -20,7 +20,7 @@ class FakeHtmlRenderer implements ElementRendererInterface protected $options; /** - * @param string $option + * @param string $option * @param mixed|null $value */ public function setOption($option, $value) @@ -29,7 +29,7 @@ public function setOption($option, $value) } /** - * @param string $option + * @param string $option * @param mixed|null $default * * @return mixed|null @@ -45,7 +45,7 @@ public function getOption(string $option, $default = null) /** * @param string $string - * @param bool $preserveEntities + * @param bool $preserveEntities * * @return string */ @@ -66,7 +66,7 @@ public function renderInlines(iterable $inlines): string /** * @param AbstractBlock $block - * @param bool $inTightList + * @param bool $inTightList * * @throws \RuntimeException * @@ -79,7 +79,7 @@ public function renderBlock(AbstractBlock $block, bool $inTightList = false): st /** * @param AbstractBlock[] $blocks - * @param bool $inTightList + * @param bool $inTightList * * @return string */ diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 7ef0e71108..70c874315a 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -11,9 +11,9 @@ namespace League\CommonMark\Ext\Strikethrough\Test\StrikethroughTests; -use League\CommonMark\Ext\Strikethrough\StrikethroughExtension; use League\CommonMark\DocParser; use League\CommonMark\Environment; +use League\CommonMark\Ext\Strikethrough\StrikethroughExtension; use League\CommonMark\HtmlRenderer; use PHPUnit\Framework\TestCase; From b4bb867c9a08000061ab894a843e5a0a71538957 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 17:17:25 -0400 Subject: [PATCH 122/231] Add missing extension to composer.json --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 0375133529..a3b5152ca3 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": "^7.1", + "ext-mbstring": "*", "league/commonmark": "^0.19" }, "require-dev": { From 1aadc223d66c323aa1bd1c20fe3dfec3aca54271 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 17:17:36 -0400 Subject: [PATCH 123/231] Add additional unit test --- tests/StrikethroughRendererTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/StrikethroughRendererTest.php b/tests/StrikethroughRendererTest.php index a6b3dafca2..0dfe5e6bc4 100644 --- a/tests/StrikethroughRendererTest.php +++ b/tests/StrikethroughRendererTest.php @@ -14,6 +14,7 @@ use League\CommonMark\Ext\Strikethrough\Strikethrough; use League\CommonMark\Ext\Strikethrough\StrikethroughRenderer; use League\CommonMark\HtmlElement; +use League\CommonMark\Inline\Element\Text; use League\CommonMark\Inline\Renderer\CodeRenderer; use PHPUnit\Framework\TestCase; @@ -42,4 +43,15 @@ public function testRender() $this->assertContains('reviewed text', $result->getContents(true)); $this->assertEquals(['id' => 'some"&id'], $result->getAllAttributes()); } + + /** + * @expectedException \InvalidArgumentException + */ + public function testRenderWithInvalidNodeType() + { + $inline = new Text('ruh roh'); + $fakeRenderer = new FakeHtmlRenderer(); + + $this->renderer->render($inline, $fakeRenderer); + } } From ee4a91e298fbb3c3885e53f6b7f35cea6a5a2b21 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 17:21:51 -0400 Subject: [PATCH 124/231] Update CHANGELOG --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c73710e5cb..f25c4dd9a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] -Split this extension out of the old `uafrica/commonmark-ext` library. +We split this extension out of the old `uafrica/commonmark-ext` library for this release. + +### Changed + + - Changed the project name and namespace + - Updated to `league/commonmark` v0.19 + - Made most of the classes `final` + +# Older Releases + +These older releases come from the original `uafrica/commonmark-ext` library. ## [0.3.0] - 2019-01-08 From 7e59d85282a98ae61c7fb01a37c950affc0455f5 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 17:24:44 -0400 Subject: [PATCH 125/231] Mark this package as a replacement for uafrica/commonmark-ext --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index a3b5152ca3..f0a745656d 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,9 @@ "League\\CommonMark\\Ext\\Strikethrough\\Test\\": "tests/" } }, + "replace": { + "uafrica/commonmark-ext": ">=0.1.1" + }, "scripts": { "test": "phpunit" }, From 5ae0bc2007a4fa5973499df61624f2c3411f0431 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 19 Apr 2019 17:29:57 -0400 Subject: [PATCH 126/231] Release v0.4.0 --- CHANGELOG.md | 5 ++++- composer.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f25c4dd9a8..4831e367a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.4.0] - 2019-04-09 + We split this extension out of the old `uafrica/commonmark-ext` library for this release. ### Changed @@ -31,6 +33,7 @@ These older releases come from the original `uafrica/commonmark-ext` library. - Updated to `league/commonmark` v0.17 -[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.3.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.4.0...HEAD +[0.4.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.1.1...v0.2.0 diff --git a/composer.json b/composer.json index f0a745656d..ba81ce58de 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "0.5-dev" } } } From 7acd8b66a6735c5ae7e37c9fe6677a31864f579a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 20 Apr 2019 08:39:27 -0400 Subject: [PATCH 127/231] Refactor to use delimiter processors --- CHANGELOG.md | 9 ++++ composer.json | 2 +- src/Strikethrough.php | 11 +++- src/StrikethroughDelimiterProcessor.php | 69 +++++++++++++++++++++++++ src/StrikethroughExtension.php | 2 +- src/StrikethroughParser.php | 61 ---------------------- src/StrikethroughRenderer.php | 3 +- tests/FakeHtmlRenderer.php | 10 ++++ tests/IntegrationTest.php | 13 ++++- tests/StrikethroughParserTest.php | 60 --------------------- tests/StrikethroughRendererTest.php | 4 +- 11 files changed, 113 insertions(+), 131 deletions(-) create mode 100644 src/StrikethroughDelimiterProcessor.php delete mode 100644 src/StrikethroughParser.php delete mode 100644 tests/StrikethroughParserTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 4831e367a7..7145109016 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +### Changed + + - Updated to the next version of `league/commonmark` + - Refactored pretty much everything to use the new delimiter processing functionality + - The `Strikethrough` node now extends from `AbstractInline` + +### Removed + - Removed `StrikethroughParser` as we're now leveraging delimiter processors and no longer need a dedicated parser + ## [0.4.0] - 2019-04-09 We split this extension out of the old `uafrica/commonmark-ext` library for this release. diff --git a/composer.json b/composer.json index ba81ce58de..50ca2724bc 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1", "ext-mbstring": "*", - "league/commonmark": "^0.19" + "league/commonmark": "0.20.x-dev" }, "require-dev": { "phpunit/phpunit": "^7.5" diff --git a/src/Strikethrough.php b/src/Strikethrough.php index bf77e28a7f..94354458f9 100644 --- a/src/Strikethrough.php +++ b/src/Strikethrough.php @@ -11,8 +11,15 @@ namespace League\CommonMark\Ext\Strikethrough; -use League\CommonMark\Inline\Element\AbstractStringContainer; +use League\CommonMark\Inline\Element\AbstractInline; -class Strikethrough extends AbstractStringContainer +class Strikethrough extends AbstractInline { + /** + * @return bool + */ + public function isContainer(): bool + { + return true; + } } diff --git a/src/StrikethroughDelimiterProcessor.php b/src/StrikethroughDelimiterProcessor.php new file mode 100644 index 0000000000..2e5e54a1dd --- /dev/null +++ b/src/StrikethroughDelimiterProcessor.php @@ -0,0 +1,69 @@ + 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\Ext\Strikethrough; + +use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; +use League\CommonMark\Inline\Element\Text; + +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(Delimiter $opener, Delimiter $closer): int + { + $min = \min($opener->getNumDelims(), $closer->getNumDelims()); + + return $min >= 2 ? $min : 0; + } + + /** + * {@inheritdoc} + */ + public function process(Text $opener, Text $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/src/StrikethroughExtension.php b/src/StrikethroughExtension.php index ca749650b7..d760769194 100644 --- a/src/StrikethroughExtension.php +++ b/src/StrikethroughExtension.php @@ -18,7 +18,7 @@ final class StrikethroughExtension implements ExtensionInterface { public function register(ConfigurableEnvironmentInterface $environment) { - $environment->addInlineParser(new StrikethroughParser()); + $environment->addDelimiterProcessor(new StrikethroughDelimiterProcessor()); $environment->addInlineRenderer(Strikethrough::class, new StrikethroughRenderer()); } } diff --git a/src/StrikethroughParser.php b/src/StrikethroughParser.php deleted file mode 100644 index b865fd7309..0000000000 --- a/src/StrikethroughParser.php +++ /dev/null @@ -1,61 +0,0 @@ - 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\Ext\Strikethrough; - -use League\CommonMark\Inline\Element\Text; -use League\CommonMark\Inline\Parser\InlineParserInterface; -use League\CommonMark\InlineParserContext; - -final class StrikethroughParser implements InlineParserInterface -{ - /** - * {@inheritdoc} - */ - public function getCharacters(): array - { - return ['~']; - } - - /** - * {@inheritdoc} - */ - public function parse(InlineParserContext $inlineContext): bool - { - $cursor = $inlineContext->getCursor(); - $character = $cursor->getCharacter(); - if ($cursor->peek(1) !== $character) { - return false; - } - - $tildes = $cursor->match('/^~~+/'); - if ($tildes === '') { - return false; - } - - $previous_state = $cursor->saveState(); - while ($matching_tildes = $cursor->match('/~~+/m')) { - if ($matching_tildes === $tildes) { - $text = mb_substr($cursor->getPreviousText(), 0, -mb_strlen($tildes)); - $text = preg_replace('/[ \n]+/', ' ', $text); - $inlineContext->getContainer()->appendChild(new Strikethrough(trim($text))); - - return true; - } - } - - // If we got here, we didn't match a closing tilde pair sequence - $cursor->restoreState($previous_state); - $inlineContext->getContainer()->appendChild(new Text($tildes)); - - return true; - } -} diff --git a/src/StrikethroughRenderer.php b/src/StrikethroughRenderer.php index 27cddaeb20..16ecde6b5b 100644 --- a/src/StrikethroughRenderer.php +++ b/src/StrikethroughRenderer.php @@ -15,7 +15,6 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Inline\Renderer\InlineRendererInterface; -use League\CommonMark\Util\Xml; final class StrikethroughRenderer implements InlineRendererInterface { @@ -28,6 +27,6 @@ public function render(AbstractInline $inline, ElementRendererInterface $htmlRen throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline)); } - return new HtmlElement('del', $inline->getData('attributes', []), Xml::escape($inline->getContent())); + return new HtmlElement('del', $inline->getData('attributes', []), $htmlRenderer->renderInlines($inline->children())); } } diff --git a/tests/FakeHtmlRenderer.php b/tests/FakeHtmlRenderer.php index 790cf1452f..64e842312b 100644 --- a/tests/FakeHtmlRenderer.php +++ b/tests/FakeHtmlRenderer.php @@ -54,6 +54,16 @@ public function escape($string, $preserveEntities = false) return '::escape::' . $string; } + /** + * @param AbstractInline $inline + * + * @return string + */ + public function renderInline(AbstractInline $inline): string + { + return '::inline::'; + } + /** * @param AbstractInline[] $inlines * diff --git a/tests/IntegrationTest.php b/tests/IntegrationTest.php index 70c874315a..0754c2bce0 100644 --- a/tests/IntegrationTest.php +++ b/tests/IntegrationTest.php @@ -50,10 +50,19 @@ public function dataForIntegrationTest() ['This is a test without any ~valid~ strikethroughs', "

This is a test without any ~valid~ strikethroughs

\n"], ['This is a test `without` any ~valid~ strikethroughs', "

This is a test without any ~valid~ strikethroughs

\n"], ['This is a ~~unit~~ integration test', "

This is a unit integration test

\n"], + ['~~Strikethrough~~ on the left', "

Strikethrough on the left

\n"], + ['Strikethrough on the ~~right~~', "

Strikethrough on the right

\n"], + ['~~Strikethrough everywhere~~', "

Strikethrough everywhere

\n"], ['This ~~test has no ending match', "

This ~~test has no ending match

\n"], - ['This ~~test~~~ has mismatched tildes', "

This ~~test~~~ has mismatched tildes

\n"], - ['This ~~~test~~ also has mismatched tildes', "

This ~~~test~~ also has mismatched tildes

\n"], + ['This ~~test~~~ has mismatched tildes', "

This test~ has mismatched tildes

\n"], + ['This ~~~test~~ also has mismatched tildes', "

This ~test also has mismatched tildes

\n"], ['This one has ~~~three~~~ tildes', "

This one has three tildes

\n"], + ["This ~~has a\n\nnew paragraph~~.", "

This ~~has a

\n

new paragraph~~.

\n"], + ['Hello ~~ ~~ world', "

Hello ~~ ~~ world

\n"], + ['This **is ~~a little** test of mismatched delimiters~~', "

This is ~~a little test of mismatched delimiters~~

\n"], + ['Из: твоя ~~тест~~ ветка', "

Из: твоя тест ветка

\n"], + ['This one combines ~~nested ~~strikethrough~~ text~~', "

This one combines nested strikethrough text

\n"], + ['Here we have **emphasized text containing a ~~strikethrough~~**', "

Here we have emphasized text containing a strikethrough

\n"], ]; } } diff --git a/tests/StrikethroughParserTest.php b/tests/StrikethroughParserTest.php deleted file mode 100644 index b6af5b0f4d..0000000000 --- a/tests/StrikethroughParserTest.php +++ /dev/null @@ -1,60 +0,0 @@ - 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\Ext\Strikethrough\Test; - -use League\CommonMark\Block\Element\Paragraph; -use League\CommonMark\Ext\Strikethrough\Strikethrough; -use League\CommonMark\Ext\Strikethrough\StrikethroughParser; -use League\CommonMark\InlineParserContext; -use League\CommonMark\Reference\ReferenceMap; -use PHPUnit\Framework\TestCase; - -class StrikethroughParserTest extends TestCase -{ - /** - * @param $string - * @param $expected - * - * @dataProvider dataForTestParse - */ - public function testParse($string, $expected) - { - $nodeStub = $this->createMock(Paragraph::class); - $nodeStub->expects($this->any())->method('getStringContent')->willReturn($string); - $nodeStub - ->expects($this->once()) - ->method('appendChild') - ->with($this->callback(function (Strikethrough $s) use ($expected) { - return $s instanceof Strikethrough && $expected === $s->getContent(); - })); - $inline_context = new InlineParserContext($nodeStub, new ReferenceMap()); - - // Move to just before the first tilde pair - $first_tilde_pos = mb_strpos($string, '~~', null, 'utf-8'); - $inline_context->getCursor()->advanceBy($first_tilde_pos); - - $parser = new StrikethroughParser(); - $parser->parse($inline_context); - } - - /** - * @return array - */ - public function dataForTestParse() - { - return [ - ['This is just an ~~integration~~ unit test', 'integration'], - ['Из: твоя ~~feature~~ ветка', 'feature'], - ['Из: твоя ~~тест~~ ветка', 'тест'], - ]; - } -} diff --git a/tests/StrikethroughRendererTest.php b/tests/StrikethroughRendererTest.php index 0dfe5e6bc4..4bd7c5765c 100644 --- a/tests/StrikethroughRendererTest.php +++ b/tests/StrikethroughRendererTest.php @@ -32,7 +32,7 @@ protected function setUp() public function testRender() { - $inline = new Strikethrough('reviewed text'); + $inline = new Strikethrough(); $inline->data['attributes'] = ['id' => 'some"&id']; $fakeRenderer = new FakeHtmlRenderer(); @@ -40,7 +40,7 @@ public function testRender() $this->assertTrue($result instanceof HtmlElement); $this->assertEquals('del', $result->getTagName()); - $this->assertContains('reviewed text', $result->getContents(true)); + $this->assertContains('::inlines::', $result->getContents(true)); $this->assertEquals(['id' => 'some"&id'], $result->getAllAttributes()); } From 6894d9f4a0fbbacb9816f91020d5048075f74dda Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 12 May 2019 19:12:40 -0400 Subject: [PATCH 128/231] Initial commit --- .editorconfig | 15 +++++ .gitattributes | 13 ++++ .gitignore | 4 ++ .scrutinizer.yml | 39 ++++++++++++ .styleci.yml | 13 ++++ .travis.yml | 24 ++++++++ CHANGELOG.md | 12 ++++ CONDUCT.md | 22 +++++++ CONTRIBUTING.md | 45 ++++++++++++++ LICENSE | 29 +++++++++ README.md | 85 +++++++++++++++++++++++++ composer.json | 41 +++++++++++++ phpunit.xml.dist | 26 ++++++++ src/TaskListExtension.php | 24 ++++++++ src/TaskListItemMarker.php | 36 +++++++++++ src/TaskListItemMarkerParser.php | 63 +++++++++++++++++++ src/TaskListItemMarkerRenderer.php | 41 +++++++++++++ tests/TaskListTest.php | 99 ++++++++++++++++++++++++++++++ 18 files changed, 631 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/TaskListExtension.php create mode 100644 src/TaskListItemMarker.php create mode 100644 src/TaskListItemMarkerParser.php create mode 100644 src/TaskListItemMarkerRenderer.php create mode 100644 tests/TaskListTest.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..42120e234c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.styleci.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/scrutinizer.yml export-ignore +/tests/ export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7aa851fa06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/build/ +/composer.lock +/vendor/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..a2baf35af7 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: + enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..af9054cd43 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,13 @@ +preset: recommended + +enabled: + - concat_with_spaces + - no_useless_else + - strict + +disabled: + - concat_without_spaces + - no_trailing_comma_in_list_call + - phpdoc_summary + - post_increment + - self_accessor diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..35297f5ce4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: php + +php: + - 7.1 + - 7.2 + - 7.3 + +env: + matrix: + - COMPOSER_FLAGS="" + - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + +sudo: false + +before_script: + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + +after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..400c9290bc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# 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] + +Initial release! + +[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v0.1.0...HEAD diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000000..6ff94ca3a4 --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..82829a59b9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,45 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-ext-task-list). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Adhere to the spec!** - Any changes should align with the (official GFM spec)[https://github.github.com/gfm/] + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +- **Docblocks** - All files should start with the following docblock: + +~~~ +/* + * This file is part of the league/commonmark-ext-task-list package. + * + * (c) Colin O'Dell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +~~~ + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..fb2c3afc49 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Colin O'Dell +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..7bbcb00cf4 --- /dev/null +++ b/README.md @@ -0,0 +1,85 @@ +# GFM-style task list extension for `league/commonmark` + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-travis]][link-travis] +[![Coverage Status][ico-scrutinizer]][link-scrutinizer] +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] + +This extension adds [GFM-style task list items][link-gfm-spec-task-lists] to the [`league/commonmark` Markdown parser for PHP][link-league-commonmark]. + +## Install + +Via Composer + +``` bash +$ composer require league/commonmark-ext-task-list +``` + +## 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\Ext\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 = <<convertToHtml($markdown); +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + +## Testing + +``` bash +$ composer test +``` + +## Security + +If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. + +## Credits + +- [Colin O'Dell][link-author] +- [All Contributors][link-contributors] + +## License + +This library is licensed under the BSD-3 license. See the [License File](LICENSE) for more information. + +[ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-task-list.svg?style=flat-square +[ico-license]: http://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/thephpleague/commonmark-ext-task-list/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-task-list.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-task-list.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/league/commonmark-ext-task-list.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/league/commonmark-ext-task-list +[link-travis]: https://travis-ci.org/thephpleague/commonmark-ext-task-list +[link-scrutinizer]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-task-list/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-task-list +[link-downloads]: https://packagist.org/packages/league/commonmark-ext-task-list +[link-author]: https://github.com/colinodell +[link-contributors]: ../../contributors +[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/composer.json b/composer.json new file mode 100644 index 0000000000..59ed6bad05 --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "league/commonmark-ext-task-list", + "type": "commonmark-extension", + "description": "Extension for league/commonmark which supports GFM-style task lists", + "keywords": ["markdown", "commonmark", "extension", "github", "gfm", "task", "lists"], + "homepage": "https://github.com/thephpleague/commonmark-ext-task-list", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "require": { + "php" : "^7.1", + "league/commonmark": "^0.19" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\Ext\\TaskList\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "League\\CommonMark\\Ext\\TaskList\\Test\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "0.2-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..c56cba45c3 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + tests + + + + + src/ + + + + + + + diff --git a/src/TaskListExtension.php b/src/TaskListExtension.php new file mode 100644 index 0000000000..a1dd372786 --- /dev/null +++ b/src/TaskListExtension.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\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/src/TaskListItemMarker.php b/src/TaskListItemMarker.php new file mode 100644 index 0000000000..d8e4ceb588 --- /dev/null +++ b/src/TaskListItemMarker.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\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/src/TaskListItemMarkerParser.php b/src/TaskListItemMarkerParser.php new file mode 100644 index 0000000000..f161f790ca --- /dev/null +++ b/src/TaskListItemMarkerParser.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\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('/\[( |x)\]/i'); + if ($m === null) { + return false; + } + + if ($cursor->getNextNonSpaceCharacter() === null) { + $cursor->restoreState($oldState); + + return false; + } + + $isChecked = $m !== '[ ]'; + + $inlineContext->getContainer()->appendChild(new TaskListItemMarker($isChecked)); + + return true; + } +} diff --git a/src/TaskListItemMarkerRenderer.php b/src/TaskListItemMarkerRenderer.php new file mode 100644 index 0000000000..5a29f3acec --- /dev/null +++ b/src/TaskListItemMarkerRenderer.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\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', ['disabled' => '', 'type' => 'checkbox'], '', true); + + if ($inline->isChecked()) { + $checkbox->setAttribute('checked', ''); + } + + return $checkbox; + } +} diff --git a/tests/TaskListTest.php b/tests/TaskListTest.php new file mode 100644 index 0000000000..0626802e21 --- /dev/null +++ b/tests/TaskListTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\Autolink\Test; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\TaskList\TaskListExtension; +use PHPUnit\Framework\TestCase; + +final class TaskListTest extends TestCase +{ + public function testTaskLists() + { + $input = <<<'EOT' +- [x] foo + - [ ] bar + - [X] baz +- [ ] bim + +This works for ordered lists too: + +1. [x] foo +2. [X] bar +3. [ ] baz + +Some examples which should not match: + + - Checkbox [x] in the middle + - Checkbox at the end [ ] + - **[x] Checkbox inside of emphasis** + - No text, as shown in these examples: + - [x] + - [ ] + - [x] + - [x] +EOT; + + $expected = <<<'EOT' +
    +
  • + foo +
      +
    • + bar
    • +
    • + baz
    • +
    +
  • +
  • + bim
  • +
+

This works for ordered lists too:

+
    +
  1. + foo
  2. +
  3. + bar
  4. +
  5. + baz
  6. +
+

Some examples which should not match:

+
    +
  • Checkbox [x] in the middle
  • +
  • Checkbox at the end [ ]
  • +
  • +[x] Checkbox inside of emphasis +
  • +
  • No text, as shown in these examples: +
      +
    • [x]
    • +
    • [ ]
    • +
    • [x]
    • +
    • +
            [x]
      +
      +
    • +
    +
  • +
+ +EOT; + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addExtension(new TaskListExtension()); + + $converter = new CommonMarkConverter([], $environment); + + $this->assertEquals($expected, $converter->convertToHtml($input)); + } +} From a74f918625994262e25b64a05994986b1d1c2242 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 12 May 2019 19:26:08 -0400 Subject: [PATCH 129/231] Expand test coverage --- ...ListTest.php => TaskListExtensionTest.php} | 4 +- tests/TaskListItemMarkerRendererTest.php | 65 +++++++++++++++++++ tests/TaskListItemMarkerTest.php | 27 ++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) rename tests/{TaskListTest.php => TaskListExtensionTest.php} (95%) create mode 100644 tests/TaskListItemMarkerRendererTest.php create mode 100644 tests/TaskListItemMarkerTest.php diff --git a/tests/TaskListTest.php b/tests/TaskListExtensionTest.php similarity index 95% rename from tests/TaskListTest.php rename to tests/TaskListExtensionTest.php index 0626802e21..fceb57dd50 100644 --- a/tests/TaskListTest.php +++ b/tests/TaskListExtensionTest.php @@ -16,7 +16,7 @@ use League\CommonMark\Ext\TaskList\TaskListExtension; use PHPUnit\Framework\TestCase; -final class TaskListTest extends TestCase +final class TaskListExtensionTest extends TestCase { public function testTaskLists() { @@ -36,6 +36,7 @@ public function testTaskLists() - Checkbox [x] in the middle - Checkbox at the end [ ] + - [ ] too many spaces - **[x] Checkbox inside of emphasis** - No text, as shown in these examples: - [x] @@ -71,6 +72,7 @@ public function testTaskLists()
  • Checkbox [x] in the middle
  • Checkbox at the end [ ]
  • +
  • [ ] too many spaces
  • [x] Checkbox inside of emphasis
  • diff --git a/tests/TaskListItemMarkerRendererTest.php b/tests/TaskListItemMarkerRendererTest.php new file mode 100644 index 0000000000..a7ce6ddbe8 --- /dev/null +++ b/tests/TaskListItemMarkerRendererTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\Autolink\Test; + +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Ext\TaskList\TaskListItemMarker; +use League\CommonMark\Ext\TaskList\TaskListItemMarkerRenderer; +use League\CommonMark\HtmlElement; +use League\CommonMark\Inline\Element\AbstractInline; +use PHPUnit\Framework\TestCase; + +class TaskListItemMarkerRendererTest extends TestCase +{ + public function testWithCheckedItem() + { + $renderer = new TaskListItemMarkerRenderer(); + $htmlRenderer = $this->getMockForAbstractClass(ElementRendererInterface::class); + + $item = new TaskListItemMarker(true); + + $result = $renderer->render($item, $htmlRenderer); + + $this->assertInstanceOf(HtmlElement::class, $result); + $this->assertSame('input', $result->getTagName()); + $this->assertSame('checkbox', $result->getAttribute('type')); + $this->assertNotNull($result->getAttribute('checked')); + } + + public function testWithUncheckedItem() + { + $renderer = new TaskListItemMarkerRenderer(); + $htmlRenderer = $this->getMockForAbstractClass(ElementRendererInterface::class); + + $item = new TaskListItemMarker(false); + + $result = $renderer->render($item, $htmlRenderer); + + $this->assertInstanceOf(HtmlElement::class, $result); + $this->assertSame('input', $result->getTagName()); + $this->assertSame('checkbox', $result->getAttribute('type')); + $this->assertNull($result->getAttribute('checked')); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testWithInvalidInlineElement() + { + $renderer = new TaskListItemMarkerRenderer(); + $htmlRenderer = $this->getMockForAbstractClass(ElementRendererInterface::class); + + $item = $this->getMockForAbstractClass(AbstractInline::class); + + $renderer->render($item, $htmlRenderer); + } +} diff --git a/tests/TaskListItemMarkerTest.php b/tests/TaskListItemMarkerTest.php new file mode 100644 index 0000000000..af070788c8 --- /dev/null +++ b/tests/TaskListItemMarkerTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\Autolink\Test; + +use League\CommonMark\Ext\TaskList\TaskListItemMarker; +use PHPUnit\Framework\TestCase; + +final class TaskListItemMarkerTest extends TestCase +{ + public function testIt() + { + $marker = new TaskListItemMarker(true); + $this->assertTrue($marker->isChecked()); + + $marker->setChecked(false); + $this->assertFalse($marker->isChecked()); + } +} From 5ef380260a24b57dc3207e08aa1bb405c95fa628 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 12 May 2019 19:26:48 -0400 Subject: [PATCH 130/231] Release 0.1.0 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 400c9290bc..3066c0ff13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.1.0] - 2019-05-12 + Initial release! [unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/thephpleague/commonmark-ext-task-list/commits/v0.1.0 From bac1b9e6b8faf1b3d94e58152a4d70e30eff0dd7 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 13 May 2019 17:25:53 -0400 Subject: [PATCH 131/231] Configure Stale bot --- .github/stale.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..8cc3396a4b --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - on hold + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From e6d88bd383091966da72b5d7084abef18c8e9950 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 13 May 2019 17:27:02 -0400 Subject: [PATCH 132/231] Configure Stale bot --- .github/stale.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..8cc3396a4b --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - on hold + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 654aabb0022e6d34f819402c54ec1a1c61a88369 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 13 May 2019 17:28:08 -0400 Subject: [PATCH 133/231] Configure Stale bot --- .github/stale.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..8cc3396a4b --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - on hold + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 3a0b6b1038f02e0dda9efc9d8d32feb49a36b656 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 13 May 2019 17:28:45 -0400 Subject: [PATCH 134/231] Configure Stale bot --- .github/stale.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..8cc3396a4b --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - on hold + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 8e4987dacc642920081762bb9ce4873111ddabb7 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 19 May 2019 10:28:50 -0400 Subject: [PATCH 135/231] Initial commit --- .editorconfig | 15 +++ .gitattributes | 13 +++ .github/stale.yml | 18 ++++ .gitignore | 4 + .scrutinizer.yml | 39 +++++++ .styleci.yml | 13 +++ .travis.yml | 24 +++++ CHANGELOG.md | 12 +++ CONDUCT.md | 22 ++++ CONTRIBUTING.md | 48 +++++++++ LICENSE | 29 ++++++ README.md | 151 ++++++++++++++++++++++++++++ composer.json | 41 ++++++++ phpunit.xml.dist | 26 +++++ src/ExternalLinkExtension.php | 23 +++++ src/ExternalLinkProcessor.php | 107 ++++++++++++++++++++ tests/ExternalLinkProcessorTest.php | 94 +++++++++++++++++ 17 files changed, 679 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/stale.yml create mode 100644 .gitignore create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/ExternalLinkExtension.php create mode 100644 src/ExternalLinkProcessor.php create mode 100644 tests/ExternalLinkProcessorTest.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..42120e234c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.styleci.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/scrutinizer.yml export-ignore +/tests/ export-ignore diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..8cc3396a4b --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - on hold + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7aa851fa06 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.idea/ +/build/ +/composer.lock +/vendor/ diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000000..a2baf35af7 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: + enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000000..af9054cd43 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,13 @@ +preset: recommended + +enabled: + - concat_with_spaces + - no_useless_else + - strict + +disabled: + - concat_without_spaces + - no_trailing_comma_in_list_call + - phpdoc_summary + - post_increment + - self_accessor diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..35297f5ce4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: php + +php: + - 7.1 + - 7.2 + - 7.3 + +env: + matrix: + - COMPOSER_FLAGS="" + - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + +sudo: false + +before_script: + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + +script: + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + +after_script: + - wget https://github.com/scrutinizer-ci/ocular/releases/download/1.5.2/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..011cde7270 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# 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] + +Initial release! + +[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000000..6ff94ca3a4 --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..58ebd9b89c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/thephpleague/commonmark-ext-external-link). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Adhere to the spec!** - Any changes should align with the (official GFM spec)[https://github.github.com/gfm/] + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +- **Docblocks** - All files should start with the following docblock: + +~~~ +/* + * This file is part of the league/commonmark-ext-external-link package. + * + * (c) Colin O'Dell + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +~~~ + +The "Authored by" line is optional. + + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..fb2c3afc49 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Colin O'Dell +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..04a996bbd2 --- /dev/null +++ b/README.md @@ -0,0 +1,151 @@ +# Extension to denote external links for `league/commonmark` + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-travis]][link-travis] +[![Coverage Status][ico-scrutinizer]][link-scrutinizer] +[![Quality Score][ico-code-quality]][link-code-quality] +[![Total Downloads][ico-downloads]][link-downloads] + +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 + +## Install + +Via Composer + +``` bash +$ composer require league/commonmark-ext-external-link +``` + +## 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\Ext\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-ext-external-link extension!'); +``` + +## Configuration + +This extension supports three configuration options under the `external_link` configuration: + +### `internal_hosts` + +This option defines a whitelist of hosts which are considered non-external and should not receive the external link treatment. + +This can be a single host name, like `'example.com'`, which must match exactly. + +If you need to match subdomains, use a regular expression like `'/(^|\.)example\.com$/'`. Note that you must use `/` characters to delimit your regex. + +This configuration option also accepts an array of multiple strings and/or regexes: + +```php +$config = [ + 'external_link' => [ + 'internal_hosts' => ['foo.example.com', 'bar.example.com', '/(^|\.)google\.com$/], + ], +]; +``` + +By default, if this option is not provided, all links will be considered external. + +### `open_in_new_window` + +This option (which defaults to `false`) determines whether any external links should open in a new tab/window. + +### `html_class` + +This option allows you to provide a `string` containing one or more HTML classes that should be added to the external link `` tags: No classes are added by default. + +## Advanced Rendering + +When an external link is detected, the `ExternalLinkProcessor` will set the `external` data option on the `Link` node to either `true` or `false`. You can therefore create a [custom link renderer](https://commonmark.thephpleague.com/customization/inline-rendering/) which checks this value and behaves accordingly: + +```php +class MyCustomLinkRenderer implements InlineRendererInterface +{ + + /** + * @param Link $inline + * @param ElementRendererInterface $htmlRenderer + * + * @return HtmlElement + */ + public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) + { + if (!($inline instanceof Link)) { + throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline)); + } + + if ($inline->getData('external')) { + // This is an external link - render it accordingly + } else { + // This is an internal link + } + + // ... + } +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + +## Testing + +``` bash +$ composer test +``` + +## Security + +If you discover any security related issues, please email colinodell@gmail.com instead of using the issue tracker. + +## Credits + +- [Colin O'Dell][link-author] +- [All Contributors][link-contributors] + +## License + +This library is licensed under the BSD-3 license. See the [License File](LICENSE) for more information. + +[ico-version]: https://img.shields.io/packagist/v/league/commonmark-ext-external-link.svg?style=flat-square +[ico-license]: http://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/thephpleague/commonmark-ext-external-link/master.svg?style=flat-square +[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-external-link.svg?style=flat-square +[ico-code-quality]: https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-external-link.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/league/commonmark-ext-external-link.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/league/commonmark-ext-external-link +[link-travis]: https://travis-ci.org/thephpleague/commonmark-ext-external-link +[link-scrutinizer]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-external-link/code-structure +[link-code-quality]: https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-external-link +[link-downloads]: https://packagist.org/packages/league/commonmark-ext-external-link +[link-author]: https://github.com/colinodell +[link-contributors]: ../../contributors +[link-league-commonmark]: https://github.com/thephpleague/commonmark diff --git a/composer.json b/composer.json new file mode 100644 index 0000000000..76691cd66e --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "league/commonmark-ext-external-link", + "type": "commonmark-extension", + "description": "Extension for league/commonmark which adds extra classes and HTML attributes to external links", + "keywords": ["markdown", "commonmark", "extension", "links"], + "homepage": "https://github.com/thephpleague/commonmark-ext-external-link", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "require": { + "php" : "^7.1", + "league/commonmark": "^0.19.2" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\Ext\\ExternalLink\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "League\\CommonMark\\Ext\\ExternalLink\\Test\\": "tests" + } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "0.4-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..cda047abcc --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,26 @@ + + + + + tests + + + + + src/ + + + + + + + diff --git a/src/ExternalLinkExtension.php b/src/ExternalLinkExtension.php new file mode 100644 index 0000000000..6231129701 --- /dev/null +++ b/src/ExternalLinkExtension.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\ExternalLink; + +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; + +final class ExternalLinkExtension implements ExtensionInterface +{ + public function register(ConfigurableEnvironmentInterface $environment) + { + $environment->addDocumentProcessor(new ExternalLinkProcessor()); + } +} diff --git a/src/ExternalLinkProcessor.php b/src/ExternalLinkProcessor.php new file mode 100644 index 0000000000..6a953a21e7 --- /dev/null +++ b/src/ExternalLinkProcessor.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\ExternalLink; + +use League\CommonMark\Block\Element\Document; +use League\CommonMark\DocumentProcessorInterface; +use League\CommonMark\Inline\Element\Link; +use League\CommonMark\Util\Configuration; +use League\CommonMark\Util\ConfigurationAwareInterface; + +final class ExternalLinkProcessor implements DocumentProcessorInterface, ConfigurationAwareInterface +{ + /** @var Configuration */ + private $configuration; + + /** + * {@inheritdoc} + */ + public function setConfiguration(Configuration $configuration) + { + $this->configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + public function processDocument(Document $document) + { + $internalHosts = $this->configuration->getConfig('external_link/internal_hosts', []); + $openInNewWindow = $this->configuration->getConfig('external_link/open_in_new_window', false); + $classes = $this->configuration->getConfig('external_link/html_class', ''); + + $walker = $document->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/tests/ExternalLinkProcessorTest.php b/tests/ExternalLinkProcessorTest.php new file mode 100644 index 0000000000..07ca915052 --- /dev/null +++ b/tests/ExternalLinkProcessorTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace League\CommonMark\Ext\ExternalLink\Test\Email; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\ExternalLink\ExternalLinkExtension; +use League\CommonMark\Ext\ExternalLink\ExternalLinkProcessor; +use PHPUnit\Framework\TestCase; + +final class ExternalLinkProcessorTest extends TestCase +{ + private const INPUT = 'My favorite sites are and '; + + public function testDefaultConfiguration() + { + $expected = '

    My favorite sites are https://www.colinodell.com and https://commonmark.thephpleague.com

    ' . "\n"; + + $this->assertEquals($expected, $this->parse(self::INPUT)); + } + + public function testCustomConfiguration() + { + $expected = '

    My favorite sites are https://www.colinodell.com and https://commonmark.thephpleague.com

    ' . "\n"; + + $config = [ + 'external_link' => [ + 'internal_hosts' => ['commonmark.thephpleague.com'], + 'open_in_new_window' => true, + 'html_class' => 'external-link', + ] + ]; + + $this->assertEquals($expected, $this->parse(self::INPUT, $config)); + } + + public function testWithBadUrls() + { + $input = 'Report [xss](javascript:alert(0);) vulnerabilities by emailing '; + + $expected = '

    Report xss vulnerabilities by emailing colinodell@gmail.com

    ' . "\n"; + + $this->assertEquals($expected, $this->parse($input)); + } + + private function parse(string $markdown, array $config = []) + { + $e = Environment::createCommonMarkEnvironment(); + $e->addExtension(new ExternalLinkExtension()); + + $c = new CommonMarkConverter($config, $e); + + return $c->convertToHtml($markdown); + } + + /** + * @param string $host + * @param mixed $compareTo + * @param bool $expected + * + * @dataProvider dataProviderForTestHostMatches + */ + public function testHostMatches(string $host, $compareTo, bool $expected) + { + $this->assertEquals($expected, ExternalLinkProcessor::hostMatches($host, $compareTo)); + } + + public function dataProviderForTestHostMatches() + { + // String-to-string comparison must match exactly + yield ['colinodell.com', 'commonmark.thephpleague.com', false]; + yield ['colinodell.com', 'colinodell.com', true]; + + // Subdomains won't match unless using regex + yield ['www.colinodell.com', 'colinodell.com', false]; + yield ['www.colinodell.com', '/colinodell\.com/', true]; + + // Multiple strings can be checked + yield ['www.colinodell.com', ['www.colinodell.com', 'commonmark.thephpleague.com'], true]; + yield ['www.colinodell.com', ['google.com', 'aol.com'], false]; + + // You can even mix-and-match multiple strings with multiple regexes + yield ['www.colinodell.com', ['/colinodell\.com/', 'aol.com'], true]; + } +} From 6b36fa6ed8e37227f6bd811f9169e57c296117e1 Mon Sep 17 00:00:00 2001 From: colinodell Date: Sun, 19 May 2019 14:33:39 +0000 Subject: [PATCH 136/231] Apply fixes from StyleCI --- tests/ExternalLinkProcessorTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ExternalLinkProcessorTest.php b/tests/ExternalLinkProcessorTest.php index 07ca915052..3cbcc9b6c5 100644 --- a/tests/ExternalLinkProcessorTest.php +++ b/tests/ExternalLinkProcessorTest.php @@ -34,10 +34,10 @@ public function testCustomConfiguration() $config = [ 'external_link' => [ - 'internal_hosts' => ['commonmark.thephpleague.com'], + 'internal_hosts' => ['commonmark.thephpleague.com'], 'open_in_new_window' => true, - 'html_class' => 'external-link', - ] + 'html_class' => 'external-link', + ], ]; $this->assertEquals($expected, $this->parse(self::INPUT, $config)); From 92209d52fd53d09ca286c0fbb1669aa5a553e6e2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 19 May 2019 10:40:19 -0400 Subject: [PATCH 137/231] Fix code example --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 04a996bbd2..65e6a9a8c8 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ class MyCustomLinkRenderer implements InlineRendererInterface // ... } +} ``` ## Changelog From 3e9fd6f2773f2f0417624cfbf791fabe06cb84fe Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 19 May 2019 10:40:33 -0400 Subject: [PATCH 138/231] Release 0.1.0 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 011cde7270..97f38b9f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.1.0] - 2019-05-19 + Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link +[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/thephpleague/commonmark-ext-external-link/commits/v0.1.0 From fca95e5f9cb946e8fe89eb50db34b472ed7b624f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 19 May 2019 10:41:44 -0400 Subject: [PATCH 139/231] Fix branch alias --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 76691cd66e..2a3b41eabf 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "0.2-dev" } } } From 0bfc2f6bf402a83363da92b68efc4bbaa8714356 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 May 2019 08:35:46 -0400 Subject: [PATCH 140/231] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..09cdff5dac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: colinodell From bf2958e0335fa703df6a7e7dec61a0a7e2154321 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 May 2019 08:36:08 -0400 Subject: [PATCH 141/231] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..09cdff5dac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: colinodell From 7440862f03848fe23d421703a9796bcda1d37b5a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 May 2019 08:36:49 -0400 Subject: [PATCH 142/231] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..09cdff5dac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: colinodell From d0c235cb8bc338d69b82956985b1eb38b540ba22 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 May 2019 08:37:29 -0400 Subject: [PATCH 143/231] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..09cdff5dac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: colinodell From 7289cdce8d403f3900561e8ffa6053f29014ed2a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 May 2019 08:38:16 -0400 Subject: [PATCH 144/231] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..09cdff5dac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: colinodell From a88c94654e3b728d29c60a85634e83451f95c547 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 May 2019 08:38:34 -0400 Subject: [PATCH 145/231] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..09cdff5dac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: colinodell From 45070bcf9a6fa70abb7194f152e02a76a63ed9fa Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 10:55:56 -0400 Subject: [PATCH 146/231] Mark as compatible with league/commonmark 1.0.0-beta1 --- CHANGELOG.md | 9 ++++++++- composer.json | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bcb419456..9322c24fdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta1] - 2019-05-27 + +### Changed + + - Marked extension as compatible with `league/commonmark` 1.0.0-beta1 + ## [0.3.0] - 2019-04-10 ### Changed @@ -41,7 +47,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta1...HEAD +[1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...v1.0.0-beta1 [0.3.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...v0.2.0 diff --git a/composer.json b/composer.json index 7a9e050373..dd25cbd27d 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19" + "league/commonmark": "^0.19 || ^1.0-beta" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "1.0-dev" } } } From d24e66e1d2b5fc3eba6458306121f685cfb481ff Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 11:09:05 -0400 Subject: [PATCH 147/231] Make compatible with league/commonmark 1.0.0-beta1 --- CHANGELOG.md | 9 ++++++++- composer.json | 4 ++-- src/InlinesOnlyExtension.php | 12 ++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5969b515ee..42fbfb218f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes will be documented in this file. ## [Unreleased][unreleased] +## [1.0.0-beta1] - 2019-05-27 + +## Changed + + - Made compatible with `league/commonmark` 1.0.0-beta1 + ## [0.2.0] - 2019-04-10 ### Changed @@ -14,5 +20,6 @@ All notable changes will be documented in this file. Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.2.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v1.0.0-beta1...HEAD +[1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.2.0...v1.0.0-beta1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.1.0...v0.2.0 diff --git a/composer.json b/composer.json index d8c17a55f4..7619c3bcd4 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19" + "league/commonmark": "^1.0-beta" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.3-dev" + "dev-master": "1.0-dev" } } } diff --git a/src/InlinesOnlyExtension.php b/src/InlinesOnlyExtension.php index 9159f6e3e5..4b21979aa9 100644 --- a/src/InlinesOnlyExtension.php +++ b/src/InlinesOnlyExtension.php @@ -18,10 +18,10 @@ 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\Processor as InlineProcessor; use League\CommonMark\Inline\Renderer as InlineRenderer; final class InlinesOnlyExtension implements ExtensionInterface @@ -37,15 +37,12 @@ public function register(ConfigurableEnvironmentInterface $environment) ->addInlineParser(new InlineParser\BacktickParser(), 150) ->addInlineParser(new InlineParser\EscapableParser(), 80) ->addInlineParser(new InlineParser\EntityParser(), 70) - ->addInlineParser(new InlineParser\EmphasisParser(), 60) ->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) - ->addInlineProcessor(new InlineProcessor\EmphasisProcessor(), 0) - ->addBlockRenderer(Document::class, $childRenderer, 0) ->addBlockRenderer(Paragraph::class, $childRenderer, 0) @@ -58,5 +55,12 @@ public function register(ConfigurableEnvironmentInterface $environment) ->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('_')); + } } } From d6c904ac5657f67ab951e6aeeb7ed37c07c75883 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 11:12:26 -0400 Subject: [PATCH 148/231] Fix changelog header --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42fbfb218f..0300a6acb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes will be documented in this file. ## [1.0.0-beta1] - 2019-05-27 -## Changed +### Changed - Made compatible with `league/commonmark` 1.0.0-beta1 From 11b414730dc13603379dff548b74cb4b38fc37cc Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 13:42:39 -0400 Subject: [PATCH 149/231] Make compatible with league/commonmark 1.0.0-beta2 --- CHANGELOG.md | 9 ++- composer.json | 4 +- src/Quote.php | 28 +++++++++ src/QuoteParser.php | 29 +++++----- src/QuoteProcessor.php | 108 +++++++++++++++++++++++++++-------- src/QuoteRenderer.php | 47 +++++++++++++++ src/SmartPunctExtension.php | 4 +- tests/QuoteProcessorTest.php | 66 +++++++++++++++++++++ tests/QuoteRendererTest.php | 75 ++++++++++++++++++++++++ 9 files changed, 330 insertions(+), 40 deletions(-) create mode 100644 src/Quote.php create mode 100644 src/QuoteRenderer.php create mode 100644 tests/QuoteProcessorTest.php create mode 100644 tests/QuoteRendererTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 77377d203e..1cc1c2270e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta1] - 2019-05-27 + +### Changed + + - Made extension compatible with `league/commonmark` 1.0.0-beta2 + ## [0.2.0] - 2019-04-10 ### Changed @@ -17,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Split this extension out of the old `league/commonmark-extras` library. -[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.2.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta1...HEAD +[1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.2.0...v1.0.0-beta1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/commits/v0.1.0 diff --git a/composer.json b/composer.json index 97f9354f9a..fa2954cdcf 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19" + "league/commonmark": "^1.0.0-beta2" }, "require-dev": { "jgm/smartpunct": "0.29", @@ -49,7 +49,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.3-dev" + "dev-master": "1.0-dev" } } } diff --git a/src/Quote.php b/src/Quote.php new file mode 100644 index 0000000000..1d86759a3f --- /dev/null +++ b/src/Quote.php @@ -0,0 +1,28 @@ + + * + * 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\Ext\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/src/QuoteParser.php b/src/QuoteParser.php index 019c177720..e3af51b877 100644 --- a/src/QuoteParser.php +++ b/src/QuoteParser.php @@ -15,25 +15,26 @@ namespace League\CommonMark\Ext\SmartPunct; use League\CommonMark\Delimiter\Delimiter; -use League\CommonMark\Inline\Element\Text; use League\CommonMark\Inline\Parser\InlineParserInterface; use League\CommonMark\InlineParserContext; use League\CommonMark\Util\RegexHelper; -class QuoteParser implements InlineParserInterface +final class QuoteParser implements InlineParserInterface { - protected $double = ['"', '“', '”']; - protected $single = ["'", '‘', '’']; + 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($this->double, $this->single); + 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 @@ -41,7 +42,7 @@ public function getCharacters(): array public function parse(InlineParserContext $inlineContext): bool { $cursor = $inlineContext->getCursor(); - $character = $this->getCharacterType($cursor->getCharacter()); + $normalizedCharacter = $this->getNormalizedQuoteCharacter($cursor->getCharacter()); $charBefore = $cursor->peek(-1); if ($charBefore === null) { @@ -59,11 +60,11 @@ public function parse(InlineParserContext $inlineContext): bool $canOpen = $leftFlanking && !$rightFlanking; $canClose = $rightFlanking; - $node = new Text($character, ['delim' => true]); + $node = new Quote($normalizedCharacter, ['delim' => true]); $inlineContext->getContainer()->appendChild($node); // Add entry to stack to this opener - $inlineContext->getDelimiterStack()->push(new Delimiter($character, 1, $node, $canOpen, $canClose)); + $inlineContext->getDelimiterStack()->push(new Delimiter($normalizedCharacter, 1, $node, $canOpen, $canClose)); return true; } @@ -73,13 +74,15 @@ public function parse(InlineParserContext $inlineContext): bool * * @return string|null */ - private function getCharacterType($character) + private function getNormalizedQuoteCharacter($character) { - if (in_array($character, $this->double)) { - return '“'; - } elseif (in_array($character, $this->single)) { - return '’'; + if (in_array($character, self::DOUBLE_QUOTES)) { + return Quote::DOUBLE_QUOTE; + } elseif (in_array($character, self::SINGLE_QUOTES)) { + return Quote::SINGLE_QUOTE; } + + return $character; } /** diff --git a/src/QuoteProcessor.php b/src/QuoteProcessor.php index 03e031e3f6..646123330d 100644 --- a/src/QuoteProcessor.php +++ b/src/QuoteProcessor.php @@ -15,30 +15,92 @@ namespace League\CommonMark\Ext\SmartPunct; use League\CommonMark\Delimiter\Delimiter; -use League\CommonMark\Delimiter\DelimiterStack; -use League\CommonMark\Inline\Processor\InlineProcessorInterface; +use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; +use League\CommonMark\Inline\Element\AbstractStringContainer; -class QuoteProcessor implements InlineProcessorInterface +final class QuoteProcessor implements DelimiterProcessorInterface { - public function processInlines(DelimiterStack $delimiterStack, Delimiter $stackBottom = null) - { - $callback = function (Delimiter $opener, Delimiter $closer) { - // Open quote - $openerInline = $opener->getInlineNode(); - $openerInline->setContent( - $openerInline->getContent() === '“' ? '“' : '‘' - ); - - // Close quote - $closerInline = $closer->getInlineNode(); - $closerInline->setContent( - $closerInline->getContent() === '“' ? '”' : '’' - ); - - return $closer->getNext(); - }; - - // Process the emphasis characters - $delimiterStack->iterateByCharacters(['“', '’'], $callback, $stackBottom); + /** @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(Delimiter $opener, Delimiter $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 + * + * @return QuoteProcessor + */ + public static function createDoubleQuoteProcessor(): self + { + return new self(Quote::DOUBLE_QUOTE, Quote::DOUBLE_QUOTE_OPENER, Quote::DOUBLE_QUOTE_CLOSER); + } + + /** + * Create a single-quote processor + * + * @return QuoteProcessor + */ + public static function createSingleQuoteProcessor(): self + { + return new self(Quote::SINGLE_QUOTE, Quote::SINGLE_QUOTE_OPENER, Quote::SINGLE_QUOTE_CLOSER); } } diff --git a/src/QuoteRenderer.php b/src/QuoteRenderer.php new file mode 100644 index 0000000000..c8f91d3d58 --- /dev/null +++ b/src/QuoteRenderer.php @@ -0,0 +1,47 @@ + + * + * 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\Ext\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/src/SmartPunctExtension.php b/src/SmartPunctExtension.php index a2e222181d..97a6b8f1e2 100644 --- a/src/SmartPunctExtension.php +++ b/src/SmartPunctExtension.php @@ -30,11 +30,13 @@ public function register(ConfigurableEnvironmentInterface $environment) ->addInlineParser(new QuoteParser(), 10) ->addInlineParser(new PunctuationParser(), 0) - ->addInlineProcessor(new QuoteProcessor(), 10) + ->addDelimiterProcessor(QuoteProcessor::createDoubleQuoteProcessor()) + ->addDelimiterProcessor(QuoteProcessor::createSingleQuoteProcessor()) ->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/tests/QuoteProcessorTest.php b/tests/QuoteProcessorTest.php new file mode 100644 index 0000000000..93f8886ea3 --- /dev/null +++ b/tests/QuoteProcessorTest.php @@ -0,0 +1,66 @@ + + * + * 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\Ext\SmartPunct\Tests; + +use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Ext\SmartPunct\QuoteProcessor; +use League\CommonMark\Inline\Element\Text; +use PHPUnit\Framework\TestCase; + +/** + * Tests the quote processor + */ +final class QuoteProcessorTest extends TestCase +{ + public function testSingleQuoteProcessor() + { + $mockDelimiter = $this->createMock(Delimiter::class); + + $processor = QuoteProcessor::createSingleQuoteProcessor(); + + $this->assertEquals("'", $processor->getOpeningCharacter()); + $this->assertEquals("'", $processor->getClosingCharacter()); + $this->assertEquals(1, $processor->getMinLength()); + $this->assertEquals(1, $processor->getDelimiterUse($mockDelimiter, $mockDelimiter)); + + $opener = new Text(); + $closer = new Text(); + + $processor->process($opener, $closer, 1); + + $this->assertEquals('‘', $opener->next()->getContent()); + $this->assertEquals('’', $closer->previous()->getContent()); + } + + public function testDoubleQuoteProcessor() + { + $mockDelimiter = $this->createMock(Delimiter::class); + + $processor = QuoteProcessor::createDoubleQuoteProcessor(); + + $this->assertEquals('"', $processor->getOpeningCharacter()); + $this->assertEquals('"', $processor->getClosingCharacter()); + $this->assertEquals(1, $processor->getMinLength()); + $this->assertEquals(1, $processor->getDelimiterUse($mockDelimiter, $mockDelimiter)); + + $opener = new Text(); + $closer = new Text(); + + $processor->process($opener, $closer, 1); + + $this->assertEquals('“', $opener->next()->getContent()); + $this->assertEquals('”', $closer->previous()->getContent()); + } +} diff --git a/tests/QuoteRendererTest.php b/tests/QuoteRendererTest.php new file mode 100644 index 0000000000..18d5930248 --- /dev/null +++ b/tests/QuoteRendererTest.php @@ -0,0 +1,75 @@ + + * + * 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\Ext\SmartPunct\Tests; + +use League\CommonMark\ElementRendererInterface; +use League\CommonMark\Ext\SmartPunct\Quote; +use League\CommonMark\Ext\SmartPunct\QuoteRenderer; +use League\CommonMark\Inline\Element\Text; +use PHPUnit\Framework\TestCase; + +/** + * Tests the quote renderer + */ +final class QuoteRendererTest extends TestCase +{ + /** @var QuoteRenderer */ + private $renderer; + + /** @var ElementRendererInterface */ + private $htmlRenderer; + + protected function setUp() + { + $this->renderer = new QuoteRenderer(); + $this->htmlRenderer = $this->createMock(ElementRendererInterface::class); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidInlineType() + { + $inline = $this->createMock(Text::class); + + $this->renderer->render($inline, $this->htmlRenderer); + } + + /** + * @param string $character + * @param string $expected + * + * @dataProvider dataForTestRender + */ + public function testRender(string $character, string $expected) + { + $inline = new Quote($character); + + $this->assertEquals($expected, $this->renderer->render($inline, $this->htmlRenderer)); + } + + public function dataForTestRender() + { + // Single-quotes should render as an apostrophe + yield ["'", "’"]; + + // Double-quotes should render as an opening quote + yield ['"', '“']; + + // Already-stylized quotes should be rendered as-is + yield ["’", "’"]; + yield ['“', '“']; + } +} From 674a3558e63bab0114527152b59c741a2fb00e7a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 13:55:56 -0400 Subject: [PATCH 150/231] Fix code style --- tests/QuoteRendererTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/QuoteRendererTest.php b/tests/QuoteRendererTest.php index 18d5930248..dc1135fead 100644 --- a/tests/QuoteRendererTest.php +++ b/tests/QuoteRendererTest.php @@ -63,13 +63,13 @@ public function testRender(string $character, string $expected) public function dataForTestRender() { // Single-quotes should render as an apostrophe - yield ["'", "’"]; + yield ["'", '’']; // Double-quotes should render as an opening quote yield ['"', '“']; // Already-stylized quotes should be rendered as-is - yield ["’", "’"]; + yield ['’', '’']; yield ['“', '“']; } } From fc20398498eddbfb95059696e849c3670ebb9ac2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 14:25:45 -0400 Subject: [PATCH 151/231] Make compatible with league/commonmark 1.0.0-beta2 --- composer.json | 4 ++-- src/StrikethroughDelimiterProcessor.php | 5 +++-- tests/StrikethroughTest.php | 25 +++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 tests/StrikethroughTest.php diff --git a/composer.json b/composer.json index 50ca2724bc..2514685276 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1", "ext-mbstring": "*", - "league/commonmark": "0.20.x-dev" + "league/commonmark": "^1.0.0-beta2" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -41,7 +41,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.5-dev" + "dev-master": "1.0-dev" } } } diff --git a/src/StrikethroughDelimiterProcessor.php b/src/StrikethroughDelimiterProcessor.php index 2e5e54a1dd..98e1fef096 100644 --- a/src/StrikethroughDelimiterProcessor.php +++ b/src/StrikethroughDelimiterProcessor.php @@ -13,7 +13,7 @@ use League\CommonMark\Delimiter\Delimiter; use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; -use League\CommonMark\Inline\Element\Text; +use League\CommonMark\Inline\Element\AbstractStringContainer; final class StrikethroughDelimiterProcessor implements DelimiterProcessorInterface { @@ -24,6 +24,7 @@ public function getOpeningCharacter(): string { return '~'; } + /** * {@inheritdoc} */ @@ -53,7 +54,7 @@ public function getDelimiterUse(Delimiter $opener, Delimiter $closer): int /** * {@inheritdoc} */ - public function process(Text $opener, Text $closer, int $delimiterUse) + public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse) { $strikethrough = new Strikethrough(); diff --git a/tests/StrikethroughTest.php b/tests/StrikethroughTest.php new file mode 100644 index 0000000000..2beb7d5de9 --- /dev/null +++ b/tests/StrikethroughTest.php @@ -0,0 +1,25 @@ + 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\Ext\Strikethrough\Test; + +use League\CommonMark\Ext\Strikethrough\Strikethrough; +use PHPUnit\Framework\TestCase; + +final class StrikethroughTest extends TestCase +{ + public function testIsContainer() + { + $s = new Strikethrough(); + + $this->assertTrue($s->isContainer()); + } +} From 62d731520ade5920e3781f02ae2e97dc3f899bf2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 14:52:53 -0400 Subject: [PATCH 152/231] Release 1.0.0-beta1 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7145109016..e304e39bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta1] - 2019-05-27 + ### Changed - Updated to the next version of `league/commonmark` @@ -42,7 +44,8 @@ These older releases come from the original `uafrica/commonmark-ext` library. - Updated to `league/commonmark` v0.17 -[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.4.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta1...HEAD +[1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.4.0...v1.0.0-beta1 [0.4.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.1.1...v0.2.0 From d2d2b375bb2203788a4a199e5b88f4a99bf512fa Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 14:57:32 -0400 Subject: [PATCH 153/231] Make compatible with league/commonmark 1.0.0-beta1 --- CHANGELOG.md | 9 ++++++++- composer.json | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3066c0ff13..a04c292b49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta1] - 2019-05-27 + +### Changed + + - Added support for `league/commonmark` 1.0.0-beta1 + ## [0.1.0] - 2019-05-12 Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v0.1.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0-beta1...HEAD +[1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v0.1.0...v1.0.0-beta1 [0.1.0]: https://github.com/thephpleague/commonmark-ext-task-list/commits/v0.1.0 diff --git a/composer.json b/composer.json index 59ed6bad05..f0ba8543de 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19" + "league/commonmark": "^0.19|^1.0.0-beta1" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "1.0-dev" } } } From 30386b859a7b503e244b2478a04ae4f6d37a920e Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 21:00:48 -0400 Subject: [PATCH 154/231] Make compatible with league/commonmark 1.0.0-beta3 --- CHANGELOG.md | 9 ++++++++- composer.json | 2 +- src/QuoteProcessor.php | 4 ++-- tests/QuoteProcessorTest.php | 6 +++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cc1c2270e..e0670f298a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta2] - 2019-05-27 + +### Changed + + - Made extension compatible with `league/commonmark` 1.0.0-beta3 + ## [1.0.0-beta1] - 2019-05-27 ### Changed @@ -23,7 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Split this extension out of the old `league/commonmark-extras` library. -[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta2...HEAD +[1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.2.0...v1.0.0-beta1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/commits/v0.1.0 diff --git a/composer.json b/composer.json index fa2954cdcf..e62d23cafc 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^1.0.0-beta2" + "league/commonmark": "^1.0.0-beta3" }, "require-dev": { "jgm/smartpunct": "0.29", diff --git a/src/QuoteProcessor.php b/src/QuoteProcessor.php index 646123330d..d4202977c8 100644 --- a/src/QuoteProcessor.php +++ b/src/QuoteProcessor.php @@ -14,7 +14,7 @@ namespace League\CommonMark\Ext\SmartPunct; -use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Delimiter\DelimiterInterface; use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; use League\CommonMark\Inline\Element\AbstractStringContainer; @@ -70,7 +70,7 @@ public function getMinLength(): int /** * {@inheritdoc} */ - public function getDelimiterUse(Delimiter $opener, Delimiter $closer): int + public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int { return 1; } diff --git a/tests/QuoteProcessorTest.php b/tests/QuoteProcessorTest.php index 93f8886ea3..cb7ea74d37 100644 --- a/tests/QuoteProcessorTest.php +++ b/tests/QuoteProcessorTest.php @@ -14,7 +14,7 @@ namespace League\CommonMark\Ext\SmartPunct\Tests; -use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Delimiter\DelimiterInterface; use League\CommonMark\Ext\SmartPunct\QuoteProcessor; use League\CommonMark\Inline\Element\Text; use PHPUnit\Framework\TestCase; @@ -26,7 +26,7 @@ final class QuoteProcessorTest extends TestCase { public function testSingleQuoteProcessor() { - $mockDelimiter = $this->createMock(Delimiter::class); + $mockDelimiter = $this->createMock(DelimiterInterface::class); $processor = QuoteProcessor::createSingleQuoteProcessor(); @@ -46,7 +46,7 @@ public function testSingleQuoteProcessor() public function testDoubleQuoteProcessor() { - $mockDelimiter = $this->createMock(Delimiter::class); + $mockDelimiter = $this->createMock(DelimiterInterface::class); $processor = QuoteProcessor::createDoubleQuoteProcessor(); From 53bd6ba80beccb672dc293c10c7d03d1d037699c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 27 May 2019 21:05:15 -0400 Subject: [PATCH 155/231] Make compatible with league/commonmark 1.0.0-beta3 --- CHANGELOG.md | 9 ++++++++- composer.json | 2 +- src/StrikethroughDelimiterProcessor.php | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e304e39bbc..c0c81909da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta2] - 2019-05-27 + +### Changed + + - Updated extension to work with `league/commonmark` 1.0.0-beta3 + ## [1.0.0-beta1] - 2019-05-27 ### Changed @@ -44,7 +50,8 @@ These older releases come from the original `uafrica/commonmark-ext` library. - Updated to `league/commonmark` v0.17 -[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta2...HEAD +[1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.4.0...v1.0.0-beta1 [0.4.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.2.0...v0.3.0 diff --git a/composer.json b/composer.json index 2514685276..19e7b3273a 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1", "ext-mbstring": "*", - "league/commonmark": "^1.0.0-beta2" + "league/commonmark": "^1.0.0-beta3" }, "require-dev": { "phpunit/phpunit": "^7.5" diff --git a/src/StrikethroughDelimiterProcessor.php b/src/StrikethroughDelimiterProcessor.php index 98e1fef096..431f4d9b22 100644 --- a/src/StrikethroughDelimiterProcessor.php +++ b/src/StrikethroughDelimiterProcessor.php @@ -11,7 +11,7 @@ namespace League\CommonMark\Ext\Strikethrough; -use League\CommonMark\Delimiter\Delimiter; +use League\CommonMark\Delimiter\DelimiterInterface; use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface; use League\CommonMark\Inline\Element\AbstractStringContainer; @@ -44,9 +44,9 @@ public function getMinLength(): int /** * {@inheritdoc} */ - public function getDelimiterUse(Delimiter $opener, Delimiter $closer): int + public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int { - $min = \min($opener->getNumDelims(), $closer->getNumDelims()); + $min = \min($opener->getLength(), $closer->getLength()); return $min >= 2 ? $min : 0; } From de2ce9f47b394ba79688d2b40f461e8168b5b3ed Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 5 Jun 2019 17:54:16 -0400 Subject: [PATCH 156/231] Make compatible with league/commonmark 1.0.0-beta4 --- CHANGELOG.md | 9 ++++++++- composer.json | 2 +- src/AutolinkExtension.php | 5 +++-- src/EmailAutolinkProcessor.php | 11 +++++------ src/UrlAutolinkProcessor.php | 11 +++++------ 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9322c24fdd..4bbf248c9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta2] - 2019-06-05 + +### Changed + + - Made extension compatible with `league/commonmark` 1.0.0-beta4 + ## [1.0.0-beta1] - 2019-05-27 ### Changed @@ -47,7 +53,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta2...HEAD +[1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...v1.0.0-beta1 [0.3.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...v0.2.1 diff --git a/composer.json b/composer.json index dd25cbd27d..d9e0b6eb3a 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19 || ^1.0-beta" + "league/commonmark": "^1.0.0-beta4" }, "require-dev": { "phpunit/phpunit": "^7.5" diff --git a/src/AutolinkExtension.php b/src/AutolinkExtension.php index e0330487fb..234795afc3 100644 --- a/src/AutolinkExtension.php +++ b/src/AutolinkExtension.php @@ -12,13 +12,14 @@ namespace League\CommonMark\Ext\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->addDocumentProcessor(new EmailAutolinkProcessor()); - $environment->addDocumentProcessor(new UrlAutolinkProcessor()); + $environment->addEventListener(DocumentParsedEvent::class, new EmailAutolinkProcessor()); + $environment->addEventListener(DocumentParsedEvent::class, new UrlAutolinkProcessor()); } } diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index f4d436c8a5..9651a4b038 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -11,23 +11,22 @@ namespace League\CommonMark\Ext\Autolink; -use League\CommonMark\Block\Element\Document; -use League\CommonMark\DocumentProcessorInterface; +use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Inline\Element\Link; use League\CommonMark\Inline\Element\Text; -final class EmailAutolinkProcessor implements DocumentProcessorInterface +final class EmailAutolinkProcessor { const REGEX = '/([A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+)/'; /** - * @param Document $document + * @param DocumentParsedEvent $e * * @return void */ - public function processDocument(Document $document) + public function __invoke(DocumentParsedEvent $e) { - $walker = $document->walker(); + $walker = $e->getDocument()->walker(); while ($event = $walker->next()) { if ($event->getNode() instanceof Text) { diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 4fb4097689..2bde6be610 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -11,12 +11,11 @@ namespace League\CommonMark\Ext\Autolink; -use League\CommonMark\Block\Element\Document; -use League\CommonMark\DocumentProcessorInterface; +use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Inline\Element\Link; use League\CommonMark\Inline\Element\Text; -final class UrlAutolinkProcessor implements DocumentProcessorInterface +final class UrlAutolinkProcessor { // RegEx adapted from https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/UrlValidator.php const REGEX = '~ @@ -50,13 +49,13 @@ public function __construct(array $allowedProtocols = ['http', 'https', 'ftp']) } /** - * @param Document $document + * @param DocumentParsedEvent $e * * @return void */ - public function processDocument(Document $document) + public function __invoke(DocumentParsedEvent $e) { - $walker = $document->walker(); + $walker = $e->getDocument()->walker(); while ($event = $walker->next()) { if ($event->getNode() instanceof Text) { From 45f2879d71f02f9e40ad008b6b64925d9a1aa801 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 5 Jun 2019 18:13:59 -0400 Subject: [PATCH 157/231] Make compatible with league/commonmark 1.0.0-beta4 --- CHANGELOG.md | 9 ++++++++- composer.json | 4 ++-- src/ExternalLinkExtension.php | 3 ++- src/ExternalLinkProcessor.php | 30 ++++++++++++++---------------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97f38b9f0e..b0304989d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta1] - 2019-06-05 + +### Changed + + - Made compatible with `league/commonmark` 1.0.0-beta4 + ## [0.1.0] - 2019-05-19 Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v0.1.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v1.0.0-beta1...HEAD +[v1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v0.1.0...v1.0.0-beta1 [0.1.0]: https://github.com/thephpleague/commonmark-ext-external-link/commits/v0.1.0 diff --git a/composer.json b/composer.json index 2a3b41eabf..9d698389af 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19.2" + "league/commonmark": "^1.0.0-beta4" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.2-dev" + "dev-master": "1.0-dev" } } } diff --git a/src/ExternalLinkExtension.php b/src/ExternalLinkExtension.php index 6231129701..eeae60fe43 100644 --- a/src/ExternalLinkExtension.php +++ b/src/ExternalLinkExtension.php @@ -12,12 +12,13 @@ namespace League\CommonMark\Ext\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->addDocumentProcessor(new ExternalLinkProcessor()); + $environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment)); } } diff --git a/src/ExternalLinkProcessor.php b/src/ExternalLinkProcessor.php index 6a953a21e7..b284487c9d 100644 --- a/src/ExternalLinkProcessor.php +++ b/src/ExternalLinkProcessor.php @@ -11,35 +11,33 @@ namespace League\CommonMark\Ext\ExternalLink; -use League\CommonMark\Block\Element\Document; -use League\CommonMark\DocumentProcessorInterface; +use League\CommonMark\EnvironmentInterface; +use League\CommonMark\Event\DocumentParsedEvent; use League\CommonMark\Inline\Element\Link; -use League\CommonMark\Util\Configuration; -use League\CommonMark\Util\ConfigurationAwareInterface; -final class ExternalLinkProcessor implements DocumentProcessorInterface, ConfigurationAwareInterface +final class ExternalLinkProcessor { - /** @var Configuration */ - private $configuration; + /** @var EnvironmentInterface */ + private $environment; /** - * {@inheritdoc} + * @param EnvironmentInterface $environment */ - public function setConfiguration(Configuration $configuration) + public function __construct(EnvironmentInterface $environment) { - $this->configuration = $configuration; + $this->environment = $environment; } /** - * {@inheritdoc} + * @param DocumentParsedEvent $e */ - public function processDocument(Document $document) + public function __invoke(DocumentParsedEvent $e) { - $internalHosts = $this->configuration->getConfig('external_link/internal_hosts', []); - $openInNewWindow = $this->configuration->getConfig('external_link/open_in_new_window', false); - $classes = $this->configuration->getConfig('external_link/html_class', ''); + $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 = $document->walker(); + $walker = $e->getDocument()->walker(); while ($event = $walker->next()) { if ($event->isEntering() && $event->getNode() instanceof Link) { /** @var Link $link */ From 84b15dcde5c9f9c34689597b83588ad4a1a345dc Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 5 Jun 2019 18:17:51 -0400 Subject: [PATCH 158/231] Fix CHANGELOG reference --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0304989d2..90e9002784 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,5 +18,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Initial release! [unreleased]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v1.0.0-beta1...HEAD -[v1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v0.1.0...v1.0.0-beta1 +[1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v0.1.0...v1.0.0-beta1 [0.1.0]: https://github.com/thephpleague/commonmark-ext-external-link/commits/v0.1.0 From aa88bb56060b876d23ff930ffd67decf7e55a1a5 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 17 Jun 2019 19:34:03 -0400 Subject: [PATCH 159/231] Fix incorrect double-linking of standard CommonMark autolinks (fixes #12) --- CHANGELOG.md | 9 ++++++++- src/EmailAutolinkProcessor.php | 5 +++-- src/UrlAutolinkProcessor.php | 5 +++-- tests/EmailAutolinkProcessorTest.php | 3 +++ tests/UrlAutolinkProcessorTest.php | 3 +++ 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bcb419456..2a2e4bc31f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [0.3.1] - 2019-06-17 + +### Fixed + + - Fixed extension incorrectly double-linking standard CommonMark autolinks (#12) + ## [0.3.0] - 2019-04-10 ### Changed @@ -41,7 +47,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.1...HEAD +[0.3.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.1.0...v0.2.0 diff --git a/src/EmailAutolinkProcessor.php b/src/EmailAutolinkProcessor.php index f4d436c8a5..51d1a11544 100644 --- a/src/EmailAutolinkProcessor.php +++ b/src/EmailAutolinkProcessor.php @@ -30,8 +30,9 @@ public function processDocument(Document $document) $walker = $document->walker(); while ($event = $walker->next()) { - if ($event->getNode() instanceof Text) { - self::processAutolinks($event->getNode()); + $node = $event->getNode(); + if ($node instanceof Text && !($node->parent() instanceof Link)) { + self::processAutolinks($node); } } } diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 4fb4097689..c011eaf9b2 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -59,8 +59,9 @@ public function processDocument(Document $document) $walker = $document->walker(); while ($event = $walker->next()) { - if ($event->getNode() instanceof Text) { - self::processAutolinks($event->getNode(), $this->finalRegex); + $node = $event->getNode(); + if ($node instanceof Text && !($node->parent() instanceof Link)) { + self::processAutolinks($node, $this->finalRegex); } } } diff --git a/tests/EmailAutolinkProcessorTest.php b/tests/EmailAutolinkProcessorTest.php index 6ccb1e3088..c53c97a0b8 100644 --- a/tests/EmailAutolinkProcessorTest.php +++ b/tests/EmailAutolinkProcessorTest.php @@ -47,5 +47,8 @@ public function dataProviderForEmailAutolinks() yield ['a.b-c_d@a.b.', '

    a.b-c_d@a.b.

    ']; yield ['a.b-c_d@a.b-', '

    a.b-c_d@a.b-

    ']; yield ['a.b-c_d@a.b_', '

    a.b-c_d@a.b_

    ']; + + // Regression: CommonMark autolinks should not be double-linked + yield ['', '

    foo@example.com

    ']; } } diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index 3132fbd230..f3502b5ce9 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -72,5 +72,8 @@ public function dataProviderForAutolinkTests() // Regression: two links with one underscore each yield ["https://eventum.example.net/history.php?iss_id=107092\nhttps://gitlab.example.net/group/project/merge_requests/39#note_150630", "

    https://eventum.example.net/history.php?iss_id=107092\nhttps://gitlab.example.net/group/project/merge_requests/39#note_150630

    "]; + + // Regression: CommonMark autolinks should not be double-linked + yield ['', '

    https://www.google.com

    ']; } } From 5c992e9f03f8421d5b4a1d7c2b6aa5a3d8ebd005 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 17 Jun 2019 19:45:21 -0400 Subject: [PATCH 160/231] Release 1.0.0-beta3 --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62fad9fcd5..55c4e093b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0-beta3] - 2019-06-17 + +### Fixed + + - Fixed extension incorrectly double-linking standard CommonMark autolinks (#12) + ## [0.3.1] - 2019-06-17 ### Fixed @@ -59,7 +65,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta2...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta3...HEAD +[1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta2...v1.0.0-beta3 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...v1.0.0-beta1 [0.3.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...v0.3.1 From 9f6da88485412b1c37a982c9fee8f4fbc2fa5ade Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 29 Jun 2019 07:23:54 -0400 Subject: [PATCH 161/231] Prepare to release v1.0.0 --- CHANGELOG.md | 7 ++++++- composer.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55c4e093b2..8dfaf3c013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0] - 2019-06-29 + +No changes have been introduced since 1.0.0-beta3. + ## [1.0.0-beta3] - 2019-06-17 ### Fixed @@ -65,7 +69,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta3...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta3...v1.0.0 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta2...v1.0.0-beta3 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v0.3.0...v1.0.0-beta1 diff --git a/composer.json b/composer.json index d9e0b6eb3a..bac5221ae1 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^1.0.0-beta4" + "league/commonmark": "^1.0" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } From 46a5c80ca67ec4077ed4bb563b7978f35c02efbd Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 29 Jun 2019 07:31:45 -0400 Subject: [PATCH 162/231] Prepare to release v1.0.0 --- CHANGELOG.md | 7 ++++++- composer.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0670f298a..37b588d952 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0] - 2019-06-29 + +No code changes have been introduced since 1.0.0-beta2. + ## [1.0.0-beta2] - 2019-05-27 ### Changed @@ -29,7 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Split this extension out of the old `league/commonmark-extras` library. -[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta2...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta2...v1.0.0 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.2.0...v1.0.0-beta1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.1.0...v0.2.0 diff --git a/composer.json b/composer.json index e62d23cafc..fd72632058 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^1.0.0-beta3" + "league/commonmark": "^1.0" }, "require-dev": { "jgm/smartpunct": "0.29", @@ -49,7 +49,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } From 99892ad549e101fe1fbe424ff71224efc32d2d68 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 29 Jun 2019 07:34:00 -0400 Subject: [PATCH 163/231] Prepare to release v1.0.0 --- CHANGELOG.md | 7 ++++++- composer.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0c81909da..86f3668d3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0] - 2019-06-29 + +No code changes have been introduced since 1.0.0-beta2. + ## [1.0.0-beta2] - 2019-05-27 ### Changed @@ -50,7 +54,8 @@ These older releases come from the original `uafrica/commonmark-ext` library. - Updated to `league/commonmark` v0.17 -[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta2...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta2...v1.0.0 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.4.0...v1.0.0-beta1 [0.4.0]: https://github.com/thephpleague/commonmark-ext-strikethrough/compare/v0.3.0...v0.4.0 diff --git a/composer.json b/composer.json index 19e7b3273a..4046eb4f97 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1", "ext-mbstring": "*", - "league/commonmark": "^1.0.0-beta3" + "league/commonmark": "^1.0" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -41,7 +41,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } From 1a9ed08eb0564e6277282488dda640cb1b31c74c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 29 Jun 2019 07:36:34 -0400 Subject: [PATCH 164/231] Prepare to release v1.0.0 --- CHANGELOG.md | 7 ++++++- composer.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a04c292b49..cf9eed038b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0] - 2019-06-29 + +No code changes have been introduced since 1.0.0-beta1. + ## [1.0.0-beta1] - 2019-05-27 ### Changed @@ -17,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0-beta1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0-beta1...v1.0.0 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v0.1.0...v1.0.0-beta1 [0.1.0]: https://github.com/thephpleague/commonmark-ext-task-list/commits/v0.1.0 diff --git a/composer.json b/composer.json index f0ba8543de..a6c5f47e0d 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^0.19|^1.0.0-beta1" + "league/commonmark": "^0.19|^1.0" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } From 45927a788aec4918004304183d958bef86ddbe62 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 29 Jun 2019 07:38:22 -0400 Subject: [PATCH 165/231] Prepare to release v1.0.0 --- CHANGELOG.md | 7 ++++++- composer.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0300a6acb4..9259769f5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes will be documented in this file. ## [Unreleased][unreleased] +## [1.0.0] - 2019-06-29 + +No code changes have been introduced since 1.0.0-beta1. + ## [1.0.0-beta1] - 2019-05-27 ### Changed @@ -20,6 +24,7 @@ All notable changes will be documented in this file. Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v1.0.0-beta1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v1.0.0-beta1...v1.0.0 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.2.0...v1.0.0-beta1 [0.2.0]: https://github.com/thephpleague/commonmark-ext-inlines-only/compare/v0.1.0...v0.2.0 diff --git a/composer.json b/composer.json index 7619c3bcd4..ff9c634e64 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^1.0-beta" + "league/commonmark": "^1.0" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } From b2e68fd3dedb8ef9b4c666f2adbe48775466680f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 29 Jun 2019 07:41:14 -0400 Subject: [PATCH 166/231] Prepare to release v1.0.0 --- CHANGELOG.md | 7 ++++++- composer.json | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90e9002784..b1c81519d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.0] - 2019-06-29 + +No code changes have been introduced since 1.0.0-beta1. + ## [1.0.0-beta1] - 2019-06-05 ### Changed @@ -17,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v1.0.0-beta1...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v1.0.0-beta1...v1.0.0 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-external-link/compare/v0.1.0...v1.0.0-beta1 [0.1.0]: https://github.com/thephpleague/commonmark-ext-external-link/commits/v0.1.0 diff --git a/composer.json b/composer.json index 9d698389af..261c1837d6 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ ], "require": { "php" : "^7.1", - "league/commonmark": "^1.0.0-beta4" + "league/commonmark": "^1.0" }, "require-dev": { "phpunit/phpunit": "^7.5" @@ -35,7 +35,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "1.1-dev" } } } From 30942564ca213bea820b843396b210493d02fc53 Mon Sep 17 00:00:00 2001 From: Evgenii G Nikitin Date: Tue, 18 Jun 2019 15:58:09 +0300 Subject: [PATCH 167/231] Add support of league commonmark 0.19 --- .travis.yml | 3 --- composer.json | 2 +- src/Table.php | 4 +++- src/TableCaption.php | 8 +++++++- src/TableCaptionRenderer.php | 4 ++-- src/TableCell.php | 4 +++- src/TableCellRenderer.php | 4 ++-- src/TableExtension.php | 32 +++++++++++--------------------- src/TableParser.php | 4 ++-- src/TableRenderer.php | 4 ++-- src/TableRowRenderer.php | 4 ++-- src/TableRows.php | 4 +++- src/TableRowsRenderer.php | 4 ++-- 13 files changed, 40 insertions(+), 41 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e627cb029..4c49117f43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,13 +12,10 @@ php: - 7.3 env: - - COMMONMARK_VERSION=0.17.* - - COMMONMARK_VERSION=0.18.* - COMMONMARK_VERSION=0.19.*@dev before_script: - if [ $TRAVIS_PHP_VERSION = '7.3' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi - - if [ $TRAVIS_PHP_VERSION = '7.1' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi - composer self-update - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS diff --git a/composer.json b/composer.json index dd3010f4af..176ea7ebc5 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.1", - "league/commonmark": "^0.17|^0.18|^0.19@dev" + "league/commonmark": "^0.19" }, "require-dev": { "phpstan/phpstan": "~0.11", diff --git a/src/Table.php b/src/Table.php index 7858a75d8a..2865d6a69f 100644 --- a/src/Table.php +++ b/src/Table.php @@ -15,11 +15,13 @@ namespace Webuni\CommonMark\TableExtension; 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; use League\CommonMark\Node\Node; -class Table extends AbstractBlock +class Table extends AbstractStringContainerBlock implements InlineContainerInterface { private $caption; private $head; diff --git a/src/TableCaption.php b/src/TableCaption.php index b4945ddc8f..c2d8d7ea1f 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -15,12 +15,14 @@ namespace Webuni\CommonMark\TableExtension; 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; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Node\Node; -class TableCaption extends AbstractBlock implements InlineContainerInterface +class TableCaption extends AbstractStringContainerBlock implements InlineContainerInterface { public $id; @@ -58,4 +60,8 @@ public function children(): array { return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractInline; }); } + + public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void + { + } } diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index 87efbf64f6..ac0f46c117 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -22,7 +22,7 @@ class TableCaptionRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableCaption) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); @@ -30,7 +30,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value, true); + $attrs[$key] = Xml::escape($value); } if ($block->id) { diff --git a/src/TableCell.php b/src/TableCell.php index 9d937cee57..83781fac56 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -15,13 +15,14 @@ namespace Webuni\CommonMark\TableExtension; 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; use League\CommonMark\Inline\Element\AbstractInline; use League\CommonMark\Node\Node; -class TableCell extends AbstractBlock implements InlineContainerInterface +class TableCell extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'th'; const TYPE_BODY = 'td'; @@ -72,4 +73,5 @@ public function children(): array { return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractInline; }); } + } diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 9f99d89120..cbfacf02f5 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -22,7 +22,7 @@ class TableCellRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableCell) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); @@ -30,7 +30,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value, true); + $attrs[$key] = Xml::escape($value); } if ($block->align) { diff --git a/src/TableExtension.php b/src/TableExtension.php index 1b4621bfd1..576ee0b189 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -14,30 +14,20 @@ namespace Webuni\CommonMark\TableExtension; -use League\CommonMark\Extension\Extension; +use League\CommonMark\ConfigurableEnvironmentInterface; +use League\CommonMark\Extension\ExtensionInterface; -class TableExtension extends Extension +final class TableExtension implements ExtensionInterface { - public function getBlockParsers(): array - { - return [ - new TableParser(), - ]; - } + public function register(ConfigurableEnvironmentInterface $environment) { + $environment + ->addBlockParser(new TableParser()) - public function getBlockRenderers(): array - { - return [ - __NAMESPACE__.'\\Table' => new TableRenderer(), - __NAMESPACE__.'\\TableCaption' => new TableCaptionRenderer(), - __NAMESPACE__.'\\TableRows' => new TableRowsRenderer(), - __NAMESPACE__.'\\TableRow' => new TableRowRenderer(), - __NAMESPACE__.'\\TableCell' => new TableCellRenderer(), - ]; - } + ->addBlockRenderer(Table::class, new TableRenderer()) + ->addBlockRenderer(TableCaption::class, new TableCaptionRenderer()) + ->addBlockRenderer(TableRows::class, new TableRowsRenderer()) + ->addBlockRenderer(TableRow::class, new TableRowRenderer()) + ->addBlockRenderer(TableCell::class, new TableCellRenderer()); - public function getName(): string - { - return 'table'; } } diff --git a/src/TableParser.php b/src/TableParser.php index 2daeb24f62..fcfdba0abf 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -15,12 +15,12 @@ namespace Webuni\CommonMark\TableExtension; use League\CommonMark\Block\Element\Paragraph; -use League\CommonMark\Block\Parser\AbstractBlockParser; +use League\CommonMark\Block\Parser\BlockParserInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; use League\CommonMark\Util\RegexHelper; -class TableParser extends AbstractBlockParser +class TableParser implements BlockParserInterface { const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\||\\\\|[^|`\\\\]+)+(?=\||$)/'; diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 8ec9a5dabd..14acc6580f 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -22,7 +22,7 @@ class TableRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof Table) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); @@ -30,7 +30,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value, true); + $attrs[$key] = Xml::escape($value); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index f94b43a311..c9372445dd 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -22,7 +22,7 @@ class TableRowRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableRow) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); @@ -30,7 +30,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value, true); + $attrs[$key] = Xml::escape($value); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); diff --git a/src/TableRows.php b/src/TableRows.php index 48bbf92d92..5a32d09bbb 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -15,11 +15,13 @@ namespace Webuni\CommonMark\TableExtension; 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; use League\CommonMark\Node\Node; -class TableRows extends AbstractBlock +class TableRows extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'thead'; const TYPE_BODY = 'tbody'; diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 87360e41a0..5d43bff65c 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -22,7 +22,7 @@ class TableRowsRenderer implements BlockRendererInterface { - public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false) + public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { if (!$block instanceof TableRows) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); @@ -34,7 +34,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $attrs = []; foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value, true); + $attrs[$key] = Xml::escape($value); } $separator = $htmlRenderer->getOption('inner_separator', "\n"); From f35d895a7e660d0cd3aa5f81bf16eb4f7ad42e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Fri, 5 Jul 2019 21:56:08 +0300 Subject: [PATCH 168/231] composer: allow 1.0; fix 0.x semver --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 176ea7ebc5..413d44fedc 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.1", - "league/commonmark": "^0.19" + "league/commonmark": "~0.19|^1.0" }, "require-dev": { "phpstan/phpstan": "~0.11", From dfbf10b4c7607c9a853df6e0d33dc12a302fa1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 12:34:42 +0200 Subject: [PATCH 169/231] chore: Update run and travis script --- .gitattributes | 1 + .travis.yml | 8 +++++--- run | 21 +++++++++++++++++---- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.gitattributes b/.gitattributes index 8c7e284d18..b78f076b50 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,4 +5,5 @@ /.travis.yml export-ignore /phpunit.xml.dist export-ignore /psalm.xml +/run /tests export-ignore diff --git a/.travis.yml b/.travis.yml index 4c49117f43..6738631566 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,16 +12,18 @@ php: - 7.3 env: - - COMMONMARK_VERSION=0.19.*@dev + - COMMONMARK_VERSION=0.19 + - COMMONMARK_VERSION=1.0 before_script: - if [ $TRAVIS_PHP_VERSION = '7.3' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi + - if [ $TRAVIS_PHP_VERSION = '7.1' ]; then COMPOSER_FLAGS="--prefer-lowest"; fi - composer self-update - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS script: - - vendor/bin/psalm - - phpunit $PHPUNIT_COVERAGE + - if [ $TRAVIS_PHP_VERSION != '7.1' ]; then ./run analyse; fi + - ./run test $PHPUNIT_COVERAGE after_script: - if [[ "$PHPUNIT_COVERAGE" != "" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/run b/run index fbd673c469..8071c8b431 100755 --- a/run +++ b/run @@ -1,12 +1,29 @@ #!/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 + +_decorator()( + if [ -n "$(command -v docker)" ]; then + _docker_run webuni/php:7.3 ./run "$@" + else + "$@" + fi +) + # 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 "$@" @@ -16,7 +33,3 @@ task_cs_fix()( task_tests()( ./vendor/bin/phpunit "$@" ) - -url="https://raw.githubusercontent.com/webuni/shell-task-runner/master/runner" -! if [ -n "$(command -v 'wget')" ]; then r="$(wget -qT 1 "$url" -O-)" && echo "$r" > .runner; else curl --connect-timeout 1 -fso .runner "$url"; fi -. ./.runner From 01d0694a5146e20afd2c90cb28ff32739b45ac8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 12:36:14 +0200 Subject: [PATCH 170/231] fix: Fix cs and remove obsolete code --- src/Table.php | 14 -------------- src/TableCaption.php | 15 --------------- src/TableCell.php | 17 +---------------- src/TableExtension.php | 7 ++++--- src/TableRow.php | 9 ++------- src/TableRows.php | 14 -------------- 6 files changed, 7 insertions(+), 69 deletions(-) diff --git a/src/Table.php b/src/Table.php index 2865d6a69f..cfa3800344 100644 --- a/src/Table.php +++ b/src/Table.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -use League\CommonMark\Node\Node; class Table extends AbstractStringContainerBlock implements InlineContainerInterface { @@ -41,11 +40,6 @@ public function canContain(AbstractBlock $block): bool return $block instanceof TableRows || $block instanceof TableCaption; } - public function acceptsLines(): bool - { - return true; - } - public function isCode(): bool { return false; @@ -87,12 +81,4 @@ public function matchesNextLine(Cursor $cursor): bool public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } - - /** - * @return AbstractBlock[] - */ - public function children(): array - { - return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractBlock; }); - } } diff --git a/src/TableCaption.php b/src/TableCaption.php index c2d8d7ea1f..64e203edea 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -19,8 +19,6 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -use League\CommonMark\Inline\Element\AbstractInline; -use League\CommonMark\Node\Node; class TableCaption extends AbstractStringContainerBlock implements InlineContainerInterface { @@ -38,11 +36,6 @@ public function canContain(AbstractBlock $block): bool return false; } - public function acceptsLines(): bool - { - return false; - } - public function isCode(): bool { return false; @@ -53,14 +46,6 @@ public function matchesNextLine(Cursor $cursor): bool return false; } - /** - * @return AbstractInline[] - */ - public function children(): array - { - return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractInline; }); - } - public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } diff --git a/src/TableCell.php b/src/TableCell.php index 83781fac56..cc4348d9ad 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -19,8 +19,6 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -use League\CommonMark\Inline\Element\AbstractInline; -use League\CommonMark\Node\Node; class TableCell extends AbstractStringContainerBlock implements InlineContainerInterface { @@ -38,6 +36,7 @@ public function __construct(string $string = '', string $type = self::TYPE_BODY, { parent::__construct(); $this->finalStringContents = $string; + $this->addLine($string); $this->type = $type; $this->align = $align; } @@ -47,11 +46,6 @@ public function canContain(AbstractBlock $block): bool return false; } - public function acceptsLines(): bool - { - return false; - } - public function isCode(): bool { return false; @@ -65,13 +59,4 @@ public function matchesNextLine(Cursor $cursor): bool public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } - - /** - * @return AbstractInline[] - */ - public function children(): array - { - return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractInline; }); - } - } diff --git a/src/TableExtension.php b/src/TableExtension.php index 576ee0b189..85cf7d634f 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -19,7 +19,8 @@ final class TableExtension implements ExtensionInterface { - public function register(ConfigurableEnvironmentInterface $environment) { + public function register(ConfigurableEnvironmentInterface $environment): void + { $environment ->addBlockParser(new TableParser()) @@ -27,7 +28,7 @@ public function register(ConfigurableEnvironmentInterface $environment) { ->addBlockRenderer(TableCaption::class, new TableCaptionRenderer()) ->addBlockRenderer(TableRows::class, new TableRowsRenderer()) ->addBlockRenderer(TableRow::class, new TableRowRenderer()) - ->addBlockRenderer(TableCell::class, new TableCellRenderer()); - + ->addBlockRenderer(TableCell::class, new TableCellRenderer()) + ; } } diff --git a/src/TableRow.php b/src/TableRow.php index 03ab1f2070..cc78c877dd 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -26,11 +26,6 @@ public function canContain(AbstractBlock $block): bool return $block instanceof TableCell; } - public function acceptsLines(): bool - { - return false; - } - public function isCode(): bool { return false; @@ -48,8 +43,8 @@ public function handleRemainingContents(ContextInterface $context, Cursor $curso /** * @return AbstractBlock[] */ - public function children(): array + public function children(): iterable { - return array_filter(parent::children(), 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/src/TableRows.php b/src/TableRows.php index 5a32d09bbb..958c75adea 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Element\InlineContainerInterface; use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -use League\CommonMark\Node\Node; class TableRows extends AbstractStringContainerBlock implements InlineContainerInterface { @@ -49,11 +48,6 @@ public function canContain(AbstractBlock $block): bool return $block instanceof TableRow; } - public function acceptsLines(): bool - { - return false; - } - public function isCode(): bool { return false; @@ -67,12 +61,4 @@ public function matchesNextLine(Cursor $cursor): bool public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void { } - - /** - * @return AbstractBlock[] - */ - public function children(): array - { - return array_filter(parent::children(), function (Node $child): bool { return $child instanceof AbstractBlock; }); - } } From d31729917212e0b3b00728a23de23fe9499188c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 14:04:42 +0200 Subject: [PATCH 171/231] chore: Use composer cache from host in docker --- run | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/run b/run index 8071c8b431..27186a3edd 100755 --- a/run +++ b/run @@ -5,9 +5,12 @@ 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 webuni/php:7.3 ./run "$@" + _docker_run -v "$HOME/.composer/cache:/composer-cache" -v "$HOME/.composer/auth.json:/composer/auth.json" webuni/php:7.3 ./run "$@" else "$@" fi From 93a3fd9d930eb555c54b277e63bfab2b3a311451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 14:13:07 +0200 Subject: [PATCH 172/231] feat: Prepare 1.0.0 vesion --- CHANGELOG.md | 5 +++-- README.md | 9 +++++++++ composer.json | 7 +++++-- run | 5 +++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75d46be1c6..7a589dcdf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,12 @@ CHANGELOG ========= -0.10.0 (2019-xx-xx) +1.0.0 (2019-07-09) ------------------- * Increased minimum PHP version to 7.1 - * Removed support for commonmark 0.16 + * Updated to the commonmark 0.19 and 1.0 + * Removed support for commonmark 0.16, 0.17 and 0.18 0.9.0 (2018-11-28) ------------------ diff --git a/README.md b/README.md index 05f7359ec8..f9f872d677 100644 --- a/README.md +++ b/README.md @@ -110,3 +110,12 @@ Result: ``` + +Development +----------- + +You need to have *php* or *docker* installed to develop the library. To list all available commands run: + +```bash +./run +``` diff --git a/composer.json b/composer.json index 413d44fedc..ff7fd617c6 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.1", - "league/commonmark": "~0.19|^1.0" + "league/commonmark": "~0.19.3|^1.0" }, "require-dev": { "phpstan/phpstan": "~0.11", @@ -31,9 +31,12 @@ "Webuni\\CommonMark\\TableExtension\\": "src" } }, + "config": { + "preferred-install": "dist" + }, "extra": { "branch-alias": { - "dev-master": "0.10-dev" + "dev-master": "1.0-dev" } } } diff --git a/run b/run index 27186a3edd..b7d570457d 100755 --- a/run +++ b/run @@ -16,6 +16,11 @@ _decorator()( fi ) +# Install dependencies +task_deps()( + composer install +) + # Static analyse task_analyse()( ./vendor/bin/phpstan analyse -l7 src "$@" From 410157485f613e94f0ecc6f0efb5d96a09b9811c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 15:13:16 +0200 Subject: [PATCH 173/231] chore: Fix travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6738631566..9f0eb11cb3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ php: - 7.3 env: - - COMMONMARK_VERSION=0.19 - - COMMONMARK_VERSION=1.0 + - COMMONMARK_VERSION=~0.19.3 + - COMMONMARK_VERSION=^1.0 before_script: - if [ $TRAVIS_PHP_VERSION = '7.3' ]; then PHPUNIT_COVERAGE="--coverage-clover=coverage.clover"; fi From 783147209cc1c138e757fc8350ad003b26f58acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 15:26:29 +0200 Subject: [PATCH 174/231] chore: Fix condition in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9f0eb11cb3..ff21e00e00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_script: - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS script: - - if [ $TRAVIS_PHP_VERSION != '7.1' ]; then ./run analyse; fi + - if [ $COMMONMARK_VERSION != '~0.19.3' ]; then ./run analyse; fi - ./run test $PHPUNIT_COVERAGE after_script: From 9b976a59d50586b7334d63d3383d325f2576990f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 9 Jul 2019 15:34:17 +0200 Subject: [PATCH 175/231] chore: Disable analyse for php 7.1 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff21e00e00..8ea334ebf8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_script: - composer require "league/commonmark:${COMMONMARK_VERSION}" --prefer-dist --no-interaction $COMPOSER_FLAGS script: - - if [ $COMMONMARK_VERSION != '~0.19.3' ]; then ./run analyse; fi + - if [ $COMMONMARK_VERSION != '~0.19.3' ] && [ $TRAVIS_PHP_VERSION != '7.1' ]; then ./run analyse; fi - ./run test $PHPUNIT_COVERAGE after_script: From ccc83f8eed4b6a1c1cf18963e2b88b342a806c68 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Jul 2019 20:27:27 -0400 Subject: [PATCH 176/231] Add additional test cases --- tests/TaskListExtensionTest.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/TaskListExtensionTest.php b/tests/TaskListExtensionTest.php index fceb57dd50..f8afcdbf12 100644 --- a/tests/TaskListExtensionTest.php +++ b/tests/TaskListExtensionTest.php @@ -26,6 +26,10 @@ public function testTaskLists() - [X] baz - [ ] bim +* [x] foo +* [X] bar +* [ ] baz + This works for ordered lists too: 1. [x] foo @@ -43,6 +47,15 @@ public function testTaskLists() - [ ] - [x] - [x] + +Here's a test using ``: + + - [x] Checkbox inside of strikeout + +And another which does not render the checkbox: + + - [x] Checkbox inside of strikeout + EOT; $expected = <<<'EOT' @@ -59,6 +72,14 @@ public function testTaskLists()
  • bim
  • +
      +
    • + foo
    • +
    • + bar
    • +
    • + baz
    • +

    This works for ordered lists too:

    1. @@ -88,6 +109,18 @@ public function testTaskLists()
    2. +

      Here's a test using <del>:

      +
        +
      • + Checkbox inside of strikeout +
      • +
      +

      And another which does not render the checkbox:

      +
        +
      • +[x] Checkbox inside of strikeout +
      • +
      EOT; From e4b06f703e89893ad3fa03fe03abe6d2e0c64f28 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Jul 2019 20:31:34 -0400 Subject: [PATCH 177/231] Fix code not reusing an existing variable --- CHANGELOG.md | 4 ++++ src/TaskListItemMarkerParser.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf9eed038b..383702c6ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +### Changed + + - Fixed code not reusing an existing variable + ## [1.0.0] - 2019-06-29 No code changes have been introduced since 1.0.0-beta1. diff --git a/src/TaskListItemMarkerParser.php b/src/TaskListItemMarkerParser.php index f161f790ca..e83674097e 100644 --- a/src/TaskListItemMarkerParser.php +++ b/src/TaskListItemMarkerParser.php @@ -56,7 +56,7 @@ public function parse(InlineParserContext $inlineContext): bool $isChecked = $m !== '[ ]'; - $inlineContext->getContainer()->appendChild(new TaskListItemMarker($isChecked)); + $container->appendChild(new TaskListItemMarker($isChecked)); return true; } From 7e9e899c7371546f0088822f15c3332ad0f389d6 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Jul 2019 20:33:34 -0400 Subject: [PATCH 178/231] Optimize a regular expression --- CHANGELOG.md | 1 + src/TaskListItemMarkerParser.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 383702c6ae..dc8dd0410d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed + - Optimized a regular expression - Fixed code not reusing an existing variable ## [1.0.0] - 2019-06-29 diff --git a/src/TaskListItemMarkerParser.php b/src/TaskListItemMarkerParser.php index e83674097e..c7833215c6 100644 --- a/src/TaskListItemMarkerParser.php +++ b/src/TaskListItemMarkerParser.php @@ -43,7 +43,7 @@ public function parse(InlineParserContext $inlineContext): bool $cursor = $inlineContext->getCursor(); $oldState = $cursor->saveState(); - $m = $cursor->match('/\[( |x)\]/i'); + $m = $cursor->match('/\[[ xX]\]/'); if ($m === null) { return false; } From 9fe28f3527ab913b60d44bdc8d66829733cad7c6 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Wed, 10 Jul 2019 20:35:13 -0400 Subject: [PATCH 179/231] Release v1.0.1 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc8dd0410d..09e94f641f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.1] - 2019-07-10 + ### Changed - Optimized a regular expression @@ -26,7 +28,8 @@ No code changes have been introduced since 1.0.0-beta1. Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.1...HEAD +[1.0.1]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v1.0.0-beta1...v1.0.0 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-task-list/compare/v0.1.0...v1.0.0-beta1 [0.1.0]: https://github.com/thephpleague/commonmark-ext-task-list/commits/v0.1.0 From 201c5662dce7ba27a8a3f2c7cf30eb34200bb20f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 07:32:07 -0400 Subject: [PATCH 180/231] Change the namespace --- composer.json | 2 +- src/Table.php | 2 +- src/TableCaption.php | 2 +- src/TableCaptionRenderer.php | 2 +- src/TableCell.php | 2 +- src/TableCellRenderer.php | 2 +- src/TableExtension.php | 2 +- src/TableParser.php | 2 +- src/TableRenderer.php | 2 +- src/TableRow.php | 2 +- src/TableRowRenderer.php | 2 +- src/TableRows.php | 2 +- src/TableRowsRenderer.php | 2 +- tests/Functional/LocalDataTest.php | 4 ++-- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index ff7fd617c6..38db52b487 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ }, "autoload": { "psr-4": { - "Webuni\\CommonMark\\TableExtension\\": "src" + "League\\CommonMark\\Ext\\Table\\": "src" } }, "config": { diff --git a/src/Table.php b/src/Table.php index cfa3800344..f9e2922ef0 100644 --- a/src/Table.php +++ b/src/Table.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; diff --git a/src/TableCaption.php b/src/TableCaption.php index 64e203edea..513badfb21 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index ac0f46c117..ada0383aba 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; diff --git a/src/TableCell.php b/src/TableCell.php index cc4348d9ad..d7c2fee94e 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index cbfacf02f5..6f149ef7c4 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; diff --git a/src/TableExtension.php b/src/TableExtension.php index 85cf7d634f..f435903c70 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\ConfigurableEnvironmentInterface; use League\CommonMark\Extension\ExtensionInterface; diff --git a/src/TableParser.php b/src/TableParser.php index fcfdba0abf..22c3b72255 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\Paragraph; use League\CommonMark\Block\Parser\BlockParserInterface; diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 14acc6580f..8d6a686fd8 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; diff --git a/src/TableRow.php b/src/TableRow.php index cc78c877dd..a0ba289f85 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\ContextInterface; diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index c9372445dd..b62ed841ce 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; diff --git a/src/TableRows.php b/src/TableRows.php index 958c75adea..5181bbad42 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Element\AbstractStringContainerBlock; diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 5d43bff65c..226fd93b37 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -12,7 +12,7 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension; +namespace League\CommonMark\Ext\Table; use League\CommonMark\Block\Element\AbstractBlock; use League\CommonMark\Block\Renderer\BlockRendererInterface; diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index 8f903f4e72..98a22a6281 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -12,14 +12,14 @@ * file that was distributed with this source code. */ -namespace Webuni\CommonMark\TableExtension\Tests\Functional; +namespace League\CommonMark\Ext\Table\Tests\Functional; use League\CommonMark\DocParser; use League\CommonMark\ElementRendererInterface; use League\CommonMark\Environment; +use League\CommonMark\Ext\Table\TableExtension; use League\CommonMark\HtmlRenderer; use PHPUnit\Framework\TestCase; -use Webuni\CommonMark\TableExtension\TableExtension; /** * @internal From 3d7d3d0d8e5311d3122dfd99681bf81c08164b36 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 07:37:07 -0400 Subject: [PATCH 181/231] Add Colin O'Dell as a maintainer --- .php_cs | 1 + LICENSE | 2 +- composer.json | 5 +++++ src/Table.php | 1 + src/TableCaption.php | 1 + src/TableCaptionRenderer.php | 1 + src/TableCell.php | 1 + src/TableCellRenderer.php | 1 + src/TableExtension.php | 1 + src/TableParser.php | 1 + src/TableRenderer.php | 1 + src/TableRow.php | 1 + src/TableRowRenderer.php | 1 + src/TableRows.php | 1 + src/TableRowsRenderer.php | 1 + tests/Functional/LocalDataTest.php | 1 + 16 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.php_cs b/.php_cs index 9f00fefcc3..f922e5dfb2 100644 --- a/.php_cs +++ b/.php_cs @@ -5,6 +5,7 @@ This is part of the webuni/commonmark-table-extension package. (c) Martin Hasoň (c) Webuni s.r.o. +(c) Colin O'Dell For the full copyright and license information, please view the LICENSE file that was distributed with this source code. diff --git a/LICENSE b/LICENSE index a5d81ec8ac..522628ac93 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) Martin Hasoň +Copyright (c) Martin Hasoň , Colin O'Dell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/composer.json b/composer.json index 38db52b487..8aa924d90c 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,11 @@ { "name": "Webuni s.r.o.", "homepage": "https://www.webuni.cz" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" } ], "require": { diff --git a/src/Table.php b/src/Table.php index f9e2922ef0..78069d7d89 100644 --- a/src/Table.php +++ b/src/Table.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableCaption.php b/src/TableCaption.php index 513badfb21..4100957f98 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index ada0383aba..39749fad35 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableCell.php b/src/TableCell.php index d7c2fee94e..1501718164 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 6f149ef7c4..824f8fde26 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableExtension.php b/src/TableExtension.php index f435903c70..ec67f1b010 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableParser.php b/src/TableParser.php index 22c3b72255..9c06b03cdf 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 8d6a686fd8..3e6e498acc 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRow.php b/src/TableRow.php index a0ba289f85..b123eb051d 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index b62ed841ce..37be2a17ce 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRows.php b/src/TableRows.php index 5181bbad42..121f3beeb7 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 226fd93b37..11727025d2 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index 98a22a6281..f655bdb0b3 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -7,6 +7,7 @@ * * (c) Martin Hasoň * (c) Webuni s.r.o. + * (c) Colin O'Dell * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. From d5e0b0cb99422a11678444611900ba45d40b0af3 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 07:37:29 -0400 Subject: [PATCH 182/231] Update package name --- .php_cs | 2 +- README.md | 10 +++++----- composer.json | 8 ++++---- phpunit.xml.dist | 2 +- src/Table.php | 2 +- src/TableCaption.php | 2 +- src/TableCaptionRenderer.php | 2 +- src/TableCell.php | 2 +- src/TableCellRenderer.php | 2 +- src/TableExtension.php | 2 +- src/TableParser.php | 2 +- src/TableRenderer.php | 2 +- src/TableRow.php | 2 +- src/TableRowRenderer.php | 2 +- src/TableRows.php | 2 +- src/TableRowsRenderer.php | 2 +- tests/Functional/LocalDataTest.php | 2 +- 17 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.php_cs b/.php_cs index f922e5dfb2..ba83572889 100644 --- a/.php_cs +++ b/.php_cs @@ -1,7 +1,7 @@ (c) Webuni s.r.o. diff --git a/README.md b/README.md index f9f872d677..fe2ae84b6e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ CommonMark Table Extension ========================== -[![Latest Version](https://img.shields.io/packagist/v/webuni/commonmark-table-extension.svg?style=flat-square)](https://packagist.org/packages/webuni/commonmark-table-extension) -[![Build Status](https://img.shields.io/travis/webuni/commonmark-table-extension.svg?style=flat-square)](https://travis-ci.org/webuni/commonmark-table-extension) -[![Code Quality](https://img.shields.io/scrutinizer/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension/code-structure) -[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/webuni/commonmark-table-extension.svg?style=flat-square)](https://scrutinizer-ci.com/g/webuni/commonmark-table-extension) +[![Latest Version](https://img.shields.io/packagist/v/league/commonmark-ext-table.svg?style=flat-square)](https://packagist.org/packages/league/commonmark-ext-table) +[![Build Status](https://img.shields.io/travis/league/commonmark-ext-table.svg?style=flat-square)](https://travis-ci.org/league/commonmark-ext-table) +[![Code Quality](https://img.shields.io/scrutinizer/g/league/commonmark-ext-table.svg?style=flat-square)](https://scrutinizer-ci.com/g/league/commonmark-ext-table/code-structure) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/league/commonmark-ext-table.svg?style=flat-square)](https://scrutinizer-ci.com/g/league/commonmark-ext-table) The Table extension adds the ability to create tables in CommonMark documents. @@ -13,7 +13,7 @@ Installation This project can be installed via Composer: - composer require webuni/commonmark-table-extension + composer require league/commonmark-ext-table Usage ----- diff --git a/composer.json b/composer.json index 8aa924d90c..17e0dced23 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,9 @@ { - "name": "webuni/commonmark-table-extension", + "name": "league/commonmark-ext-table", "type": "commonmark-extension", - "description": "The table extension for CommonMark PHP implementation", - "keywords": ["markdown","table","commonmark"], - "homepage": "https://github.com/webuni/commonmark-table-extension", + "description": "Table extension for league/commonmark", + "keywords": ["markdown", "commonmark", "extension", "table"], + "homepage": "https://github.com/thephpleague/commonmark-ext-table", "license": "MIT", "authors": [ { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index e8cc856d1b..5752b9c598 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -11,7 +11,7 @@ bootstrap="vendor/autoload.php" > - + ./tests/ diff --git a/src/Table.php b/src/Table.php index 78069d7d89..04af0ecf11 100644 --- a/src/Table.php +++ b/src/Table.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableCaption.php b/src/TableCaption.php index 4100957f98..b488eb8b3c 100644 --- a/src/TableCaption.php +++ b/src/TableCaption.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index 39749fad35..470c3db4ad 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableCell.php b/src/TableCell.php index 1501718164..c8b326a03b 100644 --- a/src/TableCell.php +++ b/src/TableCell.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 824f8fde26..4cc8ff3764 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableExtension.php b/src/TableExtension.php index ec67f1b010..27187ec8b3 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableParser.php b/src/TableParser.php index 9c06b03cdf..3b481947ed 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 3e6e498acc..05d4f2672b 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableRow.php b/src/TableRow.php index b123eb051d..506dd34b23 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index 37be2a17ce..1c91aee289 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableRows.php b/src/TableRows.php index 121f3beeb7..0e0c8ae876 100644 --- a/src/TableRows.php +++ b/src/TableRows.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 11727025d2..3926ac9c81 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index f655bdb0b3..d8a6af7bc7 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); /* - * This is part of the webuni/commonmark-table-extension package. + * This is part of the league/commonmark-ext-table package. * * (c) Martin Hasoň * (c) Webuni s.r.o. From f699489b440e745e8fac07faaadca3f9287fedbd Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 07:41:34 -0400 Subject: [PATCH 183/231] Allow scripts to be run via Composer --- composer.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/composer.json b/composer.json index 17e0dced23..5013dc75da 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,13 @@ "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" }, From cce7710143dac11db2a4f92e864237e775d89353 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 08:00:49 -0400 Subject: [PATCH 184/231] Refactor changelog to follow Keep A Changelog --- CHANGELOG.md | 139 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a589dcdf9..b8c25a3e92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,71 +1,118 @@ -CHANGELOG -========= +# Changelog -1.0.0 (2019-07-09) -------------------- +All notable changes to this project will be documented in this file. - * Increased minimum PHP version to 7.1 - * Updated to the commonmark 0.19 and 1.0 - * Removed support for commonmark 0.16, 0.17 and 0.18 +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). -0.9.0 (2018-11-28) ------------------- +## [Unreleased][unreleased] - * Allowed the commonmark 0.18 +## [1.0.0] - 2019-07-09 +### Changed -0.8.0 (2018-01-24) ------------------- + - Increased minimum PHP version to 7.1 + - Updated to the commonmark 0.19 and 1.0 - * Replaced align attribute with text-align style +### Removed -0.7.1 (2018-01-23) ------------------- + - Removed support for commonmark 0.16, 0.17 and 0.18 - * Fixed undefined method in commonmark 0.17 +## [0.9.0] - 2018-11-28 +### Changed -0.7.0 (2018-01-09) ------------------- + - Allowed the commonmark 0.18 - * Increased minimum PHP version to 5.6 - * Removed support for commonmark 0.14 and 0.15 API - * Updated to the commonmark 0.16 and 0.17 API - * Fixed a problem with parsing whitespaces at the end of line +## [0.8.0] - 2018-01-24 +### Changed -0.6.1 (2017-01-11) ------------------- + - Replaced align attribute with text-align style - * Fixed parsing of one column tables +## [0.7.1] - 2018-01-23 +### Fixed -0.6.0 (2016-09-26) ------------------- + - Fixed undefined method in commonmark 0.17 - * Updated to the commonmark 0.15 API - * Moved twig template to [webuni/commonmark-twig-renderer](https://packagist.org/packages/webuni/commonmark-twig-renderer) +## [0.7.0] - 2018-01-09 +### Changed -0.5.0 (2016-07-13) ------------------- + - Increased minimum PHP version to 5.6 + - Updated to the commonmark 0.16 and 0.17 API + +### Fixed - * Added support for table caption (MultiMarkdown) - * Added a template for twig renderer - * Updated to the commonmark 0.14 API + - Fixed a problem with parsing whitespaces at the end of line + +### Removed -0.4.0 (2015-09-21) ------------------- + - Removed support for commonmark 0.14 and 0.15 API - * Updated to the new commonmark 0.11 API +## [0.6.1] - 2017-01-11 +### Fixed -0.3.0 (2015-07-27) ------------------- + - Fixed parsing of one column tables - * Added support for custom attributes in renderers +## [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.2.0 (2015-07-27) ------------------- +## [0.5.0] - 2016-07-13 +### Added - * Updated to the new commonmark 0.10 API + - Added support for table caption (MultiMarkdown) + - Added a template for twig renderer -0.1.0 (2015-06-24) ------------------- +### Changed - * Implemented GFM tables + - 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/1.0.0...HEAD +[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.2.0 From 1baf3bb1f95d474c441d6aec1f557a0a41b03374 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 08:01:03 -0400 Subject: [PATCH 185/231] Add .editorconfig file --- .editorconfig | 15 +++++++++++++++ .gitattributes | 1 + 2 files changed, 16 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..cd8eb86efa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes index b78f076b50..77950c1c07 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ +/.editorconfig export-ignore /.gitattributes export-ignore /.gitignore export-ignore /.php_cs export-ignore From c083b00bf6723449746c77c821a8bce7cb2ba3e2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 08:01:17 -0400 Subject: [PATCH 186/231] Bump branch alias to 2.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5013dc75da..5f98d49a1e 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } } } From d2abd0e2b3e4a9e130f27f612aba7c87ba3d016a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 08:15:10 -0400 Subject: [PATCH 187/231] Update .scrutinizer.yml --- .scrutinizer.yml | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 45b1aef3f4..a2baf35af7 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,5 +1,39 @@ +filter: + excluded_paths: [tests/*] + +checks: + php: + code_rating: true + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + tools: external_code_coverage: - timeout: 900 - php_code_coverage: + timeout: 600 + runs: 3 + php_analyzer: true + php_code_coverage: false + php_code_sniffer: + config: + standard: PSR2 + filter: + paths: ['src'] + php_cpd: enabled: true + excluded_dirs: [vendor, tests] + php_loc: + enabled: true + excluded_dirs: [vendor, tests] + php_pdepend: true + php_sim: true From b7afc0fc9ff5a0c51f5634d52c128f8e03a856a1 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 11 Jul 2019 10:36:41 -0400 Subject: [PATCH 188/231] Fix badge URLs --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe2ae84b6e..421c99d572 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ CommonMark Table Extension ========================== [![Latest Version](https://img.shields.io/packagist/v/league/commonmark-ext-table.svg?style=flat-square)](https://packagist.org/packages/league/commonmark-ext-table) -[![Build Status](https://img.shields.io/travis/league/commonmark-ext-table.svg?style=flat-square)](https://travis-ci.org/league/commonmark-ext-table) -[![Code Quality](https://img.shields.io/scrutinizer/g/league/commonmark-ext-table.svg?style=flat-square)](https://scrutinizer-ci.com/g/league/commonmark-ext-table/code-structure) -[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/league/commonmark-ext-table.svg?style=flat-square)](https://scrutinizer-ci.com/g/league/commonmark-ext-table) +[![Build Status](https://img.shields.io/travis/thephpleague/commonmark-ext-table.svg?style=flat-square)](https://travis-ci.org/thephpleague/commonmark-ext-table) +[![Code Quality](https://img.shields.io/scrutinizer/g/thephpleague/commonmark-ext-table.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-table/code-structure) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark-ext-table.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/commonmark-ext-table) The Table extension adds the ability to create tables in CommonMark documents. From 96012cb20cb7e5789a3f503659ba7c01c342c700 Mon Sep 17 00:00:00 2001 From: baijunyao Date: Sat, 13 Jul 2019 08:16:23 +0800 Subject: [PATCH 189/231] Change Webuni to League --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 421c99d572..bd057eed13 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ use League\CommonMark\Converter; use League\CommonMark\DocParser; use League\CommonMark\Environment; use League\CommonMark\HtmlRenderer; -use Webuni\CommonMark\TableExtension\TableExtension; +use League\CommonMark\Ext\Table\TableExtension; $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new TableExtension()); From 634555855df49a89a395d4db70a589869d6436e3 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:04:06 -0400 Subject: [PATCH 190/231] Update the README --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index bd057eed13..f432c34093 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ This project can be installed via Composer: Usage ----- +Configure your `Environment` as usual and simply add the `TableExtension` provided by this package: + ```php use League\CommonMark\Converter; use League\CommonMark\DocParser; @@ -25,9 +27,13 @@ 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!'); @@ -36,6 +42,8 @@ echo $converter->convertToHtml('# Hello World!'); Syntax ------ +This package is fully compatible with GFM-style tables: + ### Simple Code: @@ -111,6 +119,11 @@ Result:
    ``` +Changelog +--------- + +Please refer to the [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + Development ----------- @@ -119,3 +132,21 @@ You need to have *php* or *docker* installed to develop the library. To list all ```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. From 4daefec685dc42c163c6e3ca4ddd49dd222b3acd Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:04:27 -0400 Subject: [PATCH 191/231] Add information on CONTRIBUTING --- .gitattributes | 1 + .github/CONTRIBUTING.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 .github/CONTRIBUTING.md diff --git a/.gitattributes b/.gitattributes index 77950c1c07..e765a486d0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ /.editorconfig export-ignore /.gitattributes export-ignore +/.github export-ignore /.gitignore export-ignore /.php_cs export-ignore /.scrutinizer.yml export-ignore diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..734cde8634 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [GitHub](https://github.com/thephpleague/commonmark-ext-table). + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. + +- **Adhere to the spec** - Any changes to how tables are parsed and rendered should adhere to the official GFM spec and behavior of Github's Markdown parser. + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! From 601d5fbb76de66b06a931bd2a8de1b15fd15b88c Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:05:34 -0400 Subject: [PATCH 192/231] Add CODE_OF_CONDUCT.md --- .gitattributes | 1 + CODE_OF_CONDUCT.md | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/.gitattributes b/.gitattributes index e765a486d0..87977652de 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,7 @@ /.php_cs export-ignore /.scrutinizer.yml export-ignore /.travis.yml export-ignore +/CODE_OF_CONDUCT.md export-ignore /phpunit.xml.dist export-ignore /psalm.xml /run diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..01b8644f13 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,22 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic addresses, without explicit permission +* Other unethical or unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. + +This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) From d6e6fc23329cf07210a41d21707c38c83af8938f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:05:52 -0400 Subject: [PATCH 193/231] Configure stalebot --- .github/stale.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..e5101bf5d2 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,18 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 90 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 21 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - on hold + - security +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false From 2e0fff2f4c6ad2b47d4ae565bddd0741208027d2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:06:02 -0400 Subject: [PATCH 194/231] Add issue templates --- .github/ISSUE_TEMPLATE/1_Bug_report.md | 19 +++++++++++++++++++ .github/ISSUE_TEMPLATE/2_Feature_request.md | 12 ++++++++++++ .github/ISSUE_TEMPLATE/3_Security_issue.md | 9 +++++++++ 3 files changed, 40 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/1_Bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/2_Feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/3_Security_issue.md diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md new file mode 100644 index 0000000000..323e9a541e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.md @@ -0,0 +1,19 @@ +--- +name: 🐛 Bug Report +about: Report errors and problems + +--- + +**Version(s) affected**: x.y.z + +**Description** + + +**How to reproduce** + + +**Possible Solution** + + +**Additional context** + diff --git a/.github/ISSUE_TEMPLATE/2_Feature_request.md b/.github/ISSUE_TEMPLATE/2_Feature_request.md new file mode 100644 index 0000000000..066ad8b36b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2_Feature_request.md @@ -0,0 +1,12 @@ +--- +name: 🚀 Feature Request +about: RFC and ideas for new features and improvements + +--- + +**Description** + + +**Example** + diff --git a/.github/ISSUE_TEMPLATE/3_Security_issue.md b/.github/ISSUE_TEMPLATE/3_Security_issue.md new file mode 100644 index 0000000000..b6c1b0ea6e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3_Security_issue.md @@ -0,0 +1,9 @@ +--- +name: ⛔ Security Issue +about: See the README instructions for reporting security issues + +--- + +⚠ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY + +To report a security vulnerability, please use email colinodell@gmail.com directly instead of using this issue tracker. From e5585df7624420b4bbb6d61f8b9cbd9f66c853c2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:22:44 -0400 Subject: [PATCH 195/231] Fix code coverage uploads --- .scrutinizer.yml | 2 +- .travis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index a2baf35af7..d66bdb6343 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -21,7 +21,7 @@ checks: tools: external_code_coverage: timeout: 600 - runs: 3 + runs: 2 php_analyzer: true php_code_coverage: false php_code_sniffer: diff --git a/.travis.yml b/.travis.yml index 8ea334ebf8..bbafd6ec89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_script: script: - if [ $COMMONMARK_VERSION != '~0.19.3' ] && [ $TRAVIS_PHP_VERSION != '7.1' ]; then ./run analyse; fi - - ./run test $PHPUNIT_COVERAGE + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover after_script: - if [[ "$PHPUNIT_COVERAGE" != "" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi From 67bac658c0f0b28b3321d8c656d79aa94c35c35f Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 12 Jul 2019 21:28:59 -0400 Subject: [PATCH 196/231] Include function tests in code coverage calculation --- tests/Functional/LocalDataTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Functional/LocalDataTest.php b/tests/Functional/LocalDataTest.php index d8a6af7bc7..82c58698ba 100644 --- a/tests/Functional/LocalDataTest.php +++ b/tests/Functional/LocalDataTest.php @@ -24,7 +24,6 @@ /** * @internal - * @coversNothing */ class LocalDataTest extends TestCase { From c7aa3b9fb928baa9bff74dda42774fca7200d6ed Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 13 Jul 2019 07:26:21 -0400 Subject: [PATCH 197/231] Mark all renderers as final --- src/TableCaptionRenderer.php | 2 +- src/TableCellRenderer.php | 2 +- src/TableRenderer.php | 2 +- src/TableRowRenderer.php | 2 +- src/TableRowsRenderer.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index 470c3db4ad..1b5caac127 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -21,7 +21,7 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Util\Xml; -class TableCaptionRenderer implements BlockRendererInterface +final class TableCaptionRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 4cc8ff3764..9074ddd673 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -21,7 +21,7 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Util\Xml; -class TableCellRenderer implements BlockRendererInterface +final class TableCellRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { diff --git a/src/TableRenderer.php b/src/TableRenderer.php index 05d4f2672b..e9f7604dad 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -21,7 +21,7 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Util\Xml; -class TableRenderer implements BlockRendererInterface +final class TableRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index 1c91aee289..edf7bd3199 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -21,7 +21,7 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Util\Xml; -class TableRowRenderer implements BlockRendererInterface +final class TableRowRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { diff --git a/src/TableRowsRenderer.php b/src/TableRowsRenderer.php index 3926ac9c81..501afee552 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableRowsRenderer.php @@ -21,7 +21,7 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Util\Xml; -class TableRowsRenderer implements BlockRendererInterface +final class TableRowsRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { From 1146c2ab0e46e986c16b655770a6660903a89ebc Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 13 Jul 2019 07:27:38 -0400 Subject: [PATCH 198/231] Mark the parser as final --- src/TableParser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TableParser.php b/src/TableParser.php index 3b481947ed..63d173f332 100644 --- a/src/TableParser.php +++ b/src/TableParser.php @@ -21,7 +21,7 @@ use League\CommonMark\Cursor; use League\CommonMark\Util\RegexHelper; -class TableParser implements BlockParserInterface +final class TableParser implements BlockParserInterface { const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\||\\\\|[^|`\\\\]+)+(?=\||$)/'; From fafac0aad4be4cb8b697761622bb9baf22270dfc Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 13 Jul 2019 07:28:44 -0400 Subject: [PATCH 199/231] Remove unused function --- src/TableRow.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/TableRow.php b/src/TableRow.php index 506dd34b23..17b5e96598 100644 --- a/src/TableRow.php +++ b/src/TableRow.php @@ -37,10 +37,6 @@ public function matchesNextLine(Cursor $cursor): bool return false; } - public function handleRemainingContents(ContextInterface $context, Cursor $cursor): void - { - } - /** * @return AbstractBlock[] */ From e4d066ce34ba656b857633b476e01ad29114cf31 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 13 Jul 2019 07:31:03 -0400 Subject: [PATCH 200/231] Rename TableRows to TableSection --- src/Table.php | 10 +++++----- src/TableExtension.php | 2 +- src/{TableRows.php => TableSection.php} | 2 +- ...{TableRowsRenderer.php => TableSectionRenderer.php} | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename src/{TableRows.php => TableSection.php} (94%) rename src/{TableRowsRenderer.php => TableSectionRenderer.php} (91%) diff --git a/src/Table.php b/src/Table.php index 04af0ecf11..22aa812ee8 100644 --- a/src/Table.php +++ b/src/Table.php @@ -31,14 +31,14 @@ class Table extends AbstractStringContainerBlock implements InlineContainerInter public function __construct(\Closure $parser) { parent::__construct(); - $this->appendChild($this->head = new TableRows(TableRows::TYPE_HEAD)); - $this->appendChild($this->body = new TableRows(TableRows::TYPE_BODY)); + $this->appendChild($this->head = new TableSection(TableSection::TYPE_HEAD)); + $this->appendChild($this->body = new TableSection(TableSection::TYPE_BODY)); $this->parser = $parser; } public function canContain(AbstractBlock $block): bool { - return $block instanceof TableRows || $block instanceof TableCaption; + return $block instanceof TableSection || $block instanceof TableCaption; } public function isCode(): bool @@ -64,12 +64,12 @@ public function getCaption(): ?TableCaption return $this->caption; } - public function getHead(): TableRows + public function getHead(): TableSection { return $this->head; } - public function getBody(): TableRows + public function getBody(): TableSection { return $this->body; } diff --git a/src/TableExtension.php b/src/TableExtension.php index 27187ec8b3..b19ee4dc03 100644 --- a/src/TableExtension.php +++ b/src/TableExtension.php @@ -27,7 +27,7 @@ public function register(ConfigurableEnvironmentInterface $environment): void ->addBlockRenderer(Table::class, new TableRenderer()) ->addBlockRenderer(TableCaption::class, new TableCaptionRenderer()) - ->addBlockRenderer(TableRows::class, new TableRowsRenderer()) + ->addBlockRenderer(TableSection::class, new TableSectionRenderer()) ->addBlockRenderer(TableRow::class, new TableRowRenderer()) ->addBlockRenderer(TableCell::class, new TableCellRenderer()) ; diff --git a/src/TableRows.php b/src/TableSection.php similarity index 94% rename from src/TableRows.php rename to src/TableSection.php index 0e0c8ae876..b19e4274dc 100644 --- a/src/TableRows.php +++ b/src/TableSection.php @@ -21,7 +21,7 @@ use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; -class TableRows extends AbstractStringContainerBlock implements InlineContainerInterface +class TableSection extends AbstractStringContainerBlock implements InlineContainerInterface { const TYPE_HEAD = 'thead'; const TYPE_BODY = 'tbody'; diff --git a/src/TableRowsRenderer.php b/src/TableSectionRenderer.php similarity index 91% rename from src/TableRowsRenderer.php rename to src/TableSectionRenderer.php index 501afee552..1fb1f84238 100644 --- a/src/TableRowsRenderer.php +++ b/src/TableSectionRenderer.php @@ -21,11 +21,11 @@ use League\CommonMark\HtmlElement; use League\CommonMark\Util\Xml; -final class TableRowsRenderer implements BlockRendererInterface +final class TableSectionRenderer implements BlockRendererInterface { public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { - if (!$block instanceof TableRows) { + if (!$block instanceof TableSection) { throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } From 4bb680b784bd6c04b5cb7a6335eb66b6609a7b8d Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sat, 13 Jul 2019 07:43:25 -0400 Subject: [PATCH 201/231] Prepare to release 2.0.0 --- CHANGELOG.md | 15 ++++++++++++++- composer.json | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8c25a3e92..b4fdabff24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [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 @@ -100,7 +112,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Implemented GFM tables -[unreleased]: https://github.com/thephpleague/commonmark-ext-table/compare/1.0.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-table/compare/v2.0.0...HEAD +[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 diff --git a/composer.json b/composer.json index 5f98d49a1e..ae69a257b6 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } } } From 8b36bf38c4e6aaf3e12bc903a4c5e893a4b12573 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Sun, 14 Jul 2019 21:04:01 -0400 Subject: [PATCH 202/231] Fix link in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4fdabff24..2c6c11be39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -128,4 +128,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [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.2.0 +[0.1.0]: https://github.com/thephpleague/commonmark-ext-table/commits/0.1.0 From 75d9a415f1cf87c0b62be469972c97b8bfa89299 Mon Sep 17 00:00:00 2001 From: baijunyao Date: Mon, 5 Aug 2019 19:37:55 +0800 Subject: [PATCH 203/231] Update the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f432c34093..4612bc3cd6 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ 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] +- [All Contributors](../../contributors) License ------- From bf865993aaaf16e389f3de28d9e6d9235f7cb13a Mon Sep 17 00:00:00 2001 From: nanaya Date: Wed, 25 Sep 2019 19:02:06 +0900 Subject: [PATCH 204/231] Remove manual escaping of attributes --- src/TableCaptionRenderer.php | 6 +----- src/TableCellRenderer.php | 6 +----- src/TableRenderer.php | 6 +----- src/TableRowRenderer.php | 6 +----- src/TableSectionRenderer.php | 6 +----- 5 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/TableCaptionRenderer.php b/src/TableCaptionRenderer.php index 1b5caac127..a02a0bbd75 100644 --- a/src/TableCaptionRenderer.php +++ b/src/TableCaptionRenderer.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\Util\Xml; final class TableCaptionRenderer implements BlockRendererInterface { @@ -29,10 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } - $attrs = []; - foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value); - } + $attrs = $block->getData('attributes', []); if ($block->id) { $attrs['id'] = $block->id; diff --git a/src/TableCellRenderer.php b/src/TableCellRenderer.php index 9074ddd673..400e94e546 100644 --- a/src/TableCellRenderer.php +++ b/src/TableCellRenderer.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\Util\Xml; final class TableCellRenderer implements BlockRendererInterface { @@ -29,10 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } - $attrs = []; - foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value); - } + $attrs = $block->getData('attributes', []); if ($block->align) { $attrs['style'] = (isset($attrs['style']) ? $attrs['style'].' ' : '').'text-align: '.$block->align; diff --git a/src/TableRenderer.php b/src/TableRenderer.php index e9f7604dad..2381780dad 100644 --- a/src/TableRenderer.php +++ b/src/TableRenderer.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\Util\Xml; final class TableRenderer implements BlockRendererInterface { @@ -29,10 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } - $attrs = []; - foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value); - } + $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); diff --git a/src/TableRowRenderer.php b/src/TableRowRenderer.php index edf7bd3199..9f4d852e1b 100644 --- a/src/TableRowRenderer.php +++ b/src/TableRowRenderer.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\Util\Xml; final class TableRowRenderer implements BlockRendererInterface { @@ -29,10 +28,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende throw new \InvalidArgumentException('Incompatible block type: '.get_class($block)); } - $attrs = []; - foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value); - } + $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); diff --git a/src/TableSectionRenderer.php b/src/TableSectionRenderer.php index 1fb1f84238..7ea2a33fba 100644 --- a/src/TableSectionRenderer.php +++ b/src/TableSectionRenderer.php @@ -19,7 +19,6 @@ use League\CommonMark\Block\Renderer\BlockRendererInterface; use League\CommonMark\ElementRendererInterface; use League\CommonMark\HtmlElement; -use League\CommonMark\Util\Xml; final class TableSectionRenderer implements BlockRendererInterface { @@ -33,10 +32,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende return ''; } - $attrs = []; - foreach ($block->getData('attributes', []) as $key => $value) { - $attrs[$key] = Xml::escape($value); - } + $attrs = $block->getData('attributes', []); $separator = $htmlRenderer->getOption('inner_separator', "\n"); From 3228888ea69636e855efcf6636ff8e6316933fe7 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 26 Sep 2019 09:28:33 -0400 Subject: [PATCH 205/231] Prepare to release v2.1.0 --- CHANGELOG.md | 9 ++++++++- composer.json | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c6c11be39..0616de81eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [2.1.0] - 2019-09-26 + +### Fixed + + - Fixed attributes being double-escaped (#31) + ## [2.0.0] - 2019-07-13 ### Changed @@ -112,7 +118,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Implemented GFM tables -[unreleased]: https://github.com/thephpleague/commonmark-ext-table/compare/v2.0.0...HEAD +[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 diff --git a/composer.json b/composer.json index ae69a257b6..9689c501b1 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" } } } From 3d03105f5028cac72c1a149c0de8ea48bcf10f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Klva=C4=8D?= Date: Thu, 3 Oct 2019 09:55:01 +0200 Subject: [PATCH 206/231] Make the quote characters customizable. Some languages, such as Czech or French use quote characters different from those currently hardcoded. This commit introduces following configuration options: - `smartpunct/double_quote_opener` - `smartpunct/double_quote_closer` - `smartpunct/single_quote_opener` - `smartpunct/single_quote_closer` Currently hardcoded character is used as a default value for each option and this is also covered by a test. Configuration options are passed to `QuoteProcessor::createDoubleQuoteProcessor()` and `QuoteProcessor::createSingleQuoteProcessor()` during extension registration. --- README.md | 10 ++++++ src/QuoteProcessor.php | 14 +++++--- src/SmartPunctExtension.php | 10 ++++-- tests/SmartPunctExtensionTest.php | 59 +++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 tests/SmartPunctExtensionTest.php diff --git a/README.md b/README.md index ca52bdcec1..adb8d3a1bf 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,16 @@ $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!'); diff --git a/src/QuoteProcessor.php b/src/QuoteProcessor.php index d4202977c8..6b587219e3 100644 --- a/src/QuoteProcessor.php +++ b/src/QuoteProcessor.php @@ -87,20 +87,26 @@ public function process(AbstractStringContainer $opener, AbstractStringContainer /** * Create a double-quote processor * + * @param string $opener + * @param string $closer + * * @return QuoteProcessor */ - public static function createDoubleQuoteProcessor(): self + public static function createDoubleQuoteProcessor(string $opener = Quote::DOUBLE_QUOTE_OPENER, string $closer = Quote::DOUBLE_QUOTE_CLOSER): self { - return new self(Quote::DOUBLE_QUOTE, Quote::DOUBLE_QUOTE_OPENER, Quote::DOUBLE_QUOTE_CLOSER); + 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(): self + public static function createSingleQuoteProcessor(string $opener = Quote::SINGLE_QUOTE_OPENER, string $closer = Quote::SINGLE_QUOTE_CLOSER): self { - return new self(Quote::SINGLE_QUOTE, Quote::SINGLE_QUOTE_OPENER, Quote::SINGLE_QUOTE_CLOSER); + return new self(Quote::SINGLE_QUOTE, $opener, $closer); } } diff --git a/src/SmartPunctExtension.php b/src/SmartPunctExtension.php index 97a6b8f1e2..eb7bb53841 100644 --- a/src/SmartPunctExtension.php +++ b/src/SmartPunctExtension.php @@ -30,8 +30,14 @@ public function register(ConfigurableEnvironmentInterface $environment) ->addInlineParser(new QuoteParser(), 10) ->addInlineParser(new PunctuationParser(), 0) - ->addDelimiterProcessor(QuoteProcessor::createDoubleQuoteProcessor()) - ->addDelimiterProcessor(QuoteProcessor::createSingleQuoteProcessor()) + ->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) diff --git a/tests/SmartPunctExtensionTest.php b/tests/SmartPunctExtensionTest.php new file mode 100644 index 0000000000..bcdf10fa3c --- /dev/null +++ b/tests/SmartPunctExtensionTest.php @@ -0,0 +1,59 @@ + + * + * 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\Ext\SmartPunct\Tests; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Ext\SmartPunct\SmartPunctExtension; +use PHPUnit\Framework\TestCase; + +/** + * Tests the extension + */ +final class SmartPunctExtensionTest extends TestCase +{ + /** + * @var Environment + */ + protected $environment; + + protected function setUp() + { + $this->environment = Environment::createCommonMarkEnvironment(); + $this->environment->addExtension(new SmartPunctExtension()); + } + + public function testDefaultConfiguration() + { + $converter = new CommonMarkConverter([], $this->environment); + $actualResult = $converter->convertToHtml('"double" \'single\''); + $this->assertEquals("

    “double” ‘single’

    \n", $actualResult); + } + + public function testCustomConfiguration() + { + $converter = new CommonMarkConverter([ + 'smartpunct' => [ + 'double_quote_opener' => '«', + 'double_quote_closer' => '»', + 'single_quote_opener' => '‹', + 'single_quote_closer' => '›', + ], + ], $this->environment); + + $actualResult = $converter->convertToHtml('"double" \'single\''); + $this->assertEquals("

    «double» ‹single›

    \n", $actualResult); + } +} From 3746a86c91903fe200999a992de064f87b352019 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 3 Oct 2019 08:57:34 -0400 Subject: [PATCH 207/231] Prepare to release v1.1.0 --- CHANGELOG.md | 9 ++++++++- composer.json | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37b588d952..7fd8bd81fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.1.0] - 2019-10-03 + +### Added + +Added the ability to customize the opener and closer characters (#5) + ## [1.0.0] - 2019-06-29 No code changes have been introduced since 1.0.0-beta2. @@ -33,7 +39,8 @@ No code changes have been introduced since 1.0.0-beta2. Split this extension out of the old `league/commonmark-extras` library. -[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.1.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0...v1.1.0 [1.0.0]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta2...v1.0.0 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v1.0.0-beta1...v1.0.0-beta2 [1.0.0-beta1]: https://github.com/thephpleague/commonmark-ext-smartpunct/compare/v0.2.0...v1.0.0-beta1 diff --git a/composer.json b/composer.json index fd72632058..e015835afc 100644 --- a/composer.json +++ b/composer.json @@ -49,7 +49,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } } } From 163529a46fb22f586d10085aca895589b9428d11 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 11 Oct 2019 16:12:48 -0400 Subject: [PATCH 208/231] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 09cdff5dac..40a26fbffe 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ +github: colinodell patreon: colinodell From ce7ee5cd8b92b7482226ff0f28de816ccc48e228 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 11 Oct 2019 16:14:18 -0400 Subject: [PATCH 209/231] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 09cdff5dac..40a26fbffe 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ +github: colinodell patreon: colinodell From 14627519d1595fdc6dad3dbe11199b0e1cbc7bb2 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 11 Oct 2019 16:14:50 -0400 Subject: [PATCH 210/231] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 09cdff5dac..40a26fbffe 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ +github: colinodell patreon: colinodell From b3c0c50863b73ae080407010223657b84d522db4 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 11 Oct 2019 16:15:14 -0400 Subject: [PATCH 211/231] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 09cdff5dac..40a26fbffe 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ +github: colinodell patreon: colinodell From f831603ab8817964e6b8d9c1eddc5f6b97ecdb48 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Fri, 11 Oct 2019 16:16:26 -0400 Subject: [PATCH 212/231] Update FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 09cdff5dac..40a26fbffe 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1,2 @@ +github: colinodell patreon: colinodell From c13eefe68e809b1760b013974009f5468eb40fb3 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 3 Dec 2019 08:04:35 -0500 Subject: [PATCH 213/231] Test on PHP 7.4 stable --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35297f5ce4..910eed2a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,19 @@ language: php +dist: bionic + php: - 7.1 - 7.2 - 7.3 + - 7.4 env: matrix: - COMPOSER_FLAGS="" - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" -sudo: false - -before_script: - - travis_retry composer self-update +install: - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source script: From 062dc664daf5097cf9dfbc1f09add05e6cfc2919 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 3 Dec 2019 08:05:02 -0500 Subject: [PATCH 214/231] Test on PHP 7.4 stable --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35297f5ce4..910eed2a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,19 @@ language: php +dist: bionic + php: - 7.1 - 7.2 - 7.3 + - 7.4 env: matrix: - COMPOSER_FLAGS="" - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" -sudo: false - -before_script: - - travis_retry composer self-update +install: - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source script: From 91f807435fdec41880ccdb32a75b4996a2c4d8e9 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 3 Dec 2019 08:08:29 -0500 Subject: [PATCH 215/231] Test on PHP 7.4 stable --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35297f5ce4..910eed2a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,19 @@ language: php +dist: bionic + php: - 7.1 - 7.2 - 7.3 + - 7.4 env: matrix: - COMPOSER_FLAGS="" - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" -sudo: false - -before_script: - - travis_retry composer self-update +install: - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source script: From c79c667405290858d28ae5f44f0078583f4ccceb Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 3 Dec 2019 08:09:10 -0500 Subject: [PATCH 216/231] Test on PHP 7.4 stable --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35297f5ce4..910eed2a9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,19 @@ language: php +dist: bionic + php: - 7.1 - 7.2 - 7.3 + - 7.4 env: matrix: - COMPOSER_FLAGS="" - COMPOSER_FLAGS="--prefer-stable --prefer-lowest" -sudo: false - -before_script: - - travis_retry composer self-update +install: - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source script: From 5113a6b62e01252dc68ede71ee10afe1a27bf820 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Tue, 3 Dec 2019 08:10:14 -0500 Subject: [PATCH 217/231] Test on PHP 7.4 stable --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bbafd6ec89..ecffa3ecec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -sudo: false +dist: bionic cache: directories: @@ -10,6 +10,7 @@ php: - 7.1 - 7.2 - 7.3 + - 7.4 env: - COMMONMARK_VERSION=~0.19.3 From 128893ca6dcdf42fcc3466863fc3a505c772d8b1 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 13 Jan 2020 20:52:09 -0500 Subject: [PATCH 218/231] Fix incorrect parenthesis order (#13) --- CHANGELOG.md | 4 ++++ src/UrlAutolinkProcessor.php | 2 +- tests/UrlAutolinkProcessorTest.php | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dfaf3c013..79dcf68a9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +### Fixed + + - Fixed incorrect parenthesis order (#13) + ## [1.0.0] - 2019-06-29 No changes have been introduced since 1.0.0-beta3. diff --git a/src/UrlAutolinkProcessor.php b/src/UrlAutolinkProcessor.php index 49bd689f16..b36a3ce60a 100644 --- a/src/UrlAutolinkProcessor.php +++ b/src/UrlAutolinkProcessor.php @@ -105,7 +105,7 @@ private static function processAutolinks(Text $node, $regex) // Does the URL need its closing paren chopped off? if (\substr($content, -1) === ')' && self::hasMoreCloserParensThanOpeners($content)) { $content = \substr($content, 0, -1); - $leftovers .= ')'; + $leftovers = ')' . $leftovers; } self::addLink($node, $content); diff --git a/tests/UrlAutolinkProcessorTest.php b/tests/UrlAutolinkProcessorTest.php index f3502b5ce9..0b9ac90c59 100644 --- a/tests/UrlAutolinkProcessorTest.php +++ b/tests/UrlAutolinkProcessorTest.php @@ -62,6 +62,7 @@ public function dataProviderForAutolinkTests() yield ['www.google.com/search?q=Markup+(business)', '

    www.google.com/search?q=Markup+(business)

    ']; yield ['(www.google.com/search?q=Markup+(business))', '

    (www.google.com/search?q=Markup+(business))

    ']; yield ['www.google.com/search?q=(business))+ok', '

    www.google.com/search?q=(business))+ok

    ']; + yield ['(https://www.example.com/test).', '

    (https://www.example.com/test).

    ']; // Tests involving semi-colon endings yield ['www.google.com/search?q=commonmark&hl=en', '

    www.google.com/search?q=commonmark&hl=en

    ']; From 9b10753fa6cb21893f63d16680f01712adbc0f61 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 13 Jan 2020 20:53:02 -0500 Subject: [PATCH 219/231] Prepare to release v1.0.1 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79dcf68a9c..77d9af3e6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased][unreleased] +## [1.0.1] - 2020-01-13 + ### Fixed - Fixed incorrect parenthesis order (#13) @@ -73,7 +75,8 @@ This release brings the email and URL autolink processors into alignment with th Initial release! -[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0...HEAD +[unreleased]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.1...HEAD +[1.0.1]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta3...v1.0.0 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta2...v1.0.0-beta3 [1.0.0-beta2]: https://github.com/thephpleague/commonmark-ext-autolink/compare/v1.0.0-beta1...v1.0.0-beta2 From 75d76f7f518bcd9754dc294be60a2991fdccaecf Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 20 Jan 2020 20:16:09 -0500 Subject: [PATCH 220/231] Fix phpstan issues in imported extensions --- src/Extension/Autolink/EmailAutolinkProcessor.php | 2 +- src/Extension/Autolink/UrlAutolinkProcessor.php | 2 +- src/Extension/InlinesOnly/ChildRenderer.php | 9 +++++++-- src/Extension/SmartPunct/QuoteParser.php | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Extension/Autolink/EmailAutolinkProcessor.php b/src/Extension/Autolink/EmailAutolinkProcessor.php index 555f184c57..6916d3c2e2 100644 --- a/src/Extension/Autolink/EmailAutolinkProcessor.php +++ b/src/Extension/Autolink/EmailAutolinkProcessor.php @@ -40,7 +40,7 @@ private static function processAutolinks(Text $node) { $contents = \preg_split(self::REGEX, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); - if (\count($contents) === 1) { + if ($contents === false || \count($contents) === 1) { return; } diff --git a/src/Extension/Autolink/UrlAutolinkProcessor.php b/src/Extension/Autolink/UrlAutolinkProcessor.php index b166a93403..8783e4e2e7 100644 --- a/src/Extension/Autolink/UrlAutolinkProcessor.php +++ b/src/Extension/Autolink/UrlAutolinkProcessor.php @@ -69,7 +69,7 @@ private static function processAutolinks(Text $node, $regex) { $contents = \preg_split($regex, $node->getContent(), -1, PREG_SPLIT_DELIM_CAPTURE); - if (\count($contents) === 1) { + if ($contents === false || \count($contents) === 1) { return; } diff --git a/src/Extension/InlinesOnly/ChildRenderer.php b/src/Extension/InlinesOnly/ChildRenderer.php index 7a9391c1ed..e7d892be54 100644 --- a/src/Extension/InlinesOnly/ChildRenderer.php +++ b/src/Extension/InlinesOnly/ChildRenderer.php @@ -19,6 +19,7 @@ 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. @@ -33,9 +34,13 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $out = ''; if ($block instanceof InlineContainerInterface) { - $out .= $htmlRenderer->renderInlines($block->children()); + /** @var iterable $children */ + $children = $block->children(); + $out .= $htmlRenderer->renderInlines($children); } else { - $out .= $htmlRenderer->renderBlocks($block->children()); + /** @var iterable $children */ + $children = $block->children(); + $out .= $htmlRenderer->renderBlocks($children); } if (!($block instanceof Document)) { diff --git a/src/Extension/SmartPunct/QuoteParser.php b/src/Extension/SmartPunct/QuoteParser.php index 527d94d36f..bc3ea0cd24 100644 --- a/src/Extension/SmartPunct/QuoteParser.php +++ b/src/Extension/SmartPunct/QuoteParser.php @@ -56,7 +56,7 @@ public function parse(InlineParserContext $inlineContext): bool $charAfter = "\n"; } - list($leftFlanking, $rightFlanking) = $this->determineFlanking($charBefore, $charAfter); + [$leftFlanking, $rightFlanking] = $this->determineFlanking($charBefore, $charAfter); $canOpen = $leftFlanking && !$rightFlanking; $canClose = $rightFlanking; @@ -89,7 +89,7 @@ private function getNormalizedQuoteCharacter($character) * @param string $charBefore * @param string $charAfter * - * @return string[] + * @return bool[] */ private function determineFlanking($charBefore, $charAfter) { From 39feb16417d6c3bb801a3ec7b4f45961b1f7567e Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 20 Jan 2020 20:19:22 -0500 Subject: [PATCH 221/231] Fix extension namespaces and paths --- src/Extension/ExternalLink/ExternalLinkExtension.php | 2 +- src/Extension/ExternalLink/ExternalLinkProcessor.php | 2 +- src/Extension/InlinesOnly/ChildRenderer.php | 5 +---- src/Extension/InlinesOnly/InlinesOnlyExtension.php | 5 +---- .../Extension/InlinesOnly/InlinesOnlyFunctionalTest.php | 7 ++----- .../Extension/SmartPunct/SmartPunctFunctionalTest.php | 2 +- .../unit/Extension/Autolink/EmailAutolinkProcessorTest.php | 2 +- tests/unit/Extension/Autolink/InlineMentionParserTest.php | 2 +- tests/unit/Extension/Autolink/UrlAutolinkProcessorTest.php | 2 +- .../Extension/ExternalLink/ExternalLinkProcessorTest.php | 2 +- 10 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/Extension/ExternalLink/ExternalLinkExtension.php b/src/Extension/ExternalLink/ExternalLinkExtension.php index fa00e88c5d..9deee0bd0e 100644 --- a/src/Extension/ExternalLink/ExternalLinkExtension.php +++ b/src/Extension/ExternalLink/ExternalLinkExtension.php @@ -1,7 +1,7 @@ * diff --git a/src/Extension/ExternalLink/ExternalLinkProcessor.php b/src/Extension/ExternalLink/ExternalLinkProcessor.php index 0a35edc334..200f35c0f1 100644 --- a/src/Extension/ExternalLink/ExternalLinkProcessor.php +++ b/src/Extension/ExternalLink/ExternalLinkProcessor.php @@ -1,7 +1,7 @@ * diff --git a/src/Extension/InlinesOnly/ChildRenderer.php b/src/Extension/InlinesOnly/ChildRenderer.php index e7d892be54..defd4ceed9 100644 --- a/src/Extension/InlinesOnly/ChildRenderer.php +++ b/src/Extension/InlinesOnly/ChildRenderer.php @@ -1,13 +1,10 @@ * - * 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. */ diff --git a/src/Extension/InlinesOnly/InlinesOnlyExtension.php b/src/Extension/InlinesOnly/InlinesOnlyExtension.php index ccf4214507..29ffb303a5 100644 --- a/src/Extension/InlinesOnly/InlinesOnlyExtension.php +++ b/src/Extension/InlinesOnly/InlinesOnlyExtension.php @@ -1,13 +1,10 @@ * - * 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. */ diff --git a/tests/functional/Extension/InlinesOnly/InlinesOnlyFunctionalTest.php b/tests/functional/Extension/InlinesOnly/InlinesOnlyFunctionalTest.php index 8bdf82f9df..18784c1ad2 100644 --- a/tests/functional/Extension/InlinesOnly/InlinesOnlyFunctionalTest.php +++ b/tests/functional/Extension/InlinesOnly/InlinesOnlyFunctionalTest.php @@ -1,18 +1,15 @@ * - * 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\Tests\Functional\ExtensionInlinesOnly; +namespace League\CommonMark\Tests\Functional\Extension\InlinesOnly; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Converter; diff --git a/tests/functional/Extension/SmartPunct/SmartPunctFunctionalTest.php b/tests/functional/Extension/SmartPunct/SmartPunctFunctionalTest.php index dc99d6708b..691e28281d 100644 --- a/tests/functional/Extension/SmartPunct/SmartPunctFunctionalTest.php +++ b/tests/functional/Extension/SmartPunct/SmartPunctFunctionalTest.php @@ -67,7 +67,7 @@ public function testExample($markdown, $html, $section, $number) */ public function dataProvider() { - $filename = __DIR__ . '/../vendor/jgm/smartpunct/smart_punct.txt'; + $filename = __DIR__ . '/../../../../vendor/commonmark/commonmark.js/test/smart_punct.txt'; if (($data = file_get_contents($filename)) === false) { $this->fail(sprintf('Failed to load spec from %s', $filename)); } diff --git a/tests/unit/Extension/Autolink/EmailAutolinkProcessorTest.php b/tests/unit/Extension/Autolink/EmailAutolinkProcessorTest.php index 926868fa4e..f0ef74b0af 100644 --- a/tests/unit/Extension/Autolink/EmailAutolinkProcessorTest.php +++ b/tests/unit/Extension/Autolink/EmailAutolinkProcessorTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace League\CommonMark\Tests\Extension\Autolink\Test\Email; +namespace League\CommonMark\Tests\Unit\Extension\Autolink; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; diff --git a/tests/unit/Extension/Autolink/InlineMentionParserTest.php b/tests/unit/Extension/Autolink/InlineMentionParserTest.php index 07568da309..d8cdd3dc56 100644 --- a/tests/unit/Extension/Autolink/InlineMentionParserTest.php +++ b/tests/unit/Extension/Autolink/InlineMentionParserTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace League\CommonMark\Tests\Extension\Autolink\Test; +namespace League\CommonMark\Tests\Unit\Extension\Autolink; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; diff --git a/tests/unit/Extension/Autolink/UrlAutolinkProcessorTest.php b/tests/unit/Extension/Autolink/UrlAutolinkProcessorTest.php index 1ffeef9510..e77e752957 100644 --- a/tests/unit/Extension/Autolink/UrlAutolinkProcessorTest.php +++ b/tests/unit/Extension/Autolink/UrlAutolinkProcessorTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace League\CommonMark\Tests\Extension\Autolink\Test\Url; +namespace League\CommonMark\Tests\Unit\Extension\Autolink; use League\CommonMark\CommonMarkConverter; use League\CommonMark\Environment; diff --git a/tests/unit/Extension/ExternalLink/ExternalLinkProcessorTest.php b/tests/unit/Extension/ExternalLink/ExternalLinkProcessorTest.php index 5be649388a..d5e45cb62d 100644 --- a/tests/unit/Extension/ExternalLink/ExternalLinkProcessorTest.php +++ b/tests/unit/Extension/ExternalLink/ExternalLinkProcessorTest.php @@ -1,7 +1,7 @@ * From 79474604d22b2e12d0582fa5e649ebbc1530ce6a Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 Jan 2020 16:36:34 -0500 Subject: [PATCH 222/231] Use the 'align' attribute instead of hard-coded CSS --- src/Extension/Table/TableCellRenderer.php | 2 +- .../Extension/Table/data/aligned_table.html | 18 +++++++++--------- .../Extension/Table/data/simple_table.html | 6 +++--- .../Extension/Table/data/table-aligned.html | 8 ++++---- .../Extension/Table/data/table-caption.html | 18 +++++++++--------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Extension/Table/TableCellRenderer.php b/src/Extension/Table/TableCellRenderer.php index 0f0e6da58a..eafb85520e 100644 --- a/src/Extension/Table/TableCellRenderer.php +++ b/src/Extension/Table/TableCellRenderer.php @@ -31,7 +31,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $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/tests/functional/Extension/Table/data/aligned_table.html b/tests/functional/Extension/Table/data/aligned_table.html index f983f54efd..4c1d319c57 100644 --- a/tests/functional/Extension/Table/data/aligned_table.html +++ b/tests/functional/Extension/Table/data/aligned_table.html @@ -1,21 +1,21 @@
    - - - + + + - - - + + + - - - + + +
    header 1header 2header 2header 1header 2header 2
    cell 1.1cell 1.2cell 1.3cell 1.1cell 1.2cell 1.3
    cell 2.1cell 2.2cell 2.3cell 2.1cell 2.2cell 2.3
    diff --git a/tests/functional/Extension/Table/data/simple_table.html b/tests/functional/Extension/Table/data/simple_table.html index 5b381589fd..d38b1df177 100644 --- a/tests/functional/Extension/Table/data/simple_table.html +++ b/tests/functional/Extension/Table/data/simple_table.html @@ -20,17 +20,17 @@ - + - + - + diff --git a/tests/functional/Extension/Table/data/table-aligned.html b/tests/functional/Extension/Table/data/table-aligned.html index d9076608b4..2fc996c9a8 100644 --- a/tests/functional/Extension/Table/data/table-aligned.html +++ b/tests/functional/Extension/Table/data/table-aligned.html @@ -2,15 +2,15 @@ - - + + - - + +
    header 1header 1 header 2
    cell 1.1cell 1.1 cell 1.2
    cell 2.1cell 2.1 cell 2.2
    thth(center)th(right)th(center)th(right)
    tdtdtdtdtd
    diff --git a/tests/functional/Extension/Table/data/table-caption.html b/tests/functional/Extension/Table/data/table-caption.html index 7e032428c7..94970e7e64 100644 --- a/tests/functional/Extension/Table/data/table-caption.html +++ b/tests/functional/Extension/Table/data/table-caption.html @@ -21,21 +21,21 @@ Prototype table -First Header -Second Header -Third Header +First Header +Second Header +Third Header -First row -Data -Very long data entry +First row +Data +Very long data entry -Second row -Cell -Cell +Second row +Cell +Cell From d347978670ac15b513fc1544c5d553dbedc2c7e9 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Thu, 23 Jan 2020 16:38:01 -0500 Subject: [PATCH 223/231] Add new DisallowedRawHtml extension --- .../DisallowedRawHtmlBlockRenderer.php | 53 +++++++++++ .../DisallowedRawHtmlExtension.php | 28 ++++++ .../DisallowedRawHtmlInlineRenderer.php | 53 +++++++++++ .../DisallowedRawHtmlExtensionTest.php | 92 +++++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php create mode 100644 src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php create mode 100644 src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php create mode 100644 tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php diff --git a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php new file mode 100644 index 0000000000..a41c4dfc2a --- /dev/null +++ b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php @@ -0,0 +1,53 @@ + + * + * 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 /> + 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/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlExtension.php new file mode 100644 index 0000000000..f5579dba5f --- /dev/null +++ b/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/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php new file mode 100644 index 0000000000..9d86a14032 --- /dev/null +++ b/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 /> + 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/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php b/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php new file mode 100644 index 0000000000..1e26f264d9 --- /dev/null +++ b/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php @@ -0,0 +1,92 @@ +<?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\Tests\Functional\Extension\DisallowedRawHtml; + +use League\CommonMark\CommonMarkConverter; +use League\CommonMark\Environment; +use League\CommonMark\Extension\DisallowedRawHtml\DisallowedRawHtmlExtension; +use PHPUnit\Framework\TestCase; + +class DisallowedRawHtmlExtensionTest extends TestCase +{ + public function testDisallowedRawHtmlExtensionWithSpecExample() + { + $input = <<<MD +<strong> <title> <style> <em> + +<blockquote> + <xmp> is disallowed. <XMP> is also disallowed. +</blockquote> +MD; + + $expected = <<<HTML +<p><strong> <title> <style> <em></p> +<blockquote> + <xmp> is disallowed. <XMP> is also disallowed. +</blockquote> + +HTML; + + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addExtension(new DisallowedRawHtmlExtension()); + $converter = new CommonMarkConverter([], $environment); + + $this->assertSame($expected, $converter->convertToHtml($input)); + } + + public function testIndividualHtmlTagsAsBlocks() + { + $input = <<<MD +<title>My Cool Website + + + + +Itallic font should be marked up using the <i> and </i> tags. + + + +<h1>Alternative content</h1> + +<h1>Alternative content</h1> + +
    + +foo</plaintext> +MD; + + $expected = <<<HTML +&lt;title>My Cool Website&lt;/title> +&lt;textarea> + foo=bar +&lt;/textarea> +&lt;style>* { display: none; &lt;/style> +<p>&lt;xmp>Itallic font should be marked up using the <i> and </i> tags.&lt;/xmp></p> +&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>&lt;/iframe> +<p>&lt;noembed><h1>Alternative content</h1>&lt;/noembed></p> +&lt;noframes><h1>Alternative content</h1>&lt;/noframes> +<hr> +&lt;script type="application/javascript">alert('XSS is fun!')&lt;/script> +&lt;plaintext>foo&lt;/plaintext> + +HTML; + + $environment = Environment::createCommonMarkEnvironment(); + $environment->addExtension(new DisallowedRawHtmlExtension()); + $converter = new CommonMarkConverter([], $environment); + + $this->assertSame($expected, $converter->convertToHtml($input)); + } +} From f48f356788b9ac1d8f5d348140675bb50f1f9c25 Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Fri, 31 Jan 2020 19:40:59 -0500 Subject: [PATCH 224/231] Create a new GFM extension to replace the suggest commonmark-extra library --- README.md | 41 +++++++++++++------ composer.json | 3 -- docs/1.0/customization/extensions.md | 28 +++++++++++++ src/Environment.php | 9 ++++ src/Extension/Autolink/README.md | 2 +- src/Extension/ExternalLink/README.md | 2 +- .../GithubFlavoredMarkdownExtension.php | 31 ++++++++++++++ src/GithubFlavoredMarkdownConverter.php | 33 +++++++++++++++ 8 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 src/Extension/GithubFlavoredMarkdownExtension.php create mode 100644 src/GithubFlavoredMarkdownConverter.php diff --git a/README.md b/README.md index d878c5d0d2..82b53d1545 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,33 @@ 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 + +Github-Flavored Markdown can be parsed by using the `GithubFlavoredMarkdownConverter`: + +```php +use League\CommonMark\GithubFlavoredMarkdownConverter; + +$converter = new GithubFlavoredMarkdownConverter([ + 'html_input' => 'strip', + 'allow_unsafe_links' => false, +]); + +echo $converter->convertToHtml('# Hello World!'); + +// <h1>Hello World!</h1> +``` + +This 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,19 +89,7 @@ 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: - -| 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 +### 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. diff --git a/composer.json b/composer.json index 5e80aa2de6..73bcd95a91 100644 --- a/composer.json +++ b/composer.json @@ -35,9 +35,6 @@ "scrutinizer/ocular": "^1.5", "symfony/finder": "^4.2" }, - "suggest": { - "league/commonmark-extras": "Library of useful extensions including smart punctuation" - }, "repositories": [ { "type": "package", diff --git a/docs/1.0/customization/extensions.md b/docs/1.0/customization/extensions.md index 31afae6756..9713e06cdd 100644 --- a/docs/1.0/customization/extensions.md +++ b/docs/1.0/customization/extensions.md @@ -34,3 +34,31 @@ $environment->addExtension(new EmojiExtension(); $converter = new CommonMarkConverter([], $environment); echo $converter->convertToHtml('Hello! :wave:'); ``` + +## Included Extensions + +Starting in v1.3, this library includes several extensions to support Github-Flavored Markdown. You can manually add the GFM extension to your environment like this: + +```php +$environment = Environment::createCommonMarkExtension(); +$environment->addExtension(new GithubFlavoredMarkdownExtension(); + +$converter = new CommonMarkConverter([], $environment); +echo $converter->convertToHtml('Hello GFM!'); + +``` + +Or, if you only want a subset of GFM extensions, you can add them individually like this instead: + +```php +$environment = Environment::createCommonMarkExtension(); +// Remove any of the lines below if you don't want those features +$environment->addExtension(new AutolinkExtension()); +$environment->addExtension(new DisallowedRawHtmlExtension()); +$environment->addExtension(new StrikethroughExtension()); +$environment->addExtension(new TableExtension()); +$environment->addExtension(new TaskListExtension()); + +$converter = new CommonMarkConverter([], $environment); +echo $converter->convertToHtml('Hello GFM!'); +``` diff --git a/src/Environment.php b/src/Environment.php index 443bf257fb..eea85fdbac 100644 --- a/src/Environment.php +++ b/src/Environment.php @@ -21,6 +21,7 @@ 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; @@ -354,6 +355,14 @@ public static function createCommonMarkEnvironment(): Environment return $environment; } + public static function createGFMEnvironment(): EnvironmentInterface + { + $environment = self::createCommonMarkEnvironment(); + $environment->addExtension(new GithubFlavoredMarkdownExtension()); + + return $environment; + } + /** * {@inheritdoc} */ diff --git a/src/Extension/Autolink/README.md b/src/Extension/Autolink/README.md index 6c45a38c78..3dfdb62477 100644 --- a/src/Extension/Autolink/README.md +++ b/src/Extension/Autolink/README.md @@ -21,7 +21,7 @@ $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-ext-autolink extension!'); +echo $converter->convertToHtml('I successfully installed the https://github.com/thephpleague/commonmark project with the Autolink extension!'); ``` ## `@mention` Autolinking diff --git a/src/Extension/ExternalLink/README.md b/src/Extension/ExternalLink/README.md index 4c74461019..2eec7e22c4 100644 --- a/src/Extension/ExternalLink/README.md +++ b/src/Extension/ExternalLink/README.md @@ -31,7 +31,7 @@ $config = [ // 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-ext-external-link extension!'); +echo $converter->convertToHtml('I successfully installed the https://github.com/thephpleague/commonmark project with the Autolink extension!'); ``` ## Configuration diff --git a/src/Extension/GithubFlavoredMarkdownExtension.php b/src/Extension/GithubFlavoredMarkdownExtension.php new file mode 100644 index 0000000000..41659c126b --- /dev/null +++ b/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/src/GithubFlavoredMarkdownConverter.php b/src/GithubFlavoredMarkdownConverter.php new file mode 100644 index 0000000000..ef4b5946a1 --- /dev/null +++ b/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); + } +} From a14ac190c23c29591294d3c303178a27b1e795ae Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Fri, 31 Jan 2020 19:45:33 -0500 Subject: [PATCH 225/231] Test the GFM extension against the GFM spec --- composer.json | 12 ++++++ tests/functional/AbstractSpecTest.php | 16 +++++--- .../GithubFlavoredMarkdownExtensionTest.php | 41 +++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php diff --git a/composer.json b/composer.json index 73bcd95a91..668ce4567d 100644 --- a/composer.json +++ b/composer.json @@ -28,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", @@ -46,6 +47,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": { diff --git a/tests/functional/AbstractSpecTest.php b/tests/functional/AbstractSpecTest.php index b3c619d83c..8e4d07ad79 100644 --- a/tests/functional/AbstractSpecTest.php +++ b/tests/functional/AbstractSpecTest.php @@ -52,6 +52,11 @@ public function testSpecExample($markdown, $html) } public function dataProvider() + { + yield from $this->loadSpecExamples(); + } + + public function loadSpecExamples() { if (($data = file_get_contents($this->getFileName())) === false) { $this->fail('Could not load tests from ' . $this->getFileName()); @@ -61,26 +66,27 @@ public function dataProvider() // Normalize newlines for platform independence $data = preg_replace('/\r\n?/', "\n", $data); $data = preg_replace('/<!-- END TESTS -->.*$/', '', $data); - preg_match_all('/^`{32} example\n([\s\S]*?)^\.\n([\s\S]*?)^`{32}$|^#{1,6} *(.*)$/m', $data, $matches, PREG_SET_ORDER); + preg_match_all('/^`{32} (example ?\w*)\n([\s\S]*?)^\.\n([\s\S]*?)^`{32}$|^#{1,6} *(.*)$/m', $data, $matches, PREG_SET_ORDER); $examples = []; $currentSection = 'Example'; $exampleNumber = 0; foreach ($matches as $match) { - if (isset($match[3])) { - $currentSection = $match[3]; + if (isset($match[4])) { + $currentSection = $match[4]; } else { $exampleNumber++; $testName = trim($currentSection . ' #' . $exampleNumber); - $markdown = $match[1]; + $markdown = $match[2]; $markdown = str_replace('→', "\t", $markdown); yield $testName => [ 'markdown' => $markdown, - 'html' => $match[2], + 'html' => $match[3], + 'type' => $match[1], ]; } } diff --git a/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php b/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php new file mode 100644 index 0000000000..c02e817a65 --- /dev/null +++ b/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php @@ -0,0 +1,41 @@ +<?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\Tests\Functional\Extension; + +use League\CommonMark\GithubFlavoredMarkdownConverter; +use League\CommonMark\Tests\Functional\AbstractSpecTest; + +class GithubFlavoredMarkdownExtensionTest extends AbstractSpecTest +{ + protected function setUp() + { + $this->converter = new GithubFlavoredMarkdownConverter(); + } + + protected function getFileName(): string + { + return __DIR__.'/../../../vendor/github/gfm/test/spec.txt'; + } + + public function dataProvider() + { + foreach ($this->loadSpecExamples() as $title => $data) { + // In the GFM spec, standard CommonMark tests are tagged 'example' + // and we don't want to test those (because we test those against the + // official CommonMark spec), but we DO want to test the GFM-specific ones + // which will be tagged something like 'example autolink' + if ($data['type'] !== 'example') { + yield $title => $data; + } + } + } +} From 08a8e14ed5904b417788cb5ee6fc8b9143ad1219 Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Fri, 31 Jan 2020 20:18:05 -0500 Subject: [PATCH 226/231] Modify Task List functionality to match the GFM spec --- src/Block/Renderer/ListItemRenderer.php | 11 ++++++- .../TaskList/TaskListItemMarkerRenderer.php | 5 ++- src/HtmlElement.php | 2 ++ .../TaskList/TaskListExtensionTest.php | 33 +++++++------------ 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/Block/Renderer/ListItemRenderer.php b/src/Block/Renderer/ListItemRenderer.php index 6f165a8af0..c9972fad5a 100644 --- a/src/Block/Renderer/ListItemRenderer.php +++ b/src/Block/Renderer/ListItemRenderer.php @@ -16,7 +16,9 @@ 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 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende } $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 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende return $li; } + + private function startsTaskListItem(ListItem $block): bool + { + $firstChild = $block->firstChild(); + + return $firstChild instanceof Paragraph && $firstChild->firstChild() instanceof TaskListItemMarker; + } } diff --git a/src/Extension/TaskList/TaskListItemMarkerRenderer.php b/src/Extension/TaskList/TaskListItemMarkerRenderer.php index c066bb2fd4..a65513adc1 100644 --- a/src/Extension/TaskList/TaskListItemMarkerRenderer.php +++ b/src/Extension/TaskList/TaskListItemMarkerRenderer.php @@ -30,12 +30,15 @@ public function render(AbstractInline $inline, ElementRendererInterface $htmlRen throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline)); } - $checkbox = new HtmlElement('input', ['disabled' => '', 'type' => 'checkbox'], '', true); + $checkbox = new HtmlElement('input', [], '', true); if ($inline->isChecked()) { $checkbox->setAttribute('checked', ''); } + $checkbox->setAttribute('disabled', ''); + $checkbox->setAttribute('type', 'checkbox'); + return $checkbox; } } diff --git a/src/HtmlElement.php b/src/HtmlElement.php index 19f997538c..93f1046305 100644 --- a/src/HtmlElement.php +++ b/src/HtmlElement.php @@ -137,6 +137,8 @@ public function __toString(): string if ($this->contents !== '') { $result .= '>' . $this->getContentsAsString() . '</' . $this->tagName . '>'; + } elseif ($this->selfClosing && $this->tagName === 'input') { + $result .= '>'; } elseif ($this->selfClosing) { $result .= ' />'; } else { diff --git a/tests/unit/Extension/TaskList/TaskListExtensionTest.php b/tests/unit/Extension/TaskList/TaskListExtensionTest.php index 6913af0165..133c51772e 100644 --- a/tests/unit/Extension/TaskList/TaskListExtensionTest.php +++ b/tests/unit/Extension/TaskList/TaskListExtensionTest.php @@ -60,34 +60,24 @@ public function testTaskLists() $expected = <<<'EOT' <ul> -<li> -<input disabled="" type="checkbox" checked="" /> foo +<li><input checked="" disabled="" type="checkbox"> foo <ul> -<li> -<input disabled="" type="checkbox" /> bar</li> -<li> -<input disabled="" type="checkbox" checked="" /> baz</li> +<li><input disabled="" type="checkbox"> bar</li> +<li><input checked="" disabled="" type="checkbox"> baz</li> </ul> </li> -<li> -<input disabled="" type="checkbox" /> bim</li> +<li><input disabled="" type="checkbox"> bim</li> </ul> <ul> -<li> -<input disabled="" type="checkbox" checked="" /> foo</li> -<li> -<input disabled="" type="checkbox" checked="" /> bar</li> -<li> -<input disabled="" type="checkbox" /> baz</li> +<li><input checked="" disabled="" type="checkbox"> foo</li> +<li><input checked="" disabled="" type="checkbox"> bar</li> +<li><input disabled="" type="checkbox"> baz</li> </ul> <p>This works for ordered lists too:</p> <ol> -<li> -<input disabled="" type="checkbox" checked="" /> foo</li> -<li> -<input disabled="" type="checkbox" checked="" /> bar</li> -<li> -<input disabled="" type="checkbox" /> baz</li> +<li><input checked="" disabled="" type="checkbox"> foo</li> +<li><input checked="" disabled="" type="checkbox"> bar</li> +<li><input disabled="" type="checkbox"> baz</li> </ol> <p>Some examples which should not match:</p> <ul> @@ -111,8 +101,7 @@ public function testTaskLists() </ul> <p>Here's a test using <code>&lt;del&gt;</code>:</p> <ul> -<li> -<input disabled="" type="checkbox" checked="" /> <del>Checkbox inside of strikeout</del> +<li><input checked="" disabled="" type="checkbox"> <del>Checkbox inside of strikeout</del> </li> </ul> <p>And another which does not render the checkbox:</p> From 396168526cf4166e7159e947908644142ff2f21b Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Mon, 3 Feb 2020 20:36:03 -0500 Subject: [PATCH 227/231] Modify table functionality to match GFM spec --- src/Extension/Table/TableParser.php | 217 +++++++++++++++--- src/Extension/Table/TableRenderer.php | 4 +- .../Table/data/single_column_table.html | 8 +- ...ingle_column_table_and_block_elements.html | 7 + .../single_column_table_and_block_elements.md | 18 +- .../data/single_column_table_caption.html | 8 +- .../Table/data/table-and-block-elements.html | 41 +--- .../Extension/Table/data/table-caption.html | 11 +- .../Extension/Table/data/table-caption.md | 59 ++++- .../Table/data/table_inline_markdown.html | 6 +- 10 files changed, 289 insertions(+), 90 deletions(-) diff --git a/src/Extension/Table/TableParser.php b/src/Extension/Table/TableParser.php index 327ea60ee5..0a78a3ba07 100644 --- a/src/Extension/Table/TableParser.php +++ b/src/Extension/Table/TableParser.php @@ -15,46 +15,65 @@ 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; use League\CommonMark\Util\RegexHelper; -final class TableParser implements BlockParserInterface +final class TableParser implements BlockParserInterface, EnvironmentAwareInterface { - const REGEXP_DEFINITION = '/(?: *(:?) *-+ *(:?) *)+(?=\||$)/'; - const REGEXP_CELLS = '/(?:`[^`]*`|\\\\\||\\\\|[^|`\\\\]+)+(?=\||$)/'; const REGEXP_CAPTION = '/^\[(.+?)\](?:\[(.+)\])?\s*$/'; + /** + * @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) { + if (count($lines) !== 1) { return false; } - $expressionOffset = $cursor->getNextNonSpacePosition(); + if (\strpos($lines[0], '|') === false) { + return false; + } - $match = RegexHelper::matchAll(self::REGEXP_DEFINITION, $cursor->getLine(), $expressionOffset); - if (null === $match) { + $oldState = $cursor->saveState(); + $cursor->advanceToNextNonSpaceOrTab(); + $columns = $this->parseColumns($cursor); + + if (empty($columns)) { + $cursor->restoreState($oldState); return false; } - $columns = $this->parseColumns($match); - $head = $this->parseRow(trim((string) array_pop($lines)), $columns, TableCell::TYPE_HEAD); + $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 { - $row = $this->parseRow($cursor->getLine(), $columns); + // 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) { if (null !== $table->getCaption()) { return false; @@ -91,40 +110,27 @@ public function parse(ContextInterface $context, Cursor $cursor): bool 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); + $cells = $this->split(new Cursor(\trim($line))); - if (null === $cells || $line === $cells[0]) { + 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 ((array) $cells[0] as $i => $cell) { - if (!isset($columns[$i])) { + foreach ($cells as $i => $cell) { + if (!array_key_exists($i, $columns)) { return $row; } - $row->appendChild(new TableCell(trim($cell), $type, isset($columns[$i]) ? $columns[$i] : null)); + $row->appendChild(new TableCell(trim($cell), $type, $columns[$i])); } for ($j = count($columns) - 1; $j > $i; --$j) { @@ -134,6 +140,46 @@ private function parseRow(string $line, array $columns, string $type = TableCell 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; + } + private function parseCaption(string $line): ?TableCaption { $caption = RegexHelper::matchAll(self::REGEXP_CAPTION, $line); @@ -144,4 +190,107 @@ private function parseCaption(string $line): ?TableCaption return new TableCaption($caption[1], $caption[2]); } + + /** + * @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/src/Extension/Table/TableRenderer.php b/src/Extension/Table/TableRenderer.php index 27c95ecf09..33d8b94558 100644 --- a/src/Extension/Table/TableRenderer.php +++ b/src/Extension/Table/TableRenderer.php @@ -32,6 +32,8 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $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/tests/functional/Extension/Table/data/single_column_table.html b/tests/functional/Extension/Table/data/single_column_table.html index 19674224df..0bcd5815d3 100644 --- a/tests/functional/Extension/Table/data/single_column_table.html +++ b/tests/functional/Extension/Table/data/single_column_table.html @@ -20,9 +20,11 @@ <tr> <td>cell 1.1</td> </tr> +<tr> +<td>`</td> +</tr> </tbody> </table> -<p><code>| not a cell |</code></p> <table> <thead> <tr> @@ -33,6 +35,8 @@ <tr> <td>cell 1.1</td> </tr> +<tr> +<td>| not a cell |</td> +</tr> </tbody> </table> -<p>| not a cell |</p> diff --git a/tests/functional/Extension/Table/data/single_column_table_and_block_elements.html b/tests/functional/Extension/Table/data/single_column_table_and_block_elements.html index 28a3633304..8163c93928 100644 --- a/tests/functional/Extension/Table/data/single_column_table_and_block_elements.html +++ b/tests/functional/Extension/Table/data/single_column_table_and_block_elements.html @@ -9,6 +9,13 @@ <tr> <td>cell 1.1</td> </tr> +<tr> +<td>Not a paragraph</td> +</tr> </tbody> </table> <p>Paragraph</p> +<p>Paragraph and not a table +| header 1 | +| -------- | +| cell 1.1 |</p> diff --git a/tests/functional/Extension/Table/data/single_column_table_and_block_elements.md b/tests/functional/Extension/Table/data/single_column_table_and_block_elements.md index 9736af7c7f..c348fa8009 100644 --- a/tests/functional/Extension/Table/data/single_column_table_and_block_elements.md +++ b/tests/functional/Extension/Table/data/single_column_table_and_block_elements.md @@ -1,5 +1,13 @@ -Paragraph -| header 1 | -| -------- | -| cell 1.1 | -Paragraph +Paragraph + +| header 1 | +| -------- | +| cell 1.1 | +Not a paragraph + +Paragraph + +Paragraph and not a table +| header 1 | +| -------- | +| cell 1.1 | diff --git a/tests/functional/Extension/Table/data/single_column_table_caption.html b/tests/functional/Extension/Table/data/single_column_table_caption.html index 1d93e6af83..2e1623ddf1 100644 --- a/tests/functional/Extension/Table/data/single_column_table_caption.html +++ b/tests/functional/Extension/Table/data/single_column_table_caption.html @@ -1,5 +1,4 @@ <table> -<caption>Simple table</caption> <thead> <tr> <th>header 1</th> @@ -9,10 +8,12 @@ <tr> <td>cell 1.1</td> </tr> +<tr> +<td>[Simple table]</td> +</tr> </tbody> </table> <table> -<caption>Simple table 2</caption> <thead> <tr> <th>header 1</th> @@ -25,5 +26,8 @@ <tr> <td>[Not a caption]</td> </tr> +<tr> +<td>[Simple table 2]</td> +</tr> </tbody> </table> diff --git a/tests/functional/Extension/Table/data/table-and-block-elements.html b/tests/functional/Extension/Table/data/table-and-block-elements.html index ce8168989a..f9e1ff0415 100644 --- a/tests/functional/Extension/Table/data/table-and-block-elements.html +++ b/tests/functional/Extension/Table/data/table-and-block-elements.html @@ -18,7 +18,10 @@ <h2>H2</h2> <li>list</li> <li>list</li> </ul> -<p>Paragraph</p> +<p>Paragraph +th | th +---|--- +td | td</p> <table> <thead> <tr> @@ -31,36 +34,14 @@ <h2>H2</h2> <td>td</td> <td>td</td> </tr> -</tbody> -</table> -<table> -<thead> -<tr> -<th>th</th> -<th>th</th> -</tr> -</thead> -<tbody> -<tr> -<td>td</td> -<td>td</td> -</tr> -</tbody> -</table> -<p>Paragraph</p> -<p>Paragraph</p> -<table> -<thead> <tr> -<th>th</th> -<th>th</th> -</tr> -</thead> -<tbody> -<tr> -<td>td</td> -<td>td</td> +<td>Paragraph</td> +<td></td> </tr> </tbody> </table> -<p>Paragraph</p> +<p>Paragraph +th | th +---|--- +td | td +Paragraph</p> diff --git a/tests/functional/Extension/Table/data/table-caption.html b/tests/functional/Extension/Table/data/table-caption.html index 94970e7e64..fb67000b0f 100644 --- a/tests/functional/Extension/Table/data/table-caption.html +++ b/tests/functional/Extension/Table/data/table-caption.html @@ -1,5 +1,4 @@ <table> -<caption>Simple table</caption> <thead> <tr> <th>header 1</th> @@ -15,10 +14,13 @@ <td>cell 2.1</td> <td>cell 2.2</td> </tr> +<tr> +<td>[Simple table]</td> +<td></td> +</tr> </tbody> </table> <table> -<caption id="reference_table"><em>Prototype</em> table</caption> <thead> <tr> <th align="left">First Header</th> @@ -37,5 +39,10 @@ <td align="center"><strong>Cell</strong></td> <td align="right"><em>Cell</em></td> </tr> +<tr> +<td align="left">[<em>Prototype</em> table][reference_table]</td> +<td align="center"></td> +<td align="right"></td> +</tr> </tbody> </table> diff --git a/tests/functional/Extension/Table/data/table-caption.md b/tests/functional/Extension/Table/data/table-caption.md index 2c8a05bf58..fb67000b0f 100644 --- a/tests/functional/Extension/Table/data/table-caption.md +++ b/tests/functional/Extension/Table/data/table-caption.md @@ -1,11 +1,48 @@ -header 1 | header 2 --------- | -------- -cell 1.1 | cell 1.2 -cell 2.1 | cell 2.2 -[Simple table] - -| First Header | Second Header | Third Header | -| :----------- | :-----------: | -------------------: | -| First row | Data | Very long data entry | -| Second row | **Cell** | *Cell* | -[*Prototype* table][reference_table] +<table> +<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> +<tr> +<td>cell 2.1</td> +<td>cell 2.2</td> +</tr> +<tr> +<td>[Simple table]</td> +<td></td> +</tr> +</tbody> +</table> +<table> +<thead> +<tr> +<th align="left">First Header</th> +<th align="center">Second Header</th> +<th align="right">Third Header</th> +</tr> +</thead> +<tbody> +<tr> +<td align="left">First row</td> +<td align="center">Data</td> +<td align="right">Very long data entry</td> +</tr> +<tr> +<td align="left">Second row</td> +<td align="center"><strong>Cell</strong></td> +<td align="right"><em>Cell</em></td> +</tr> +<tr> +<td align="left">[<em>Prototype</em> table][reference_table]</td> +<td align="center"></td> +<td align="right"></td> +</tr> +</tbody> +</table> diff --git a/tests/functional/Extension/Table/data/table_inline_markdown.html b/tests/functional/Extension/Table/data/table_inline_markdown.html index b294088941..7867526e39 100644 --- a/tests/functional/Extension/Table/data/table_inline_markdown.html +++ b/tests/functional/Extension/Table/data/table_inline_markdown.html @@ -11,11 +11,11 @@ <td><strong>cell</strong> 1.2</td> </tr> <tr> -<td><code>|</code> 2.1</td> -<td>| 2.2</td> +<td>`</td> +<td>` 2.1</td> </tr> <tr> -<td><code>\|</code> 2.1</td> +<td><code>|</code> 2.1</td> <td><a href="/">link</a></td> </tr> <tr> From 7d034ffabaa8ad95b4a958c549183136d237dbb8 Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Mon, 3 Feb 2020 21:03:08 -0500 Subject: [PATCH 228/231] Fix code style --- .styleci.yml | 3 +++ .../DisallowedRawHtmlBlockRenderer.php | 4 ++-- .../DisallowedRawHtmlInlineRenderer.php | 4 ++-- src/Extension/Table/TableCaptionRenderer.php | 2 +- src/Extension/Table/TableCellRenderer.php | 2 +- src/Extension/Table/TableParser.php | 6 ++++-- src/Extension/Table/TableRenderer.php | 4 ++-- src/Extension/Table/TableRow.php | 5 +++-- src/Extension/Table/TableRowRenderer.php | 4 ++-- src/Extension/Table/TableSectionRenderer.php | 4 ++-- .../DisallowedRawHtmlExtensionTest.php | 9 ++++----- .../Extension/GithubFlavoredMarkdownExtensionTest.php | 2 +- tests/functional/Extension/Table/LocalDataTest.php | 10 +++++----- 13 files changed, 32 insertions(+), 27 deletions(-) diff --git a/.styleci.yml b/.styleci.yml index eef87ee7bc..af07887da9 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -17,5 +17,8 @@ finder: - ".phpstorm.meta.php" - "CommonMarkCoreExtension.php" - "FakeEmptyHtmlRenderer.php" + - "InlinesOnlyExtension.php" + - "SmartPunctExtension.php" + - "TableExtension.php" not-path: - ".ripstech" diff --git a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php index a41c4dfc2a..7947c5e7e5 100644 --- a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php +++ b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlBlockRenderer.php @@ -27,7 +27,7 @@ public function __construct(BlockRendererInterface $htmlBlockRenderer) } /** - * @inheritDoc + * {@inheritdoc} */ public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false) { @@ -42,7 +42,7 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende } /** - * @inheritDoc + * {@inheritdoc} */ public function setConfiguration(ConfigurationInterface $configuration) { diff --git a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php index 9d86a14032..2783281ec9 100644 --- a/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php +++ b/src/Extension/DisallowedRawHtml/DisallowedRawHtmlInlineRenderer.php @@ -27,7 +27,7 @@ public function __construct(InlineRendererInterface $htmlBlockRenderer) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { @@ -42,7 +42,7 @@ public function render(AbstractInline $inline, ElementRendererInterface $htmlRen } /** - * @inheritDoc + * {@inheritdoc} */ public function setConfiguration(ConfigurationInterface $configuration) { diff --git a/src/Extension/Table/TableCaptionRenderer.php b/src/Extension/Table/TableCaptionRenderer.php index 0f6f31b949..4c0e341434 100644 --- a/src/Extension/Table/TableCaptionRenderer.php +++ b/src/Extension/Table/TableCaptionRenderer.php @@ -25,7 +25,7 @@ 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)); + throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block)); } $attrs = $block->getData('attributes', []); diff --git a/src/Extension/Table/TableCellRenderer.php b/src/Extension/Table/TableCellRenderer.php index eafb85520e..c149633efa 100644 --- a/src/Extension/Table/TableCellRenderer.php +++ b/src/Extension/Table/TableCellRenderer.php @@ -25,7 +25,7 @@ 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', []); diff --git a/src/Extension/Table/TableParser.php b/src/Extension/Table/TableParser.php index 0a78a3ba07..5f902e3944 100644 --- a/src/Extension/Table/TableParser.php +++ b/src/Extension/Table/TableParser.php @@ -56,12 +56,14 @@ public function parse(ContextInterface $context, Cursor $cursor): bool if (empty($columns)) { $cursor->restoreState($oldState); + return false; } - $head = $this->parseRow(trim((string)array_pop($lines)), $columns, TableCell::TYPE_HEAD); + $head = $this->parseRow(trim((string) array_pop($lines)), $columns, TableCell::TYPE_HEAD); if (null === $head) { $cursor->restoreState($oldState); + return false; } @@ -271,7 +273,7 @@ private static function getAlignment(bool $left, bool $right): ?string } /** - * @inheritDoc + * {@inheritdoc} */ public function setEnvironment(EnvironmentInterface $environment) { diff --git a/src/Extension/Table/TableRenderer.php b/src/Extension/Table/TableRenderer.php index 33d8b94558..1d414c6162 100644 --- a/src/Extension/Table/TableRenderer.php +++ b/src/Extension/Table/TableRenderer.php @@ -25,7 +25,7 @@ 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', []); @@ -34,6 +34,6 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $children = $htmlRenderer->renderBlocks($block->children()); - return new HtmlElement('table', $attrs, $separator.\trim($children).$separator); + return new HtmlElement('table', $attrs, $separator . \trim($children) . $separator); } } diff --git a/src/Extension/Table/TableRow.php b/src/Extension/Table/TableRow.php index c44bca7bcc..30ea6b86e7 100644 --- a/src/Extension/Table/TableRow.php +++ b/src/Extension/Table/TableRow.php @@ -16,7 +16,6 @@ namespace League\CommonMark\Extension\Table; use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\ContextInterface; use League\CommonMark\Cursor; use League\CommonMark\Node\Node; @@ -42,6 +41,8 @@ public function matchesNextLine(Cursor $cursor): bool */ 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/src/Extension/Table/TableRowRenderer.php b/src/Extension/Table/TableRowRenderer.php index 9909654191..dbbcd13238 100644 --- a/src/Extension/Table/TableRowRenderer.php +++ b/src/Extension/Table/TableRowRenderer.php @@ -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/src/Extension/Table/TableSectionRenderer.php b/src/Extension/Table/TableSectionRenderer.php index 98a0d89571..02e17d3caa 100644 --- a/src/Extension/Table/TableSectionRenderer.php +++ b/src/Extension/Table/TableSectionRenderer.php @@ -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 @@ public function render(AbstractBlock $block, ElementRendererInterface $htmlRende $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/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php b/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php index 1e26f264d9..6e561c9be1 100644 --- a/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php +++ b/tests/functional/Extension/DisallowedRawHtml/DisallowedRawHtmlExtensionTest.php @@ -20,7 +20,7 @@ class DisallowedRawHtmlExtensionTest extends TestCase { public function testDisallowedRawHtmlExtensionWithSpecExample() { - $input = <<<MD + $input = <<<'MD' <strong> <title> <style> <em> <blockquote> @@ -28,7 +28,7 @@ public function testDisallowedRawHtmlExtensionWithSpecExample() </blockquote> MD; - $expected = <<<HTML + $expected = <<<'HTML' <p><strong> &lt;title> &lt;style> <em></p> <blockquote> &lt;xmp> is disallowed. &lt;XMP> is also disallowed. @@ -36,7 +36,6 @@ public function testDisallowedRawHtmlExtensionWithSpecExample() HTML; - $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new DisallowedRawHtmlExtension()); $converter = new CommonMarkConverter([], $environment); @@ -46,7 +45,7 @@ public function testDisallowedRawHtmlExtensionWithSpecExample() public function testIndividualHtmlTagsAsBlocks() { - $input = <<<MD + $input = <<<'MD' <title>My Cool Website</title> <textarea> foo=bar @@ -67,7 +66,7 @@ public function testIndividualHtmlTagsAsBlocks() <plaintext>foo</plaintext> MD; - $expected = <<<HTML + $expected = <<<'HTML' &lt;title>My Cool Website&lt;/title> &lt;textarea> foo=bar diff --git a/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php b/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php index c02e817a65..5cffdaaa22 100644 --- a/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php +++ b/tests/functional/Extension/GithubFlavoredMarkdownExtensionTest.php @@ -23,7 +23,7 @@ protected function setUp() protected function getFileName(): string { - return __DIR__.'/../../../vendor/github/gfm/test/spec.txt'; + return __DIR__ . '/../../../vendor/github/gfm/test/spec.txt'; } public function dataProvider() diff --git a/tests/functional/Extension/Table/LocalDataTest.php b/tests/functional/Extension/Table/LocalDataTest.php index 7b8dd13180..0bff4c015a 100644 --- a/tests/functional/Extension/Table/LocalDataTest.php +++ b/tests/functional/Extension/Table/LocalDataTest.php @@ -53,10 +53,10 @@ public function testRenderer(string $markdown, string $html, string $testName): public function dataProvider() { $ret = []; - foreach (glob(__DIR__.'/data/*.md') as $markdownFile) { + foreach (glob(__DIR__ . '/data/*.md') as $markdownFile) { $testName = basename($markdownFile, '.md'); $markdown = file_get_contents($markdownFile); - $html = file_get_contents(__DIR__.'/data/'.$testName.'.html'); + $html = file_get_contents(__DIR__ . '/data/' . $testName . '.html'); $ret[] = [$markdown, $html, $testName]; } @@ -70,9 +70,9 @@ protected function assertCommonMark(ElementRendererInterface $renderer, $markdow $actualResult = $renderer->renderBlock($documentAST); $failureMessage = sprintf('Unexpected result for "%s" test', $testName); - $failureMessage .= "\n=== markdown ===============\n".$markdown; - $failureMessage .= "\n=== expected ===============\n".$html; - $failureMessage .= "\n=== got ====================\n".$actualResult; + $failureMessage .= "\n=== markdown ===============\n" . $markdown; + $failureMessage .= "\n=== expected ===============\n" . $html; + $failureMessage .= "\n=== got ====================\n" . $actualResult; $this->assertEquals($html, $actualResult, $failureMessage); } From 5db7c92d22698121ababafa4d6c53e7057a87157 Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Mon, 3 Feb 2020 21:10:54 -0500 Subject: [PATCH 229/231] Remove table caption functionality Table captions are not part of the CommonMark spec --- src/Extension/Table/README.md | 37 -------------- src/Extension/Table/Table.php | 21 +------- src/Extension/Table/TableCaption.php | 53 -------------------- src/Extension/Table/TableCaptionRenderer.php | 39 -------------- src/Extension/Table/TableExtension.php | 1 - src/Extension/Table/TableParser.php | 24 --------- 6 files changed, 1 insertion(+), 174 deletions(-) delete mode 100644 src/Extension/Table/TableCaption.php delete mode 100644 src/Extension/Table/TableCaptionRenderer.php diff --git a/src/Extension/Table/README.md b/src/Extension/Table/README.md index 1e83bf43c3..ff8de545d4 100644 --- a/src/Extension/Table/README.md +++ b/src/Extension/Table/README.md @@ -70,43 +70,6 @@ Result: | 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> -``` - Credits ------- diff --git a/src/Extension/Table/Table.php b/src/Extension/Table/Table.php index c6a951e2ab..913bfff512 100644 --- a/src/Extension/Table/Table.php +++ b/src/Extension/Table/Table.php @@ -23,7 +23,6 @@ class Table extends AbstractStringContainerBlock implements InlineContainerInterface { - private $caption; private $head; private $body; private $parser; @@ -38,7 +37,7 @@ public function __construct(\Closure $parser) 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 @@ public function isCode(): bool 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/src/Extension/Table/TableCaption.php b/src/Extension/Table/TableCaption.php deleted file mode 100644 index 89dd4409fb..0000000000 --- a/src/Extension/Table/TableCaption.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This is part of the league/commonmark package. - * - * (c) Martin Hasoň <martin.hason@gmail.com> - * (c) Webuni s.r.o. <info@webuni.cz> - * (c) Colin O'Dell <colinodell@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace League\CommonMark\Extension\Table; - -use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\Block\Element\AbstractStringContainerBlock; -use League\CommonMark\Block\Element\InlineContainerInterface; -use League\CommonMark\ContextInterface; -use League\CommonMark\Cursor; - -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/src/Extension/Table/TableCaptionRenderer.php b/src/Extension/Table/TableCaptionRenderer.php deleted file mode 100644 index 4c0e341434..0000000000 --- a/src/Extension/Table/TableCaptionRenderer.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -declare(strict_types=1); - -/* - * This is part of the league/commonmark package. - * - * (c) Martin Hasoň <martin.hason@gmail.com> - * (c) Webuni s.r.o. <info@webuni.cz> - * (c) Colin O'Dell <colinodell@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace League\CommonMark\Extension\Table; - -use League\CommonMark\Block\Element\AbstractBlock; -use League\CommonMark\Block\Renderer\BlockRendererInterface; -use League\CommonMark\ElementRendererInterface; -use League\CommonMark\HtmlElement; - -final class 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/src/Extension/Table/TableExtension.php b/src/Extension/Table/TableExtension.php index 61fded5434..0046b1bea6 100644 --- a/src/Extension/Table/TableExtension.php +++ b/src/Extension/Table/TableExtension.php @@ -26,7 +26,6 @@ public function register(ConfigurableEnvironmentInterface $environment): void ->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/src/Extension/Table/TableParser.php b/src/Extension/Table/TableParser.php index 5f902e3944..4f53fca56a 100644 --- a/src/Extension/Table/TableParser.php +++ b/src/Extension/Table/TableParser.php @@ -23,12 +23,9 @@ use League\CommonMark\Cursor; use League\CommonMark\EnvironmentAwareInterface; use League\CommonMark\EnvironmentInterface; -use League\CommonMark\Util\RegexHelper; final class TableParser implements BlockParserInterface, EnvironmentAwareInterface { - const REGEXP_CAPTION = '/^\[(.+?)\](?:\[(.+)\])?\s*$/'; - /** * @var EnvironmentInterface */ @@ -77,16 +74,6 @@ public function parse(ContextInterface $context, Cursor $cursor): bool $row = $this->parseRow(\trim($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; } @@ -182,17 +169,6 @@ private function split(Cursor $cursor): array return $cells; } - 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]); - } - /** * @param Cursor $cursor * From 90b144f955378764f41e658e7f238063bcc8887e Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Tue, 4 Feb 2020 08:56:21 -0500 Subject: [PATCH 230/231] Avoid using buggy version of scrutinizer/ocular (fixes #410) See https://github.com/thephpleague/commonmark/issues/410 --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 668ce4567d..8afe81d772 100644 --- a/composer.json +++ b/composer.json @@ -36,6 +36,9 @@ "scrutinizer/ocular": "^1.5", "symfony/finder": "^4.2" }, + "conflict": { + "scrutinizer/ocular": "1.7.*" + }, "repositories": [ { "type": "package", From c93840dedd1ae232b38aa28aec5494f4f0a8416e Mon Sep 17 00:00:00 2001 From: Colin O'Dell <colinodell@gmail.com> Date: Sat, 8 Feb 2020 17:25:20 -0500 Subject: [PATCH 231/231] Update the documentation --- docs/1.0/configuration.md | 6 ++++-- docs/1.0/customization/extensions.md | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/1.0/configuration.md b/docs/1.0/configuration.md index 5b9aedea61..4d68429fe8 100644 --- a/docs/1.0/configuration.md +++ b/docs/1.0/configuration.md @@ -7,7 +7,7 @@ redirect_from: /0.20/configuration/ Configuration ============= -You can provide an array of configuration options to the `CommonMarkConverter` when creating it:: +You can provide an array of configuration options to the `CommonMarkConverter` when creating it: ~~~php <?php @@ -34,7 +34,7 @@ Here's a list of currently-supported options: * `renderer` - Array of options for rendering HTML * `block_separator` - String to use for separating renderer block elements - * `inner_separator` - String to use for separating inner block contents + * `inner_separator` - String to use for separating inner block contents * `soft_break` - String to use for rendering soft breaks * `enable_em` - Disable `<em>` parsing by setting to `false`; enable with `true` (default: `true`) * `enable_strong` - Disable `<strong>` parsing by setting to `false`; enable with `true` (default: `true`) @@ -47,6 +47,8 @@ Here's a list of currently-supported options: * `allow_unsafe_links` - Remove risky link and image URLs by setting this to `false` (default: `true`) * `max_nesting_level` - The maximum nesting level for blocks (default: infinite). Setting this to a positive integer can help protect against long parse times and/or segfaults if blocks are too deeply-nested. Added in 0.17. +Additional configuration options are available for some of the [available extensions](/1.0/customization/extensions/) - refer to their individual documentation for more details. + The following options have been deprecated. They will no longer work once 1.0.0 is released: * `safe` - Prevents rendering of raw HTML if set to `true` (default: `false`) diff --git a/docs/1.0/customization/extensions.md b/docs/1.0/customization/extensions.md index 9713e06cdd..8abfa5d901 100644 --- a/docs/1.0/customization/extensions.md +++ b/docs/1.0/customization/extensions.md @@ -18,6 +18,7 @@ final class EmojiExtension implements ExtensionInterface public function register(ConfigurableEnvironmentInterface $environment) { $environment + // TODO: Create the EmojiParser, Emoji, and EmojiRenderer classes ->addInlineParser(new EmojiParser(), 20) ->addInlineRenderer(Emoji::class, new EmojiRenderer(), 0) ; @@ -52,7 +53,7 @@ Or, if you only want a subset of GFM extensions, you can add them individually l ```php $environment = Environment::createCommonMarkExtension(); -// Remove any of the lines below if you don't want those features +// Remove any of the lines below if you don't want a particular feature $environment->addExtension(new AutolinkExtension()); $environment->addExtension(new DisallowedRawHtmlExtension()); $environment->addExtension(new StrikethroughExtension()); @@ -62,3 +63,22 @@ $environment->addExtension(new TaskListExtension()); $converter = new CommonMarkConverter([], $environment); echo $converter->convertToHtml('Hello GFM!'); ``` + +### GFM Extensions + +| Extension | Purpose | Documentation | +| --------- | ------- | ------------- | +| **`GithubFlavoredMarkdownExtension`** | Enables full support for GFM. Includes the following sub-extensions by default: | | +| `AutolinkExtension` | Enables automatic linking of URLs within text without needing to wrap them with Markdown syntax | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/Autolink/README.md) | +| `DisallowedRawHtmlExtension` | Disables certain kinds of HTML tags that could affect page rendering | | +| `StrikethroughExtension` | Allows using tilde characters (`~~`) for ~strikethrough~ formatting | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/Strikethrough/README.md) | +| `TableExtension` | Enables you to create HTML tables | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/Table/README.md) | +| `TaskListExtension` | Allows the creation of task lists | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/TaskList/README.md) | + +### Other Useful Extensions + +| Extension | Purpose | Documentation | +| --------- | ------- | ------------- | +| `ExternalLinkExtension` | Tags external links with additional markup | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/ExternalLink/README.md) | +| `InlinesOnlyExtension` | Only includes standard CommonMark inline elements - perfect for handling comments and other short bits of text where you only want bold, italic, links, etc. | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/InlinesOnly/README.md) | +| `SmartPunctExtension` | Intelligently converts ASCII quotes, dashes, and ellipses to their fancy Unicode equivalents | [Documentation](https://github.com/thephpleague/commonmark/blob/master/src/Extension/SmartPunct/README.md) |