1<?php 2/** 3 * APIDoc plugin by marcus.runsten@stilit.se 4 * 5 * ToDo: Add coude highlighting 6 */ 7 8if(!defined('DOKU_INC')) die("Caller error"); 9 10class syntax_plugin_apidoc_data_class { 11 public $name="", $filename="", $extends="", $description=""; 12 public $methods=array(); 13 public $fields=array(); 14 15 public function __construct( $f ) { 16 switch( min( count( $f ), 4 ) ) { 17 case 4: 18 $this->description = $f[3]; 19 case 3: 20 $this->extends = $f[2]; 21 case 2: 22 $this->filename = $f[1]; 23 case 1: 24 $this->name = $f[0]; 25 default: 26 } 27 } 28} 29 30class syntax_plugin_apidoc_data_field { 31 public $definition="", $name="", $description=""; 32 33 public function __construct( $f ) { 34 switch( min( count( $f ), 3 ) ) { 35 case 3: 36 $this->description = $f[2]; 37 case 2: 38 $this->definition = $f[1]; 39 case 1: 40 $this->name = $f[0]; 41 default: 42 } 43 } 44} 45 46class syntax_plugin_apidoc_data_method { 47 public $name="", $definition="", $description="", $parameters=array(), $returns=""; 48 49 public function __construct( $f ) { 50 switch( min( count( $f ), 4 ) ) { 51 case 4: 52 $this->description = $f[3]; 53 case 3: 54 $this->returns = $f[2]; 55 case 2: 56 $this->definition = $f[1]; 57 case 1: 58 $this->name = $f[0]; 59 default: 60 } 61 } 62} 63 64class syntax_plugin_apidoc_data_parameter { 65 public $name="", $type="", $defaultvalue="", $description=""; 66 67 public function __construct( $f, &$c ) { 68 switch( min( count( $f ), 4 ) ) { 69 case 4: 70 $this->description = $f[3]; 71 case 3: 72 $this->defaultvalue = $f[2]; 73 case 2: 74 $this->type = $f[1]; 75 case 1: 76 $this->name = $f[0]; 77 default: 78 } 79 } 80} 81 82class syntax_plugin_apidoc extends DokuWiki_Syntax_Plugin { 83 84 function getInfo(){ 85 return array( 86 'author' => 'Marcus Runsten', 87 'email' => 'marcus@stilit.se', 88 'date' => '2015-11-12', 89 'name' => 'API Documentation Plugin', 90 'desc' => 'Adds syntax for API Documentation to DokuWiki. Version 1.1', 91 'url' => 'http://www.stilit.se/?page_id=107' 92 ); 93 } 94 95 function getType(){ return 'protected';} 96 function getPType(){ return 'block';} 97 function getSort(){ return 100; } 98 99 function connectTo($mode) { 100 $this->Lexer->addEntryPattern( '<apidoc(?=>.*?</apidoc>)', $mode, 'plugin_apidoc' ); 101 } 102 103 function postConnect() { 104 $this->Lexer->addExitPattern('</apidoc>', 'plugin_apidoc'); 105 } 106 107 function handle($match, $state, $pos, &$handler){ 108 switch ($state) { 109 case DOKU_LEXER_ENTER: 110 $this->syntax = substr($match, 1); 111 return false; 112 113 case DOKU_LEXER_UNMATCHED: 114 file_put_contents( "/tmp/handle.txt", "Hanterar " . $match ); 115 if( $this->syntax == 'apidoc' ) { 116 return $this->apidoc_parse( substr( $match, 1 ) ); 117 } 118 } 119 return false; 120 } 121 122 /** 123 * Create output 124 */ 125 function render($mode, &$renderer, $data) { 126 if( $data ) $renderer->doc .= $data[0]; 127 return true; 128 } 129 130 private function apidoc_highlight( $str, $bool ) { 131 $p = array( "/[\"\'].*?[\"\']/", 132 "/\[\[(.*?);(.*?)\]\]/", 133 "/\[\[(.*?)\]\]/", 134 "/[\d]x[\d]+?|[\d]/", 135 "/(^)([\w]+?)(\(.*?\))|(\s)([\w]+?)(\(.*?\))/", 136 "/[()]/", 137 "/[\\[\\]]/", 138 "/[\\{\\}]/", 139 '/(\$\w+?)([\s$])/', 140 "/(?i)const\s|public|private|protected|new/", 141 "/(?i)string|integer|boolean|bool|int|char|function/" 142 ); 143 144 $r = array( '<span class="apidoc_highlight_string">$0</span>', 145 '<a href="$1" class="apidoc_link">$2</a>', 146 '<a href="$1" class="apidoc_link">$1</a>', 147 '<span class="apidoc_highlight_digit">$0</span>', 148 '$1$4<span class="apidoc_highlight_method">$2$5</span>$3$6 ', 149 '<span class="apidoc_highlight_bracket">$0</span>', 150 '<span class="apidoc_highlight_squarebracket">$0</span>', 151 '<span class="apidoc_highlight_birdbracket">$0</span>', 152 '<span class="apidoc_highlight_variable">$1</span>$2', 153 '<span class="apidoc_highlight_avail">$0</span>', 154 '<span class="apidoc_highlight_type">$0</span>', 155 ); 156 return preg_replace( $p, $r, $str ); 157 } 158 159 private function apidoc_out_html( $data ) { 160 $html = "<p class='apidoc_head'><span class='apidoc_classname apidoc_code'>"; 161 $html .= $this->apidoc_highlight( $data->name, true ); 162 $html .= "</span></p><table class='apidoc'><tr><td><div class='apidoc_left'><p class='apidoc_left_head'>Fields</p><ul class='apidoc_left_content'>"; 163 164 foreach( $data->fields AS $f ) { 165 $html .= "<li><a href='#field_" . $f->name . "'><span class='apidoc_code'>" . $this->apidoc_highlight( $f->name, true ) . "</span></a></li>"; 166 } 167 168 $html .= "</ul><p class='apidoc_left_head'>Methods</p><ul class='apidoc_left_content'>"; 169 foreach( $data->methods AS $m ) { 170 $html .= "<li><a href='#method_" . $m->name . "'><span class='apidoc_code'>" . $this->apidoc_highlight( $m->name, true ) . "</span></a></li>"; 171 } 172 173 $html .= "</ul></div></td><td class='apidoc_right'>"; 174 175 $html .= "<p class='apidoc_right_bighead apidoc_code'>" . $this->apidoc_highlight( $data->name, true ) . "</p>"; 176 $html .= "<p class='apidoc_right'><span class='apidoc_bold'>Filename : </span> " . $data->filename . "<br />"; 177 $html .= "<span class='apidoc_bold'>Extends : </span><span class='apidoc_code'>" . $this->apidoc_highlight( $data->extends, true ) . "</span></p>"; 178 $html .= "<p class='apidoc_right_head'>Description</p>"; 179 $html .= "<p class='apidoc_right'>" . $data->description . "</p>"; 180 181 $html .= "<p class='apidoc_right_bighead'>Fields</p>"; 182 foreach( $data->fields AS $f ) { 183 $html .= "<div id='field_" . $f->name . "' class='apidoc_right_field'>"; 184 $html .= "<p class='apidoc_right_head apidoc_code'>" . $this->apidoc_highlight( $f->name, true ) . "</p>"; 185 $html .= "<p class='apidoc_right'><span class='apidoc_bold'>Definition : </span><span class='apidoc_code'>" . $this->apidoc_highlight( $f->definition, true ) . "<br />"; 186 $html .= "<span class='apidoc_bold'>Description</span><br />" . $f->description . "</p>"; 187 $html .= "</div>"; 188 } 189 190 $html .= "<p class='apidoc_right_bighead'>Methods</p>"; 191 foreach( $data->methods AS $m ) { 192 $html .= "<div id='method_" . $m->name . "' class='apidoc_right_method'>"; 193 $html .= "<p class='apidoc_right_head apidoc_code'>" . $this->apidoc_highlight( $m->name, true ) . "</p>"; 194 $html .= "<p class='apidoc_right'><span class='apidoc_bold'>Definition : </span><span class='apidoc_code'>" . $this->apidoc_highlight( $m->definition, true ) . "</span></p>"; 195 $html .= "<p class='apidoc_right'><span class='apidoc_bold'>Returns : </span><span class='apidoc_code'>" . $this->apidoc_highlight( $m->returns, true ) . "</span></p>"; 196 $html .= "<p class='apidoc_right'><span class='apidoc_bold'>Description</span><br />" . $m->description . "</p>"; 197 198 $html .= "<div class='apidoc_right_parameters'>"; 199 $html .= "<p class='apidoc_right_head'>Parameters</p>"; 200 foreach( $m->parameters AS $p ) { 201 $html .= "<div class='apidoc_right_param'>"; 202 $html .= "<p class='apidoc_right_head apidoc_code'>" . $this->apidoc_highlight( $p->name, true ) . "</p>"; 203 $html .= "<p class='apidoc_right'>"; 204 $html .= "<span class='apidoc_bold'>Type : </span><span class='apidoc_code'>" . $this->apidoc_highlight( $p->type, true ) . "</span><br />"; 205 $html .= "<span class='apidoc_bold'>Default value : </span><span class='apidoc_code'>" . $this->apidoc_highlight( $p->defaultvalue, true ) . "</span>"; 206 $html .= "</p>"; 207 $html .= "<p class='apidoc_right'><span class='apidoc_bold'>Description</span><br />" . $p->description . "</p>"; 208 $html .= "</div>"; 209 } 210 211 $html .= "</div>"; 212 213 $html .= "</div>"; 214 } 215 216 217 return $html; 218 } 219 220 private function apidoc_parse( $str ) { 221 $data = $this->apidoc_parse_data( $str ); 222 if( !$data ) return false; 223 224 $data = $this->apidoc_sort_data( $data ); 225 if( !$data ) return false; 226 227 $html = $this->apidoc_out_html( $data ); 228 229 return array( $html ); 230 } 231 232 private function apidoc_parse_data( $str ) { 233 $rData = null; 234 $co = null; 235 236 $matches = preg_split( "/(CLASS|FIELD|METHOD|PARAMETER)\|/", $str, -1, PREG_SPLIT_DELIM_CAPTURE ); 237 for( $i=0; $i < count( $matches )-1; $i++ ) { 238 switch( $matches[$i] ) { 239 case 'CLASS': 240 $rData = new syntax_plugin_apidoc_data_class( explode( "|", $matches[++$i] ) ); 241 break; 242 case 'FIELD': 243 if( $rData == null ) return false; 244 $co = $rData->fields[] = new syntax_plugin_apidoc_data_field( explode( "|", $matches[++$i] ) ); 245 break; 246 case 'METHOD': 247 if( $rData == null ) return false; 248 $co = $rData->methods[] = new syntax_plugin_apidoc_data_method( explode( "|", $matches[++$i] ) ); 249 break; 250 case 'PARAMETER': 251 if( $rData == null || $co == null ) return false; 252 $co->parameters[] = new syntax_plugin_apidoc_data_parameter( explode( "|", $matches[++$i] ) ); 253 default: // Do nothing 254 break; 255 } 256 } 257 return $rData; 258 } 259 260 private function apidoc_sort( $arr ) { 261 $tgt = array(); 262 while( count( $arr ) > 0 ) { 263 $smallest = 0; 264 for( $i=0; $i < count( $arr ); $i++ ) if( strcasecmp( $arr[$smallest]->name, $arr[$i]->name ) > 0 ) $smallest = $i; 265 $tgt[] = $arr[$smallest]; 266 unset( $arr[$smallest] ); 267 $arr = array_values( $arr ); 268 } 269 return $tgt; 270 } 271 272 private function apidoc_sort_data( $data ) { 273 $data->fields = $this->apidoc_sort( $data->fields ); 274 $data->methods = $this->apidoc_sort( $data->methods ); 275 for( $i=0; $i < count( $data->methods ); $i++ ) $data->methods[$i]->parameters = $this->apidoc_sort( $data->methods[$i]->parameters ); 276 return $data; 277 } 278} 279 280?> 281