text = $text; $this->children = array(); } function AddChild($point) { $this->children[] = $point; } function LastChild() { if(is_array($this->children) && count($this->children)>0) return $this->children[count($this->children)-1]; return null; } function HasChildren() { if(count($this->children)<1) return true; return false; } } class WikiParser { function __construct() { $this->reference_wiki = 'index.php?module=wiki&action=list&name='; $this->image_uri = ''; $this->ignore_images = true; $this->Index = new IndexPoint(); } function BuildIndex() { if(count($this->Index->children)==0) return false; $out = ""; } function AddToIndex($text, $level) { if($level==1) $this->Index->AddChild(new IndexPoint($text)); $secondlevel = $this->Index->LastChild(); if($level==2 && $secondlevel!=null) { $secondlevel->AddChild(new IndexPoint($text)); } $thirdlevel = $secondlevel->LastChild(); if($level==3 && $thirdlevel!=null) { $thirdlevel->AddChild(new IndexPoint($text)); } } function handle_sections($matches) { $level = strlen($matches[1]); $content = $matches[2]; $this->AddToIndex($content, $level); $this->stop = true; $id = $this->Normalize($content); // avoid accidental run-on emphasis return $this->emphasize_off() . "\n\n{$content}\n\n"; } function Normalize($text) { $text = str_replace(' ', '_', $text); $text = str_replace('Ä', 'A', $text); $text = str_replace('ä', 'a', $text); $text = str_replace('Ö', 'O', $text); $text = str_replace('ö', 'o', $text); $text = str_replace('Ü', 'U', $text); $text = str_replace('ü', 'u', $text); $text = str_replace('ß', 'ss', $text); return $text; } function handle_newline($matches) { if ($this->suppress_linebreaks) return $this->emphasize_off(); $this->stop = true; // avoid accidental run-on emphasis return $this->emphasize_off() . "

"; } function handle_list($matches,$close=false) { $listtypes = array( '*'=>'ul', '#'=>'ol', ); $output = ""; $newlevel = ($close) ? 0 : strlen($matches[1]); while ($this->list_level!=$newlevel) { $listchar = substr($matches[1],-1); $listtype = $listtypes[$listchar]; //$output .= "[".$this->list_level."->".$newlevel."]"; if ($this->list_level>$newlevel) { $listtype = '/'.array_pop($this->list_level_types); $this->list_level--; } else { $this->list_level++; array_push($this->list_level_types,$listtype); } $output .= "\n<{$listtype}>\n"; } if ($close) return $output; $output .= "
  • ".$matches[2]."
  • \n"; return $output; } function handle_definitionlist($matches,$close=false) { if ($close) { $this->deflist = false; return "\n"; } $output = ""; if (!$this->deflist) $output .= "
    \n"; $this->deflist = true; switch($matches[1]) { case ';': $term = $matches[2]; $p = strpos($term,' :'); if ($p!==false) { list($term,$definition) = explode(':',$term); $output .= "
    {$term}
    {$definition}
    "; } else { $output .= "
    {$term}
    "; } break; case ':': $definition = $matches[2]; $output .= "
    {$definition}
    \n"; break; } return $output; } function handle_preformat($matches,$close=false) { if ($close) { $this->preformat = false; return "\n"; } $this->stop_all = true; $output = ""; if (!$this->preformat) $output .= "
    ";
    		$this->preformat = true;
    		
    		$output .= $matches[1];
    		
    		return $output."\n";
    	}
    	
    	function handle_horizontalrule($matches) {
    		return "
    "; } function wiki_link($topic) { return ucfirst(str_replace(' ','_',$topic)); } function handle_image($href,$title,$options) { if ($this->ignore_images) return ""; if (!$this->image_uri) return $title; $href = $this->image_uri . $href; $imagetag = sprintf( '%s', $href, $title ); foreach ($options as $k=>$option) { switch($option) { case 'frame': $imagetag = sprintf( '
    '. '%s'. '
    %s
    '. '
    ', $imagetag, $title ); break; case 'right': $imagetag = sprintf( '
    %s
    ', $imagetag ); break; } } return $imagetag; } function handle_internallink($matches) { //var_dump($matches); $nolink = false; $href = $matches[4]; $title = $matches[6] ? $matches[6] : $href.$matches[7]; $namespace = $matches[3]; if ($namespace=='Image') { $options = explode('|',$title); $title = array_pop($options); return $this->handle_image($href,$title,$options); } $title = preg_replace('/\(.*?\)/','',$title); $title = preg_replace('/^.*?\:/','',$title); if ($this->reference_wiki) { $href = $this->reference_wiki.($namespace?$namespace.':':'').$this->wiki_link($href); } else { $nolink = true; } if ($nolink) return $title; return sprintf( '%s', $href, ($newwindow?' target="_blank"':''), $title ); } function handle_externallink($matches) { $href = $matches[2]; $title = $matches[3]; if (!$title) { $this->linknumber++; $title = "[{$this->linknumber}]"; } $newwindow = true; return sprintf( '%s', $href, ($newwindow?' target="_blank"':''), $title ); } function emphasize($amount) { $amounts = array( 2=>array('',''), 3=>array('',''), 4=>array('',''), 5=>array('',''), ); $output = ""; // handle cases where emphasized phrases end in an apostrophe, eg: ''somethin''' // should read somethin' rather than somethin if ( (!$this->emphasis[$amount]) && ($this->emphasis[$amount-1]) ) { $amount--; $output = "'"; } $output .= $amounts[$amount][(int) $this->emphasis[$amount]]; $this->emphasis[$amount] = !$this->emphasis[$amount]; return $output; } function handle_emphasize($matches) { $amount = strlen($matches[1]); return $this->emphasize($amount); } function emphasize_off() { $output = ""; foreach ($this->emphasis as $amount=>$state) { if ($state) $output .= $this->emphasize($amount); } return $output; } function handle_eliminate($matches) { return ""; } function handle_variable($matches) { switch($matches[2]) { case 'CURRENTMONTH': return date('m'); case 'CURRENTMONTHNAMEGEN': case 'CURRENTMONTHNAME': return date('F'); case 'CURRENTDAY': return date('d'); case 'CURRENTDAYNAME': return date('l'); case 'CURRENTYEAR': return date('Y'); case 'CURRENTTIME': return date('H:i'); case 'NUMBEROFARTICLES': return 0; case 'PAGENAME': return $this->page_title; case 'NAMESPACE': return 'None'; case 'SITENAME': return $_SERVER['HTTP_HOST']; default: return ''; } } function parse_line($line) { $line_regexes = array( 'preformat'=>'^\s(.*?)$', 'definitionlist'=>'^([\;\:])\s*(.*?)$', 'newline'=>'^$', 'list'=>'^([\*\#]+)(.*?)$', 'sections'=>'^(={1,6})(.*?)(={1,6})$', 'horizontalrule'=>'^----$', ); $char_regexes = array( // 'link'=>'(\[\[((.*?)\:)?(.*?)(\|(.*?))?\]\]([a-z]+)?)', 'internallink'=>'('. '\[\['. // opening brackets '(([^\]]*?)\:)?'. // namespace (if any) '([^\]]*?)'. // target '(\|([^\]]*?))?'. // title (if any) '\]\]'. // closing brackets '([a-z]+)?'. // any suffixes ')', 'externallink'=>'('. '\['. '([^\]]*?)'. '(\s+[^\]]*?)?'. '\]'. ')', 'emphasize'=>'(\'{2,5})', 'eliminate'=>'(__TOC__|__NOTOC__|__NOEDITSECTION__)', 'variable'=>'('. '\{\{' . '([^\}]*?)' . '\}\}' . ')', ); $this->stop = false; $this->stop_all = false; $called = array(); $line = rtrim($line); foreach ($line_regexes as $func=>$regex) { if (preg_match("/$regex/i",$line,$matches)) { $called[$func] = true; $func = "handle_".$func; $line = $this->$func($matches); if ($this->stop || $this->stop_all) break; } } if (!$this->stop_all) { $this->stop = false; foreach ($char_regexes as $func=>$regex) { $line = preg_replace_callback("/$regex/i",array(&$this,"handle_".$func),$line); if ($this->stop) break; } } $isline = strlen(trim($line))>0; // if this wasn't a list item, and we are in a list, close the list tag(s) if (($this->list_level>0) && !$called['list']) $line = $this->handle_list(false,true) . $line; if ($this->deflist && !$called['definitionlist']) $line = $this->handle_definitionlist(false,true) . $line; if (!empty($this->preformat) && empty($called['preformat'])) $line = $this->handle_preformat(false,true) . $line; // suppress linebreaks for the next line if we just displayed one; otherwise re-enable them if ($isline) $this->suppress_linebreaks = (!empty($called['newline']) || !empty($called['sections'])); return $line; } function test() { $text = "WikiParser stress tester.
    Testing... __TOC__ == Nowiki test == [[wooticles|narf]] and '''test''' and stuff. == Character formatting == This is ''emphasized'', this is '''really emphasized''', this is ''''grossly emphasized'''', and this is just '''''freeking insane'''''. Done. == Variables == {{CURRENTDAY}}/{{CURRENTMONTH}}/{{CURRENTYEAR}} Done. == Image test == [[:Image:bao1.jpg]] [[Image:bao1.jpg|frame|alternate text]] [[Image:bao1.jpg|right|alternate text]] Done. == Horizontal Rule == Above the rule. ---- Done. == Hyperlink test == This is a [[namespace:link target|bitchin hypalink]] to another document for [[click]]ing, with [[(some) hidden text]] and a [[namespace:hidden namespace]]. A link to an external site [http://www.google.ca] as well another [http://www.esitemedia.com], and a [http://www.blitzaffe.com titled link] -- woo! Done. == Preformat == Not preformatted. Totally preformatted 01234 o o Again, this is preformatted b <-- It's a face Again, this is preformatted ---' Done. == Bullet test == * One bullet * Another '''bullet''' *# a list item *# another list item *#* unordered, ordered, unordered *#* again *# back down one Done. == Definition list == ; yes : opposite of no ; no : opposite of yes ; maybe : somewhere in between yes and no Done. == Indent == Normal : indented woo : more indentation Done. "; return $this->parse($text); } function parse($text,$title="") { $this->redirect = false; $this->nowikis = array(); $this->list_level_types = array(); $this->list_level = 0; $this->deflist = false; $this->linknumber = 0; $this->suppress_linebreaks = false; $this->page_title = $title; $output = ""; $text = preg_replace_callback('/([\s\S]*)<\/nowiki>/i',array(&$this,"handle_save_nowiki"),$text); $lines = explode("\n",$text); if (preg_match('/^\#REDIRECT\s+\[\[(.*?)\]\]$/',trim($lines[0]),$matches)) { $this->redirect = $matches[1]; } foreach ($lines as $k=>$line) { $line = $this->parse_line($line); $output .= $line; } $output = preg_replace_callback('/<\/nowiki>/i',array(&$this,"handle_restore_nowiki"),$output); return $output; } function handle_save_nowiki($matches) { array_push($this->nowikis,$matches[1]); return ""; } function handle_restore_nowiki($matches) { return array_pop($this->nowikis); } } ?>