diff options
Diffstat (limited to 'plugins/55/edittable/renderer/inverse.php')
-rw-r--r-- | plugins/55/edittable/renderer/inverse.php | 778 |
1 files changed, 778 insertions, 0 deletions
diff --git a/plugins/55/edittable/renderer/inverse.php b/plugins/55/edittable/renderer/inverse.php new file mode 100644 index 0000000..65dbb17 --- /dev/null +++ b/plugins/55/edittable/renderer/inverse.php @@ -0,0 +1,778 @@ +<?php +/** + * Renderer for WikiText output + * + * @author Adrian Lang <lang@cosmocode.de> + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +require_once DOKU_INC.'inc/parser/renderer.php'; + +class renderer_plugin_edittable_inverse extends Doku_Renderer { + /** @var string will contain the whole document */ + public $doc = ''; + + // bunch of internal state variables + private $prepend_not_block = ''; + private $_key = 0; + private $_pos = 0; + private $_ownspan = 0; + private $previous_block = false; + private $_row = 0; + private $_rowspans = array(); + private $_table = array(); + private $_liststack = array(); + private $quotelvl = 0; + private $extlinkparser = null; + protected $extlinkPatterns = []; + + function getFormat() { + return 'wiki'; + } + + function document_start() { + } + + function document_end() { + $this->block(); + $this->doc = rtrim($this->doc); + } + + function header($text, $level, $pos) { + $this->block(); + if(!$text) return; //skip empty headlines + + // write the header + $markup = str_repeat('=', 7 - $level); + $this->doc .= "$markup $text $markup".DOKU_LF; + } + + function section_open($level) { + $this->block(); +# $this->doc .= DOKU_LF; + } + + function section_close() { + $this->block(); + $this->doc .= DOKU_LF; + } + + // FIXME this did something compllicated with surrounding whitespaces. Why? + function cdata($text) { + if(strlen($text) === 0) { + $this->not_block(); + return; + } + +// if(!$this->previous_block && trim(substr($text, 0, 1)) === '' && trim($text) !== '') { +// $this->doc .= ' '; +// } + $this->not_block(); + +// if(trim(substr($text, -1, 1)) === '' && trim($text) !== '') { +// $this->prepend_not_block = ' '; +// } +// $this->doc .= trim($text); + + $this->doc .= $text; + } + + function p_close() { + $this->block(); + if($this->quotelvl === 0) { + $this->doc = rtrim($this->doc, DOKU_LF).DOKU_LF.DOKU_LF; + } + } + + function p_open() { + $this->block(); + if(strlen($this->doc) > 0 && substr($this->doc, 1, -1) !== DOKU_LF) { + $this->doc .= DOKU_LF.DOKU_LF; + } + $this->doc .= str_repeat('>', $this->quotelvl); + } + + function linebreak() { + $this->not_block(); + $this->doc .= '\\\\ '; + } + + function hr() { + $this->block(); + $this->doc .= '----'; + } + + function block() { + if(isset($this->prepend_not_block)) { + unset($this->prepend_not_block); + } + $this->previous_block = true; + } + + function not_block() { + if(isset($this->prepend_not_block)) { + $this->doc .= $this->prepend_not_block; + unset($this->prepend_not_block); + } + $this->previous_block = false; + } + + function strong_open() { + $this->not_block(); + $this->doc .= '**'; + } + + function strong_close() { + $this->not_block(); + $this->doc .= '**'; + } + + function emphasis_open() { + $this->not_block(); + $this->doc .= '//'; + } + + function emphasis_close() { + $this->not_block(); + $this->doc .= '//'; + } + + function underline_open() { + $this->not_block(); + $this->doc .= '__'; + } + + function underline_close() { + $this->not_block(); + $this->doc .= '__'; + } + + function monospace_open() { + $this->not_block(); + $this->doc .= "''"; + } + + function monospace_close() { + $this->not_block(); + $this->doc .= "''"; + } + + function subscript_open() { + $this->not_block(); + $this->doc .= '<sub>'; + } + + function subscript_close() { + $this->not_block(); + $this->doc .= '</sub>'; + } + + function superscript_open() { + $this->not_block(); + $this->doc .= '<sup>'; + } + + function superscript_close() { + $this->not_block(); + $this->doc .= '</sup>'; + } + + function deleted_open() { + $this->not_block(); + $this->doc .= '<del>'; + } + + function deleted_close() { + $this->not_block(); + $this->doc .= '</del>'; + } + + function footnote_open() { + $this->not_block(); + $this->doc .= '(('; + } + + function footnote_close() { + $this->not_block(); + $this->doc .= '))'; + } + + function listu_open() { + $this->block(); + if(!isset($this->_liststack)) { + $this->_liststack = array(); + } + if(count($this->_liststack) === 0) { + $this->doc .= DOKU_LF; + } + $this->_liststack[] = '*'; + } + + function listu_close() { + $this->block(); + array_pop($this->_liststack); + if(count($this->_liststack) === 0) { + $this->doc .= DOKU_LF; + } + } + + function listo_open() { + $this->block(); + if(!isset($this->_liststack)) { + $this->_liststack = array(); + } + if(count($this->_liststack) === 0) { + $this->doc .= DOKU_LF; + } + $this->_liststack[] = '-'; + } + + function listo_close() { + $this->block(); + array_pop($this->_liststack); + if(count($this->_liststack) === 0) { + $this->doc .= DOKU_LF; + } + } + + function listitem_open($level, $node = false) { + $this->block(); + $this->doc .= str_repeat(' ', $level * 2).end($this->_liststack).' '; + } + + function listcontent_close() { + $this->block(); + $this->doc .= DOKU_LF; + } + + function unformatted($text) { + $this->not_block(); + if(strpos($text, '%%') !== false) { + $this->doc .= "<nowiki>$text</nowiki>"; + } elseif($text[0] == "\n") { + $this->doc .= "<nowiki>$text</nowiki>"; + } else { + $this->doc .= "%%$text%%"; + } + } + + function php($text, $wrapper = 'code') { + $this->not_block(); + $this->doc .= "<php>$text</php>"; + } + + function phpblock($text) { + $this->block(); + $this->doc .= "<PHP>$text</PHP>"; + } + + function html($text, $wrapper = 'code') { + $this->not_block(); + $this->doc .= "<html>$text</html>"; + } + + function htmlblock($text) { + $this->block(); + $this->doc .= "<HTML>$text</HTML>"; + } + + function quote_open() { + $this->block(); + if(substr($this->doc, -(++$this->quotelvl)) === DOKU_LF.str_repeat('>', $this->quotelvl - 1)) { + $this->doc .= '>'; + } else { + $this->doc .= DOKU_LF.str_repeat('>', $this->quotelvl); + } + $this->prepend_not_block = ' '; + } + + function quote_close() { + $this->block(); + $this->quotelvl--; + if(strrpos($this->doc, DOKU_LF) === strlen($this->doc) - 1) { + return; + } + $this->doc .= DOKU_LF.DOKU_LF; + } + + function preformatted($text) { + $this->block(); + $this->doc .= preg_replace('/^/m', ' ', $text).DOKU_LF; + } + + function file($text, $language = null, $filename = null) { + $this->_highlight('file', $text, $language, $filename); + } + + function code($text, $language = null, $filename = null) { + $this->_highlight('code', $text, $language, $filename); + } + + function _highlight($type, $text, $language = null, $filename = null) { + if( $this->previous_block ) $this->doc .= "\n"; + + $this->block(); + $this->doc .= "<$type"; + if($language != null) { + $this->doc .= " $language"; + } + if($filename != null) { + $this->doc .= " $filename"; + } + $this->doc .= ">"; + $this->doc .= $text; + if($text[0] == "\n") $this->doc .= "\n"; + $this->doc .= "</$type>"; + } + + function acronym($acronym) { + $this->not_block(); + $this->doc .= $acronym; + } + + function smiley($smiley) { + $this->not_block(); + $this->doc .= $smiley; + } + + function entity($entity) { + $this->not_block(); + $this->doc .= $entity; + } + + function multiplyentity($x, $y) { + $this->not_block(); + $this->doc .= "{$x}x{$y}"; + } + + function singlequoteopening() { + $this->not_block(); + $this->doc .= "'"; + } + + function singlequoteclosing() { + $this->not_block(); + $this->doc .= "'"; + } + + function apostrophe() { + $this->not_block(); + $this->doc .= "'"; + } + + function doublequoteopening() { + $this->not_block(); + $this->doc .= '"'; + } + + function doublequoteclosing() { + $this->not_block(); + $this->doc .= '"'; + } + + /** + */ + function camelcaselink($link) { + $this->not_block(); + $this->doc .= $link; + } + + function locallink($hash, $name = null) { + $this->not_block(); + $this->doc .= "[[#$hash"; + if($name !== null) { + $this->doc .= '|'; + $this->_echoLinkTitle($name); + } + $this->doc .= ']]'; + } + + function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content') { + $this->not_block(); + $this->doc .= "[[$id"; + if($name !== null) { + $this->doc .= '|'; + $this->_echoLinkTitle($name); + } + $this->doc .= ']]'; + } + + /** + * Handle external Links + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param $url + * @param null $name + */ + function externallink($url, $name = null) { + $this->not_block(); + + /* + * When $name is null it might have been a match of an URL that was in the text without + * any link syntax. These are recognized by a bunch of patterns in Doku_Parser_Mode_externallink. + * We simply reuse these patterns here. However, since we don't parse the pattern through the Lexer, + * no escaping is done on the patterns - this means we need a non-conflicting delimiter. I decided for + * a single tick >>'<< which seems to work. Since the patterns contain wordboundaries they are matched + * against the URL surrounded by spaces. + */ + if($name === null) { + // get the patterns from the parser if available, otherwise use a duplicate + if(is_null($this->extlinkparser)) { + if ( + class_exists('\dokuwiki\Parsing\ParserMode\Externallink') && + method_exists('\dokuwiki\Parsing\ParserMode\Externallink', 'getPatterns') + ) { + $this->extlinkparser = new \dokuwiki\Parsing\ParserMode\Externallink(); + $this->extlinkparser->preConnect(); + $this->extlinkPatterns = $this->extlinkparser->getPatterns(); + } else { + $ltrs = '\w'; + $gunk = '/\#~:.?+=&%@!\-\[\]'; + $punc = '.:?\-;,'; + $host = $ltrs . $punc; + $any = $ltrs . $gunk . $punc; + + $schemes = getSchemes(); + foreach ($schemes as $scheme) { + $this->extlinkPatterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; + } + + $this->extlinkPatterns[] = '(?<=\s)(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; + $this->extlinkPatterns[] = '(?<=\s)(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; + } + } + + // check if URL matches pattern + foreach($this->extlinkPatterns as $pattern) { + if(preg_match("'$pattern'", " $url ")) { + $this->doc .= $url; // gotcha! + return; + } + } + } + + // still here? + if($url === "http://$name" || $url === "ftp://$name") { + // special case - www.* or ftp.* matching + $this->doc .= $name; + } else { + // link syntax! definitively link syntax + $this->doc .= "[[$url"; + if(!is_null($name)) { + // we do have a name! + $this->doc .= '|'; + $this->_echoLinkTitle($name); + } + $this->doc .= ']]'; + } + } + + function interwikilink($match, $name = null, $wikiName, $wikiUri) { + $this->not_block(); + $this->doc .= "[[$wikiName>$wikiUri"; + if($name !== null) { + $this->doc .= '|'; + $this->_echoLinkTitle($name); + } + $this->doc .= ']]'; + } + + function windowssharelink($url, $name = null) { + $this->not_block(); + $this->doc .= "[[$url"; + if($name !== null) { + $this->doc .= '|'; + $this->_echoLinkTitle($name); + } + $this->doc .= "]]"; + } + + function emaillink($address, $name = null) { + $this->not_block(); + if($name === null) { + $this->doc .= "<$address>"; + } else { + $this->doc .= "[[$address|"; + $this->_echoLinkTitle($name); + $this->doc .= ']]'; + } + } + + function internalmedia($src, $title = null, $align = null, $width = null, + $height = null, $cache = null, $linking = null) { + $this->not_block(); + $this->doc .= '{{'; + if($align === 'center' || $align === 'right') { + $this->doc .= ' '; + } + $this->doc .= $src; + + $params = array(); + if($width !== null) { + $params[0] = $width; + if($height !== null) { + $params[0] .= "x$height"; + } + } + if($cache !== 'cache') { + $params[] = $cache; + } + if($linking !== 'details') { + $params[] = $linking; + } + if(count($params) > 0) { + $this->doc .= '?'; + } + $this->doc .= join('&', $params); + + if($align === 'center' || $align === 'left') { + $this->doc .= ' '; + } + if($title != null) { + $this->doc .= "|$title"; + } + $this->doc .= '}}'; + } + + function externalmedia($src, $title = null, $align = null, $width = null, + $height = null, $cache = null, $linking = null) { + $this->internalmedia($src, $title, $align, $width, $height, $cache, $linking); + } + + /** + * Renders an RSS feed + * + * @author Andreas Gohr <andi@splitbrain.org> + */ + function rss($url, $params) { + $this->block(); + $this->doc .= '{{rss>'.$url; + $vals = array(); + if($params['max'] !== 8) { + $vals[] = $params['max']; + } + if($params['reverse']) { + $vals[] = 'reverse'; + } + if($params['author']) { + $vals[] = 'author'; + } + if($params['date']) { + $vals[] = 'date'; + } + if($params['details']) { + $vals[] = 'desc'; + } + if($params['refresh'] !== 14400) { + $val = '10m'; + foreach(array('d' => 86400, 'h' => 3600, 'm' => 60) as $p => $div) { + $res = $params['refresh'] / $div; + if($res === intval($res)) { + $val = "$res$p"; + break; + } + } + $vals[] = $val; + } + if(count($vals) > 0) { + $this->doc .= ' '.join(' ', $vals); + } + $this->doc .= '}}'; + } + + function table_open($maxcols = null, $numrows = null, $pos = null) { + $this->block(); + $this->_table = array(); + $this->_row = 0; + $this->_rowspans = array(); + } + + function table_close($pos = null) { + $this->doc .= $this->_table_to_wikitext($this->_table); + } + + function tablerow_open() { + $this->block(); + $this->_table[++$this->_row] = array(); + $this->_key = 1; + while(isset($this->_rowspans[$this->_key])) { + --$this->_rowspans[$this->_key]; + if($this->_rowspans[$this->_key] === 1) { + unset($this->_rowspans[$this->_key]); + } + ++$this->_key; + } + } + + function tablerow_close() { + $this->block(); + } + + function tableheader_open($colspan = 1, $align = null, $rowspan = 1) { + $this->_cellopen('th', $colspan, $align, $rowspan); + } + + function _cellopen($tag, $colspan, $align, $rowspan) { + $this->block(); + $this->_table[$this->_row][$this->_key] = compact('tag', 'colspan', 'align', 'rowspan'); + if($rowspan > 1) { + $this->_rowspans[$this->_key] = $rowspan; + $this->_ownspan = true; + } + $this->_pos = strlen($this->doc); + } + + function tableheader_close() { + $this->_cellclose(); + } + + function _cellclose() { + $this->block(); + $this->_table[$this->_row][$this->_key]['text'] = trim(substr($this->doc, $this->_pos)); + $this->doc = substr($this->doc, 0, $this->_pos); + $this->_key += $this->_table[$this->_row][$this->_key]['colspan']; + while(isset($this->_rowspans[$this->_key]) && !$this->_ownspan) { + --$this->_rowspans[$this->_key]; + if($this->_rowspans[$this->_key] === 1) { + unset($this->_rowspans[$this->_key]); + } + ++$this->_key; + } + $this->_ownspan = false; + } + + function tablecell_open($colspan = 1, $align = null, $rowspan = 1) { + $this->_cellopen('td', $colspan, $align, $rowspan); + } + + function tablecell_close() { + $this->_cellclose(); + } + + function plugin($name, $args, $state = '', $match = '') { + $this->not_block(); + // This will break for plugins which provide a catch-all render method + // like the do or pagenavi plugins +# $plugin =& plugin_load('syntax',$name); +# if($plugin === null || !$plugin->render($this->getFormat(),$this,$args)) { + $this->doc .= $match; +# } + } + + function _echoLinkTitle($title) { + if(is_array($title)) { + $this->internalmedia( + $title['src'], + $title['title'], + $title['align'], + $title['width'], + $title['height'], + $title['cache'], + $title['linking'] + ); + } else { + $this->doc .= $title; + } + } + + /** + * Helper for table to wikitext conversion + * + * @author Adrian Lang <lang@cosmocode.de> + * @param array $_table + * @return string + */ + private function _table_to_wikitext($_table) { + // Preprocess table for rowspan, make table 0-based. + $table = array(); + $keys = array_keys($_table); + $start = array_pop($keys); + foreach($_table as $i => $row) { + $inorm = $i - $start; + if(!isset($table[$inorm])) $table[$inorm] = array(); + $nextkey = 0; + foreach($row as $cell) { + while(isset($table[$inorm][$nextkey])) { + $nextkey++; + } + $nextkey += $cell['colspan'] - 1; + $table[$inorm][$nextkey] = $cell; + $rowspan = $cell['rowspan']; + $i2 = $inorm + 1; + while($rowspan-- > 1) { + if(!isset($table[$i2])) $table[$i2] = array(); + $nu_cell = $cell; + $nu_cell['text'] = ':::'; + $nu_cell['rowspan'] = 1; + $table[$i2++][$nextkey] = $nu_cell; + } + } + ksort($table[$inorm]); + } + + // Get the max width for every column to do table prettyprinting. + $m_width = array(); + foreach($table as $row) { + foreach($row as $n => $cell) { + // Calculate cell width. + $diff = (utf8_strlen($cell['text']) + $cell['colspan'] + + ($cell['align'] === 'center' ? 3 : 2)); + + // Calculate current max width. + $span = $cell['colspan']; + while(--$span >= 0) { + if(isset($m_width[$n - $span])) { + $diff -= $m_width[$n - $span]; + } + } + + if($diff > 0) { + // Just add the difference to all cols. + while(++$span < $cell['colspan']) { + $m_width[$n - $span] = (isset($m_width[$n - $span]) ? $m_width[$n - $span] : 0) + ceil($diff / $cell['colspan']); + } + } + } + } + + // Write the table. + $types = array('th' => '^', 'td' => '|'); + $str = ''; + foreach($table as $row) { + $pos = 0; + foreach($row as $n => $cell) { + $pos += utf8_strlen($cell['text']) + 1; + $span = $cell['colspan']; + $target = 0; + while(--$span >= 0) { + if(isset($m_width[$n - $span])) { + $target += $m_width[$n - $span]; + } + } + $pad = $target - utf8_strlen($cell['text']); + $pos += $pad + ($cell['colspan'] - 1); + switch($cell['align']) { + case 'right': + $lpad = $pad - 1; + break; + case 'left': + case '': + $lpad = 1; + break; + case 'center': + $lpad = floor($pad / 2); + break; + } + $str .= $types[$cell['tag']].str_repeat(' ', $lpad). + $cell['text'].str_repeat(' ', $pad - $lpad). + str_repeat($types[$cell['tag']], $cell['colspan'] - 1); + } + $str .= $types[$cell['tag']].DOKU_LF; + } + return $str; + } +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : |