From 0cecf9d507451346a32ddf45a85b425784fbb0f8 Mon Sep 17 00:00:00 2001 From: andi Date: Thu, 31 Mar 2005 16:57:49 +0200 Subject: new parser added (define DOKU_USENEWPARSER to use it) darcs-hash:20050331145749-9977f-f011ea6c65a278197e9087b685c635c60a204cd2.gz --- inc/parser/xhtml.php | 816 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 816 insertions(+) create mode 100644 inc/parser/xhtml.php (limited to 'inc/parser/xhtml.php') diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php new file mode 100644 index 000000000..ca8f08990 --- /dev/null +++ b/inc/parser/xhtml.php @@ -0,0 +1,816 @@ + Source + define ('DOKU_LF',"\n"); +} + +if ( !defined('DOKU_TAB') ) { + // Some whitespace to help View > Source + define ('DOKU_TAB',"\t"); +} + +/** +* @TODO Probably useful for have constant for linefeed formatting +*/ +class Doku_Renderer_XHTML { + + var $doc = ''; + + var $headers = array(); + + var $footnotes = array(); + + var $footnoteIdStack = array(); + + var $acronyms = array(); + var $smileys = array(); + var $badwords = array(); + var $entities = array(); + var $interwiki = array(); + + //@todo why ob? + function document_start() { + ob_start(); + } + + function document_end() { + + if ( count ($this->footnotes) > 0 ) { + echo '
'.DOKU_LF; + foreach ( $this->footnotes as $footnote ) { + echo $footnote; + } + echo '
'.DOKU_LF; + } + + $this->doc .= ob_get_contents(); + ob_end_clean(); + + } + + function toc_open() { + echo '
'.DOKU_LF; + echo '
Table of Contents
'.DOKU_LF; + echo '
'.DOKU_LF; + } + + function tocbranch_open($level) { + echo '
    '.DOKU_LF; + } + + function tocitem_open($level, $empty = FALSE) { + if ( !$empty ) { + echo '
  • '; + } else { + echo '
  • '; + } + } + + function tocelement($level, $title) { + echo ''; + echo $this->__xmlEntities($title); + echo ''; + } + + function tocitem_close($level) { + echo '
  • '.DOKU_LF; + } + + function tocbranch_close($level) { + echo '
'.DOKU_LF; + } + + function toc_close() { + echo '
'.DOKU_LF.'
'.DOKU_LF; + } + + function header($text, $level) { + echo DOKU_LF.''; + echo $this->__xmlEntities($text); + echo "".DOKU_LF; + } + + function section_open($level) { + echo "
".DOKU_LF; + } + + function section_close() { + echo DOKU_LF.'
'.DOKU_LF; + } + + function cdata($text) { + echo $this->__xmlEntities($text); + } + + function p_open() { + echo DOKU_LF.'

'.DOKU_LF; + } + + function p_close() { + echo DOKU_LF.'

'.DOKU_LF; + } + + function linebreak() { + echo '
'.DOKU_LF; + } + + function hr() { + echo '
'.DOKU_LF; + } + + function strong_open() { + echo ''; + } + + function strong_close() { + echo ''; + } + + function emphasis_open() { + echo ''; + } + + function emphasis_close() { + echo ''; + } + + function underline_open() { + echo ''; + } + + function underline_close() { + echo ''; + } + + function monospace_open() { + echo ''; + } + + function monospace_close() { + echo ''; + } + + function subscript_open() { + echo ''; + } + + function subscript_close() { + echo ''; + } + + function superscript_open() { + echo ''; + } + + function superscript_close() { + echo ''; + } + + function deleted_open() { + echo ''; + } + + function deleted_close() { + echo ''; + } + + function footnote_open() { + $id = $this->__newFootnoteId(); + echo ''.$id.')'; + $this->footnoteIdStack[] = $id; + ob_start(); + } + + function footnote_close() { + $contents = ob_get_contents(); + ob_end_clean(); + $id = array_pop($this->footnoteIdStack); + + $contents = '
'. + $id.') ' .DOKU_LF .$contents. "\n" . '
' . DOKU_LF; + $this->footnotes[$id] = $contents; + } + + function listu_open() { + echo ''.DOKU_LF; + } + + function listo_open() { + echo '
    '.DOKU_LF; + } + + function listo_close() { + echo '
