diff --git a/packages/guides-markdown/resources/config/guides-markdown.php b/packages/guides-markdown/resources/config/guides-markdown.php index 4037a9933..49edb3f7f 100644 --- a/packages/guides-markdown/resources/config/guides-markdown.php +++ b/packages/guides-markdown/resources/config/guides-markdown.php @@ -18,6 +18,7 @@ use phpDocumentor\Guides\Markdown\Parsers\ListItemParser; use phpDocumentor\Guides\Markdown\Parsers\ParagraphParser; use phpDocumentor\Guides\Markdown\Parsers\SeparatorParser; +use phpDocumentor\Guides\Markdown\Parsers\Table\TableParser; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\String\Slugger\AsciiSlugger; @@ -58,6 +59,10 @@ ->tag('phpdoc.guides.markdown.parser.blockParser') ->tag('phpdoc.guides.markdown.parser.subParser') + ->set(TableParser::class) + ->arg('$subParsers', tagged_iterator('phpdoc.guides.markdown.parser.inlineParser')) + ->tag('phpdoc.guides.markdown.parser.blockParser') + ->set(EmphasisParser::class) ->arg('$inlineParsers', tagged_iterator('phpdoc.guides.markdown.parser.inlineParser')) ->tag('phpdoc.guides.markdown.parser.inlineParser') diff --git a/packages/guides-markdown/src/Markdown/MarkupLanguageParser.php b/packages/guides-markdown/src/Markdown/MarkupLanguageParser.php index 80de96b93..0a56ac918 100644 --- a/packages/guides-markdown/src/Markdown/MarkupLanguageParser.php +++ b/packages/guides-markdown/src/Markdown/MarkupLanguageParser.php @@ -16,6 +16,7 @@ use League\CommonMark\Environment\Environment as CommonMarkEnvironment; use League\CommonMark\Extension\Autolink\AutolinkExtension; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; +use League\CommonMark\Extension\Table\TableExtension; use League\CommonMark\Node\Block\Document; use League\CommonMark\Node\NodeWalker; use League\CommonMark\Parser\MarkdownParser; @@ -46,6 +47,7 @@ public function __construct( ) { $cmEnvironment = new CommonMarkEnvironment(['html_input' => 'strip']); $cmEnvironment->addExtension(new CommonMarkCoreExtension()); + $cmEnvironment->addExtension(new TableExtension()); $cmEnvironment->addExtension(new AutolinkExtension()); $this->markdownParser = new MarkdownParser($cmEnvironment); } diff --git a/packages/guides-markdown/src/Markdown/ParserException.php b/packages/guides-markdown/src/Markdown/ParserException.php new file mode 100644 index 000000000..c01eb09ee --- /dev/null +++ b/packages/guides-markdown/src/Markdown/ParserException.php @@ -0,0 +1,20 @@ + */ +final class TableParser extends AbstractBlockParser +{ + /** @param iterable> $subParsers */ + public function __construct( + private readonly iterable $subParsers, + private readonly LoggerInterface $logger, + ) { + } + + public function parse(GuidesParser $parser, NodeWalker $walker, CommonMarkNode $current): TableNode + { + $headerRows = []; + $bodyRows = []; + + while ($event = $walker->next()) { + $commonMarkNode = $event->getNode(); + + if ($event->isEntering()) { + if ($commonMarkNode instanceof TableSection) { + if ($commonMarkNode->isHead()) { + $headerRows = $this->parseTableSection($parser, $walker); + continue; + } + + $bodyRows = $this->parseTableSection($parser, $walker); + } + + continue; + } + + if ($commonMarkNode instanceof CommonMarkTable) { + return new TableNode($bodyRows, $headerRows); + } + + $this->logger->warning(sprintf('"%s" node is not yet supported in context %s. ', $commonMarkNode::class, 'Header')); + } + + throw new ParserException('Unexpected end of NodeWalker'); + } + + public function supports(NodeWalkerEvent $event): bool + { + return $event->isEntering() && $event->getNode() instanceof CommonMarkTable; + } + + /** @return TableRow[] */ + private function parseTableSection(GuidesParser $parser, NodeWalker $walker): array + { + $rows = []; + while ($event = $walker->next()) { + if ($event->isEntering()) { + $rows[] = $this->parseRow($parser, $walker); + continue; + } + + if ($event->getNode() instanceof TableSection) { + return $rows; + } + + $this->logger->warning(sprintf('"%s" node is not yet supported in context %s. ', $event->getNode()::class, 'Table section')); + } + + throw new ParserException('Unexpected end of NodeWalker'); + } + + private function parseRow(GuidesParser $parser, NodeWalker $walker): TableRow + { + $cells = []; + while ($event = $walker->next()) { + if ($event->isEntering()) { + $cells[] = $this->parseCell($parser, $walker); + continue; + } + + if ($event->getNode() instanceof CommonMarkTableRow) { + return new TableRow($cells); + } + + $this->logger->warning(sprintf('"%s" node is not yet supported in context %s. ', $event->getNode()::class, 'Table row')); + } + + throw new ParserException('Unexpected end of NodeWalker'); + } + + private function parseCell(GuidesParser $parser, NodeWalker $walker): TableColumn + { + $nodes = []; + while ($event = $walker->next()) { + if ($event->isEntering()) { + foreach ($this->subParsers as $subParser) { + if ($subParser->supports($event)) { + $nodes[] = $subParser->parse($parser, $walker, $event->getNode()); + break; + } + } + + continue; + } + + if ($event->getNode() instanceof TableCell) { + return new TableColumn('', 1, $nodes, 1); + } + + $this->logger->warning(sprintf('"%s" node is not yet supported in context %s. ', $event->getNode()::class, 'Table Cell')); + } + + throw new ParserException('Unexpected end of NodeWalker'); + } +} diff --git a/tests/Integration/tests/markdown/table-md/expected/index.html b/tests/Integration/tests/markdown/table-md/expected/index.html index 5d370e610..953dfb7f3 100644 --- a/tests/Integration/tests/markdown/table-md/expected/index.html +++ b/tests/Integration/tests/markdown/table-md/expected/index.html @@ -1,32 +1,31 @@ -
-

Table Markdown

- - - - - - - - +
+

Table Markdown

+
NameAgeCity
+ + + + + + - - + + - - + + - - + + - - -
NameAgeCity
John Doe 29 New York
Jane Smith 34 San Francisco
Sam Green 22 Boston
-
+ + + + diff --git a/tests/Integration/tests/markdown/table-md/input/skip b/tests/Integration/tests/markdown/table-md/input/skip deleted file mode 100644 index 84c06c528..000000000 --- a/tests/Integration/tests/markdown/table-md/input/skip +++ /dev/null @@ -1 +0,0 @@ -Tables are currently not supported in Markdown \ No newline at end of file