浏览代码

Extension block pour un div avec une classe, marchotte

Sangfroid 1 月之前
父节点
当前提交
67820664cc

+ 18 - 0
src/Markdown/Block/IntroBlock.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Markdown\Block;
+
+use League\CommonMark\Node\Block\AbstractBlock;
+
+class IntroBlock extends AbstractBlock
+{
+    public function __construct(protected string $className)
+    {
+        
+    }
+
+    public function getClassName(): string
+    {
+        return $this->className;
+    }
+}

+ 18 - 0
src/Markdown/Extension/IntroExtension.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Markdown\Extension;
+
+use App\Markdown\Block\IntroBlock;
+use App\Markdown\Parser\IntroParser;
+use App\Markdown\Render\IntroRenderer;
+use League\CommonMark\Environment\EnvironmentBuilderInterface;
+use League\CommonMark\Extension\ExtensionInterface;
+
+class IntroExtension implements ExtensionInterface
+{
+    public function register(EnvironmentBuilderInterface $environment): void
+    {
+        $environment->addBlockStartParser(IntroParser::createBlockStartParser(), 100);
+        $environment->addRenderer(IntroBlock::class, new IntroRenderer(), 10);
+    }
+}

+ 76 - 0
src/Markdown/Parser/IntroParser.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace App\Markdown\Parser;
+
+use App\Markdown\Block\IntroBlock;
+use League\CommonMark\Node\Block\AbstractBlock;
+use League\CommonMark\Node\Block\Paragraph;
+use League\CommonMark\Node\Inline\Text;
+use League\CommonMark\Parser\Block\AbstractBlockContinueParser;
+use League\CommonMark\Parser\Cursor;
+use League\CommonMark\Parser\Block\BlockContinueParserInterface;
+use League\CommonMark\Parser\Block\BlockContinue;
+use League\CommonMark\Parser\Block\BlockContinueParserWithInlinesInterface;
+use League\CommonMark\Parser\Block\BlockStart;
+use League\CommonMark\Parser\Block\BlockStartParserInterface;
+use League\CommonMark\Parser\InlineParserEngineInterface;
+use League\CommonMark\Parser\MarkdownParserStateInterface;
+
+class IntroParser extends AbstractBlockContinueParser implements BlockContinueParserWithInlinesInterface
+{
+    protected IntroBlock $introBlock;
+    protected Paragraph $paragraph;
+
+    public function __construct(string $className ='')
+    {
+        $this->introBlock = new IntroBlock($className);
+        $this->paragraph = new Paragraph();
+        $this->introBlock->appendChild($this->paragraph);
+    }
+
+    public function getBlock(): AbstractBlock
+    {
+        return $this->introBlock;
+    }
+
+    public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue
+    {
+        if ($cursor->getLine() === ':::') {
+            return BlockContinue::finished();
+        }
+        $line = $cursor->getRemainder();
+        $this->paragraph->appendChild(new Text($line));
+
+        return BlockContinue::at($cursor);
+    }
+
+    public function parseInlines(InlineParserEngineInterface $inlineParser): void
+    {
+        $textContent = '';
+        foreach($this->paragraph->children() as $child) {
+            if ($child instanceof Text) {
+                $textContent .= $child->getLiteral();
+            }
+        }
+        foreach($this->paragraph->children() as $child) {
+            $child->detach();
+        }
+
+        $inlineParser->parse($textContent, $this->paragraph);
+    }
+
+    public static function createBlockStartParser(): BlockStartParserInterface
+    {
+        return new class implements BlockStartParserInterface
+        {
+            public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart
+            {
+                if ($match = $cursor->match('/^:::\s+([^\s]+)/')) {
+                    $className = explode(' ', $match)[1] ?? '';
+                    return BlockStart::of(new IntroParser($className))->at($cursor);
+                }
+                return BlockStart::none();
+            }
+        };
+    }
+}

+ 21 - 0
src/Markdown/Render/IntroRenderer.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Markdown\Render;
+
+use App\Markdown\Block\IntroBlock;
+use League\CommonMark\Node\Node;
+use League\CommonMark\Renderer\ChildNodeRendererInterface;
+use League\CommonMark\Renderer\NodeRendererInterface;
+use League\CommonMark\Util\HtmlElement;
+
+class IntroRenderer implements NodeRendererInterface
+{
+    public function render(Node $node, ChildNodeRendererInterface $childRenderer)
+    {
+        IntroBlock::assertInstanceOf($node);
+        /** @var IntroBlock $node */
+        $attrs = ['class' => $node->getClassName()];
+        dump($node);
+        return new HtmlElement('div', $attrs, $childRenderer->renderNodes($node->children()));
+    }
+}

+ 2 - 0
src/Service/MarkdownParser.php

@@ -3,6 +3,7 @@
 namespace App\Service;
 
 use App\Markdown\Extension\ColorExtension;
+use App\Markdown\Extension\IntroExtension;
 use Embed\Embed;
 use League\CommonMark\Environment\Environment;
 use League\CommonMark\Extension\Autolink\AutolinkExtension;
@@ -65,6 +66,7 @@ class MarkdownParser
         $environment->addExtension(new TableExtension());
         $environment->addExtension(new EmbedExtension());
         $environment->addExtension(new ColorExtension());
+        $environment->addExtension(new IntroExtension());
 
         $this->converter = new MarkdownConverter($environment);
     }