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 public $incOptions = array('width', 'min-width', 'max-width', 'height', 'min-height', 'max-height', 'overflow', 'tooltip', 'tooltip-html', 'tooltop-left', 'tooltip-top', 'tooltip-right', 'tooltip-bottom', 'tooltip-html-top', 'tooltip-html-left', 'tooltip-html-right', 'tooltip-html-bottom'); 23 24 25 function __construct() { 26 if(count($this->incClasses) > 0) { 27 $this->options = array_merge($this->options, $this->incClasses, $this->incOptions); 28 } 29 } 30 31 public function getType() { 32 return 'formatting'; 33 } 34 35 36 public function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); } 37 public function getSort(){ return 32; } 38 39 40 public function connectTo($mode) { 41 if($this->pattern_entry == '' && $this->tag != '') { 42 if($this->noEndTag) { 43 $this->pattern_entry = '<(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ').*?>'; 44 } else { 45 $this->pattern_entry = '<(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ').*?>(?=.*?</(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ')>)'; 46 } 47 } 48 49 if($this->pattern_entry != '') { 50 if($this->noEndTag) { 51 $this->Lexer->addSpecialPattern($this->pattern_entry, $mode, 'plugin_mikioplugin_'.$this->getPluginComponent()); 52 } else { 53 $this->Lexer->addEntryPattern($this->pattern_entry, $mode, 'plugin_mikioplugin_'.$this->getPluginComponent()); 54 } 55 } 56 } 57 58 59 public function postConnect() { 60 if(!$this->noEndTag) { 61 if($this->pattern_exit == '' && $this->tag != '') { 62 $this->pattern_exit = '</(?:' . strtoupper($this->tag) . '|' . strtolower($this->tag) . ')>'; 63 } 64 65 if($this->pattern_exit != '') { 66 $this->Lexer->addExitPattern($this->pattern_exit, 'plugin_mikioplugin_'.$this->getPluginComponent()); 67 } 68 } 69 } 70 71 public function handle($match, $state, $pos, Doku_Handler $handler){ 72 switch($state) { 73 case DOKU_LEXER_ENTER: 74 case DOKU_LEXER_SPECIAL: 75 $optionlist = preg_split('/\s(?=([^"]*"[^"]*")*[^"]*$)/', substr($match, strlen($this->tag) + 1, -1)); 76 77 $options = array(); 78 foreach($optionlist as $item) { 79 $i = strpos($item, '='); 80 if($i !== false) { 81 $value = substr($item, $i + 1); 82 83 if(substr($value, 0, 1) == '"') $value = substr($value, 1); 84 if(substr($value, -1) == '"') $value = substr($value, 0, -1); 85 86 $options[substr($item, 0, $i)] = $value; 87 } else { 88 $options[$item] = true; 89 } 90 } 91 92 $options_clean = $this->cleanOptions($options); 93 94 $this->values = $options_clean; 95 96 return array($state, $options_clean); 97 98 case DOKU_LEXER_UNMATCHED: 99 return array($state, $match); 100 101 case DOKU_LEXER_EXIT: 102 return array($state, ''); 103 } 104 105 return array(); 106 } 107 108 109 public function cleanOptions($options) { 110 $options_clean = array(); 111 112 foreach($this->options as $item => $value) { 113 if(is_string($value)) { 114 if(array_key_exists($value, $options)) { 115 $options_clean[$value] = $options[$value]; 116 } else { 117 $options_clean[$value] = false; 118 } 119 } else if(is_array($value)) { 120 foreach($value as $avalue) { 121 if(array_key_exists($avalue, $options)) { 122 $options_clean[$item] = $avalue; 123 } 124 } 125 } 126 } 127 128 foreach($this->defaults as $item => $value) { 129 if(array_key_exists($item, $options_clean) == false) { 130 $options_clean[$item] = $value; 131 } 132 } 133 134 return $options_clean; 135 } 136 137 138 public function render_lexer_enter(Doku_Renderer $renderer, $data) { 139 140 } 141 142 143 public function render_lexer_unmatched(Doku_Renderer $renderer, $data) { 144 $renderer->doc .= $renderer->_xmlEntities($data); 145 } 146 147 148 public function render_lexer_exit(Doku_Renderer $renderer, $data) { 149 150 } 151 152 153 public function render_lexer_special(Doku_Renderer $renderer, $data) { 154 155 } 156 157 158 public function render($mode, Doku_Renderer $renderer, $data) { 159 if($mode == 'xhtml'){ 160 list($state,$match) = $data; 161 162 switch ($state) { 163 case DOKU_LEXER_ENTER: 164 $this->render_lexer_enter($renderer, $match); 165 return true; 166 167 case DOKU_LEXER_UNMATCHED : 168 $this->render_lexer_unmatched($renderer, $match); 169 return true; 170 171 case DOKU_LEXER_EXIT : 172 $this->render_lexer_exit($renderer, $match); 173 return true; 174 175 case DOKU_LEXER_SPECIAL: 176 $this->render_lexer_special($renderer, $match); 177 return true; 178 } 179 180 return true; 181 } 182 183 return false; 184 } 185 186 187 public function buildClassString($options=null, $classes=null, $prefix='') { 188 $s = array(); 189 190 if($options != null) { 191 if($classes != null) { 192 foreach($classes as $item) { 193 if(array_key_exists($item, $options) && $options[$item] !== false) { 194 $classname = $item; 195 196 if(is_string($options[$item])) { 197 $classname = $options[$item]; 198 } 199 200 if(is_string($prefix)) { 201 $classname = $prefix . $classname; 202 } else if(is_array($prefix)) { 203 foreach($prefix as $pitem => $pvalue) { 204 if(is_string($pvalue)) { 205 if($pvalue == $item) { 206 if(is_string($options[$item])) { 207 $classname = $pitem . $options[$item]; 208 } else { 209 $classname = $pitem . $item; 210 } 211 } 212 } 213 214 if(is_array($pvalue)) { 215 foreach($pvalue as $ppitem) { 216 if($ppitem == $item) { 217 if(is_string($options[$item])) { 218 $classname = $pitem . $options[$item]; 219 } else { 220 $classname = $pitem . $item; 221 } 222 } 223 } 224 } 225 } 226 } 227 228 $s[] = $classname; 229 } 230 } 231 } 232 233 foreach($this->incClasses as $item => $value) { 234 if(array_key_exists($value, $options) && $options[$value] == true) { 235 $pre = substr($value, 0, 3); 236 if($pre == 'sm-' || $pre == 'md-' || $pre == 'lg-') $value = 'col-' . $value; 237 238 $s[] = $value; 239 } 240 } 241 } 242 243 $s = ' ' . implode(' ', $s); 244 return $s; 245 } 246 247 public function buildStyleString($options, $ignore=null, $append='') { 248 $s = array(); 249 250 if($options != null) { 251 foreach($options as $item => $value) { 252 if($value != false && ($ignore == null || (is_string($ignore) && $ignore != $item) || (is_array($ignore) && in_array($item, $ignore) == false))) { 253 switch($item) { 254 case 'width': 255 $s[] = 'width:' . $value; 256 break; 257 case 'height': 258 $s[] = 'height:' . $value; 259 break; 260 case 'min-width': 261 $s[] = 'min-width:' . $value; 262 break; 263 case 'min-height': 264 $s[] = 'min-height:' . $value; 265 break; 266 case 'max-width': 267 $s[] = 'max-width:' . $value; 268 break; 269 case 'max-height': 270 $s[] = 'max-height:' . $value; 271 break; 272 case 'overflow': 273 $s[] = 'overflow:' . $value; 274 break; 275 } 276 } 277 } 278 } 279 280 $s = implode(';', $s) . $append; 281 282 if($s != '') $s = ' style="' . $s . '" '; 283 284 return $s; 285 } 286 287 public function buildTooltipString($options) { 288 $dataPlacement = 'top'; 289 $dataHtml = false; 290 $title = ''; 291 292 if($options != null) { 293 if(array_key_exists('tooltip-html-top', $options) && $options['tooltip-html-top'] != '') { 294 $title = $options['tooltip-html-top']; 295 $dataPlacement = 'top'; 296 } 297 298 if(array_key_exists('tooltip-html-left', $options) && $options['tooltip-html-left'] != '') { 299 $title = $options['tooltip-html-left']; 300 $dataPlacement = 'left'; 301 } 302 303 if(array_key_exists('tooltip-html-bottom', $options) && $options['tooltip-html-bottom'] != '') { 304 $title = $options['tooltip-html-bottom']; 305 $dataPlacement = 'bottom'; 306 } 307 308 if(array_key_exists('tooltip-html-right', $options) && $options['tooltip-html-right'] != '') { 309 $title = $options['tooltip-html-right']; 310 $dataPlacement = 'right'; 311 } 312 313 if(array_key_exists('tooltip-top', $options) && $options['tooltip-top'] != '') { 314 $title = $options['tooltip-top']; 315 $dataPlacement = 'top'; 316 } 317 318 if(array_key_exists('tooltip-left', $options) && $options['tooltip-left'] != '') { 319 $title = $options['tooltip-left']; 320 $dataPlacement = 'left'; 321 } 322 323 if(array_key_exists('tooltip-bottom', $options) && $options['tooltip-bottom'] != '') { 324 $title = $options['tooltip-bottom']; 325 $dataPlacement = 'bottom'; 326 } 327 328 if(array_key_exists('tooltip-right', $options) && $options['tooltip-right'] != '') { 329 $title = $options['tooltip-right']; 330 $dataPlacement = 'right'; 331 } 332 333 if(array_key_exists('tooltip-html', $options) && $options['tooltip-html'] != '') { 334 $title = $options['tooltip-html']; 335 $dataPlacement = 'top'; 336 } 337 338 if(array_key_exists('tooltip', $options) && $options['tooltip'] != '') { 339 $title = $options['tooltip']; 340 $dataPlacement = 'top'; 341 } 342 } 343 344 if($title != '') { 345 return ' data-toggle="tooltip" data-placement="' . $dataPlacement . '" ' . ($dataHtml == true ? 'data-html="true" ' : '') . 'title="' . $title . '" '; 346 } 347 348 return ''; 349 } 350 351 public function getMediaFile($str) { 352 $i = strpos($str, '?'); 353 if($i !== false) $str = substr($str, 0, $i); 354 355 $str = preg_replace('/[^\da-zA-Z:_.]+/', '', $str); 356 357 return(tpl_getMediaFile(array($str), false)); 358 } 359 360 361 public function getLink($str) { 362 $i = strpos($str, '://'); 363 if($i !== false) return $str; 364 365 return wl($str); 366 } 367 368 369 public function setAttr(&$attrList, $attr, $data, $newAttrName='', $newAttrVal='') { 370 if(array_key_exists($attr, $data) && $data[$attr] !== false) { 371 $value = $data[$attr]; 372 373 if($newAttrName != '') $attr = $newAttrName; 374 if($newAttrVal != '') { 375 $newAttrVal = str_replace('%%VALUE%%', $value, $newAttrVal); 376 if(strpos($newAttrVal, '%%MEDIA%%') !== false) { 377 $newAttrVal = str_replace('%%MEDIA%%', $this->getMediaFile($value), $newAttrVal); 378 } 379 380 $value = $newAttrVal; 381 } 382 383 $attrList[$attr] = $value; 384 } 385 } 386 387 388 public function listAttr($attrName, $attrs) { 389 $s = ''; 390 391 if(count($attrs) > 0) { 392 foreach($attrs as $item => $value) { 393 $s .= $item . ':' . $value . ';'; 394 } 395 396 $s = $attrName . '="' . $s . '" '; 397 } 398 399 return $s; 400 } 401 402 403 public function syntaxRender(Doku_Renderer $renderer, $className, $text, $data=null) { 404 $class = new $className; 405 406 if(!is_array($data)) $data = array(); 407 408 $data = $class->cleanOptions($data); 409 $class->values = $data; 410 411 if($class->noEndTag) { 412 $class->render_lexer_special($renderer, $data); 413 } else { 414 $class->render_lexer_enter($renderer, $data); 415 $renderer->doc .= $text; 416 $class->render_lexer_exit($renderer, null); 417 } 418 } 419}