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