1<?php 2 3/** 4 * Plugin RefNotes: Note renderer 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Mykola Ostrovskyy <dwpforge@gmail.com> 8 */ 9 10require_once(DOKU_PLUGIN . 'refnotes/core.php'); 11 12class syntax_plugin_refnotes_notes extends DokuWiki_Syntax_Plugin { 13 14 private $mode; 15 16 /** 17 * Constructor 18 */ 19 public function __construct() { 20 $this->mode = substr(get_class($this), 7); 21 } 22 23 /** 24 * What kind of syntax are we? 25 */ 26 public function getType() { 27 return 'substition'; 28 } 29 30 public function getPType() { 31 return 'block'; 32 } 33 34 /** 35 * Where to sort in? 36 */ 37 public function getSort() { 38 return 150; 39 } 40 41 public function connectTo($mode) { 42 $this->Lexer->addSpecialPattern('~~REFNOTES.*?~~', $mode, $this->mode); 43 $this->Lexer->addSpecialPattern('<refnotes[^>]*?\/>', $mode, $this->mode); 44 $this->Lexer->addSpecialPattern('<refnotes(?:[^>]*?[^/>])?>.*?<\/refnotes>', $mode, $this->mode); 45 } 46 47 /** 48 * Handle the match 49 */ 50 public function handle($match, $state, $pos, Doku_Handler $handler) { 51 switch ($match[0]) { 52 case '~': 53 return $this->handleBasic($match); 54 55 case '<': 56 return $this->handleExtended($match); 57 } 58 59 return false; 60 } 61 62 /** 63 * Create output 64 */ 65 public function render($mode, Doku_Renderer $renderer, $data) { 66 try { 67 if($mode == 'xhtml') { 68 switch ($data[0]) { 69 case 'style': 70 refnotes_renderer_core::getInstance()->styleNamespace($data[1]['ns'], $data[2]); 71 break; 72 73 case 'map': 74 refnotes_renderer_core::getInstance()->setNamespaceMapping($data[1]['ns'], $data[2]); 75 break; 76 77 case 'render': 78 $this->renderNotes($mode, $renderer, $data[1]); 79 break; 80 } 81 82 return true; 83 } 84 elseif ($mode == 'odt') { 85 switch ($data[0]) { 86 case 'render': 87 $this->renderNotes($mode, $renderer, $data[1]); 88 break; 89 } 90 91 return true; 92 } 93 } 94 catch (Exception $error) { 95 msg($error->getMessage(), -1); 96 } 97 98 return false; 99 } 100 101 /** 102 * 103 */ 104 private function handleBasic($syntax) { 105 preg_match('/~~REFNOTES(.*?)~~/', $syntax, $match); 106 107 return array('render', $this->parseAttributes($match[1])); 108 } 109 110 /** 111 * 112 */ 113 private function handleExtended($syntax) { 114 preg_match('/<refnotes(.*?)(?:\/>|>(.*?)<\/refnotes>)/s', $syntax, $match); 115 $attribute = $this->parseAttributes($match[1]); 116 $style = array(); 117 118 if ($match[2] != '') { 119 $style = $this->parseStyles($match[2]); 120 } 121 122 if (count($style) > 0) { 123 return array('split', $attribute, $style); 124 } 125 else { 126 return array('render', $attribute); 127 } 128 } 129 130 /** 131 * 132 */ 133 private function parseAttributes($syntax) { 134 $propertyMatch = array( 135 'ns' => '/^' . refnotes_namespace::getNamePattern('required') . '$/', 136 'limit' => '/^\/?\d+$/' 137 ); 138 139 $attribute = array(); 140 $token = preg_split('/\s+/', $syntax, -1, PREG_SPLIT_NO_EMPTY); 141 foreach ($token as $t) { 142 foreach ($propertyMatch as $name => $pattern) { 143 if (preg_match($pattern, $t) == 1) { 144 $attribute[$name][] = $t; 145 break; 146 } 147 } 148 } 149 150 if (array_key_exists('ns', $attribute)) { 151 /* Ensure that namespaces are in canonic form */ 152 $attribute['ns'] = array_map('refnotes_namespace::canonizeName', $attribute['ns']); 153 154 if (count($attribute['ns']) > 1) { 155 $attribute['map'] = array_slice($attribute['ns'], 1); 156 } 157 158 $attribute['ns'] = $attribute['ns'][0]; 159 } 160 else { 161 $attribute['ns'] = ':'; 162 } 163 164 if (array_key_exists('limit', $attribute)) { 165 $attribute['limit'] = end($attribute['limit']); 166 } 167 168 return $attribute; 169 } 170 171 /** 172 * 173 */ 174 private function parseStyles($syntax) { 175 $style = array(); 176 preg_match_all('/([-\w]+)\s*:[ \t]*([^\s\n;].*?)[ \t]*?(?:[\n;]|$)/', $syntax, $match, PREG_SET_ORDER); 177 foreach ($match as $m) { 178 $style[$m[1]] = $m[2]; 179 } 180 181 /* Validate direct-to-html styles */ 182 if (array_key_exists('notes-separator', $style)) { 183 if (preg_match('/(?:\d+\.?|\d*\.\d+)(?:%|em|px)|none/', $style['notes-separator'], $match) == 1) { 184 $style['notes-separator'] = $match[0]; 185 } 186 else { 187 $style['notes-separator'] = ''; 188 } 189 } 190 191 /* Ensure that namespaces are in canonic form */ 192 if (array_key_exists('inherit', $style)) { 193 $style['inherit'] = refnotes_namespace::canonizeName($style['inherit']); 194 } 195 196 return $style; 197 } 198 199 /** 200 * 201 */ 202 private function renderNotes($mode, $renderer, $attribute) { 203 $limit = array_key_exists('limit', $attribute) ? $attribute['limit'] : ''; 204 $doc = refnotes_renderer_core::getInstance()->renderNotes($mode, $attribute['ns'], $limit); 205 206 if ($doc != '') { 207 if ($mode == 'xhtml') { 208 $open = '<div class="refnotes">' . DOKU_LF; 209 $close = '</div>' . DOKU_LF; 210 } 211 else { 212 $open = ''; 213 $close = ''; 214 } 215 216 $renderer->doc .= $open; 217 $renderer->doc .= $doc; 218 $renderer->doc .= $close; 219 } 220 } 221} 222