xref: /plugin/combo/syntax/highlightmd.php (revision 4cadd4f8c541149bdda95f080e38a6d4e3a640ca)
1*4cadd4f8SNickeau<?php
2*4cadd4f8SNickeau
3*4cadd4f8SNickeauuse ComboStrap\PluginUtility;
4*4cadd4f8SNickeau
5*4cadd4f8SNickeau
6*4cadd4f8SNickeau/**
7*4cadd4f8SNickeau *
8*4cadd4f8SNickeau * Known as code
9*4cadd4f8SNickeau * https://spec.commonmark.org/0.30/#code-spans
10*4cadd4f8SNickeau *
11*4cadd4f8SNickeau * note supported but specific highlight is done with two `==`
12*4cadd4f8SNickeau * in some processor
13*4cadd4f8SNickeau * https://www.markdownguide.org/extended-syntax/#highlight
14*4cadd4f8SNickeau *
15*4cadd4f8SNickeau */
16*4cadd4f8SNickeauclass syntax_plugin_combo_highlightmd extends DokuWiki_Syntax_Plugin
17*4cadd4f8SNickeau{
18*4cadd4f8SNickeau
19*4cadd4f8SNickeau
20*4cadd4f8SNickeau    const TAG = "highlightmd";
21*4cadd4f8SNickeau    // Only on one line
22*4cadd4f8SNickeau
23*4cadd4f8SNickeau    /**
24*4cadd4f8SNickeau     * Only on one line, otherwise
25*4cadd4f8SNickeau     * if it's not closed, it will eat all other syntaqx
26*4cadd4f8SNickeau     */
27*4cadd4f8SNickeau    const ENTRY_PATTERN = "`[^\n]*(?=`)(?!\n)";
28*4cadd4f8SNickeau
29*4cadd4f8SNickeau    const EXIT_PATTERN = "`";
30*4cadd4f8SNickeau    const CANONICAL = self::TAG;
31*4cadd4f8SNickeau
32*4cadd4f8SNickeau    public function getSort(): int
33*4cadd4f8SNickeau    {
34*4cadd4f8SNickeau
35*4cadd4f8SNickeau        return 200;
36*4cadd4f8SNickeau    }
37*4cadd4f8SNickeau
38*4cadd4f8SNickeau    public function getType(): string
39*4cadd4f8SNickeau    {
40*4cadd4f8SNickeau        return 'formatting';
41*4cadd4f8SNickeau    }
42*4cadd4f8SNickeau
43*4cadd4f8SNickeau
44*4cadd4f8SNickeau    /**
45*4cadd4f8SNickeau     *
46*4cadd4f8SNickeau     * How Dokuwiki will add P element
47*4cadd4f8SNickeau     *
48*4cadd4f8SNickeau     *  * 'normal' - The plugin can be used inside paragraphs (inline)
49*4cadd4f8SNickeau     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
50*4cadd4f8SNickeau     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
51*4cadd4f8SNickeau     *
52*4cadd4f8SNickeau     * @see DokuWiki_Syntax_Plugin::getPType()
53*4cadd4f8SNickeau     *
54*4cadd4f8SNickeau     * This is the equivalent of inline or block for css
55*4cadd4f8SNickeau     */
56*4cadd4f8SNickeau    public function getPType(): string
57*4cadd4f8SNickeau    {
58*4cadd4f8SNickeau        return 'normal';
59*4cadd4f8SNickeau    }
60*4cadd4f8SNickeau
61*4cadd4f8SNickeau    /**
62*4cadd4f8SNickeau     * @return array
63*4cadd4f8SNickeau     * Allow which kind of plugin inside
64*4cadd4f8SNickeau     *
65*4cadd4f8SNickeau     * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs')
66*4cadd4f8SNickeau     * because we manage self the content and we call self the parser
67*4cadd4f8SNickeau     *
68*4cadd4f8SNickeau     * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php
69*4cadd4f8SNickeau     */
70*4cadd4f8SNickeau    function getAllowedTypes(): array
71*4cadd4f8SNickeau    {
72*4cadd4f8SNickeau        return array('formatting', 'substition', 'protected', 'disabled');
73*4cadd4f8SNickeau    }
74*4cadd4f8SNickeau
75*4cadd4f8SNickeau
76*4cadd4f8SNickeau    public function connectTo($mode)
77*4cadd4f8SNickeau    {
78*4cadd4f8SNickeau
79*4cadd4f8SNickeau        $this->Lexer->addEntryPattern(self::ENTRY_PATTERN, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
80*4cadd4f8SNickeau
81*4cadd4f8SNickeau
82*4cadd4f8SNickeau    }
83*4cadd4f8SNickeau
84*4cadd4f8SNickeau    public function postConnect()
85*4cadd4f8SNickeau    {
86*4cadd4f8SNickeau
87*4cadd4f8SNickeau        $this->Lexer->addExitPattern(self::EXIT_PATTERN, PluginUtility::getModeFromTag($this->getPluginComponent()));
88*4cadd4f8SNickeau
89*4cadd4f8SNickeau    }
90*4cadd4f8SNickeau
91*4cadd4f8SNickeau
92*4cadd4f8SNickeau    /**
93*4cadd4f8SNickeau     * Handle the syntax
94*4cadd4f8SNickeau     *
95*4cadd4f8SNickeau     * At the end of the parser, the `section_open` and `section_close` calls
96*4cadd4f8SNickeau     * are created in {@link action_plugin_combo_headingpostprocessing}
97*4cadd4f8SNickeau     * and the text inside for the toc is captured
98*4cadd4f8SNickeau     *
99*4cadd4f8SNickeau     * @param string $match
100*4cadd4f8SNickeau     * @param int $state
101*4cadd4f8SNickeau     * @param int $pos
102*4cadd4f8SNickeau     * @param Doku_Handler $handler
103*4cadd4f8SNickeau     * @return array
104*4cadd4f8SNickeau     */
105*4cadd4f8SNickeau    public function handle($match, $state, $pos, Doku_Handler $handler): array
106*4cadd4f8SNickeau    {
107*4cadd4f8SNickeau        switch ($state) {
108*4cadd4f8SNickeau
109*4cadd4f8SNickeau            case DOKU_LEXER_EXIT:
110*4cadd4f8SNickeau            case DOKU_LEXER_ENTER:
111*4cadd4f8SNickeau
112*4cadd4f8SNickeau                $content = substr($match, 1);
113*4cadd4f8SNickeau                return array(
114*4cadd4f8SNickeau                    PluginUtility::STATE => $state,
115*4cadd4f8SNickeau                    PluginUtility::PAYLOAD => $content,
116*4cadd4f8SNickeau                );
117*4cadd4f8SNickeau            case DOKU_LEXER_UNMATCHED :
118*4cadd4f8SNickeau
119*4cadd4f8SNickeau                return PluginUtility::handleAndReturnUnmatchedData(self::TAG, $match, $handler);
120*4cadd4f8SNickeau
121*4cadd4f8SNickeau        }
122*4cadd4f8SNickeau        return array();
123*4cadd4f8SNickeau    }
124*4cadd4f8SNickeau
125*4cadd4f8SNickeau    public function render($format, Doku_Renderer $renderer, $data): bool
126*4cadd4f8SNickeau    {
127*4cadd4f8SNickeau
128*4cadd4f8SNickeau        switch ($format) {
129*4cadd4f8SNickeau            case "xhtml":
130*4cadd4f8SNickeau                /**
131*4cadd4f8SNickeau                 * @var Doku_Renderer_xhtml $renderer
132*4cadd4f8SNickeau                 */
133*4cadd4f8SNickeau                $state = $data[PluginUtility::STATE];
134*4cadd4f8SNickeau                switch ($state) {
135*4cadd4f8SNickeau
136*4cadd4f8SNickeau                    case DOKU_LEXER_ENTER:
137*4cadd4f8SNickeau                        $renderer->doc .= syntax_plugin_combo_highlightwiki::getOpenTagHighlight(self::TAG) . $data[PluginUtility::PAYLOAD];
138*4cadd4f8SNickeau                        return true;
139*4cadd4f8SNickeau                    case DOKU_LEXER_UNMATCHED:
140*4cadd4f8SNickeau                        $renderer->doc .= PluginUtility::renderUnmatched($data);
141*4cadd4f8SNickeau                        return true;
142*4cadd4f8SNickeau                    case DOKU_LEXER_EXIT:
143*4cadd4f8SNickeau                        $renderer->doc .= "</mark>";
144*4cadd4f8SNickeau                        return true;
145*4cadd4f8SNickeau
146*4cadd4f8SNickeau                }
147*4cadd4f8SNickeau                break;
148*4cadd4f8SNickeau            case "metadata":
149*4cadd4f8SNickeau                /**
150*4cadd4f8SNickeau                 * @var Doku_Renderer_metadata $renderer
151*4cadd4f8SNickeau                 */
152*4cadd4f8SNickeau                $state = $data[PluginUtility::STATE];
153*4cadd4f8SNickeau                switch ($state) {
154*4cadd4f8SNickeau                    case DOKU_LEXER_ENTER:
155*4cadd4f8SNickeau                        $renderer->doc .= $data[PluginUtility::PAYLOAD];
156*4cadd4f8SNickeau                        return true;
157*4cadd4f8SNickeau                    case DOKU_LEXER_UNMATCHED:
158*4cadd4f8SNickeau                        $renderer->doc .= PluginUtility::renderUnmatched($data);
159*4cadd4f8SNickeau                }
160*4cadd4f8SNickeau                break;
161*4cadd4f8SNickeau        }
162*4cadd4f8SNickeau
163*4cadd4f8SNickeau        return false;
164*4cadd4f8SNickeau    }
165*4cadd4f8SNickeau
166*4cadd4f8SNickeau    /**
167*4cadd4f8SNickeau     * @param $match
168*4cadd4f8SNickeau     * @return int
169*4cadd4f8SNickeau     */
170*4cadd4f8SNickeau    public
171*4cadd4f8SNickeau    function getLevelFromMatch($match)
172*4cadd4f8SNickeau    {
173*4cadd4f8SNickeau        return 7 - strlen(trim($match));
174*4cadd4f8SNickeau    }
175*4cadd4f8SNickeau
176*4cadd4f8SNickeau
177*4cadd4f8SNickeau    private
178*4cadd4f8SNickeau    function enableWikiHeading($mode)
179*4cadd4f8SNickeau    {
180*4cadd4f8SNickeau
181*4cadd4f8SNickeau
182*4cadd4f8SNickeau        /**
183*4cadd4f8SNickeau         * Basically all mode that are not `base`
184*4cadd4f8SNickeau         * To not take the dokuwiki heading
185*4cadd4f8SNickeau         */
186*4cadd4f8SNickeau        if (!(in_array($mode, ['base', 'header', 'table']))) {
187*4cadd4f8SNickeau            return true;
188*4cadd4f8SNickeau        } else {
189*4cadd4f8SNickeau            return PluginUtility::getConfValue(self::CONF_WIKI_HIGHLIGHT_ENABLE, self::CONF_DEFAULT_WIKI_ENABLE_VALUE);
190*4cadd4f8SNickeau        }
191*4cadd4f8SNickeau
192*4cadd4f8SNickeau
193*4cadd4f8SNickeau    }
194*4cadd4f8SNickeau
195*4cadd4f8SNickeau
196*4cadd4f8SNickeau}
197