1<?php 2 3// implementation of 4// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code 5 6// must be run within Dokuwiki 7use ComboStrap\PluginUtility; 8use ComboStrap\Prism; 9use ComboStrap\Tag; 10 11require_once(__DIR__ . '/../class/StringUtility.php'); 12require_once(__DIR__ . '/../class/Prism.php'); 13 14if (!defined('DOKU_INC')) die(); 15 16 17class syntax_plugin_combo_code extends DokuWiki_Syntax_Plugin 18{ 19 20 /** 21 * Enable or disable the code component 22 */ 23 const CONF_CODE_ENABLE = 'codeEnable'; 24 25 26 /** 27 * The tag of the ui component 28 */ 29 const CODE_TAG = "code"; 30 const FILE_PATH_KEY = "file-path"; 31 32 33 function getType() 34 { 35 /** 36 * You can't write in a code block 37 */ 38 return 'protected'; 39 } 40 41 /** 42 * How DokuWiki will add P element 43 * 44 * * 'normal' - The plugin can be used inside paragraphs 45 * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 46 * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 47 * 48 * @see DokuWiki_Syntax_Plugin::getPType() 49 */ 50 function getPType() 51 { 52 return 'block'; 53 } 54 55 /** 56 * @return array 57 * Allow which kind of plugin inside 58 * 59 * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs') 60 * because we manage self the content and we call self the parser 61 * 62 * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php 63 */ 64 function getAllowedTypes() 65 { 66 return array(); 67 } 68 69 function getSort() 70 { 71 /** 72 * Should be less than the code syntax plugin 73 * which is 200 74 **/ 75 return 199; 76 } 77 78 79 function connectTo($mode) 80 { 81 82 if ($this->getConf(self::CONF_CODE_ENABLE)) { 83 $pattern = PluginUtility::getContainerTagPattern(self::CODE_TAG); 84 $this->Lexer->addEntryPattern($pattern, $mode, PluginUtility::getModeForComponent($this->getPluginComponent())); 85 } 86 87 88 } 89 90 91 function postConnect() 92 { 93 if ($this->getConf(self::CONF_CODE_ENABLE)) { 94 $this->Lexer->addExitPattern('</' . self::CODE_TAG . '>', PluginUtility::getModeForComponent($this->getPluginComponent())); 95 } 96 97 98 } 99 100 /** 101 * 102 * The handle function goal is to parse the matched syntax through the pattern function 103 * and to return the result for use in the renderer 104 * This result is always cached until the page is modified. 105 * @param string $match 106 * @param int $state 107 * @param int $pos - byte position in the original source file 108 * @param Doku_Handler $handler 109 * @return array|bool 110 * @see DokuWiki_Syntax_Plugin::handle() 111 * 112 */ 113 function handle($match, $state, $pos, Doku_Handler $handler) 114 { 115 116 switch ($state) { 117 118 case DOKU_LEXER_ENTER : 119 $tagAttributes = PluginUtility::getQualifiedTagAttributes($match, true, self::FILE_PATH_KEY); 120 return array( 121 PluginUtility::STATE => $state, 122 PluginUtility::ATTRIBUTES => $tagAttributes 123 ); 124 125 case DOKU_LEXER_UNMATCHED : 126 127 $data = PluginUtility::handleAndReturnUnmatchedData(self::CODE_TAG, $match, $handler); 128 /** 129 * Attribute are send for the 130 * export of code functionality 131 */ 132 $tag = new Tag(self::CODE_TAG, array(), $state, $handler); 133 $tagAttributes = $tag->getParent()->getAttributes(); 134 $data[PluginUtility::ATTRIBUTES] = $tagAttributes; 135 return $data; 136 137 138 case DOKU_LEXER_EXIT : 139 return array(PluginUtility::STATE => $state); 140 141 142 } 143 return array(); 144 145 } 146 147 /** 148 * Render the output 149 * @param string $format 150 * @param Doku_Renderer $renderer 151 * @param array $data - what the function handle() return'ed 152 * @return boolean - rendered correctly? (however, returned value is not used at the moment) 153 * @see DokuWiki_Syntax_Plugin::render() 154 * 155 * 156 */ 157 function render($format, Doku_Renderer $renderer, $data) 158 { 159 160 161 if ($format == 'xhtml') { 162 163 /** @var Doku_Renderer_xhtml $renderer */ 164 $state = $data [PluginUtility::STATE]; 165 switch ($state) { 166 case DOKU_LEXER_ENTER : 167 $attributes = $data[PluginUtility::ATTRIBUTES]; 168 Prism::htmlEnter($renderer, $attributes, $this); 169 break; 170 171 case DOKU_LEXER_UNMATCHED : 172 $renderer->doc .= PluginUtility::renderUnmatched($data); 173 break; 174 175 case DOKU_LEXER_EXIT : 176 Prism::htmlExit($renderer); 177 break; 178 179 } 180 return true; 181 } else if ($format == 'code') { 182 183 /** @var Doku_Renderer_code $renderer */ 184 $state = $data [PluginUtility::STATE]; 185 if ($state == DOKU_LEXER_UNMATCHED) { 186 187 $attributes = $data[PluginUtility::ATTRIBUTES]; 188 $text = $data[PluginUtility::PAYLOAD]; 189 $filename = $attributes[self::FILE_PATH_KEY]; 190 $language = strtolower($attributes["type"]); 191 $renderer->code($text, $language, $filename); 192 193 } 194 } 195 196 // unsupported $mode 197 return false; 198 199 } 200 201 202} 203 204