'.DOKU_LF; + } + + function listitem_open($level) { + echo '
  • '; + } + + function listitem_close() { + echo '
  • '.DOKU_LF; + } + + function listcontent_open() { + echo ''; + } + + function listcontent_close() { + echo ''.DOKU_LF; + } + + function unformatted($text) { + echo $this->__xmlEntities($text); + } + + /** + * @TODO Support optional eval of code depending on conf/dokuwiki.php + */ + function php($text) { + $this->preformatted($text); + } + + /** + * @TODO Support optional echo of HTML depending on conf/dokuwiki.php + */ + function html($text) { + $this->file($text); + } + + function preformatted($text) { + echo '
    ' . $this->__xmlEntities($text) . '
    '. DOKU_LF; + } + + function file($text) { + echo '
    ' . $this->__xmlEntities($text). '
    '. DOKU_LF; + } + + /** + * @TODO Shouldn't this output '.DOKU_LF; + } + + /** + * @TODO Shouldn't this output ? + */ + function quote_close() { + echo ''.DOKU_LF; + } + + /** + * @TODO Hook up correctly with Geshi + */ + function code($text, $language = NULL) { + + if ( is_null($language) ) { + $this->preformatted($text); + } else { + + // Handle with Geshi here (needs tuning) + require_once(DOKU_INC . 'geshi.php'); + $geshi = new GeSHi($text, strtolower($language), DOKU_INC . 'geshi'); + $geshi->enable_classes(); + $geshi->set_header_type(GESHI_HEADER_PRE); + $geshi->set_overall_class('code'); + + // Fix this + $geshi->set_link_target('_blank'); + + $text = $geshi->parse_code(); + echo $text; + } + } + + function acronym($acronym) { + + if ( array_key_exists($acronym, $this->acronyms) ) { + + $title = $this->__xmlEntities($this->acronyms[$acronym]); + + echo ''.$this->__xmlEntities($acronym).''; + + } else { + echo $this->__xmlEntities($acronym); + } + } + + /** + * @TODO Remove hard coded link to splitbrain.org + */ + function smiley($smiley) { + + if ( array_key_exists($smiley, $this->smileys) ) { + $title = $this->__xmlEntities($this->smileys[$smiley]); + echo ''.
+                    $this->__xmlEntities($smiley).''; + } else { + echo $this->__xmlEntities($smiley); + } + } + + /** + * @TODO localization? + */ + function wordblock($word) { + if ( array_key_exists($word, $this->badwords) ) { + echo '** BLEEP **'; + } else { + echo $this->__xmlEntities($word); + } + } + + function entity($entity) { + if ( array_key_exists($entity, $this->entities) ) { + echo $this->entities[$entity]; + } else { + echo $this->__xmlEntities($entity); + } + } + + function multiplyentity($x, $y) { + echo "$x×$y"; + } + + function singlequoteopening() { + echo "‘"; + } + + function singlequoteclosing() { + echo "’"; + } + + function doublequoteopening() { + echo "“"; + } + + function doublequoteclosing() { + echo "”"; + } + + /** + * @TODO Handle local vs. global namespace checks + */ + function camelcaselink($link) { + + echo ''; + echo $this->__xmlEntities($link); + echo ''; + } + + /** + * @TODO Hook up with page resolver. + * @TODO Support media + * @TODO correct attributes + */ + function internallink($link, $title = NULL) { + + echo '__getLinkTitle($title,$link, $isImage); + + if ( !$isImage ) { + + if ( wikiPageExists($link) ) { + echo ' class="wikilink1"'; + } else { + echo ' class="wikilink2"'; + } + + } else { + echo ' class="media"'; + } + + echo ' href="http://wiki.splitbrain.org/'.$this->__xmlEntities($link).'"'; + + echo ' onclick="return svchk()" onkeypress="return svchk()">'; + + echo $title; + + echo ''; + } + + + /** + * @TODO Should list assume blacklist check already made? + * @TODO External link icon + * @TODO correct attributes + */ + function externallink($link, $title = NULL) { + + echo '__getLinkTitle($title, $link, $isImage); + + if ( !$isImage ) { + echo ' class="urlextern"'; + } else { + echo ' class="media"'; + } + + echo ' target="_blank" href="'.$this->__xmlEntities($link).'"'; + + echo ' onclick="return svchk()" onkeypress="return svchk()">'; + + echo $title; + + echo ''; + } + + /** + * @TODO Remove hard coded link to splitbrain.org on style + */ + function interwikilink($link, $title = NULL, $wikiName, $wikiUri) { + + // RESOLVE THE URL + if ( isset($this->interwiki[$wikiName]) ) { + + $wikiUriEnc = urlencode($wikiUri); + + if ( strstr($this->interwiki[$wikiName],'{URL}' ) !== FALSE ) { + + $url = str_replace('{URL}', $wikiUriEnc, $this->interwiki[$wikiName] ); + + } else if ( strstr($this->interwiki[$wikiName],'{NAME}' ) !== FALSE ) { + + $url = str_replace('{NAME}', $wikiUriEnc, $this->interwiki[$wikiName] ); + + } else { + + $url = $this->interwiki[$wikiName] . urlencode($wikiUri); + + } + + } else { + // Default to Google I'm feeling lucky + $url = 'http://www.google.com/search?q='.urlencode($wikiUri).'&btnI=lucky'; + } + + // BUILD THE LINK + echo '__getLinkTitle($title, $wikiUri, $isImage); + + if ( !$isImage ) { + echo ' class="interwiki"'; + } else { + echo ' class="media"'; + } + + echo ' href="'.$this->__xmlEntities($url).'"'; + + if ( FALSE !== ( $type = interwikiImgExists($wikiName) ) ) { + echo ' style="background: transparent url(http://wiki.splitbrain.org/interwiki/'. + $wikiName.'.'.$type.') 0px 1px no-repeat;"'; + } + + echo ' onclick="return svchk()" onkeypress="return svchk()">'; + + echo $title; + + echo ''; + } + + /** + * @TODO Correct the CSS class for files? (not windows) + * @TODO Remove hard coded URL to splitbrain.org + */ + function filelink($link, $title = NULL) { + echo '__getLinkTitle($title, $link, $isImage); + + if ( !$isImage ) { + echo ' class="windows"'; + } else { + echo ' class="media"'; + } + + echo ' href="'.$this->__xmlEntities($link).'"'; + + echo ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"'; + + echo ' onclick="return svchk()" onkeypress="return svchk()">'; + + echo $title; + + echo ''; + } + + /** + * @TODO Remove hard coded URL to splitbrain.org + * @TODO Add error message for non-IE users + */ + function windowssharelink($link, $title = NULL) { + echo '__getLinkTitle($title, $link, $isImage); + + if ( !$isImage ) { + echo ' class="windows"'; + } else { + echo ' class="media"'; + } + + $link = str_replace('\\','/',$link); + $link = 'file:///'.$link; + echo ' href="'.$this->__xmlEntities($link).'"'; + + echo ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"'; + + echo ' onclick="return svchk()" onkeypress="return svchk()">'; + + echo $title; + + echo ''; + } + + /** + * @TODO Protect email address from harvesters + * @TODO Remove hard coded link to splitbrain.org + */ + function email($address, $title = NULL) { + echo '__getLinkTitle($title, $address, $isImage); + + if ( !$isImage ) { + echo ' class="mail"'; + } else { + echo ' class="media"'; + } + + echo ' href="mailto:'.$this->__xmlEntities($address).'"'; + + echo ' style="background: transparent url(http://wiki.splitbrain.org/images/mail_icon.gif) 0px 1px no-repeat;"'; + + echo ' onclick="return svchk()" onkeypress="return svchk()">'; + + echo $title; + + echo ''; + + } + + /** + * @TODO Resolve namespaces + * @TODO Add image caching + * @TODO Remove hard coded link to splitbrain.org + */ + function internalmedia ( + $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL + ) { + + // Sort out the namespace here... + if ( strpos($src,':') ) { + $src = explode(':',$src); + $src = $src[1]; + } + echo ''; + + } + + /** + * @TODO Add image caching + */ + function externalmedia ( + $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL + ) { + + echo ''; + } + + // $numrows not yet implemented + function table_open($maxcols = NULL, $numrows = NULL){ + echo ''.DOKU_LF; + } + + function table_close(){ + echo '
    '.DOKU_LF.'
    '.DOKU_LF; + } + + function tablerow_open(){ + echo DOKU_TAB . '' . DOKU_LF . DOKU_TAB . DOKU_TAB; + } + + function tablerow_close(){ + echo DOKU_LF . DOKU_TAB . '' . DOKU_LF; + } + + function tableheader_open($colspan = 1, $align = NULL){ + echo ' 1 ) { + echo ' colspan="'.$colspan.'"'; + } + echo '>'; + } + + function tableheader_close(){ + echo ''; + } + + function tablecell_open($colspan = 1, $align = NULL){ + echo ' 1 ) { + echo ' colspan="'.$colspan.'"'; + } + echo '>'; + } + + function tablecell_close(){ + echo ''; + } + + //---------------------------------------------------------- + // Utils + + function __newFootnoteId() { + static $id = 1; + return $id++; + } + + function __xmlEntities($string) { + return htmlspecialchars($string); + } + + /** + * @TODO Tuning needed - e.g. utf8 strtolower ? + */ + function __headerToLink($title) { + return preg_replace('/\W/','_',trim($title)); + } + + function __getLinkTitle($title, $default, & $isImage) { + $isImage = FALSE; + + if ( is_null($title) ) { + + return $this->__xmlEntities($default); + + } else if ( is_string($title) ) { + + return $this->__xmlEntities($title); + + } else if ( is_array($title) ) { + + $isImage = TRUE; + return $this->__imageTitle($title); + + } + } + + /** + * @TODO Resolve namespace on internal images + * @TODO Remove hard coded url to splitbrain.org + * @TODO Image caching + */ + function __imageTitle($img) { + + if ( $img['type'] == 'internalmedia' ) { + + // Resolve here... + if ( strpos($img['src'],':') ) { + $src = explode(':',$img['src']); + $src = $src[1]; + } else { + $src = $img['src']; + } + + $imgStr = '__xmlEntities($img['src']).'"'; + + } + + if ( !is_null($img['title']) ) { + $imgStr .= ' alt="'.$this->__xmlEntities($img['title']).'"'; + } else { + $imgStr .= ' alt=""'; + } + + if ( !is_null($img['align']) ) { + $imgStr .= ' align="'.$img['align'].'"'; + } + + if ( !is_null($img['width']) ) { + $imgStr .= ' width="'.$this->__xmlEntities($img['width']).'"'; + } + + if ( !is_null($img['height']) ) { + $imgStr .= ' height="'.$this->__xmlEntities($img['height']).'"'; + } + + $imgStr .= '/>'; + + return $imgStr; + } +} + +/** +* Test whether there's an image to display with this interwiki link +*/ +function interwikiImgExists($name) { + + static $exists = array(); + + if ( array_key_exists($name,$exists) ) { + return $exists[$name]; + } + + if( @file_exists( DOKU. 'interwiki/'.$name.'.png') ) { + $exists[$name] = 'png'; + } else if ( @file_exists( DOKU . 'interwiki/'.$name.'.gif') ) { + $exists[$name] = 'gif'; + } else { + $exists[$name] = FALSE; + } + + return $exists[$name]; +} + +/** +* For determining whether to use CSS class "wikilink1" or "wikilink2" +* @todo use configinstead of DOKU_DATA +*/ +function wikiPageExists($name) { + + static $pages = array(); + + if ( array_key_exists($name,$pages) ) { + return $pages[$name]; + } + + $file = str_replace(':','/',$name).'.txt'; + + if ( @file_exists( DOKU_DATA . $file ) ) { + $pages[$name] = TRUE; + } else { + $pages[$name] = FALSE; + } + + return $pages[$name]; +} + -- cgit v1.2.3