1<?php
2
3use ComboStrap\PluginUtility;
4
5if (!defined('DOKU_INC')) die();
6require_once(__DIR__ . '/../ComboStrap/PluginUtility.php');
7
8
9/**
10 * Class syntax_plugin_combo_math
11 */
12class syntax_plugin_combo_math extends DokuWiki_Syntax_Plugin
13{
14
15    const TAG = "math";
16
17
18    /**
19     * Syntax Type
20     *
21     * Protected in order to say that we don't want it to be modified
22     * The mathjax javascript will take care of the rendering
23     *
24     * @return string
25     */
26    public function getType()
27    {
28        return 'substition';
29    }
30
31    /**
32     * @return array
33     * Allow which kind of plugin inside
34     *
35     * No one of array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs')
36     * because we manage self the content and we call self the parser
37     */
38    public function getAllowedTypes()
39    {
40        return array();
41    }
42
43    /**
44     * How Dokuwiki will add P element
45     *
46     *  * 'normal' - The plugin can be used inside paragraphs
47     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
48     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
49     *
50     * @see DokuWiki_Syntax_Plugin::getPType()
51     */
52    function getPType()
53    {
54        return 'normal';
55    }
56
57    /**
58     *
59     * @return int
60     */
61    public function getSort()
62    {
63        return 195;
64    }
65
66    /**
67     *
68     * @param string $mode
69     */
70    public function connectTo($mode)
71    {
72
73        // Add the entry patterns
74        foreach (self::getTags() as $element) {
75
76            $pattern = PluginUtility::getLeafContainerTagPattern($element);
77            $this->Lexer->addSpecialPattern($pattern, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
78
79        }
80
81
82    }
83
84
85    /**
86     *
87     * @param string $match The text matched by the patterns
88     * @param int $state The lexer state for the match
89     * @param int $pos The character position of the matched text
90     * @param Doku_Handler $handler The Doku_Handler object
91     * @return  array Return an array with all data you want to use in render
92     */
93    public function handle($match, $state, $pos, Doku_Handler $handler)
94    {
95
96        return array($match);
97    }
98
99    /**
100     * Render the output
101     * @param string $format
102     * @param Doku_Renderer $renderer
103     * @param array $data - what the function handle() return'ed
104     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
105     * @see DokuWiki_Syntax_Plugin::render()
106     *
107     *
108     */
109    function render($format, Doku_Renderer $renderer, $data)
110    {
111
112        list($content) = $data;
113        switch ($format) {
114            case 'xhtml':
115            case 'odt':
116                /** @var Doku_Renderer_xhtml $renderer */
117
118                /**
119                 * MathJax finds the item via the the FindMath Interface
120                 *
121                 * FindMath Interface that has three implementations (https://github.com/mathjax/MathJax-src/blob/master/ts/core/FindMath.ts)
122                 *      * tex (https://github.com/mathjax/MathJax-src/blob/master/ts/input/tex.ts)
123                 *      * asciimath (https://github.com/mathjax/MathJax-src/blob/master/ts/input/asciimath.ts)
124                 *      * mathml (https://github.com/mathjax/MathJax-src/blob/master/ts/input/mathml.ts)
125                 *
126                 * For Tex and AsciiMath, FindMath will all text text
127                 * and scan them to find the math formula through delimiter.
128                 * The ProtoItem interface (MathJax Item) stores the start and end location - https://github.com/mathjax/MathJax-src/blob/master/ts/core/MathItem.ts#L219
129                 *
130                 * We output then the math expression as character data that will end up
131                 * in a text node.
132                 */
133                $renderer->doc .= $renderer->_xmlEntities($content) . DOKU_LF;
134
135                /**
136                 * CSS
137                 */
138                $snippetManager = PluginUtility::getSnippetManager();
139                $snippetManager->attachCssInternalStyleSheet(self::TAG);
140
141                /**
142                 * Javascript config
143                 */
144                $headHtmlElement = <<<EOD
145MathJax.Hub.Config({
146    showProcessingMessages: true,
147    extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js"],
148    jax: ["input/TeX", "output/HTML-CSS"],
149    tex2jax: {
150        inlineMath: [ ["<math>","</math>"]],
151        displayMath: [ ["<MATH>","</MATH>"] ],
152        processEscapes: true,
153        scale:120
154    },
155    "HTML-CSS": { fonts: ["TeX"] }
156});
157EOD;
158
159                $snippetManager
160                    ->attachJavascriptFromComponentId(
161                        self::TAG,
162                        $headHtmlElement
163                    )
164                    ->addHtmlAttribute("type", "text/x-mathjax-config");
165                $snippetManager->attachRemoteJavascriptLibrary(
166                    self::TAG,
167                    "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js"
168                )
169                    ->setDoesManipulateTheDomOnRun(false);
170                break;
171
172            case 'latexport':
173                // Pass math expressions to latexport renderer
174                /** @noinspection PhpUndefinedMethodInspection */
175                $renderer->mathjax_content($content);
176                break;
177
178        }
179
180        return true;
181
182    }
183
184    static public function getTags(): array
185    {
186        return PluginUtility::getTags(get_called_class());
187    }
188
189    public static function getComponentName(): string
190    {
191        return PluginUtility::getTagName(get_called_class());
192    }
193
194}
195
196