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