xref: /plugin/commonmark/src/Dokuwiki/Plugin/Commonmark/DWRenderer.php (revision 8ec9a8f2fa8d03e80395a040a2626880092b4ddf)
1*8ec9a8f2SSungbin Jeon<?php
2*8ec9a8f2SSungbin Jeon
3*8ec9a8f2SSungbin Jeon/*
4*8ec9a8f2SSungbin Jeon * This file is part of the clockoon/dokuwiki-commonmark-plugin package.
5*8ec9a8f2SSungbin Jeon *
6*8ec9a8f2SSungbin Jeon * (c) Sungbin Jeon <clockoon@gmail.com>
7*8ec9a8f2SSungbin Jeon *
8*8ec9a8f2SSungbin Jeon * Original code based on the followings:
9*8ec9a8f2SSungbin Jeon * - CommonMark JS reference parser (https://bitly.com/commonmark-js) (c) John MacFarlane
10*8ec9a8f2SSungbin Jeon * - league/commonmark (https://github.com/thephpleague/commonmark) (c) Colin O'Dell <colinodell@gmail.com>
11*8ec9a8f2SSungbin Jeon *
12*8ec9a8f2SSungbin Jeon * For the full copyright and license information, please view the LICENSE
13*8ec9a8f2SSungbin Jeon * file that was distributed with this source code.
14*8ec9a8f2SSungbin Jeon */
15*8ec9a8f2SSungbin Jeon
16*8ec9a8f2SSungbin Jeonnamespace Dokuwiki\Plugin\Commonmark;
17*8ec9a8f2SSungbin Jeon
18*8ec9a8f2SSungbin Jeonuse League\CommonMark\Block\Element\AbstractBlock;
19*8ec9a8f2SSungbin Jeonuse League\CommonMark\Block\Renderer\BlockRendererInterface;
20*8ec9a8f2SSungbin Jeonuse League\CommonMark\Inline\Element\AbstractInline;
21*8ec9a8f2SSungbin Jeonuse League\CommonMark\Inline\Renderer\InlineRendererInterface;
22*8ec9a8f2SSungbin Jeonuse League\CommonMark\ElementRendererInterface;
23*8ec9a8f2SSungbin Jeonuse League\CommonMark\EnvironmentInterface;
24*8ec9a8f2SSungbin Jeon
25*8ec9a8f2SSungbin Jeon/**
26*8ec9a8f2SSungbin Jeon * Renders a parsed AST to DW
27*8ec9a8f2SSungbin Jeon */
28*8ec9a8f2SSungbin Jeonfinal class DWRenderer implements ElementRendererInterface
29*8ec9a8f2SSungbin Jeon{
30*8ec9a8f2SSungbin Jeon    /**
31*8ec9a8f2SSungbin Jeon     * @var EnvironmentInterface
32*8ec9a8f2SSungbin Jeon     */
33*8ec9a8f2SSungbin Jeon    protected $environment;
34*8ec9a8f2SSungbin Jeon
35*8ec9a8f2SSungbin Jeon    /**
36*8ec9a8f2SSungbin Jeon     * @param EnvironmentInterface $environment
37*8ec9a8f2SSungbin Jeon     */
38*8ec9a8f2SSungbin Jeon    public function __construct(EnvironmentInterface $environment)
39*8ec9a8f2SSungbin Jeon    {
40*8ec9a8f2SSungbin Jeon        $this->environment = $environment;
41*8ec9a8f2SSungbin Jeon    }
42*8ec9a8f2SSungbin Jeon
43*8ec9a8f2SSungbin Jeon    /**
44*8ec9a8f2SSungbin Jeon     * @param string $option
45*8ec9a8f2SSungbin Jeon     * @param mixed  $default
46*8ec9a8f2SSungbin Jeon     *
47*8ec9a8f2SSungbin Jeon     * @return mixed|null
48*8ec9a8f2SSungbin Jeon     */
49*8ec9a8f2SSungbin Jeon    public function getOption(string $option, $default = null)
50*8ec9a8f2SSungbin Jeon    {
51*8ec9a8f2SSungbin Jeon        return $this->environment->getConfig('renderer/' . $option, $default);
52*8ec9a8f2SSungbin Jeon    }
53*8ec9a8f2SSungbin Jeon
54*8ec9a8f2SSungbin Jeon    /**
55*8ec9a8f2SSungbin Jeon     * @param AbstractInline $inline
56*8ec9a8f2SSungbin Jeon     *
57*8ec9a8f2SSungbin Jeon     * @throws \RuntimeException
58*8ec9a8f2SSungbin Jeon     *
59*8ec9a8f2SSungbin Jeon     * @return string
60*8ec9a8f2SSungbin Jeon     */
61*8ec9a8f2SSungbin Jeon    public function renderInline(AbstractInline $inline): string
62*8ec9a8f2SSungbin Jeon    {
63*8ec9a8f2SSungbin Jeon        $renderers = $this->environment->getInlineRenderersForClass(\get_class($inline));
64*8ec9a8f2SSungbin Jeon
65*8ec9a8f2SSungbin Jeon        /** @var InlineRendererInterface $renderer */
66*8ec9a8f2SSungbin Jeon        foreach ($renderers as $renderer) {
67*8ec9a8f2SSungbin Jeon            if (($result = $renderer->render($inline, $this)) !== null) {
68*8ec9a8f2SSungbin Jeon                return $result;
69*8ec9a8f2SSungbin Jeon            }
70*8ec9a8f2SSungbin Jeon        }
71*8ec9a8f2SSungbin Jeon
72*8ec9a8f2SSungbin Jeon        throw new \RuntimeException('Unable to find corresponding renderer for inline type ' . \get_class($inline));
73*8ec9a8f2SSungbin Jeon    }
74*8ec9a8f2SSungbin Jeon
75*8ec9a8f2SSungbin Jeon    /**
76*8ec9a8f2SSungbin Jeon     * @param AbstractInline[] $inlines
77*8ec9a8f2SSungbin Jeon     *
78*8ec9a8f2SSungbin Jeon     * @return string
79*8ec9a8f2SSungbin Jeon     */
80*8ec9a8f2SSungbin Jeon    public function renderInlines(iterable $inlines): string
81*8ec9a8f2SSungbin Jeon    {
82*8ec9a8f2SSungbin Jeon        $result = [];
83*8ec9a8f2SSungbin Jeon        foreach ($inlines as $inline) {
84*8ec9a8f2SSungbin Jeon            $result[] = $this->renderInline($inline);
85*8ec9a8f2SSungbin Jeon        }
86*8ec9a8f2SSungbin Jeon
87*8ec9a8f2SSungbin Jeon        return \implode('', $result);
88*8ec9a8f2SSungbin Jeon    }
89*8ec9a8f2SSungbin Jeon
90*8ec9a8f2SSungbin Jeon    /**
91*8ec9a8f2SSungbin Jeon     * @param AbstractBlock $block
92*8ec9a8f2SSungbin Jeon     * @param bool          $inTightList
93*8ec9a8f2SSungbin Jeon     *
94*8ec9a8f2SSungbin Jeon     * @throws \RuntimeException
95*8ec9a8f2SSungbin Jeon     *
96*8ec9a8f2SSungbin Jeon     * @return string
97*8ec9a8f2SSungbin Jeon     */
98*8ec9a8f2SSungbin Jeon    public function renderBlock(AbstractBlock $block, bool $inTightList = false): string
99*8ec9a8f2SSungbin Jeon    {
100*8ec9a8f2SSungbin Jeon        $renderers = $this->environment->getBlockRenderersForClass(\get_class($block));
101*8ec9a8f2SSungbin Jeon
102*8ec9a8f2SSungbin Jeon        /** @var BlockRendererInterface $renderer */
103*8ec9a8f2SSungbin Jeon        foreach ($renderers as $renderer) {
104*8ec9a8f2SSungbin Jeon            if (($result = $renderer->render($block, $this, $inTightList)) !== null) {
105*8ec9a8f2SSungbin Jeon                return $result;
106*8ec9a8f2SSungbin Jeon            }
107*8ec9a8f2SSungbin Jeon        }
108*8ec9a8f2SSungbin Jeon
109*8ec9a8f2SSungbin Jeon        throw new \RuntimeException('Unable to find corresponding renderer for block type ' . \get_class($block));
110*8ec9a8f2SSungbin Jeon    }
111*8ec9a8f2SSungbin Jeon
112*8ec9a8f2SSungbin Jeon    /**
113*8ec9a8f2SSungbin Jeon     * @param AbstractBlock[] $blocks
114*8ec9a8f2SSungbin Jeon     * @param bool            $inTightList
115*8ec9a8f2SSungbin Jeon     *
116*8ec9a8f2SSungbin Jeon     * @return string
117*8ec9a8f2SSungbin Jeon     */
118*8ec9a8f2SSungbin Jeon    public function renderBlocks(iterable $blocks, bool $inTightList = false): string
119*8ec9a8f2SSungbin Jeon    {
120*8ec9a8f2SSungbin Jeon        $result = [];
121*8ec9a8f2SSungbin Jeon        foreach ($blocks as $block) {
122*8ec9a8f2SSungbin Jeon            $result[] = $this->renderBlock($block, $inTightList);
123*8ec9a8f2SSungbin Jeon        }
124*8ec9a8f2SSungbin Jeon
125*8ec9a8f2SSungbin Jeon        $separator = $this->getOption('block_separator', "\n");
126*8ec9a8f2SSungbin Jeon
127*8ec9a8f2SSungbin Jeon        return \implode($separator, $result);
128*8ec9a8f2SSungbin Jeon    }
129*8ec9a8f2SSungbin Jeon}