1*c6570b71SRobertWeinmeister<?php 2*c6570b71SRobertWeinmeister/** 3*c6570b71SRobertWeinmeister * DokuWiki Plugin mermaid (Syntax Component) 4*c6570b71SRobertWeinmeister * 5*c6570b71SRobertWeinmeister * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6*c6570b71SRobertWeinmeister * @author Robert Weinmeister <develop@weinmeister.org> 7*c6570b71SRobertWeinmeister */ 8*c6570b71SRobertWeinmeister 9*c6570b71SRobertWeinmeisteruse dokuwiki\Parsing\Parser; 10*c6570b71SRobertWeinmeister 11*c6570b71SRobertWeinmeisterclass syntax_plugin_mermaid extends \dokuwiki\Extension\SyntaxPlugin 12*c6570b71SRobertWeinmeister{ 13*c6570b71SRobertWeinmeister /** @inheritDoc */ 14*c6570b71SRobertWeinmeister function getType() 15*c6570b71SRobertWeinmeister { 16*c6570b71SRobertWeinmeister return 'container'; 17*c6570b71SRobertWeinmeister } 18*c6570b71SRobertWeinmeister 19*c6570b71SRobertWeinmeister /** @inheritDoc */ 20*c6570b71SRobertWeinmeister function getSort() 21*c6570b71SRobertWeinmeister { 22*c6570b71SRobertWeinmeister return 150; 23*c6570b71SRobertWeinmeister } 24*c6570b71SRobertWeinmeister 25*c6570b71SRobertWeinmeister /** 26*c6570b71SRobertWeinmeister * Connect lookup pattern to lexer. 27*c6570b71SRobertWeinmeister * 28*c6570b71SRobertWeinmeister * @param string $mode Parser mode 29*c6570b71SRobertWeinmeister */ 30*c6570b71SRobertWeinmeister function connectTo($mode) 31*c6570b71SRobertWeinmeister { 32*c6570b71SRobertWeinmeister $this->Lexer->addEntryPattern('<mermaid.*?>(?=.*?</mermaid>)',$mode,'plugin_mermaid'); 33*c6570b71SRobertWeinmeister } 34*c6570b71SRobertWeinmeister 35*c6570b71SRobertWeinmeister function postConnect() 36*c6570b71SRobertWeinmeister { 37*c6570b71SRobertWeinmeister $this->Lexer->addExitPattern('</mermaid>','plugin_mermaid'); 38*c6570b71SRobertWeinmeister } 39*c6570b71SRobertWeinmeister 40*c6570b71SRobertWeinmeister /** 41*c6570b71SRobertWeinmeister * Handle matches of the flowcharts syntax 42*c6570b71SRobertWeinmeister */ 43*c6570b71SRobertWeinmeister function handle($match, $state, $pos, Doku_Handler $handler) 44*c6570b71SRobertWeinmeister { 45*c6570b71SRobertWeinmeister switch ($state) { 46*c6570b71SRobertWeinmeister case DOKU_LEXER_ENTER: 47*c6570b71SRobertWeinmeister return array($state, $match); 48*c6570b71SRobertWeinmeister case DOKU_LEXER_UNMATCHED : 49*c6570b71SRobertWeinmeister return array($state, $match); 50*c6570b71SRobertWeinmeister case DOKU_LEXER_EXIT : 51*c6570b71SRobertWeinmeister return array($state, ''); 52*c6570b71SRobertWeinmeister } 53*c6570b71SRobertWeinmeister return false; 54*c6570b71SRobertWeinmeister } 55*c6570b71SRobertWeinmeister 56*c6570b71SRobertWeinmeister /** 57*c6570b71SRobertWeinmeister * Render xhtml output or metadata 58*c6570b71SRobertWeinmeister */ 59*c6570b71SRobertWeinmeister function render($mode, Doku_Renderer $renderer, $indata) 60*c6570b71SRobertWeinmeister { 61*c6570b71SRobertWeinmeister if($mode == 'xhtml'){ 62*c6570b71SRobertWeinmeister list($state, $match) = $indata; 63*c6570b71SRobertWeinmeister switch ($state) { 64*c6570b71SRobertWeinmeister case DOKU_LEXER_ENTER : 65*c6570b71SRobertWeinmeister $values = explode(" ", $match); 66*c6570b71SRobertWeinmeister $divwidth = count($values) < 2 ? 'auto' : $values[1]; 67*c6570b71SRobertWeinmeister $divheight = count($values) < 3 ? 'auto' : substr($values[2], 0, -1); 68*c6570b71SRobertWeinmeister $renderer->doc .= '<div class="mermaid" style="width:'.$divwidth.'; height:'.$divheight.'">'; 69*c6570b71SRobertWeinmeister break; 70*c6570b71SRobertWeinmeister case DOKU_LEXER_UNMATCHED : 71*c6570b71SRobertWeinmeister $instructions = $this->p_get_instructions($match); 72*c6570b71SRobertWeinmeister //echo "<script>console.log('Instructions ".json_encode($instructions)."' );</script>"; 73*c6570b71SRobertWeinmeister $xhtml = $this->p_render($instructions); 74*c6570b71SRobertWeinmeister $renderer->doc .= preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $xhtml); 75*c6570b71SRobertWeinmeister break; 76*c6570b71SRobertWeinmeister case DOKU_LEXER_EXIT : 77*c6570b71SRobertWeinmeister $renderer->doc .= "\r\n</div>"; 78*c6570b71SRobertWeinmeister break; 79*c6570b71SRobertWeinmeister } 80*c6570b71SRobertWeinmeister return true; 81*c6570b71SRobertWeinmeister } 82*c6570b71SRobertWeinmeister return false; 83*c6570b71SRobertWeinmeister } 84*c6570b71SRobertWeinmeister 85*c6570b71SRobertWeinmeister /* 86*c6570b71SRobertWeinmeister * Get the parser instructions siutable for the mermaid 87*c6570b71SRobertWeinmeister * 88*c6570b71SRobertWeinmeister */ 89*c6570b71SRobertWeinmeister function p_get_instructions($text) 90*c6570b71SRobertWeinmeister { 91*c6570b71SRobertWeinmeister //import parser classes and mode definitions 92*c6570b71SRobertWeinmeister require_once DOKU_INC . 'inc/parser/parser.php'; 93*c6570b71SRobertWeinmeister 94*c6570b71SRobertWeinmeister // https://www.dokuwiki.org/devel:parser 95*c6570b71SRobertWeinmeister // https://www.dokuwiki.org/devel:parser#basic_invocation 96*c6570b71SRobertWeinmeister // Create the parser and the handler 97*c6570b71SRobertWeinmeister $Parser = new Parser(new Doku_Handler()); 98*c6570b71SRobertWeinmeister 99*c6570b71SRobertWeinmeister $modes = array(); 100*c6570b71SRobertWeinmeister 101*c6570b71SRobertWeinmeister // add default modes 102*c6570b71SRobertWeinmeister $std_modes = array( 'internallink', 'media', 'externallink'); 103*c6570b71SRobertWeinmeister 104*c6570b71SRobertWeinmeister foreach($std_modes as $m 105*c6570b71SRobertWeinmeister ){ 106*c6570b71SRobertWeinmeister $class = 'dokuwiki\\Parsing\\ParserMode\\'.ucfirst($m); 107*c6570b71SRobertWeinmeister $obj = new $class(); 108*c6570b71SRobertWeinmeister $modes[] = array( 109*c6570b71SRobertWeinmeister 'sort' => $obj->getSort(), 110*c6570b71SRobertWeinmeister 'mode' => $m, 111*c6570b71SRobertWeinmeister 'obj' => $obj 112*c6570b71SRobertWeinmeister ); 113*c6570b71SRobertWeinmeister } 114*c6570b71SRobertWeinmeister 115*c6570b71SRobertWeinmeister // add formatting modes 116*c6570b71SRobertWeinmeister $fmt_modes = array( 'strong', 'emphasis', 'underline', 'monospace', 'subscript', 'superscript', 'deleted'); 117*c6570b71SRobertWeinmeister foreach($fmt_modes as $m) 118*c6570b71SRobertWeinmeister { 119*c6570b71SRobertWeinmeister $obj = new \dokuwiki\Parsing\ParserMode\Formatting($m); 120*c6570b71SRobertWeinmeister $modes[] = array( 121*c6570b71SRobertWeinmeister 'sort' => $obj->getSort(), 122*c6570b71SRobertWeinmeister 'mode' => $m, 123*c6570b71SRobertWeinmeister 'obj' => $obj 124*c6570b71SRobertWeinmeister ); 125*c6570b71SRobertWeinmeister } 126*c6570b71SRobertWeinmeister 127*c6570b71SRobertWeinmeister //add modes to parser 128*c6570b71SRobertWeinmeister foreach($modes as $mode) 129*c6570b71SRobertWeinmeister { 130*c6570b71SRobertWeinmeister $Parser->addMode($mode['mode'],$mode['obj']); 131*c6570b71SRobertWeinmeister } 132*c6570b71SRobertWeinmeister 133*c6570b71SRobertWeinmeister // Do the parsing 134*c6570b71SRobertWeinmeister $p = $Parser->parse($text); 135*c6570b71SRobertWeinmeister 136*c6570b71SRobertWeinmeister return $p; 137*c6570b71SRobertWeinmeister } 138*c6570b71SRobertWeinmeister 139*c6570b71SRobertWeinmeister public function p_render($instructions) 140*c6570b71SRobertWeinmeister { 141*c6570b71SRobertWeinmeister $Renderer = p_get_renderer('mermaid'); 142*c6570b71SRobertWeinmeister 143*c6570b71SRobertWeinmeister // Loop through the instructions 144*c6570b71SRobertWeinmeister foreach ($instructions as $instruction) { 145*c6570b71SRobertWeinmeister if(method_exists($Renderer, $instruction[0])){ 146*c6570b71SRobertWeinmeister call_user_func_array(array(&$Renderer, $instruction[0]), $instruction[1] ? $instruction[1] : array()); 147*c6570b71SRobertWeinmeister } 148*c6570b71SRobertWeinmeister } 149*c6570b71SRobertWeinmeister 150*c6570b71SRobertWeinmeister return $Renderer->doc; 151*c6570b71SRobertWeinmeister } 152*c6570b71SRobertWeinmeister} 153