xref: /webtrees/app/Factories/MarkdownFactory.php (revision 2c6f1bd538f46b93645991518398bb087011cb42)
14d35caa7SGreg Roach<?php
24d35caa7SGreg Roach
34d35caa7SGreg Roach/**
44d35caa7SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
64d35caa7SGreg Roach * This program is free software: you can redistribute it and/or modify
74d35caa7SGreg Roach * it under the terms of the GNU General Public License as published by
84d35caa7SGreg Roach * the Free Software Foundation, either version 3 of the License, or
94d35caa7SGreg Roach * (at your option) any later version.
104d35caa7SGreg Roach * This program is distributed in the hope that it will be useful,
114d35caa7SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
124d35caa7SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
134d35caa7SGreg Roach * GNU General Public License for more details.
144d35caa7SGreg Roach * You should have received a copy of the GNU General Public License
154d35caa7SGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
164d35caa7SGreg Roach */
174d35caa7SGreg Roach
184d35caa7SGreg Roachdeclare(strict_types=1);
194d35caa7SGreg Roach
204d35caa7SGreg Roachnamespace Fisharebest\Webtrees\Factories;
214d35caa7SGreg Roach
224d35caa7SGreg Roachuse Fisharebest\Webtrees\CommonMark\CensusTableExtension;
234d35caa7SGreg Roachuse Fisharebest\Webtrees\CommonMark\XrefExtension;
244d35caa7SGreg Roachuse Fisharebest\Webtrees\Contracts\MarkdownFactoryInterface;
254d35caa7SGreg Roachuse Fisharebest\Webtrees\Tree;
266f595250SGreg Roachuse League\CommonMark\Environment\Environment;
274d35caa7SGreg Roachuse League\CommonMark\Extension\Autolink\AutolinkExtension;
286f595250SGreg Roachuse League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
296f595250SGreg Roachuse League\CommonMark\Extension\CommonMark\Node\Inline\Link;
306f595250SGreg Roachuse League\CommonMark\Extension\CommonMark\Renderer\Inline\LinkRenderer;
316f595250SGreg Roachuse League\CommonMark\Extension\Table\TableExtension;
326f595250SGreg Roachuse League\CommonMark\MarkdownConverter;
336f595250SGreg Roachuse League\CommonMark\Node\Block\Document;
346f595250SGreg Roachuse League\CommonMark\Node\Block\Paragraph;
35db3f0368SGreg Roachuse League\CommonMark\Node\Inline\Newline;
366f595250SGreg Roachuse League\CommonMark\Node\Inline\Text;
37db3f0368SGreg Roachuse League\CommonMark\Parser\Inline\NewlineParser;
386f595250SGreg Roachuse League\CommonMark\Renderer\Block\DocumentRenderer;
396f595250SGreg Roachuse League\CommonMark\Renderer\Block\ParagraphRenderer;
40db3f0368SGreg Roachuse League\CommonMark\Renderer\Inline\NewlineRenderer;
416f595250SGreg Roachuse League\CommonMark\Renderer\Inline\TextRenderer;
426f595250SGreg Roachuse League\CommonMark\Util\HtmlFilter;
434d35caa7SGreg Roach
44db3f0368SGreg Roachuse function strip_tags;
45db3f0368SGreg Roachuse function strtr;
46db3f0368SGreg Roach
474d35caa7SGreg Roach/**
484d35caa7SGreg Roach * Create a markdown converter.
494d35caa7SGreg Roach */
504d35caa7SGreg Roachclass MarkdownFactory implements MarkdownFactoryInterface
514d35caa7SGreg Roach{
5263a2c22bSGreg Roach    // Commonmark uses the self-closing form of this tag, so we do the same for consistency.
5328065790SGreg Roach    public const BREAK = '<br />';
5428065790SGreg Roach
556f595250SGreg Roach    protected const CONFIG_AUTOLINK = [
564d35caa7SGreg Roach        'allow_unsafe_links' => false,
576f595250SGreg Roach        'html_input'         => HtmlFilter::ESCAPE,
583c3c3c35SGreg Roach        'renderer'           => [
5928065790SGreg Roach            'soft_break' => self::BREAK,
603c3c3c35SGreg Roach        ],
616f595250SGreg Roach    ];
626f595250SGreg Roach
636f595250SGreg Roach    protected const CONFIG_MARKDOWN = [
646f595250SGreg Roach        'allow_unsafe_links' => false,
656f595250SGreg Roach        'html_input'         => HtmlFilter::ESCAPE,
663c3c3c35SGreg Roach        'renderer'           => [
6728065790SGreg Roach            'soft_break' => self::BREAK,
683c3c3c35SGreg Roach        ],
696f595250SGreg Roach        'table'              => [
706f595250SGreg Roach            'wrap' => [
716f595250SGreg Roach                'enabled'    => true,
726f595250SGreg Roach                'tag'        => 'div',
736f595250SGreg Roach                'attributes' => [
746f595250SGreg Roach                    'class' => 'table-responsive',
756f595250SGreg Roach                ],
766f595250SGreg Roach            ],
776f595250SGreg Roach        ],
784d35caa7SGreg Roach    ];
794d35caa7SGreg Roach
804d35caa7SGreg Roach    /**
816f595250SGreg Roach     * @param string    $markdown
824d35caa7SGreg Roach     * @param Tree|null $tree
834d35caa7SGreg Roach     *
846f595250SGreg Roach     * @return string
854d35caa7SGreg Roach     */
86*2c6f1bd5SGreg Roach    public function autolink(string $markdown, Tree|null $tree = null): string
874d35caa7SGreg Roach    {
884d35caa7SGreg Roach        // Create a minimal commonmark processor - just add support for auto-links.
896f595250SGreg Roach        $environment = new Environment(static::CONFIG_AUTOLINK);
90db3f0368SGreg Roach        $environment->addInlineParser(new NewlineParser());
916f595250SGreg Roach        $environment->addRenderer(Document::class, new DocumentRenderer());
926f595250SGreg Roach        $environment->addRenderer(Paragraph::class, new ParagraphRenderer());
936f595250SGreg Roach        $environment->addRenderer(Text::class, new TextRenderer());
946f595250SGreg Roach        $environment->addRenderer(Link::class, new LinkRenderer());
95db3f0368SGreg Roach        $environment->addRenderer(Newline::class, new NewlineRenderer());
964d35caa7SGreg Roach        $environment->addExtension(new AutolinkExtension());
974d35caa7SGreg Roach
984d35caa7SGreg Roach        // Optionally create links to other records.
994d35caa7SGreg Roach        if ($tree instanceof Tree) {
1004d35caa7SGreg Roach            $environment->addExtension(new XrefExtension($tree));
1014d35caa7SGreg Roach        }
1024d35caa7SGreg Roach
1036f595250SGreg Roach        $converter = new MarkDownConverter($environment);
1046f595250SGreg Roach
105f3dfcaedSGreg Roach        $html = $converter->convert($markdown)->getContent();
106f3dfcaedSGreg Roach
10763a2c22bSGreg Roach        // We should only have certain tags.  Make sure of this.
10863a2c22bSGreg Roach        $html = strip_tags($html, ['a', 'br', 'p']);
10963a2c22bSGreg Roach
11063a2c22bSGreg Roach        // The markdown convert adds newlines, but not in a documented way.  Safest to ignore them.
11163a2c22bSGreg Roach        return strtr($html, ["\n"   => '']);
1124d35caa7SGreg Roach    }
1134d35caa7SGreg Roach
1144d35caa7SGreg Roach    /**
1156f595250SGreg Roach     * @param string    $markdown
1164d35caa7SGreg Roach     * @param Tree|null $tree
1174d35caa7SGreg Roach     *
1186f595250SGreg Roach     * @return string
1194d35caa7SGreg Roach     */
120*2c6f1bd5SGreg Roach    public function markdown(string $markdown, Tree|null $tree = null): string
1214d35caa7SGreg Roach    {
1226f595250SGreg Roach        $environment = new Environment(static::CONFIG_MARKDOWN);
1236f595250SGreg Roach        $environment->addExtension(new CommonMarkCoreExtension());
1246f595250SGreg Roach        $environment->addExtension(new TableExtension());
1254d35caa7SGreg Roach
1264d35caa7SGreg Roach        // Convert webtrees 1.x style census tables to commonmark format.
1277a2a7291SGreg Roach        $environment->addExtension(new CensusTableExtension());
1284d35caa7SGreg Roach
1294d35caa7SGreg Roach        // Optionally create links to other records.
1304d35caa7SGreg Roach        if ($tree instanceof Tree) {
1314d35caa7SGreg Roach            $environment->addExtension(new XrefExtension($tree));
1324d35caa7SGreg Roach        }
1334d35caa7SGreg Roach
1346f595250SGreg Roach        $converter = new MarkDownConverter($environment);
1356f595250SGreg Roach
13663a2c22bSGreg Roach        $html = $converter->convert($markdown)->getContent();
13763a2c22bSGreg Roach
13863a2c22bSGreg Roach        // The markdown convert adds newlines, but not in a documented way.  Safest to ignore them.
13963a2c22bSGreg Roach        return strtr($html, ["\n"   => '']);
1404d35caa7SGreg Roach    }
1414d35caa7SGreg Roach}
142