1<?php 2if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 4 5/** 6 * Explain Terms and Definitions 7 * 8 * It works like acronym.conf, but for any term (even with more than 9 * one word). 10 * 11 * Evaluates conf/explain.conf which is in the following syntax: 12 * 13 * [<WHITESPACE>]term<TAB>explanation<TAB>link1<TAB>link2 14 * 15 * WHITESPACE: If term starts with a whitespace character (Tab, Space, …), 16 * it is considered case-sensitive 17 * term: the term to explain 18 * explanation: a short description of the term 19 * link1: link as URL or wiki page (a:b:c) to the definition 20 * link2: link as URL or wiki page (a:b:c) to alternative definition 21 * 22 * If the first link points to the current page, the second link is used. 23 * Lines starting with # are treated as comments. 24 * 25 * @license GPL 26 * @author Marc Wäckerlin <marc@waeckerlin.org> 27 * @author Adrian Lang <lang@cosmocode.de> 28 * @author Andreas Gohr <gohr@cosmocode.de> 29 */ 30class syntax_plugin_explain extends DokuWiki_Syntax_Plugin { 31 32 function getType() { 33 return 'substition'; 34 } 35 36 function getSort() { 37 return 239; // before 'acronym' 38 } 39 40 function syntax_plugin_explain() { 41 // "static" not allowed in PHP4?!? 42 //if (isset($keys[0]) return; // evaluate at most once 43 $lines = @file(DOKU_CONF.'explain.conf'); 44 if ($lines === false) { 45 return; 46 } 47 foreach ($lines as $line) { 48 $i = (trim(substr($line, 0, 1)) !== ''); 49 $line = trim($line); 50 if (empty($line)) continue; 51 if (substr($line, 0, 1) === '#') continue; 52 $parts = explode("\t", $line); 53 if ($i) $parts[0] = utf8_strtolower($parts[0]); 54 $this->map[$parts[0]] = array('desc' => $parts[1], 55 'target' => $this->link(array_slice($parts, 2)), 56 'i' => $i); 57 } 58 } 59 60 function link($targets) { 61 foreach($targets as $target) { 62 $_ret = $this->_link($target); 63 if ($_ret !== '') { 64 break; 65 } 66 } 67 return $_ret; 68 } 69 70 function _link($target) { 71 /* Match an URL. */ 72 static $url = '#^https?://#'; 73 // '^(http://)?[-_[:alnum:]]+[-_.[:alnum:]]*\.[a-z]{2}' 74 // '(/[-_./[:alnum:]&%?=#]*)?'; 75 if (preg_match($url, $target)) 76 return $target; 77 78 /* Match an internal link. */ 79 list($id, $hash) = explode('#', $target, 2); 80 global $ID; 81 82 $_ret = ''; 83 if($ID != $id) { 84 $_ret .= wl($id); 85 } 86 if($hash != '') { 87 $_ret .= '#'.$hash; 88 } 89 return $_ret; 90 } 91 92 function connectTo($mode) { 93 if (count($this->map) === 0) 94 return; 95 96 $re = '(?<=^|\W)(?i:'. 97 join('|', array_map('preg_quote_cb', array_keys($this->map))). 98 ')(?=\W|$)'; 99 100 $this->Lexer->addSpecialPattern($re, $mode, 'plugin_explain'); 101 } 102 103 function handle($match, $state, $pos, Doku_Handler $handler) { 104 /* Supply the matched text in any case. */ 105 $data = array('content' => $match); 106 foreach (array_keys($this->map) as $rxmatch) { 107 if ($match === $rxmatch || 108 ($this->map[$rxmatch]['i'] && utf8_strtolower($match) === $rxmatch)) { 109 $data += $this->map[$rxmatch]; 110 /* Handle only the first occurrence. */ 111 unset($this->map[$rxmatch]['desc']); 112 break; 113 } 114 } 115 return $data; 116 } 117 118 public function render($format, Doku_Renderer $renderer, $data) { 119 if(is_null($data['desc'])) { 120 $renderer->doc .= hsc($data['content']); 121 return true; 122 } 123 if ($format == 'xhtml') { 124 $renderer->doc .= '<a class="explain"'; 125 if(($data['target']) !== '') { 126 $renderer->doc .= ' href="' . hsc($data['target']) . '"'; 127 } 128 $renderer->doc .= '>' . hsc($data['content']); 129 if ($data['desc'] !== '') { 130 $renderer->doc .= '<span class="tooltip">'.hsc($data['desc']).'</span>'; 131 } 132 $renderer->doc .= '</a>'; 133 return true; 134 } 135 // generate output for ODT export 136 if ($format == 'odt') { 137 $renderer->doc .= hsc($data['content']); 138 return true; 139 } 140 return false; 141 } 142} 143