Skip to content

Commit 2fee0e2

Browse files
committed
Align interface with CommonMarks
- Our interface simply narrows the return type now - Keeps compatability with ElementRendererInterface - CliRenderer now uses ElementRendererInterface - Utilises CommonMark extension to simplify factory
1 parent de5677b commit 2fee0e2

34 files changed

+530
-326
lines changed

README.md

Lines changed: 10 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ use League\CommonMark\DocParser;
1616
use League\CommonMark\Environment;
1717
use AydinHassan\CliMdRenderer\CliRendererFactory;
1818

19-
$parser = new DocParser(Environment::createCommonMarkEnvironment());
20-
$cliRenderer = (new CliRendererFactory)->__invoke();
21-
$ast = $parser->parse(file_get_contents('path/to/file.md'));
19+
$parser = new DocParser(Environment::createCommonMarkEnvironment());
20+
$cliRenderer = (new CliRendererFactory)->__invoke();
21+
$ast = $parser->parse(file_get_contents('path/to/file.md'));
2222

2323
echo $cliRenderer->renderBlock($ast);
2424
```
@@ -37,7 +37,6 @@ use AydinHassan\CliMdRenderer\Renderer\FencedCodeRenderer;
3737

3838
$codeRenderer = new FencedCodeRenderer;
3939
$codeRenderer->addSyntaxHighlighter('js', new JsSyntaxHighlighter);
40-
4140
```
4241

4342
If you need to do this you cannot use the factory so construction will look something like:
@@ -46,60 +45,16 @@ If you need to do this you cannot use the factory so construction will look some
4645
<?php
4746
require_once 'vendor/autoload.php';
4847

49-
use AydinHassan\CliMdRenderer\Highlighter\PhpHighlighter;
50-
use AydinHassan\CliMdRenderer\InlineRenderer\LinkRenderer;
51-
use AydinHassan\CliMdRenderer\Renderer\DocumentRenderer;
52-
use AydinHassan\CliMdRenderer\Renderer\FencedCodeRenderer;
53-
use AydinHassan\CliMdRenderer\Renderer\HeaderRenderer;
54-
use AydinHassan\CliMdRenderer\Renderer\HorizontalRuleRenderer;
55-
use AydinHassan\CliMdRenderer\Renderer\ParagraphRenderer;
5648
use Colors\Color;
57-
use Kadet\Highlighter\KeyLighter;
58-
use League\CommonMark\Block\Element\Document;
59-
use League\CommonMark\Block\Element\Header;
60-
use League\CommonMark\Block\Element\HorizontalRule;
61-
use League\CommonMark\Block\Element\Paragraph;
62-
use League\CommonMark\Block\Element\FencedCode;
63-
use AydinHassan\CliMdRenderer\InlineRenderer\TextRenderer;
64-
use AydinHassan\CliMdRenderer\InlineRenderer\CodeRenderer;
65-
use AydinHassan\CliMdRenderer\InlineRenderer\EmphasisRenderer;
66-
use AydinHassan\CliMdRenderer\InlineRenderer\StrongRenderer;
67-
use AydinHassan\CliMdRenderer\InlineRenderer\NewlineRenderer;
68-
use League\CommonMark\Inline\Element\Link;
69-
use League\CommonMark\Inline\Element\Text;
70-
use League\CommonMark\Inline\Element\Code;
71-
use League\CommonMark\Inline\Element\Emphasis;
72-
use League\CommonMark\Inline\Element\Strong;
73-
use League\CommonMark\Inline\Element\Newline;
74-
75-
$codeRender = new FencedCodeRenderer();
76-
$keyLighter = new KeyLighter;
77-
$keyLighter->init();
78-
$codeRender->addSyntaxHighlighter('php', new PhpHighlighter($keyLighter));
79-
$codeRender->addSyntaxHighlighter('js', new JsSyntaxHighlighter);
80-
81-
$blockRenderers = [
82-
Document::class => new DocumentRenderer,
83-
Header::class => new HeaderRenderer,
84-
HorizontalRule::class => new HorizontalRuleRenderer,
85-
Paragraph::class => new ParagraphRenderer,
86-
FencedCode::class => $codeRender,
87-
];
88-
89-
$inlineBlockRenderers = [
90-
Text::class => new TextRenderer,
91-
Code::class => new CodeRenderer,
92-
Emphasis::class => new EmphasisRenderer,
93-
Strong::class => new StrongRenderer,
94-
Newline::class => new NewlineRenderer,
95-
Link::class => new LinkRenderer,
96-
];
97-
98-
$colors = new Color;
99-
$colors->setForceStyle(true);
49+
use League\CommonMark\Environment;
50+
51+
$environment = new Environment();
52+
$environment->addExtension(new CliExtension());
10053

