Source
define ('DOKU_LF',"\n");
}
if ( !defined('DOKU_TAB') ) {
// Some whitespace to help View > Source
define ('DOKU_TAB',"\t");
}
require_once DOKU_INC . 'inc/parser/renderer.php';
/**
* @TODO Probably useful for have constant for linefeed formatting
*/
class Doku_Renderer_XHTML extends Doku_Renderer {
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();
var $lastsec = 0;
function document_start() {
ob_start();
}
function document_end() {
// add button for last section if any
if($this->lastsec) $this->__secedit($this->lastsec,'');
if ( count ($this->footnotes) > 0 ) {
echo '
'.DOKU_LF;
}
$this->doc .= ob_get_contents();
ob_end_clean();
}
function toc_open() {
echo ''.DOKU_LF;
echo ''.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, $pos) {
global $conf;
//handle section editing
if($level <= $conf['maxseclevel']){
// add button for last section if any
if($this->lastsec) $this->__secedit($this->lastsec,$pos-1);
// remember current position
$this->lastsec = $pos;
}
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 = '' . DOKU_LF;
$this->footnotes[$id] = $contents;
}
function listu_open() {
echo ''.DOKU_LF;
}
function listu_close() {
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);
}
/**
*/
function php($text) {
global $conf;
if($conf['phpok']){
eval($text);
}else{
$this->file($text);
}
}
/**
*/
function html($text) {
global $conf;
if($conf['htmlok']){
echo $text;
}else{
$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;
}
/**
*/
function code($text, $language = NULL) {
global $conf;
if ( is_null($language) ) {
$this->preformatted($text);
} else {
// Handle with Geshi here FIXME: strip first beginning newline
require_once(DOKU_INC . 'inc/geshi.php');
$geshi = new GeSHi($text, strtolower($language), DOKU_INC . 'inc/geshi');
$geshi->enable_classes();
$geshi->set_header_type(GESHI_HEADER_PRE);
$geshi->set_overall_class('code');
$geshi->set_link_target($conf['target']['extern']);
$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);
}
}
/**
*/
function smiley($smiley) {
if ( array_key_exists($smiley, $this->smileys) ) {
$title = $this->__xmlEntities($this->smileys[$smiley]);
echo '
';
} else {
echo $this->__xmlEntities($smiley);
}
}
/**
* not used
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 "”";
}
/**
*/
function camelcaselink($link) {
$this->internallink($link,$link);
}
/**
* @TODO Support media
* @TODO correct attributes
*/
function internallink($id, $name = NULL) {
global $conf;
$name = $this->__getLinkTitle($name, $this->__simpleTitle($id), $isImage);
resolve_pageid($id,$exists);
if ( !$isImage ) {
if ( $exists ) {
$class='wikilink1';
} else {
$class='wikilink2';
}
} else {
$class='media';
}
//prepare for formating
$link['target'] = $conf['target']['wiki'];
$link['style'] = '';
$link['pre'] = '';
$link['suf'] = '';
$link['more'] = 'onclick="return svchk()" onkeypress="return svchk()"';
$link['class'] = $class;
$link['url'] = wl($id);
$link['name'] = $name;
$link['title'] = $id;
//output formatted
echo $this->__formatLink($link);
}
/**
* @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
/**
* Assembles all parts defined by the link formater below
* Returns HTML for the link
*
* @author Andreas Gohr
*/
function __formatLink($link){
//make sure the url is XHTML compliant (skip mailto)
if(substr($link['url'],0,7) != 'mailto:'){
$link['url'] = str_replace('&','&',$link['url']);
$link['url'] = str_replace('&','&',$link['url']);
}
//remove double encodings in titles
$link['title'] = str_replace('&','&',$link['title']);
$ret = '';
$ret .= $link['pre'];
$ret .= '
*/
function __simpleTitle($name){
global $conf;
if($conf['useslash']){
$nssep = '[:;/]';
}else{
$nssep = '[:;]';
}
return preg_replace('!.*'.$nssep.'!','',$name);
}
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));
}
/**
* Adds code for section editing button
*/
function __secedit($f, $t){
print '';
}
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['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
* @deprecated -> resolve_pagename should be used
*/
function wikiPageExists($name) {
msg("deprecated wikiPageExists called",-1);
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];
}