1<?php 2/** 3 * Mikio Core Syntax Plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author James Collins <james.collins@outlook.com.au> 7 */ 8 9if (!defined('DOKU_INC')) die(); 10if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 11 12 13class syntax_plugin_mikioplugin_core extends DokuWiki_Syntax_Plugin { 14 public $pattern_entry = ''; 15 public $pattern_exit = ''; 16 public $tag = ''; 17 public $noEndTag = false; 18 public $defaults = array(); 19 public $options = array(); 20 public $values = array(); 21 public $incClasses = array('shadow', 'shadow-none', 'shadow-sm', 'shadow-lg', 'w-25', 'w-50', 'w-75', 'w-100', 'w-auto', 'h-25', 'h-50', 'h-75', 'h-100', 'h-auto', 'text-left', 'text-center', 'text-right', 'text-justify', 'text-wrap', 'text-nowrap', 'text-truncate', 'text-break', 'text-lowercase', 'text-uppercase', 'text-capitalize', 'font-weight-bold', 'font-weight-bolder', 'font-weight-normal', 'font-weight-light', 'font-weight-lighter', 'font-italic', 'text-monospace', 'text-reset', 'text-muted', 'text-decoration-none', 'text-primary', 'text-secondary', 'text-success', 'text-danger', 'text-warning', 'text-info', 'text-light'. 'text-dark', 'text-body', 'text-white', 'text-black', 'text-white-50', 'text-black-50', 'bg-primary', 'bg-secondary', 'bg-success', 'bg-danger', 'bg-warning', 'bg-info', 'bg-light', 'bg-dark', 'bg-white', 'bg-transparent', 'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-0', 'border-top-0', 'border-right-0', 'border-bottom-0', 'border-left-0', 'border-primary', 'border-secondary', 'border-success', 'border-danger', 'border-warning', 'border-info', 'border-light', 'border-dark', 'border-white', 'rounded', 'rounded-top', 'rounded-right', 'rounded-bottom', 'rounded-left', 'rounded-circle', 'rounded-pill', 'rounded-0', 'rounded-sm', 'rounded-lg', 'clearfix', 'align-baseline', 'align-top', 'align-middle', 'align-bottom', 'align-text-top', 'align-text-bottom', 'sm-1', 'sm-2', 'sm-3', 'sm-4', 'sm-5', 'sm-6', 'sm-7', 'sm-8', 'sm-9', 'sm-10', 'sm-11', 'sm-12', 'md-1', 'md-2', 'md-3', 'md-4', 'md-5', 'md-6', 'md-7', 'md-8', 'md-9', 'md-10', 'md-11', 'md-12', 'lg-1', 'lg-2', 'lg-3', 'lg-4', 'lg-5', 'lg-6', 'lg-7', 'lg-8', 'lg-9', 'lg-10', 'lg-11', 'lg-12'); 22 23 24 function __construct() { 25 if(count($this->incClasses) > 0) { 26 $this->options = array_merge($this->options, $this->incClasses); 27 } 28 } 29 30 public function getType() { 31 return 'formatting'; 32 } 33 34 35 public function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); } 36 public function getSort(){ return 32; } 37 38 39 public function connectTo($mode) { 40 if($this->pattern_entry == '' && $this->tag != '') { 41 if($this->noEndTag) { 42 $this->pattern_entry = '<(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ').*?>'; 43 } else { 44 $this->pattern_entry = '<(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ').*?>(?=.*?</(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ')>)'; 45 } 46 } 47 48 if($this->pattern_entry != '') { 49 if($this->noEndTag) { 50 $this->Lexer->addSpecialPattern($this->pattern_entry, $mode, 'plugin_mikioplugin_'.$this->getPluginComponent()); 51 } else { 52 $this->Lexer->addEntryPattern($this->pattern_entry, $mode, 'plugin_mikioplugin_'.$this->getPluginComponent()); 53 } 54 } 55 } 56 57 58 public function postConnect() { 59 if(!$this->noEndTag) { 60 if($this->pattern_exit == '' && $this->tag != '') { 61 $this->pattern_exit = '</(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ')>'; 62 } 63 64 if($this->pattern_exit != '') { 65 $this->Lexer->addExitPattern($this->pattern_exit, 'plugin_mikioplugin_'.$this->getPluginComponent()); 66 } 67 } 68 } 69 70 public function handle($match, $state, $pos, Doku_Handler $handler){ 71 switch($state) { 72 case DOKU_LEXER_ENTER: 73 case DOKU_LEXER_SPECIAL: 74 $optionlist = preg_split('/\s(?=([^"]*"[^"]*")*[^"]*$)/', substr($match, strlen($this->tag) + 1, -1)); 75 76 $options = array(); 77 foreach($optionlist as $item) { 78 $i = strpos($item, '='); 79 if($i !== false) { 80 $value = substr($item, $i + 1); 81 82 if(substr($value, 0, 1) == '"') $value = substr($value, 1); 83 if(substr($value, -1) == '"') $value = substr($value, 0, -1); 84 85 $options[substr($item, 0, $i)] = $value; 86 } else { 87 $options[$item] = true; 88 } 89 } 90 91 $options_clean = $this->cleanOptions($options); 92 93 $this->values = $options_clean; 94 95 return array($state, $options_clean); 96 97 case DOKU_LEXER_UNMATCHED: 98 return array($state, $match); 99 100 case DOKU_LEXER_EXIT: 101 return array($state, ''); 102 } 103 104 return array(); 105 } 106 107 108 public function cleanOptions($options) { 109 $options_clean = array(); 110 111 foreach($this->options as $item => $value) { 112 if(is_string($value)) { 113 if(array_key_exists($value, $options)) { 114 $options_clean[$value] = $options[$value]; 115 } else { 116 $options_clean[$value] = false; 117 } 118 } else if(is_array($value)) { 119 foreach($value as $avalue) { 120 if(array_key_exists($avalue, $options)) { 121 $options_clean[$item] = $avalue; 122 } 123 } 124 } 125 } 126 127 foreach($this->defaults as $item => $value) { 128 if(array_key_exists($item, $options_clean) == false) { 129 $options_clean[$item] = $value; 130 } 131 } 132 133 return $options_clean; 134 } 135 136 137 public function render_lexer_enter(Doku_Renderer $renderer, $data) { 138 139 } 140 141 142 public function render_lexer_unmatched(Doku_Renderer $renderer, $data) { 143 $renderer->doc .= $renderer->_xmlEntities($data); 144 } 145 146 147 public function render_lexer_exit(Doku_Renderer $renderer, $data) { 148 149 } 150 151 152 public function render_lexer_special(Doku_Renderer $renderer, $data) { 153 154 } 155 156 157 public function render($mode, Doku_Renderer $renderer, $data) { 158 if($mode == 'xhtml'){ 159 list($state,$match) = $data; 160 161 switch ($state) { 162 case DOKU_LEXER_ENTER: 163 $this->render_lexer_enter($renderer, $match); 164 return true; 165 166 case DOKU_LEXER_UNMATCHED : 167 $this->render_lexer_unmatched($renderer, $match); 168 return true; 169 170 case DOKU_LEXER_EXIT : 171 $this->render_lexer_exit($renderer, $match); 172 return true; 173 174 case DOKU_LEXER_SPECIAL: 175 $this->render_lexer_special($renderer, $match); 176 return true; 177 } 178 179 return true; 180 } 181 182 return false; 183 } 184 185 186 public function buildClassString($options=null, $classes=null, $prefix='') { 187 $s = array(); 188 189 if($options != null) { 190 if($classes != null) { 191 foreach($classes as $item) { 192 if(array_key_exists($item, $options) && $options[$item] !== false) { 193 $classname = $item; 194 195 if(is_string($options[$item])) { 196 $classname = $options[$item]; 197 } 198 199 if(is_string($prefix)) { 200 $classname = $prefix . $classname; 201 } else if(is_array($prefix)) { 202 foreach($prefix as $pitem => $pvalue) { 203 if(is_string($pvalue)) { 204 if($pvalue == $item) { 205 if(is_string($options[$item])) { 206 $classname = $pitem . $options[$item]; 207 } else { 208 $classname = $pitem . $item; 209 } 210 } 211 } 212 213 if(is_array($pvalue)) { 214 foreach($pvalue as $ppitem) { 215 if($ppitem == $item) { 216 if(is_string($options[$item])) { 217 $classname = $pitem . $options[$item]; 218 } else { 219 $classname = $pitem . $item; 220 } 221 } 222 } 223 } 224 } 225 } 226 227 $s[] = $classname; 228 } 229 } 230 } 231 232 foreach($this->incClasses as $item => $value) { 233 if(array_key_exists($value, $options) && $options[$value] == true) { 234 $pre = substr($value, 0, 3); 235 if($pre == 'sm-' || $pre == 'md-' || $pre == 'lg-') $value = 'col-' . $value; 236 237 $s[] = $value; 238 } 239 } 240 } 241 242 $s = ' ' . implode(' ', $s); 243 return $s; 244 } 245 246 public function buildStyleString($options=null) { 247 $s = array(); 248 249 if($options != null) { 250 foreach($options as $item => $value) { 251 switch($item) { 252 case 'width': 253 $s[] = 'width:' . $value; 254 break; 255 case 'height': 256 $s[] = 'height:' . $value; 257 break; 258 case 'max-width': 259 $s[] = 'max-width:' . $value; 260 break; 261 case 'max-height': 262 $s[] = 'max-height:' . $value; 263 break; 264 } 265 } 266 } 267 268 $s = implode(';', $s); 269 return $s; 270 } 271 272 public function getMediaFile($str) { 273 $i = strpos($str, '?'); 274 if($i !== false) $str = substr($str, 0, $i); 275 276 $str = preg_replace('/[^\da-zA-Z:_.]+/', '', $str); 277 278 return(tpl_getMediaFile(array($str), false)); 279 } 280 281 282 public function getLink($str) { 283 $i = strpos($str, '://'); 284 if($i !== false) return $str; 285 286 return wl($str); 287 } 288 289 290 public function setAttr(&$attrList, $attr, $data, $newAttrName='', $newAttrVal='') { 291 if(array_key_exists($attr, $data) && $data[$attr] !== false) { 292 $value = $data[$attr]; 293 294 if($newAttrName != '') $attr = $newAttrName; 295 if($newAttrVal != '') { 296 $newAttrVal = str_replace('%%VALUE%%', $value, $newAttrVal); 297 if(strpos($newAttrVal, '%%MEDIA%%') !== false) { 298 $newAttrVal = str_replace('%%MEDIA%%', $this->getMediaFile($value), $newAttrVal); 299 } 300 301 $value = $newAttrVal; 302 } 303 304 $attrList[$attr] = $value; 305 } 306 } 307 308 309 public function listAttr($attrName, $attrs) { 310 $s = ''; 311 312 if(count($attrs) > 0) { 313 foreach($attrs as $item => $value) { 314 $s .= $item . ':' . $value . ';'; 315 } 316 317 $s = $attrName . '="' . $s . '" '; 318 } 319 320 return $s; 321 } 322 323 324 public function syntaxRender(Doku_Renderer $renderer, $className, $text, $data=null) { 325 $class = new $className; 326 327 if(!is_array($data)) $data = array(); 328 329 $data = $class->cleanOptions($data); 330 $class->values = $data; 331 332 if($class->noEndTag) { 333 $class->render_lexer_special($renderer, $data); 334 } else { 335 $class->render_lexer_enter($renderer, $data); 336 $renderer->doc .= $text; 337 $class->render_lexer_exit($renderer, null); 338 } 339 } 340}