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