101-
return new CliRenderer($blockRenderers, $inlineBlockRenderers, $colors);
54+
$colors = new Color();
55+
$colors->setForceStyle(true);
10256

57+
return new CliRenderer($environment, $colors);
10358
```
10459

10560

src/CliExtension.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AydinHassan\CliMdRenderer;
6+
7+
use AydinHassan\CliMdRenderer\Highlighter\PhpHighlighter;
8+
use AydinHassan\CliMdRenderer\InlineRenderer\CodeRenderer;
9+
use AydinHassan\CliMdRenderer\InlineRenderer\EmphasisRenderer;
10+
use AydinHassan\CliMdRenderer\InlineRenderer\LinkRenderer;
11+
use AydinHassan\CliMdRenderer\InlineRenderer\NewlineRenderer;
12+
use AydinHassan\CliMdRenderer\InlineRenderer\StrongRenderer;
13+
use AydinHassan\CliMdRenderer\InlineRenderer\TextRenderer;
14+
use AydinHassan\CliMdRenderer\Renderer\DocumentRenderer;
15+
use AydinHassan\CliMdRenderer\Renderer\FencedCodeRenderer;
16+
use AydinHassan\CliMdRenderer\Renderer\HeaderRenderer;
17+
use AydinHassan\CliMdRenderer\Renderer\HorizontalRuleRenderer;
18+
use AydinHassan\CliMdRenderer\Renderer\ListBlockRenderer;
19+
use AydinHassan\CliMdRenderer\Renderer\ListItemRenderer;
20+
use AydinHassan\CliMdRenderer\Renderer\ParagraphRenderer;
21+
use Kadet\Highlighter\KeyLighter;
22+
use League\CommonMark\Block\Element\Document;
23+
use League\CommonMark\Block\Element\FencedCode;
24+
use League\CommonMark\Block\Element\Heading;
25+
use League\CommonMark\Block\Element\ListBlock;
26+
use League\CommonMark\Block\Element\ListItem;
27+
use League\CommonMark\Block\Element\Paragraph;
28+
use League\CommonMark\Block\Element\ThematicBreak;
29+
use League\CommonMark\Block\Parser as BlockParser;
30+
use League\CommonMark\ConfigurableEnvironmentInterface;
31+
use League\CommonMark\Extension\ExtensionInterface;
32+
use League\CommonMark\Inline\Element\Code;
33+
use League\CommonMark\Inline\Element\Emphasis;
34+
use League\CommonMark\Inline\Element\Link;
35+
use League\CommonMark\Inline\Element\Newline;
36+
use League\CommonMark\Inline\Element\Strong;
37+
use League\CommonMark\Inline\Element\Text;
38+
use League\CommonMark\Inline\Parser as InlineParser;
39+
40+
class CliExtension implements ExtensionInterface
41+
{
42+
public function register(ConfigurableEnvironmentInterface $environment): void
43+
{
44+
$codeRender = new FencedCodeRenderer();
45+
$keyLighter = new KeyLighter();
46+
$keyLighter->init();
47+
$codeRender->addSyntaxHighlighter('php', new PhpHighlighter($keyLighter));
48+
49+
$environment
50+
->addBlockParser(new BlockParser\BlockQuoteParser(), 70)
51+
->addBlockParser(new BlockParser\ATXHeadingParser(), 60)
52+
->addBlockParser(new BlockParser\FencedCodeParser(), 50)
53+
->addBlockParser(new BlockParser\HtmlBlockParser(), 40)
54+
->addBlockParser(new BlockParser\SetExtHeadingParser(), 30)
55+
->addBlockParser(new BlockParser\ThematicBreakParser(), 20)
56+
->addBlockParser(new BlockParser\ListParser(), 10)
57+
->addBlockParser(new BlockParser\IndentedCodeParser(), -100)
58+
->addBlockParser(new BlockParser\LazyParagraphParser(), -200)
59+
60+
->addInlineParser(new InlineParser\NewlineParser(), 200)
61+
->addInlineParser(new InlineParser\BacktickParser(), 150)
62+
->addInlineParser(new InlineParser\EscapableParser(), 80)
63+
->addInlineParser(new InlineParser\EntityParser(), 70)
64+
->addInlineParser(new InlineParser\AutolinkParser(), 50)
65+
->addInlineParser(new InlineParser\HtmlInlineParser(), 40)
66+
->addInlineParser(new InlineParser\CloseBracketParser(), 30)
67+
->addInlineParser(new InlineParser\OpenBracketParser(), 20)
68+
->addInlineParser(new InlineParser\BangParser(), 10)
69+
70+
->addBlockRenderer(Document::class, new DocumentRenderer())
71+
->addBlockRenderer(Heading::class, new HeaderRenderer())
72+
->addBlockRenderer(ThematicBreak::class, new HorizontalRuleRenderer())
73+
->addBlockRenderer(Paragraph::class, new ParagraphRenderer())
74+
->addBlockRenderer(FencedCode::class, $codeRender)
75+
->addBlockRenderer(ListBlock::class, new ListBlockRenderer())
76+
->addBlockRenderer(ListItem::class, new ListItemRenderer())
77+
78+
->addInlineRenderer(Text::class, new TextRenderer())
79+
->addInlineRenderer(Code::class, new CodeRenderer())
80+
->addInlineRenderer(Emphasis::class, new EmphasisRenderer())
81+
->addInlineRenderer(Strong::class, new StrongRenderer())
82+
->addInlineRenderer(Newline::class, new NewlineRenderer())
83+
->addInlineRenderer(Link::class, new LinkRenderer());
84+
}
85+
}

src/CliRenderer.php

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,39 @@
66
use AydinHassan\CliMdRenderer\Renderer\CliBlockRendererInterface;
77
use Colors\Color;
88
use League\CommonMark\Block\Element\AbstractBlock;
9+
use League\CommonMark\Block\Renderer\BlockRendererInterface;
10+
use League\CommonMark\ElementRendererInterface;
11+
use League\CommonMark\EnvironmentInterface;
912
use League\CommonMark\Inline\Element\AbstractInline;
1013
use RuntimeException;
1114

12-
class CliRenderer
15+
class CliRenderer implements ElementRendererInterface
1316
{
1417
/**
15-
* @var array<CliBlockRendererInterface>
18+
* @var EnvironmentInterface
1619
*/
17-
private $renderers;
18-
19-
/**
20-
* @var array<CliInlineRendererInterface>
21-
*/
22-
private $inlineRenderers;
20+
private $environment;
2321

2422
/**
2523
* @var Color
2624
*/
2725
private $color;
2826

27+
public function __construct(EnvironmentInterface $environment, Color $color)
28+
{
29+
$this->environment = $environment;
30+
$this->color = $color;
31+
}
32+
2933
/**
30-
* @param array<CliBlockRendererInterface> $renderers
31-
* @param array<CliInlineRendererInterface> $inlineRenderers
32-
* @param Color $color
34+
* @param string $option
35+
* @param mixed $default
36+
*
37+
* @return mixed|null
3338
*/
34-
public function __construct(array $renderers, array $inlineRenderers, Color $color)
39+
public function getOption(string $option, $default = null)
3540
{
36-
$this->color = $color;
37-
$this->renderers = $renderers;
38-
$this->inlineRenderers = $inlineRenderers;
41+
return $this->environment->getConfig('renderer/' . $option, $default);
3942
}
4043

4144
/**
@@ -58,49 +61,61 @@ public function style(string $string, $colourOrStyle): string
5861
return $this->color->__invoke($string)->apply($colourOrStyle, $string);
5962
}
6063

64+
public function renderInline(AbstractInline $inline): string
65+
{
66+
$renderers = $this->environment->getInlineRenderersForClass(get_class($inline));
67+
68+
foreach ($renderers as $renderer) {
69+
if (($result = $renderer->render($inline, $this)) !== null) {
70+
return $result;
71+
}
72+
}
73+
74+
throw new RuntimeException(
75+
sprintf('Unable to find corresponding renderer for inline type: "%s"', get_class($inline))
76+
);
77+
}
78+
6179
/**
6280
* @param AbstractInline[] $inlines
6381
*
6482
* @return string
6583
*/
66-
public function renderInlines(array $inlines): string
84+
public function renderInlines(iterable $inlines): string
6785
{
6886
return implode(
6987
"",
7088
array_map(
7189
function (AbstractInline $inline) {
72-
$renderer = $this->getInlineRendererForClass(get_class($inline));
73-
if (!$renderer) {
74-
throw new RuntimeException(
75-
sprintf('Unable to find corresponding renderer for inline type: "%s"', get_class($inline))
76-
);
77-
}
78-
79-
return $renderer->render($inline, $this);
90+
return $this->renderInline($inline);
8091
},
8192
$inlines
8293
)
8394
);
8495
}
8596

86-
public function renderBlock(AbstractBlock $block): string
97+
public function renderBlock(AbstractBlock $block, bool $inTightList = false): string
8798
{
88-
$renderer = $this->getBlockRendererForClass(get_class($block));
89-
if (!$renderer) {
90-
throw new RuntimeException(
91-
sprintf('Unable to find corresponding renderer for block type: "%s"', get_class($block))
92-
);
99+
$renderers = $this->environment->getBlockRenderersForClass(\get_class($block));
100+
101+
/** @var BlockRendererInterface $renderer */
102+
foreach ($renderers as $renderer) {
103+
if (($result = $renderer->render($block, $this, $inTightList)) !== null) {
104+
return $result;
105+
}
93106
}
94107

95-
return $renderer->render($block, $this);
108+
throw new RuntimeException(
109+
sprintf('Unable to find corresponding renderer for block type: "%s"', get_class($block))
110+
);
96111
}
97112

98113
/**
99114
* @param AbstractBlock[] $blocks
100115
*
101116
* @return string
102117
*/
103-
public function renderBlocks(array $blocks): string
118+
public function renderBlocks(iterable $blocks, bool $inTightList = false): string
104119
{
105120
return implode(
106121
"\n",
@@ -112,31 +127,4 @@ function (AbstractBlock $block) {
112127
)
113128
);
114129
}
115-
116-
/**
117-
* @param class-string $inlineBlockClass
118-
* @return CliInlineRendererInterface|null
119-
*/
120-
private function getInlineRendererForClass(string $inlineBlockClass): ?CliInlineRendererInterface
121-
{
122-
if (!isset($this->inlineRenderers[$inlineBlockClass])) {
123-
return null;
124-
}
125-
126-
return $this->inlineRenderers[$inlineBlockClass];
127-
}
128-
129-
/**
130-
* @param class-string $blockClass
131-
*
132-
* @return CliBlockRendererInterface|null
133-
*/
134-
private function getBlockRendererForClass($blockClass): ?CliBlockRendererInterface
135-
{
136-
if (!isset($this->renderers[$blockClass])) {
137-
return null;
138-
}
139-
140-
return $this->renderers[$blockClass];
141-
}
142130
}

0 commit comments

Comments
 (0)