1<?php 2/** 3 * DokuWiki Plugin mathjax (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Mark Liffiton <liffiton@gmail.com> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12/** 13 * Class syntax_plugin_mathjax_protecttex 14 */ 15class syntax_plugin_mathjax_protecttex extends DokuWiki_Syntax_Plugin { 16 # We need to grab any math before dokuwiki tries to parse it. 17 # Once it's 'claimed' by this plugin (type: protected), it won't be altered. 18 19 # Set of environments that this plugin will protect from Dokuwiki parsing 20 # * is escaped to work in regexp below 21 # Note: "math", "displaymath", and "flalign" environments seem to not be 22 # recognized by Mathjax... They will still be protected from Dokuwiki, 23 # but they will not be rendered by MathJax. 24 private static $ENVIRONMENTS = array( 25 "math", 26 "displaymath", 27 "equation", 28 "equation\*", 29 "eqnarray", 30 "eqnarray\*", 31 "align", 32 "align\*", 33 "flalign", 34 "flalign\*", 35 "alignat", 36 "alignat\*", 37 "multline", 38 "multline\*", 39 "gather", 40 "gather\*", 41 ); 42 43 /** 44 * Syntax Type 45 * 46 * Needs to return one of the mode types defined in $PARSER_MODES in parser.php 47 * 48 * @return string 49 */ 50 public function getType() { 51 return 'protected'; 52 } 53 54 /** 55 * Sort for applying this mode 56 * 57 * @return int 58 */ 59 public function getSort() { 60 return 65; 61 } 62 63 /** 64 * regexp patterns adapted from jsMath plugin: https://www.dokuwiki.org/plugin:jsmath 65 * 66 * @param string $mode 67 */ 68 public function connectTo($mode) { 69 $this->Lexer->addEntryPattern('(?<!\\\\)\$(?=[^\$][^\r\n]*?\$)',$mode,'plugin_mathjax_protecttex'); 70 $this->Lexer->addEntryPattern('\$\$(?=.*?\$\$)',$mode,'plugin_mathjax_protecttex'); 71 $this->Lexer->addEntryPattern('\\\\\((?=.*?\\\\\))',$mode,'plugin_mathjax_protecttex'); 72 $this->Lexer->addEntryPattern('\\\\\[(?=.*?\\\\])',$mode,'plugin_mathjax_protecttex'); 73 foreach (self::$ENVIRONMENTS as $env) { 74 $this->Lexer->addEntryPattern('\\\\begin{' . $env . '}(?=.*?\\\\end{' . $env . '})',$mode,'plugin_mathjax_protecttex'); 75 } 76 77 if ($this->getConf('asciimath')) { 78 // Protect the default AsciiMath delimiter 79 $this->Lexer->addEntryPattern('`(?=.*?`)',$mode,'plugin_mathjax_protecttex'); 80 } 81 82 // Protect specified tags, if any 83 $conf_mathtags = $this->getConf('mathtags'); 84 $mathtags = explode(',', $conf_mathtags); 85 foreach ($mathtags as $tag) { 86 $tag = trim($tag); 87 if ($tag == "") { continue; } 88 $this->Lexer->addEntryPattern('<' . $tag . '.*?>(?=.*?</' . $tag . '>)',$mode,'plugin_mathjax_protecttex'); 89 } 90 } 91 public function postConnect() { 92 $this->Lexer->addExitPattern('\$(?!\$)','plugin_mathjax_protecttex'); 93 $this->Lexer->addExitPattern('\\\\\)','plugin_mathjax_protecttex'); 94 $this->Lexer->addExitPattern('\\\\\]','plugin_mathjax_protecttex'); 95 foreach (self::$ENVIRONMENTS as $env) { 96 $this->Lexer->addExitPattern('\\\\end{' . $env . '}','plugin_mathjax_protecttex'); 97 } 98 99 if ($this->getConf('asciimath')) { 100 // Protect the default AsciiMath delimiter 101 $this->Lexer->addExitPattern('`','plugin_mathjax_protecttex'); 102 } 103 104 // Protect specified tags, if any 105 $conf_mathtags = $this->getConf('mathtags'); 106 $mathtags = explode(',', $conf_mathtags); 107 foreach ($mathtags as $tag) { 108 $tag = trim($tag); 109 if ($tag == "") { continue; } 110 $this->Lexer->addExitPattern('</' . $tag . '>','plugin_mathjax_protecttex'); 111 } 112 } 113 114 /** 115 * Handler to prepare matched data for the rendering process 116 * 117 * This function can only pass data to render() via its return value - render() 118 * may be not be run during the object's current life. 119 * 120 * Usually you should only need the $match param. 121 * 122 * @param string $match The text matched by the patterns 123 * @param int $state The lexer state for the match 124 * @param int $pos The character position of the matched text 125 * @param Doku_Handler $handler The Doku_Handler object 126 * @return array Return an array with all data you want to use in render 127 */ 128 public function handle($match, $state, $pos, Doku_Handler $handler){ 129 // Just pass it through... 130 return $match; 131 } 132 133 /** 134 * Handles the actual output creation. 135 * 136 * @param $mode string output format being rendered 137 * @param $renderer Doku_Renderer the current renderer object 138 * @param $data array data created by handler() 139 * @return boolean rendered correctly? 140 */ 141 public function render($mode, Doku_Renderer $renderer, $data) { 142 if ($mode == 'xhtml' || $mode == 'odt') { 143 /** @var Doku_Renderer_xhtml $renderer */ 144 145 // Just pass it through, but escape xml entities... 146 $renderer->doc .= $renderer->_xmlEntities($data); 147 return true; 148 } 149 if ($mode == 'latexport') { 150 // Pass math expressions to latexport renderer 151 $renderer->mathjax_content($data); 152 return true; 153 } 154 155 // For all other modes, pass through unchanged. 156 $renderer->doc .= $data; 157 return true; 158 } 159} 160 161// vim:ts=4:sw=4:et: 162