xref: /plugin/commonmark/src/Dokuwiki/Plugin/Commonmark/Commonmark.php (revision 4c91f333b19006451b0fec4e612ae0ab106ca979)
1<?php
2
3namespace Dokuwiki\Plugin\Commonmark;
4
5use League\CommonMark\Environment\Environment;
6use League\CommonMark\Parser\MarkdownParser;
7use Dokuwiki\Plugin\Commonmark\Extension\CommonmarkToDokuwikiExtension;
8use Dokuwiki\Plugin\Commonmark\Extension\FootnoteToDokuwikiExtension;
9use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
10use Dokuwiki\Plugin\Commonmark\Extension\TableExtension;
11use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
12use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
13
14class Commonmark {
15    public static function RendtoDW($markdown, $frontmatter_tag = 'off'): array {
16        // heading info
17        $headingInfo = [];
18
19        // create environment
20        $environment = self::createDWEnvironment();
21
22        // create parser
23        $parser = new MarkdownParser($environment);
24        // create Dokuwiki Renderer
25        $DWRenderer = new DWRenderer($environment);
26
27        # separate frontmatter and main text
28        $FMresult = self::ExtractFrontmatter($markdown);
29        $frontmatter = $FMresult->getFrontMatter();
30        $markdownOnly = $FMresult->getContent();
31        $tagStr = ''; # initialize tag string
32        //print_r($frontmatter);
33
34        # extract tags only
35        if(!empty($frontmatter) && gettype($frontmatter) == "array") { // frontmatter must be array if valid
36            if (array_key_exists('tags', $frontmatter)) {
37                $tags = $frontmatter['tags'];
38                $tagStr = "{{tag>";
39                foreach ($tags as $tag) {
40                    $tagStr = $tagStr. "\"". $tag. "\" ";
41                }
42                $tagStr = $tagStr. "}}";
43            }
44        }
45
46        // pre-processing: convert slash inside wikilink to colon & image wikilinks
47        $markdownOnly = self::ParseDokuwikiWikilinks($markdownOnly);
48        $document = $parser->parse($markdownOnly);
49        $renderResult = $DWRenderer->renderNode($document);
50        // debug
51        foreach ($document->iterator() as $node) {
52            // if(strpos(get_class($node),'Block') == true) {
53            //    echo 'Current node: ' . get_class($node) . '(startline: ' . $node->getStartLine() . ', endline: ' . $node->getEndLine() . ") \n";
54            // }
55            // else {
56            //    echo 'Current node: ' . get_class($node) . "\n";
57            // }
58            if(get_class($node) == 'League\CommonMark\Extension\CommonMark\Node\Block\Heading') {
59                $headingInfo[$node->firstChild()->getLiteral()] = array(
60                    'level' => $node->getLevel(),
61                    'startline' => $node->getStartLine(),
62                    'endline' => $node->getEndLine()
63                );
64            }
65        }
66
67        if($frontmatter_tag == 'off') {
68            return array('text'=>$renderResult, 'heading'=>$headingInfo);
69        } elseif($frontmatter_tag == 'upper') {
70            return array('text'=>$tagStr."\n\n".$renderResult, 'heading'=>$headingInfo);
71            //return $tagStr."\n\n".$renderResult;
72        } else {
73            return array('text'=>$renderResult."\n\n".$tagStr, 'heading'=>$headingInfo);
74            //return $renderResult."\n\n".$tagStr;
75        }
76    }
77
78    // Temporary implementation: separate method for frontmatter extraction
79    // Since some parsed frontmatter info must be included in main text, it should be merged
80    public static function ExtractFrontmatter($markdown) {
81        $frontMatterExtension = new FrontMatterExtension();
82        $result = $frontMatterExtension->getFrontMatterParser()->parse($markdown);
83
84        return $result;
85    }
86
87    // replace slash in MD wikilink to colon to match DW syntax
88    public static function ParseDokuwikiWikilinks($text) {
89        $pattern = "/(?:\[\[\b|(?!^)\G)[^\/|\]]*\K\/+/";
90        $result = preg_replace($pattern, ":", $text);
91        $pattern = "/!\[\[(.*)\]\]/";
92        $result = preg_replace($pattern, '{{$1}}', $result);
93        return $result;
94    }
95
96    public static function createDWEnvironment(): Environment {
97        $config = [];
98        $environment = new Environment($config);
99        $environment->addExtension(new CommonMarkToDokuWikiExtension());
100        $environment->addExtension(new FootnoteToDokuwikiExtension());
101        $environment->addExtension(new StrikethroughExtension());
102        $environment->addExtension(new TableExtension());
103        $environment->addExtension(new FrontMatterExtension());
104
105        $environment->mergeConfig([
106            'html_input' => 'allow',
107        ]);
108
109        return $environment;
110    }
111}
112
113?>
114