1<?php
2
3/**
4 * DokuWiki Plugin KaTeX (Action Component: setup)
5 *
6 * handle the data that has to be written into JSINFO, e.g. KaTeX options
7 *
8 * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
9 * @author  H.-H. PENG (Hsins) <hsinspeng@gmail.com>
10 */
11
12// must be run within Dokuwiki
13if ( !defined( 'DOKU_INC' ) ) {
14    die();
15}
16
17use dokuwiki\Logger;
18
19class action_plugin_katex_setup extends DokuWiki_Action_Plugin
20{
21    // Registers the handlers with DokuWiki's event controller
22    public function register( Doku_Event_Handler $controller )
23    {
24        $controller->register_hook( 'DOKUWIKI_STARTED', 'BEFORE', $this, 'setup_options' );
25    }
26
27    public function setup_options()
28    {
29        global $JSINFO;
30
31        $JSINFO['plugins']['katex']['options']['output']          = $this->_get_option_output();
32        $JSINFO['plugins']['katex']['options']['delimiters']      = $this->_get_option_delimiters();
33        $JSINFO['plugins']['katex']['options']['ignored-tags']    = $this->_get_option_ignored_tags();
34        $JSINFO['plugins']['katex']['options']['ignored-classes'] = $this->_get_option_ignored_classes();
35        $JSINFO['plugins']['katex']['options']['throwonerror']    = $this->_get_option_throwonerror();
36        $JSINFO['plugins']['katex']['options']['error-color']     = $this->_get_option_error_color();
37        $JSINFO['plugins']['katex']['options']['macros']          = $this->_get_option_macros();
38    }
39
40    private function _get_option_output()
41    {
42        $conf_option_output  = $this->getConf( 'option-output' );
43        $value_option_output = $conf_option_output;
44
45        return $value_option_output;
46    }
47
48    private function _get_option_delimiters()
49    {
50        $DEFAULT_OPTION_DELIMITERS = array(
51            array( "left" => "$$", "right" => "$$", "display" => true ),
52            array( "left" => "$", "right" => "$", "display" => false ),
53            array( "left" => "\\[", "right" => "\\]", "display" => true ),
54            array( "left" => "\\(", "right" => "\\)", "display" => false ),
55        );
56        $conf_option_delimiters = $this->getConf( 'option-delimiters' );
57
58        try {
59            $value_option_delimiters = array_map( fn( $line ): array=> json_decode( str_replace( "\\", "\\\\", trim( $line ) ), true ), explode( "\n", trim( $conf_option_delimiters ) ) );
60            if ( !$value_option_delimiters ) {
61                throw new Exception( 'Parsing Result is null' );
62            }
63        } catch ( Throwable $e ) {
64            $log_title    = '[KaTeX] Invalid Configuration Value ("option-delimiters")';
65            $log_messages = "The configuration value shown below is invalid:
66
67            ---
68            {$conf_option_delimiters}
69            ---
70
71            The value of \"option-delimiters\" option should be mutiple lines of string in '{ \"left\": \"<LEFT_PATTERN>\", \"right\": \"<RIGHT_PATTERN>\", \"display\": \"<BOOLEAN>\" }'.
72            KaTeX plugin will fallback to the default value.";
73            Logger::error( $log_title, $log_messages, __FILE__, __LINE__ );
74
75            $value_option_delimiters = $DEFAULT_OPTION_DELIMITERS;
76        }
77
78        return $value_option_delimiters;
79    }
80
81    private function _get_option_ignored_tags()
82    {
83        $DEFAULT_OPTION_IGNORED_TAGS = array( "script", "noscript", "style", "textarea", "pre", "code", "option" );
84        $conf_option_ignored_tags    = $this->getConf( 'option-ignored-tags' );
85
86        try {
87            $value_option_ignored_tags = array_map( fn( $text ): string => trim( $text ), explode( ',', $conf_option_ignored_tags ) );
88            if ( !$value_option_ignored_tags ) {
89                throw new Exception( 'Parsing Result is null' );
90            }
91        } catch ( Throwable $e ) {
92            $log_title    = '[KaTeX] Invalid Configuration Value ("option-ignored-tags")';
93            $log_messages = "The configuration value shown below is invalid:
94
95            ---
96            {$conf_option_ignored_tags}
97            ---
98
99            The value of \"option-ignored-tags\" option should be a string containing tags separated by comma. e.g. \"script, style, textarea, pre, code\"
100            KaTeX plugin will fallback to the default value.";
101            Logger::error( $log_title, $log_messages, __FILE__, __LINE__ );
102
103            $value_option_ignored_tags = $DEFAULT_OPTION_IGNORED_TAGS;
104        }
105
106        return $value_option_ignored_tags;
107    }
108
109    private function _get_option_ignored_classes()
110    {
111        $DEFAULT_OPTION_IGNORED_CLASSES = array( "" );
112        $conf_option_ignored_classes    = $this->getConf( 'option-ignored-classes' );
113
114        try {
115            $value_option_ignored_classes = array_map( fn( $text ): string => trim( $text ), explode( ',', $conf_option_ignored_classes ) );
116            if ( !$value_option_ignored_classes ) {
117                throw new Exception( 'Parsing Result is null' );
118            }
119        } catch ( Throwable $e ) {
120            $log_title    = '[KaTeX] Invalid Configuration Value ("option-ignored-tags")';
121            $log_messages = "The configuration value shown below is invalid:
122
123            ---
124            {$conf_option_ignored_classes}
125            ---
126
127            The value of \"option-ignored-classes\" option should be a string containing tags separated by comma. e.g. \"code-mirror, annotation-box\"
128            KaTeX plugin will fallback to the default value.";
129            Logger::error( $log_title, $log_messages, __FILE__, __LINE__ );
130
131            $value_option_ignored_classes = $DEFAULT_OPTION_IGNORED_CLASSES;
132        }
133
134        return $value_option_ignored_classes;
135    }
136
137    private function _get_option_throwonerror()
138    {
139        $conf_option_throwonerror  = $this->getConf( 'option-throwonerror' );
140        $value_option_throwonerror = boolval( $conf_option_throwonerror );
141
142        return $value_option_throwonerror;
143    }
144
145    private function _get_option_error_color()
146    {
147        $DEFAULT_OPTION_ERROR_COLOR = '#CC0000';
148
149        $conf_option_error_color  = $this->getConf( 'option-error-color' );
150        $value_option_error_color = trim( $conf_option_error_color );
151
152        if ( !preg_match( '/^#(?:[0-9a-fA-F]{3}){1,2}$/i', $value_option_error_color ) ) {
153            $log_title    = '[KaTeX] Invalid Configuration Value ("option-error-color")';
154            $log_messages = "The configuration value shown below is invalid:
155
156            ---
157            {$conf_option_error_color}
158            ---
159
160            The value of \"option-error-color\" option should be in HEX3/HEX6 color code format. e.g. \"#04aa6d\" or \"#FFF\"
161            KaTeX plugin will fallback to the default value.";
162            Logger::error( $log_title, $log_messages, __FILE__, __LINE__ );
163
164            $value_option_error_color = $DEFAULT_OPTION_ERROR_COLOR;
165        }
166
167        return $value_option_error_color;
168    }
169
170    private function _get_option_macros()
171    {
172        $DEFAULT_OPTION_MACROS = array(
173            "\\NN" => "\\mathbb{N}",
174            "\\ZZ" => "\\mathbb{Z}",
175            "\\QQ" => "\\mathbb{Q}",
176            "\\RR" => "\\mathbb{R}",
177            "\\CC" => "\\mathbb{C}",
178        );
179
180        $conf_option_macros = $this->getConf( 'option-macros' );
181
182        try {
183            $value_option_macros = array_column( array_map( fn( $line ): array=> json_decode( str_replace( "\\", "\\\\", trim( $line ) ), true ), explode( "\n", trim( $conf_option_macros ) ) ), 'expansion', 'command' );
184            if ( !$value_option_macros ) {
185                throw new Exception( 'Parsing Result is null' );
186            }
187        } catch ( Throwable $e ) {
188            $log_title    = '[KaTeX] Invalid Configuration Value ("option-macros")';
189            $log_messages = "The configuration value shown below is invalid:
190
191            ---
192            {$conf_option_macros}
193            ---
194
195            The value of \"option-macros\" option should be mutiple lines of string in '{ \"command\": \"<COMMAND>\", \"expansion\": \"<EXPANSION>\" }' format.
196            KaTeX plugin will fallback to the default value.";
197            Logger::error( $log_title, $log_messages, __FILE__, __LINE__ );
198
199            $value_option_macros = $DEFAULT_OPTION_MACROS;
200        }
201
202        return $value_option_macros;
203    }
204}
205