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                if(get_class($node->firstChild()) == 'League\CommonMark\Extension\CommonMark\Node\Inline\Link') {
60                    // set headingName as [[<Url>|<text>]]
61                    $headingName = '[['.$node->firstChild()->getUrl() . '|' . $node->firstChild()->firstChild()->getLiteral() . ']]';
62                } else {
63                    $headingName = $node->firstChild()->getLiteral();
64                }
65                $headingInfo[$headingName] = array(
66                    'level' => $node->getLevel(),
67                    'startline' => $node->getStartLine(),
68                    'endline' => $node->getEndLine()
69                );
70            }
71        }
72
73        if($frontmatter_tag == 'off') {
74            return array('text'=>$renderResult, 'heading'=>$headingInfo);
75        } elseif($frontmatter_tag == 'upper') {
76            return array('text'=>$tagStr."\n\n".$renderResult, 'heading'=>$headingInfo);
77            //return $tagStr."\n\n".$renderResult;
78        } else {
79            return array('text'=>$renderResult."\n\n".$tagStr, 'heading'=>$headingInfo);
80            //return $renderResult."\n\n".$tagStr;
81        }
82    }
83
84    // Temporary implementation: separate method for frontmatter extraction
85    // Since some parsed frontmatter info must be included in main text, it should be merged
86    public static function ExtractFrontmatter($markdown) {
87        $frontMatterExtension = new FrontMatterExtension();
88        $result = $frontMatterExtension->getFrontMatterParser()->parse($markdown);
89
90        return $result;
91    }
92
93    // replace slash in MD wikilink to colon to match DW syntax
94    public static function ParseDokuwikiWikilinks($text) {
95        $pattern = "/(?:\[\[\b|(?!^)\G)[^\/|\]]*\K\/+/";
96        $result = preg_replace($pattern, ":", $text);
97        $pattern = "/!\[\[(.*)\]\]/";
98        $result = preg_replace($pattern, '{{$1}}', $result);
99        return $result;
100    }
101
102    public static function createDWEnvironment(): Environment {
103        $config = [];
104        $environment = new Environment($config);
105        $environment->addExtension(new CommonMarkToDokuWikiExtension());
106        $environment->addExtension(new FootnoteToDokuwikiExtension());
107        $environment->addExtension(new StrikethroughExtension());
108        $environment->addExtension(new TableExtension());
109        $environment->addExtension(new FrontMatterExtension());
110
111        $environment->mergeConfig([
112            'html_input' => 'allow',
113        ]);
114
115        return $environment;
116    }
117}
118
119?>
120