1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2022 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Factories; 21 22use Fisharebest\Webtrees\CommonMark\CensusTableExtension; 23use Fisharebest\Webtrees\CommonMark\XrefExtension; 24use Fisharebest\Webtrees\Contracts\MarkdownFactoryInterface; 25use Fisharebest\Webtrees\Tree; 26use League\CommonMark\Environment\Environment; 27use League\CommonMark\Extension\Autolink\AutolinkExtension; 28use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; 29use League\CommonMark\Extension\CommonMark\Node\Inline\Link; 30use League\CommonMark\Extension\CommonMark\Renderer\Inline\LinkRenderer; 31use League\CommonMark\Extension\Table\TableExtension; 32use League\CommonMark\MarkdownConverter; 33use League\CommonMark\Node\Block\Document; 34use League\CommonMark\Node\Block\Paragraph; 35use League\CommonMark\Node\Inline\Newline; 36use League\CommonMark\Node\Inline\Text; 37use League\CommonMark\Parser\Inline\NewlineParser; 38use League\CommonMark\Renderer\Block\DocumentRenderer; 39use League\CommonMark\Renderer\Block\ParagraphRenderer; 40use League\CommonMark\Renderer\Inline\NewlineRenderer; 41use League\CommonMark\Renderer\Inline\TextRenderer; 42use League\CommonMark\Util\HtmlFilter; 43 44use function strip_tags; 45use function strtr; 46use function trim; 47 48/** 49 * Create a markdown converter. 50 */ 51class MarkdownFactory implements MarkdownFactoryInterface 52{ 53 public const BREAK = '<br />'; 54 55 // Commonmark uses <br /> for hard-breaks, so we use the same for soft-breaks. 56 protected const CONFIG_AUTOLINK = [ 57 'allow_unsafe_links' => false, 58 'html_input' => HtmlFilter::ESCAPE, 59 'renderer' => [ 60 'soft_break' => self::BREAK, 61 ], 62 ]; 63 64 protected const CONFIG_MARKDOWN = [ 65 'allow_unsafe_links' => false, 66 'html_input' => HtmlFilter::ESCAPE, 67 'renderer' => [ 68 'soft_break' => self::BREAK, 69 ], 70 'table' => [ 71 'wrap' => [ 72 'enabled' => true, 73 'tag' => 'div', 74 'attributes' => [ 75 'class' => 'table-responsive', 76 ], 77 ], 78 ], 79 ]; 80 81 /** 82 * @param string $markdown 83 * @param Tree|null $tree 84 * 85 * @return string 86 */ 87 public function autolink(string $markdown, Tree $tree = null): string 88 { 89 // Create a minimal commonmark processor - just add support for auto-links. 90 $environment = new Environment(static::CONFIG_AUTOLINK); 91 $environment->addInlineParser(new NewlineParser()); 92 $environment->addRenderer(Document::class, new DocumentRenderer()); 93 $environment->addRenderer(Paragraph::class, new ParagraphRenderer()); 94 $environment->addRenderer(Text::class, new TextRenderer()); 95 $environment->addRenderer(Link::class, new LinkRenderer()); 96 $environment->addRenderer(Newline::class, new NewlineRenderer()); 97 $environment->addExtension(new AutolinkExtension()); 98 99 // Optionally create links to other records. 100 if ($tree instanceof Tree) { 101 $environment->addExtension(new XrefExtension($tree)); 102 } 103 104 $converter = new MarkDownConverter($environment); 105 106 $html = $converter->convert($markdown)->getContent(); 107 $html = strtr($html, ["</p>\n<p>" => self::BREAK . self::BREAK ]); 108 109 return trim(strip_tags($html, ['a', 'br'])); 110 } 111 112 /** 113 * @param string $markdown 114 * @param Tree|null $tree 115 * 116 * @return string 117 */ 118 public function markdown(string $markdown, Tree $tree = null): string 119 { 120 $environment = new Environment(static::CONFIG_MARKDOWN); 121 $environment->addExtension(new CommonMarkCoreExtension()); 122 $environment->addExtension(new TableExtension()); 123 124 // Convert webtrees 1.x style census tables to commonmark format. 125 $environment->addExtension(new CensusTableExtension()); 126 127 // Optionally create links to other records. 128 if ($tree instanceof Tree) { 129 $environment->addExtension(new XrefExtension($tree)); 130 } 131 132 $converter = new MarkDownConverter($environment); 133 134 return $converter->convert($markdown)->getContent(); 135 } 136} 137