3 * Renderer for metadata
5 * @author Esther Brunner <wikidesign@gmail.com>
7 if(!defined('DOKU_INC')) die('meh.');
9 if ( !defined('DOKU_LF') ) {
10 // Some whitespace to help View > Source
11 define ('DOKU_LF',"\n");
14 if ( !defined('DOKU_TAB') ) {
15 // Some whitespace to help View > Source
16 define ('DOKU_TAB',"\t");
19 require_once DOKU_INC . 'inc/parser/renderer.php';
24 class Doku_Renderer_metadata extends Doku_Renderer {
28 var $persistent = array();
30 var $headers = array();
39 function document_start(){
42 $this->headers = array();
44 // external pages are missing create date
45 if(!$this->persistent['date']['created']){
46 $this->persistent['date']['created'] = filectime(wikiFN($ID));
48 if(!isset($this->persistent['user'])){
49 $this->persistent['user'] = '';
51 if(!isset($this->persistent['creator'])){
52 $this->persistent['creator'] = '';
54 // reset metadata to persistent values
55 $this->meta = $this->persistent;
58 function document_end(){
61 // store internal info in metadata (notoc,nocache)
62 $this->meta['internal'] = $this->info;
64 if (!isset($this->meta['description']['abstract'])){
65 // cut off too long abstracts
66 $this->doc = trim($this->doc);
67 if (strlen($this->doc) > 500)
68 $this->doc = utf8_substr($this->doc, 0, 500).'…';
69 $this->meta['description']['abstract'] = $this->doc;
72 $this->meta['relation']['firstimage'] = $this->firstimage;
74 if(!isset($this->meta['date']['modified'])){
75 $this->meta['date']['modified'] = filemtime(wikiFN($ID));
80 function toc_additem($id, $text, $level) {
83 //only add items within configured levels
84 if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){
85 // the TOC is one of our standard ul list arrays ;-)
86 $this->meta['description']['tableofcontents'][] = array(
90 'level' => $level-$conf['toptoclevel']+1
96 function header($text, $level, $pos) {
97 if (!isset($this->meta['title'])) $this->meta['title'] = $text;
99 // add the header to the TOC
100 $hid = $this->_headerToLink($text,'true');
101 $this->toc_additem($hid, $text, $level);
104 if ($this->capture && ($level > 1)) $this->doc .= DOKU_LF.$text.DOKU_LF;
107 function section_open($level){}
108 function section_close(){}
110 function cdata($text){
111 if ($this->capture) $this->doc .= $text;
115 if ($this->capture) $this->doc .= DOKU_LF;
120 if (strlen($this->doc) > 250) $this->capture = false;
121 else $this->doc .= DOKU_LF;
125 function linebreak(){
126 if ($this->capture) $this->doc .= DOKU_LF;
131 if (strlen($this->doc) > 250) $this->capture = false;
132 else $this->doc .= DOKU_LF.'----------'.DOKU_LF;
136 function strong_open(){}
137 function strong_close(){}
139 function emphasis_open(){}
140 function emphasis_close(){}
142 function underline_open(){}
143 function underline_close(){}
145 function monospace_open(){}
146 function monospace_close(){}
148 function subscript_open(){}
149 function subscript_close(){}
151 function superscript_open(){}
152 function superscript_close(){}
154 function deleted_open(){}
155 function deleted_close(){}
158 * Callback for footnote start syntax
160 * All following content will go to the footnote instead of
161 * the document. To achieve this the previous rendered content
162 * is moved to $store and $doc is cleared
164 * @author Andreas Gohr <andi@splitbrain.org>
166 function footnote_open() {
168 // move current content to store and record footnote
169 $this->store = $this->doc;
175 * Callback for footnote end syntax
177 * All rendered content is moved to the $footnotes array and the old
178 * content is restored from $store again
180 * @author Andreas Gohr
182 function footnote_close() {
184 // restore old content
185 $this->doc = $this->store;
190 function listu_open(){
191 if ($this->capture) $this->doc .= DOKU_LF;
194 function listu_close(){
195 if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false;
198 function listo_open(){
199 if ($this->capture) $this->doc .= DOKU_LF;
202 function listo_close(){
203 if ($this->capture && (strlen($this->doc) > 250)) $this->capture = false;
206 function listitem_open($level){
207 if ($this->capture) $this->doc .= str_repeat(DOKU_TAB, $level).'* ';
210 function listitem_close(){
211 if ($this->capture) $this->doc .= DOKU_LF;
214 function listcontent_open(){}
215 function listcontent_close(){}
217 function unformatted($text){
218 if ($this->capture) $this->doc .= $text;
221 function php($text){}
223 function phpblock($text){}
225 function html($text){}
227 function htmlblock($text){}
229 function preformatted($text){
230 if ($this->capture) $this->doc .= $text;
233 function file($text, $lang = null, $file = null){
235 $this->doc .= DOKU_LF.$text;
236 if (strlen($this->doc) > 250) $this->capture = false;
237 else $this->doc .= DOKU_LF;
241 function quote_open(){
242 if ($this->capture) $this->doc .= DOKU_LF.DOKU_TAB.'"';
245 function quote_close(){
248 if (strlen($this->doc) > 250) $this->capture = false;
249 else $this->doc .= DOKU_LF;
253 function code($text, $language = NULL, $file = null){
255 $this->doc .= DOKU_LF.$text;
256 if (strlen($this->doc) > 250) $this->capture = false;
257 else $this->doc .= DOKU_LF;
261 function acronym($acronym){
262 if ($this->capture) $this->doc .= $acronym;
265 function smiley($smiley){
266 if ($this->capture) $this->doc .= $smiley;
269 function entity($entity){
270 if ($this->capture) $this->doc .= $entity;
273 function multiplyentity($x, $y){
274 if ($this->capture) $this->doc .= $x.'×'.$y;
277 function singlequoteopening(){
279 if ($this->capture) $this->doc .= $lang['singlequoteopening'];
282 function singlequoteclosing(){
284 if ($this->capture) $this->doc .= $lang['singlequoteclosing'];
287 function apostrophe() {
289 if ($this->capture) $this->doc .= $lang['apostrophe'];
292 function doublequoteopening(){
294 if ($this->capture) $this->doc .= $lang['doublequoteopening'];
297 function doublequoteclosing(){
299 if ($this->capture) $this->doc .= $lang['doublequoteclosing'];
302 function camelcaselink($link) {
303 $this->internallink($link, $link);
306 function locallink($hash, $name = NULL){}
309 * keep track of internal links in $this->meta['relation']['references']
311 function internallink($id, $name = NULL){
315 $this->_firstimage($name['src']);
317 $default = $this->_simpleTitle($id);
319 // first resolve and clean up the $id
320 resolve_pageid(getNS($ID), $id, $exists);
321 list($page, $hash) = explode('#', $id, 2);
324 $this->meta['relation']['references'][$page] = $exists;
325 // $data = array('relation' => array('isreferencedby' => array($ID => true)));
326 // p_set_metadata($id, $data);
328 // add link title to summary
330 $name = $this->_getLinkTitle($name, $default, $id);
335 function externallink($url, $name = NULL){
337 $this->_firstimage($name['src']);
340 $this->doc .= $this->_getLinkTitle($name, '<' . $url . '>');
344 function interwikilink($match, $name = NULL, $wikiName, $wikiUri){
346 $this->_firstimage($name['src']);
349 list($wikiUri, $hash) = explode('#', $wikiUri, 2);
350 $name = $this->_getLinkTitle($name, $wikiUri);
355 function windowssharelink($url, $name = NULL){
357 $this->_firstimage($name['src']);
360 if ($name) $this->doc .= $name;
361 else $this->doc .= '<'.$url.'>';
365 function emaillink($address, $name = NULL){
367 $this->_firstimage($name['src']);
370 if ($name) $this->doc .= $name;
371 else $this->doc .= '<'.$address.'>';
375 function internalmedia($src, $title=NULL, $align=NULL, $width=NULL,
376 $height=NULL, $cache=NULL, $linking=NULL){
377 if ($this->capture && $title) $this->doc .= '['.$title.']';
378 $this->_firstimage($src);
381 function externalmedia($src, $title=NULL, $align=NULL, $width=NULL,
382 $height=NULL, $cache=NULL, $linking=NULL){
383 if ($this->capture && $title) $this->doc .= '['.$title.']';
384 $this->_firstimage($src);
387 function rss($url,$params) {
388 $this->meta['relation']['haspart'][$url] = true;
390 $this->meta['date']['valid']['age'] =
391 isset($this->meta['date']['valid']['age']) ?
392 min($this->meta['date']['valid']['age'],$params['refresh']) :
396 function table_open($maxcols = NULL, $numrows = NULL){}
397 function table_close(){}
399 function tablerow_open(){}
400 function tablerow_close(){}
402 function tableheader_open($colspan = 1, $align = NULL, $rowspan = 1){}
403 function tableheader_close(){}
405 function tablecell_open($colspan = 1, $align = NULL, $rowspan = 1){}
406 function tablecell_close(){}
408 //----------------------------------------------------------
412 * Removes any Namespace from the given name but keeps
413 * casing and special chars
415 * @author Andreas Gohr <andi@splitbrain.org>
417 function _simpleTitle($name){
420 if(is_array($name)) return '';
422 if($conf['useslash']){
427 $name = preg_replace('!.*'.$nssep.'!','',$name);
428 //if there is a hash we use the anchor name only
429 $name = preg_replace('!.*#!','',$name);
434 * Creates a linkid from a headline
436 * @param string $title The headline title
437 * @param boolean $create Create a new unique ID?
438 * @author Andreas Gohr <andi@splitbrain.org>
440 function _headerToLink($title, $create=false) {
442 return sectionID($title,$this->headers);
445 return sectionID($title,$check);
450 * Construct a title and handle images in titles
452 * @author Harry Fuecks <hfuecks@gmail.com>
454 function _getLinkTitle($title, $default, $id=NULL) {
458 if (is_array($title)){
459 if($title['title']) return '['.$title['title'].']';
460 } else if (is_null($title) || trim($title)==''){
461 if (useHeading('content') && $id){
462 $heading = p_get_first_heading($id,METADATA_DONT_RENDER);
463 if ($heading) return $heading;
471 function _firstimage($src){
472 if($this->firstimage) return;
475 list($src,$hash) = explode('#',$src,2);
476 if(!preg_match('/^https?:\/\//i',$src)){
477 resolve_mediaid(getNS($ID),$src, $exists);
479 if(preg_match('/.(jpe?g|gif|png)$/i',$src)){
480 $this->firstimage = $src;
485 //Setup VIM: ex: et ts=4 :