Re: [cowiki-dev] coWiki definition, new parser
PAUL HANCHETT <[email protected]>
| Newsgroups | gmane.comp.php.cowiki.devel |
|---|---|
| Message-ID | <[email protected]> |
OK, I'll look at it Archie! My computer is going to be down for a good part of the day, so it will probably be tomorrow before I really get to it. I have a question for you-- The result of the parser is an XML document, right? PHP5 includes both XML and XSLT out of the box. Why not use XSLT to reverse transform the XML to wiki-text, as well as into HTML for display? Actually, I'm also wondering if there isn't an advantage to using a tool like Smarty for processing our templates. Using someone else's code base leaves that much less for us to support (of course there are risks and other debates...) Interested in opinions... Paul Archie Campbell wrote: > It's not pretty and there are some bleeding edges in this working copy. > > I've done it like this because I can't stand <1><1></1></1> giving > <1><1></1> and hurling the rest back on yourself. There are two bits > doing noop, which is why the thing is broken, probably. That was a > mistake, actually. Please toy with it. Be merciless with the copy and > gentle with me, that's probably the best idea. > > It may become necessary to permute the WikiReverseParser into > something resembling the modified WikiParser. > > I'll get there once the latter is well behaved. > > So. I'm off to Scotland for a week; enjoy breaking things. > > Regards, > > Archie > > Archie Campbell wrote: > >> Guys, >> >> The WikiParser is trotting along nicely. I'm currently working on >> links, to be followed by the toc and then variables and anything >> leftover from Paul's specification the other day. >> >> I'm going on holiday to Scotland for 5 days; from tomorrow evening >> until next Sunday, I'll be exclusively real world. I propose to send >> a patch from 0.3.4 with the new parser as a work-in-progress. If you >> chaps could patch an old copy of Boron and have some fun breaking >> things, I'll also include a TEST.IDIOM document with brief >> descriptions of any limitations that the code needs, even temporarily. >> >> The question is... where do I put the patch? And, should I go from >> 0.3.4 or CVS HEAD? >> >> I'm actually quite enjoying the coding, which is nice. It looks >> nothing like the old version, and has made strides in definition, I >> think. >> >> Regards, >> >> cmarble >> >> P.S. Post-AprilFD, would anyone at Google fancy a coWiki? chortle >> >> Sy wrote: >> >>>On Apr 2, 2005 2:54 AM, Daniel T. Gorski <[email protected]> wrote: >>> >>> >>> >>>>>>I would like to have more features listed that are beyond other wikis and >>>>>>make coWiki special, very special :) >>>>>> >>>>>> >>> >>>It is necessary to create a good document which describes things more >>>technically before the release of the Beauty milestone. We will need >>>to distinguish ourselves from other solutions. This document will >>>help us understand the coWiki "Character" and make that milestone more >>>profound. >>> >>>This is now on my to do list. =/ >>> >>>--------------------------------------------------------------------- >>>To unsubscribe, e-mail: [email protected] >>>For additional commands, e-mail: [email protected] >>> >>> >>> >>> >>> > > ------------------------------------------------------------------------ > > so we can mail * you a copy immediately. * * > > * Helping hands: Matt Ho > * > > * * @package parse * @subpackage class * @access public * * @author > Daniel T. Gorski, * @copyright (C) Daniel T. Gorski, {@link > http://www.develnet.org} * @license > http://www.gnu.org/licenses/gpl.html * @version $Revision: 1.36 $ * */ > /** * coWiki - Wiki parser class * * @package parse * @subpackage > class * @access public * * @author Daniel T. Gorski, * @since coWiki > 0.3.0 */ class WikiParser extends Object { protected static $Instance > = null; protected $aToc = array(); protected $aEmph = array(); // > -------------------------------------------------------------------- > /** * Get instance * * @access public * * @author Daniel T. Gorski, * > @since coWiki 0.3.0 */ public function getInstance() { if > (!self::$Instance) { self::$Instance = new WikiParser; } return > self::$Instance; } // > -------------------------------------------------------------------- > /** * @access protected * * @author Daniel T. Gorski, * @since coWiki > 0.3.0 */ protected function __construct() {} // --- Helper methods > ------------------------------------------------- /** * Set doc toc * > * @access protected * * @author Daniel T. Gorski, * @since coWiki > 0.3.0 */ protected function setDocToc($sStr) { $this->sDocToc = $sStr; > } // > -------------------------------------------------------------------- > /** * Get doc toc * * @access protected * * @author Daniel T. Gorski, > * @since coWiki 0.3.0 */ protected function getDocToc() { return > $this->sDocToc; } // > -------------------------------------------------------------------- > /** * Get token count * * @access protected * * @author Daniel T. > Gorski, * @since coWiki 0.3.0 */ protected function getTokenCount() { > return sizeof($this->aToken); } // > -------------------------------------------------------------------- > /** * Set restore flag * * @access protected * * @author Daniel T. > Gorski, * @since coWiki 0.3.0 */ protected function > setRestoreFlag($bFlag) { $this->bRestoreFlag = $bFlag; } // > -------------------------------------------------------------------- > /** * Get restore flag * * @access protected * * @author Daniel T. > Gorski, * @since coWiki 0.3.0 */ protected function getRestoreFlag() { > return $this->bRestoreFlag; } // > -------------------------------------------------------------------- > // --- Element creators > ----------------------------------------------- /** * Create a > -element * * @access protected * * @author Daniel T. Gorski, * @since > coWiki 0.3.0 */ protected function createNoopElement(&$sStr) { return > ''.$sStr.''; } // > -------------------------------------------------------------------- > /** * Create a -element * * @access protected * * @author Daniel T. > Gorski, * @since coWiki 0.3.0 */ protected function > createRemarkElement(&$sStr) { return ''.$sStr.''; } // > -------------------------------------------------------------------- > /** * Create a < > >>-element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createPreElement(&$sStr) { > return " > >\r".str_replace("\n", "\r", $sStr)."\r > >"; > } > > // -------------------------------------------------------------------- > > /** > * Create a <|>-element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createCodeElement(&$sStr) { > return "|\r".str_replace("\n", "\r", $sStr)."\r|"; > } > > // -------------------------------------------------------------------- > > /** > * Create a -element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createPostingElement(&$sStr) { > return "\r".str_replace("\n", "\r", $sStr)."\r"; > } > > // -------------------------------------------------------------------- > > /** > * Create a simple -element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createSimplePluginElement(&$sStr) { > return ''; > } > > // -------------------------------------------------------------------- > > /** > * Create a parameterized -element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createParamPluginElement(&$sStr, &$sAttr) { > if (trim($sAttr) == '') { > return $this->createSimplePluginElement($sStr); > } > return ''; > } > > // -------------------------------------------------------------------- > > /** > * Create a -element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createHeadingElement(&$sStr, &$sLevel) { > return ''.$sStr.''; > } > > // -------------------------------------------------------------------- > > /** > * Create a -element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createLinkElement($sStr) { > $aStr = explode(')(', $sStr); > > $sStr = ''; > $sStr .= trim($this->restoreTokens($aStr[0])); > $sStr .= ''; > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Create uri element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createUriElement(&$sStr) { > $sStr = ''; > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Create toc element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createTocElement() { > // Setting $i = 0 leads to undesired repetition of the first > // "title" element in a bullet list > > // The default behaviour of is not to display the first > // level > $i = 1; > $sStr = ''; > > if (sizeof($this->aToc) > 0) { > $sStr = $this->buildToc($i, $this->aToc[$i]['DEPTH']); > if ($sStr != '') { > $sStr = '| > > ' . $sStr . ' > >'; > } > } > > return ''.$this->restoreTokens($sStr).''; > } > > // -------------------------------------------------------------------- > > /** > * Create rule element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createRuleElement() { > return ' >------------------------------------------------------------------------ >'; > } > > // -------------------------------------------------------------------- > > /** > * Create simple table element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createSimpleTableElement(&$sStr) { > return ' > ' .$this->buildTable($sStr) .' > >'; > } > > // -------------------------------------------------------------------- > > /** > * Create param table element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createParamTableElement(&$sStr, &$sAttr) { > if (trim($sAttr) == '') { > return $this->createSimpleTableElement($sStr); > } > return ' > ' .$this->buildTable($sStr) .' > >'; > } > > // -------------------------------------------------------------------- > > /** > * Create quote element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createQuoteElement(&$sStr) { > return '"'.$this->invokeParagraphs($sStr).'"'; > } > > // -------------------------------------------------------------------- > > /** > * Create var element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createVarElement(&$sStr, &$sName) { > return ''; > } > > // -------------------------------------------------------------------- > > /** > * Create break element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createBreakElement() { > return ' >'; > } > > // -------------------------------------------------------------------- > > /** > * Create sub element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.3 > */ > protected function createSubElement(&$sStr) { > return '_'.$sStr.' '; > } > > // -------------------------------------------------------------------- > > /** > * Create sup element > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.3 > */ > protected function createSupElement(&$sStr) { > return '^'.$sStr.' '; > } > > // -------------------------------------------------------------------- > > protected function createJustificationElement(&$sStr, &$mMeta) { > return '<'.$mMeta.'>'.$this->invokeParagraphs($sStr).''; > } > > protected function createEmphasisElement(&$sStr, &$mMeta) { > > $sOpen = $sClose = ''; > for ($i=0 ; $i < strlen($mMeta) ; $i++ ){ > switch(substr($mMeta,$i,1)){ > case '_': > $sOpen .= "_"; > $sClose = "_".$sClose; > break; > case '-': > if(!strcmp(substr($mMeta,$i+1,1),'-')){ > $sOpen .= ""; > $sClose = "".$sClose; > $i++; > } > break; > case '=': > $sOpen .= ""; > $sClose = "".$sClose; > break; > case '*': > $sOpen .= "*"; > $sClose = "*".$sClose; > break; > case '/': > $sOpen .= "/"; > $sClose = "/".$sClose; > break; > } > } > return $sOpen . $sStr . $sClose; > } > > // --- Element creator helpers ---------------------------------------- > > /** > * Generate "toc" (Document Table of Contents) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function buildToc(&$i, &$nDepth) { > $sStr = ''; > > // Iterate though all toc-entries > while (isset($this->aToc[$i]['DEPTH']) > && $this->aToc[$i]['DEPTH'] == $nDepth) { > > $sStr .= ''; ># $sStr .= ''.$sAlias.''; > > $i++; > > // Recurse (indent) if toc-entry is nested > if (isset($this->aToc[$i]['DEPTH'])) { > > if ($this->aToc[$i]['DEPTH'] > $nDepth) { > $sStr .= ' > > '; $sStr .= $this->buildToc($i, $this->aToc[$i]['DEPTH']); $sStr > .= ' > >'; > } > } > > $sStr .= ' >'; > } > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Catch paragraphs > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function invokeParagraphs(&$sStr) { > // Remove multiple newlines > $sStr = preg_replace('=\n+=', "\n", $sStr); > > // Insert paragraphs > $sStr = preg_replace('=\n([^\r]+)$=Um', ' > > \1 > >', $sStr); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * All strings passed to this method MUST NOT contain any "<" or ">". > * Treat this string with "htmlentities()" or a similar function first. > * > * @access public > * @param string The wiki source string > * @return string Wiki XML > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > public function parse($sStr) { > > $sRet = ''; > $sContent = ''; > $bList = false; > $bTable = false; > $bGreedy = false; > $aList = array(); > $aTable = array(); > $aRows; > > // {{{ DEBUG }}} > Logger::info('Start parsing wiki document.'); > > // --- > > $sStr = trim(escape($sStr)); > > // Replace possible tabulators > $sStr = str_replace("\t", ' ', $sStr); > > // Replace possible \r\n or \n\r with \n > $sStr = str_replace("\r\n", "\n", $sStr); > $sStr = str_replace("\n\r", "\n", $sStr); > > $aRows = explode( "\n",$sStr."\n" ); > > > $i = 0; $n = sizeof( $aRows ); > $sRow = $aRows[$i]."\n"; > > $t = 0; $l = -1; > > > //table & list > while( true ) { > $sContent = ''; > $aMatches = array(); > //table of contents alone ^$ > if( preg_match( '=^<toc(/?)>$=', $sRow ) ) { > $sRet .= "\n\t\t\n"; > //end of table > } else if( $t > 0 && preg_match( '=^</table>=i', > $sRow, $aMatches )) { > $sParam = trim($aTable[$t][0]); > if( $sParam == '') { > $sRet .= "\n".' > '.$this->buildTable($aTable[$t]). ' > >'."\n"; > } else { > $sRet .= "\n".' > '. $this->buildTable($aTable[$t]).' > >'."\n"; > } > if( --$t == 0 ){ > $bTable = false; > } > //beginning of table > } else if( preg_match( '=^<table([^>]*)>$=i', > $sRow, $aMatches )) { > $bTable = true; > $aTable[++$t] = array(); > array_push( $aTable[$t], $aMatches[1] ); > //beginning of list > } else if( preg_match( '=^([\s*#]{0,}[*#]) ([^\n]*)$=', > $sRow, $aMatches )) { > $bList = true; > $aList[++$l] = array(); > $aList[$l]['TEXT'] = $this->processContent( $aMatches[2] ); > $aList[$l]['DEPTH'] = strlen( $aMatches[1] ); > $aList[$l]['TYPE'] = (substr($aMatches[1],-1)=='*'? > 'ul':'ol'); > //pre code posting q start at BOL, are greedy until > // closing tag anywhere on a line > } else if (preg_match( '=^<(pre|code|posting|q)>=i', > $sRow, $aMatch ) ) { > $sRow = substr( $sRow, strlen($aMatch[0]) ); > do { > if (preg_match( '=(.*)</'.$aMatch[1].'>=i', > $sRow, $aMatches )) { > $sRet .= '<'.$aMatch[1].'>'.$sContent . > $aMatches[1].''; > break; > } else { > $sContent .= $sRow; > } > if( ++$i < $n ){ > $sRow = $aRows[$i]; > }else{ > break; > } > } while(true); > if( $i == $n ) { > $sRet .= '<'.$aMatch[1].'>'. > $sContent . > ''; > break; > } > //horizontal rule > } else if (preg_match( '=^-{3,}(\s|$)=', $sRow, $aMatches ) ) { > $sRet .= ' >------------------------------------------------------------------------ >'."\n"; > //noop > } else if (preg_match( '=((.*)<noop>)=i', > $sRow, $aMatches )) { > $sContent = $this->processContent( $aMatches[2], false ) > . ''; > $sRow = substr( $sRow, strlen($aMatches[1]) ); > do { > if (preg_match( '=(.*)</noop>=' , > $sRow, $aMatches )) { > $sContent .= $aMatches[1] . ''; > break; > } else { > $sContent .= $sRow; > } > if(++$i<$n){ > $sRow = $aRows[$i]; > } else { > break; > } > } while(true); > $sRet .= $sContent; > } else { > //end of list > if($bList) { > $d = 0; > $sListType = $aList[$d]['TYPE']; > $nDepth = $aList[$d]['DEPTH']; > $sContent .= "\n".''. > '<'.$sListType.'>'. > $this->buildList($d,$nDepth,$aList). > ''. > ''."\n"; > $bList = false; > $aList = array(); > $l = -1; > if($bTable){ > array_push( $aTable[$t], $sContent ); > array_push( $aTable[$t], $sRow ); > }else{ > $sRet .= $sContent; > $sRet .= $this->processContent( $sRow ); > } > //more table > }else if($bTable) { > array_push( $aTable[$t], $sRow ); > //non table/list row > }else{ > $sContent = trim($this->processContent( $sRow )); > if( $sContent != '' ){ > $sRet .= ' > > '.$sContent.' > >'."\n"; > } > } > } > if(sizeof($aMatches)) { > $sRow = substr( $sRow, strlen( $aMatches[0] ) ); > } else if ( ++$i < $n ) { > $sRow = $aRows[$i]."\n"; > } else { > break; > } > } > > if( preg_match( '=^(.*)\n\t\t\n(.*)$=s', $sRet, $aMatches )) { > $t = 1; > if (sizeof($this->aToc) > 0) { > $sToc = $this->buildToc($t, $this->aToc[$t]['DEPTH']); > if ($sToc != '') { > $sToc = ' > > ' . $sToc . ' > >'; > } > } > return $aMatches[1] . $sToc . $aMatches[2]; > } > > // {{{ DEBUG }}} > Logger::info('Finished parsing wiki document.'); > > return $sRet; > } > > protected function resetEmphasis() { > $this->$aEmph = array( > "b" => false, > "u" => false, > "i" => false, > "f" => false, > "s" => false, > "j" => '', > "p" => '' > ); > } > > protected function processContent( $sStr, $bClose = true ) { > $sRet = ''; > $aMatches = array(); > if ($bClose) { > $this->resetEmphasis(); > } > $sStr = ltrim( $sStr ); > > while( strlen( $sStr ) > 0 ) { > if ($sStr == "\n"){ > break; > } > //noop > if (preg_match( '=^<noop>(.*)</noop>=is', > $sStr, $aMatches )) { > $sRet .= '' . $aMatches[1] . ''; > //links (()()) & [[][]] > }else if( preg_match( '=^\(\(([^\(\)]+|[^\(\)]+' . > '\([^\(\)]+\)[^\(\)]*|' . > '[^\(\)]+\)\([^\(\)]+)\)\)=Usx', > $sStr, $aMatches )) { > $aLink = explode( ')(', $aMatches[1] ); > $aLink[0] = str_replace( '|', '¦', $aLink[0] ); > $sRet .= ''; > if ( isset( $aLink[1]) ) { > $sRet .= trim($aLink[1]); > } else { > $sRet .= trim($aLink[0]); > } > $sRet .= ''; > //WikiWords > }else if( preg_match( '=^([A-Z][a-z]+([A-Z][a-z]+)+)=s', > $sStr, $aMatches )) { > $sLink = trim(preg_replace( '=([A-Z])=', ' \1', > $aMatches[1] )); > $sRet .= '' . > $sLink . ''; > //URIs > }else if( preg_match( > '=^(http://|https://|ftp://|mailto:|news:) > ([-_A-Z0-9\S]*) > (\*\s|\=\s|"|<|>|<|>|\(|\)|\s|$)?? > =six', > $sStr, $aMatches )) { > $sRet .= ''; > //headings > }else if( preg_match( '=^(\+{1,})\s*(.*)$=s', > $sStr, $aMatches )) { > $sContent = $this->processContent($aMatches[2]); > if( preg_match( '= > ([^<]*)=USx', > $sContent, $aLinkMatches ) ) { > $sAlias = !empty($aLinkMatches[2]) > ? $aLinkMatches[2] > : $aLinkMatches[1] > ; > } else { > $sAlias = $sContent; > } > $i = sizeof($this->aToc); > $this->aToc[$i]['TEXT'] = $sAlias; > $this->aToc[$i]['DEPTH'] = strlen( $aMatches[1] ); > $sTag = 'h'.strlen($aMatches[1]); > $sRet .= '<'. $sTag .'>'. > $sContent . > ''; > //breaks > //justification > }else if( preg_match( '=^<(/??)(left|center|right)>=is', > $sStr, $aMatches )) { > if( $aMatches[1] == '/' && > $this->aEmph['j'] == $aMatches[2]{0} ) { > $sRet .= ''; > $this->aEmph['j'] = ''; > } else if ( $aMatches[1] == '' && > $this->aEmph['j'] == '' ) { > $sRet .= '<'. $aMatches[2] .'>'; > $this->aEmph['j'] = $aMatches[2]{0}; > } > //subscript, superscript > }else if( preg_match( '=^<(/??)(sub|sup)>=is', > $sStr, $aMatches ) ) { > if( $aMatches[1] == '/' && > $this->aEmph['p'] == $aMatches[2] ) { > $sRet .= ''; > $this->aEmph['p'] = ''; > }else if ( $aMatches[1] == '' && > $this->aEmph['p'] == '' ) { > $sRet .= '<' . $aMatches[2] . '>'; > $this->aEmph['p'] = $aMatches[2]; > } > //emphasis > > /* > }else if( preg_match( '#^([^-=\*_/]*?) > ([-=\*_/]{2,}) > ([^-=\*_/]*?)#x', > */ > > }else if( preg_match( '#^([-=\*_/]{2,})#', > $sStr, $aMatches ) ) { > while( strlen( $aMatches[1] ) ) { > if( strlen( $aMatches[1] ) >= 2 && > $aMatches[1]{0} == $aMatches[1]{1} ) { > if( strlen( $aMatches[1] ) > 3 && > $aMatches[1]{1} == $aMatches[1]{2} && > $aMatches[1]{3} == $aMatches[1]{2} ) { > $sRet .= str_repeat( $aMatches[1]{0}, 2 ); > $aMatches[1] = substr( $aMatches[1], 4 ); > continue; > } > $sEmph = ''; > switch ( $aMatches[1]{0} ) { > case '-': > $sEmph=($this->aEmph["s"]?'/':'').'strike'; > $this->aEmph["s"] = !$this->aEmph["s"]; > break; > case '=': > $sEmph=($this->aEmph["f"]?'/':'').'tt'; > $this->aEmph["f"] = !$this->aEmph["f"]; > break; > case '*': > $sEmph=($this->aEmph["b"]?'/':'').'b'; > $this->aEmph["b"] = !$this->aEmph["b"]; > break; > case '_': > $sEmph=($this->aEmph["u"]?'/':'').'u'; > $this->aEmph["u"] = !$this->aEmph["u"]; > break; > case '/': > $sEmph=($this->aEmph["i"]?'/':'').'i'; > $this->aEmph["i"] = !$this->aEmph["i"]; > break; > } > $sRet .= '<'.$sEmph.'>'; > $aMatches[1] = substr( $aMatches[1], 2 ); > } else { > $sRet .= $aMatches[1]{0}; > $aMatches[1] = substr( $aMatches[1], 1 ); > } > } > }else if( preg_match( '#^((([-=\*_/]{1})(?!\3)|\s|[A-Za-z0-9])*)#x', > $sStr, $aMatches ) ) { > $sRet .= $aMatches[0]; > } > if( isset($aMatches[0]) ) { > $sStr = substr( $sStr, strlen($aMatches[0]) ); > }else{ > break; > } > } > if($bClose) { > if( $this->aEmph['s'] ) { $sRet .= ''; } > if( $this->aEmph['f'] ) { $sRet .= ''; } > if( $this->aEmph['b'] ) { $sRet .= ''; } > if( $this->aEmph['u'] ) { $sRet .= ''; } > if( $this->aEmph['i'] ) { $sRet .= ''; } > if( $this->aEmph['p'] != '' ) { > $sRet .= 'aEmph['p'] .'>'; > } > $this->resetEmphasis(); > } > /* > if( $this->aEmph['j'] != '' ) { > switch( $this->aEmph['j'] ) { > case 'l': $sRet .= '';break; > case 'r': $sRet .= '';break; > case 'c': $sRet .= '';break; > } > } > */ > return $sRet; > } > > /** > * &build table > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function buildTable( &$aTable ) { > > $sRet = ''; > $sContent = ''; > $sRow = ''; > $bPriorRow = false; > > $j = 1; > $v = sizeof($aTable); > > while( ++$j < $v ) { > > /* > if (!strlen(trim($aTable[$j]))) { > return ''.$sStr.''; > } > */ > > //rows expected to hold table syntax (pipes), may instead > //make room for ongoing content (tables, lists, etc) > $sRow = $aTable[$j]; > > //find table syntax within a (long?) row > while( strlen($sRow) && preg_match( > '=^([\|!][-+]?)( {0,1}[^\|!\n]*)?=', > $sRow, > $aMatches) ) { > > //found exploded row begins with pipe syntax, poss params > $sRow = substr( $sRow, strlen($aMatches[0]) ); > > $nType = 0; > //tables made of cells, headers, rows, caption > if ($aMatches[1]=="|") { > $sRet .= '\n"; > continue 1; > } > > //content can be large, room for it here > $sContent = ''; > > if ($aMatches[2]{0}==' ') { > //left a space to denote no params > $sRet .= '>'; > $sContent .= substr($aMatches[2],1); > //expect double pipe, bang or newline > } elseif (strlen($aMatches[2])) { > //got params. look for pipe syntax that blocked last preg > $sRet .= ' '.unescape($aMatches[2]).'>'; > if (preg_match('=^\|([^\|!\n]*)=',$sRow,$aMatches)) { > //got rest of pipe syntax (...|text) > $sContent .= $aMatches[1]; > $sRow = substr( $sRow, strlen($aMatches[0]) ); > } > } else { > $sRet .= '>'; > } > > //look ahead now. > if ($sRow == "\n") { > //look ahead to close our content > while( ++$j<$v ){ > $sRow = $aTable[$j]; > //pipe syntax (will force $sContent) to continue > if ($sRow{0} == '|' || $sRow{0} == '!') { > $sRet .= $this->processContent($sContent); > switch($nType){ > case 1: > $sRet .= "\n"; > break; > case 2: > $sRet .= "\n"; > break; > } > --$j; > continue 3; > } else { > //non-pipe (ever-increasing) content > $sContent .= $sRow; > } > } > $j = $v; > $sRet .= $this->processContent($sContent); > switch($nType){ > case 1: > $sRet .= "\n"; > break; > case 2: > $sRet .= "\n"; > break; > } > continue 2; > } elseif ( ( $sRow{0} == "|" || $sRow{0} == "!") && > ($sRow{1} == "|" || $sRow{1} == "!") ) { > $sRow = substr($sRow, 1); > $sRet .= $this->processContent($sContent); > switch($nType){ > case 1: > $sRet .= "\n"; > break; > case 2: > $sRet .= "\n"; > break; > } > continue 1; > } > } > } > if( $bPriorRow ) { > return $sRet.""; > } else { > return $sRet; > } > } > > protected function buildList(&$i, &$nDepth, &$aList) { > $sStr = ''; > > // Iterate though all list-entries > while (isset($aList[$i]['DEPTH']) > && $aList[$i]['DEPTH'] == $nDepth) { > > $sStr .= ''; ># $sStr .= $aList[$i]['TEXT']; > > $i++; > > // Recurse (indent) if list-entry is nested > if (isset($aList[$i]['DEPTH'])) { > > if ($aList[$i]['DEPTH'] > $nDepth) { > > // Correct items that are intended too deep > $aList[$i]['DEPTH'] = $nDepth + 1; > > $sListType = $aList[$i]['TYPE']; > > $sStr .= '<'.$sListType.'>'; > $sStr .= $this->buildList( > $i, > $aList[$i]['DEPTH'], > $aList > ); > $sStr .= ''; > } > } > > $sStr .= ' >'; > } > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Treat NOOP (no operation) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processNoOperation(&$sStr) { > > // Treat ... > // This tag can not be nested. > $sStr = preg_replace_callback( > '=<noop>(.+)</noop>=Usi', > array(&$this, 'tokenizeNoOperation'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Treat REMARKS > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processRemark(&$sStr) { > > // Treat ... > // This tag can not be nested. > $sStr = preg_replace_callback( > '=<rem>(.+)</rem>=Usi', > array(&$this, 'tokenizeRemark'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Treat preformatted PRE > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processPre(&$sStr) { > > // Treat > > ... > > > // Each tag will be recognized at the begin of a line only! > // This tag can not be nested. > $sStr = preg_replace_callback( > '=^<pre>\n(.+)\n</pre>(\s|$)=Umsi', > array(&$this, 'tokenizePre'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Treat preformatted CODE > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processCode(&$sStr) { > > // Treat | ... | > // Each tag will be recognized at the begin of a line only! > // This tag can not be nested. > $sStr = preg_replace_callback( > '=^<code>\n(.+)\n</code>(\s|$)=Umsi', > array(&$this, 'tokenizeCode'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Treat POSTING > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processPosting(&$sStr) { > > // Treat ... > // Each tag will be recognized at the begin of a line only! > // This tag can not be nested. > $sStr = preg_replace_callback( > '=^<posting>\n(.+)\n</posting>(\s|$)=Umsi', > array(&$this, 'tokenizePosting'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * ((foo)), ((foo)(bar)) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processLink(&$sStr) { > > // Treat square-bracket-links ((foo)), ((foo)(bar)) > // These tags can not be nested. > $sPattern = '=\(\(([^\(\)]+|[^\(\)]+\([^\(\)]+\)[^\(\)]*|' . > '[^\(\)]+\)\([^\(\)]+)\)\)=U'; > > $sStr = preg_replace_callback( > $sPattern, > array(&$this, 'tokenizeLink'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Convert WikiWords > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processWikiWord(&$sStr) { > > // Treat WikiWordLinks > $sStr = preg_replace_callback( > '=([ \n\[\{\']|")([A-Z][a-z]+([A-Z][a-z]+)+)=', > array(&$this, 'tokenizeWikiWord'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Automatically clickable URIs > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processClickable(&$sStr) { > > // Treat clickable URIs (http:, mailto: etc.) > $sStr = preg_replace_callback( > '= (http://|https://|ftp://|mailto:|news:) > (\S+) > (\*\s|\=\s|"|<|>|<|>|\(|\)|\s|$) > =Usmix', > array(&$this, 'tokenizeClickable'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processToc(&$sStr) { > // Treat > $sStr = preg_replace_callback( > '=\n<toc>=Usi', > array(&$this, 'tokenizeToc'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processSimplePlugin(&$sStr) { > > // Treat > $sStr = preg_replace_callback( > '=<plugin +([a-z0-9_.]+)>=Usi', > array(&$this, 'tokenizeSimplePlugin'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processParamPlugin(&$sStr) { > > // Treat > $sStr = preg_replace_callback( > '=<plugin +([a-z0-9_.]+) +(.*)>=Usi', > array(&$this, 'tokenizeParamPlugin'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Emphasis: bold, italic, monospaced ... > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processEmphasis(&$sStr) { > > /* > emphasis markup may be as widely spaced as an entire paragraph > > /x/ - italics > *x* - bold > --x-- - strikethrough > _x_ - underlined > =x= - monospaced > */ > > $sEmph= '(-{2}|[_=\*/]+)'; > $sCont= '([^\n_=*/]*)'; > $sWord= '([^ \n/](\S?|.*(\S|\t)))'; > > $sStr = $this->collapseEmphasis( $sStr ); > > $sStr = preg_replace_callback( > '~ ((-{2}|[_=*/])+) > (([^\n_=*/])+) > ((-{2}|[_=*/])+) > ~mix', > array(&$this,'tokenizeEmphasis'), > $sStr > ); > > return $sStr; > } > > protected function collapseEmphasis(&$sStr) { > > //italic > $sStr = preg_replace( > '=<(em|i)>(.*)</\1>=ms', > '/\2/', > $sStr > ); > //bold > $sStr = preg_replace( > '=<(strong|b)>(.*)</\1>=ms', > '*\2*', > $sStr > ); > //monospaced > $sStr = preg_replace( > '=<tt>(.*)</tt>=ms', > '=\1=', > $sStr > ); > //strikethrough > $sStr = preg_replace( > '=<strike>(.*)</strike>=ms', > '--\1--', > $sStr > ); > //underlined > $sStr = preg_replace( > '=<u>(.*)</u>=ms', > '_\1_', > $sStr > ); > > return $sStr; > } > > /** > * (Again) treat %VARIABLES%, that may occur in the document. > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processVariable(&$sStr) { > $sStr = preg_replace_callback( > '=%([A-Z0-9_]+)%=U', > array(&$this, 'tokenizeVariable'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Headings (+ -> H1, ++ -> H2, etc.) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processHeading(&$sStr) { > > // Treat headings (+, ++, +++ etc); > // Each tag will be recognized at the begin of a line only! > $sStr = preg_replace_callback( > '=^(\+{1,6}) ([^\r\n]+)=m', > array(&$this, 'tokenizeHeading'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Headings (+ -> H1, ++ -> H2, etc.) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processHorizontalRule(&$sStr) { > > // Treat horizontal rules (---) > $sStr = preg_replace_callback( > '=^-{3,}(\s|$)=m', > array(&$this, 'tokenizeHorizontalRule'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Breaks ( >) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processBreak(&$sStr) { > > // Treat a break > $sStr = preg_replace_callback( > '=<br>=Ui', > array(&$this, 'tokenizeBreak'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Subs (_) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.3 > */ > protected function processSub(&$sStr) { > > // Treat a _ > $sStr = preg_replace_callback( > '=<sub>(.*)</sub>=Ui', > array(&$this, 'tokenizeSub'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Sups (^) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.3 > */ > protected function processSup(&$sStr) { > > // Treat a ^ > $sStr = preg_replace_callback( > '=<sup>(.*)</sup>=Ui', > array(&$this, 'tokenizeSup'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > protected function processJustification(&$sStr) { > $sStr = preg_replace_callback( > '=<(left|center|right)>(.*)</\1>=Usi', > array(&$this, 'tokenizeJustification'), > $sStr ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Ordered and unordered bullet lists (Asterisk *, Hash #) > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processList(&$sStr) { > > // Treat lists > $sStr = preg_replace_callback( > /* '=\n(( {0,})(\*|#)+ (.*))$=Us',*/ > '=\n((\*|#) (.*)\n)(?! {0,}(\*|#))=Us', > array(&$this, 'tokenizeList'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Create list > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function createList(&$sStr, &$mMeta) { > > // Fix multiple bullets at the beginning of the line. > // E.g. fix sick things like this to make it intuitive: > // > // * Item 1 <--> * Item 1 > // * Item 2 <--> * Item 2 > // ** Item 3 <--> * Item 3 > // *** Item 4 <--> * Item 4 > // **** Item 5 <--> * Item 5 > // ** Item 6 <--> * Item 6 > > $aArr = explode("\n", $sStr); > > for ($i=0, $n=sizeof($aArr); $i<$n; $i++) { > $aArr[$i] = preg_replace_callback( > '=^((\*|#)*)(\2) (.*)$=', > array($this, 'createListMultiBulletHelper'), > $aArr[$i] > ); > } > > $sStr = join("\n", $aArr); > > preg_match_all( > '=^( {0,})(\*|#)+ (.*)$=Ums', > $sStr, > $aList > ); > > $this->aList = array(); > > for ($i=0; $iaList[$i]['TEXT'] = $this->restoreTokens($mMeta); > //$this->aList[$i]['TEXT'] = $aList[3][$i]; > $sEmp = $this->restoreTokens($this->processEmphasis($aList[3][$i])); > $this->aList[$i]['TEXT'] = $sEmp; > $this->aList[$i]['DEPTH'] = strspn($aList[1][$i], ' '); > $this->aList[$i]['TYPE'] = $aList[2][$i]; > } > > $i = 0; > $nDepth = $this->aList[$i]['DEPTH']; > > // Determine the type of the first list element: > // Ordered or unordered? > $sListType = ($aList[2][0] == '*') ? 'ul' : 'ol'; > > return '' > .'<'.$sListType.'>' > .$this->buildList($i, $nDepth) > .'' > .''; > } > > private function createListMultiBulletHelper(&$aMatches) { > return str_repeat(' ', strlen($aMatches[1])) > .$aMatches[3].' '.$aMatches[4]; > } > > // -------------------------------------------------------------------- > > /** > * Build list > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > /** > * Treat TABLE > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processSimpleTable(&$sStr) { > > // Treat > __^^... > > >__^^ // Each tag will be recognized at the begin of a line only! > // This tag can not be nested. > $sStr = preg_replace_callback( > '=^<table>\n(.+)\n</table>(\s|$)=Umsi', > array(&$this, 'tokenizeTable'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Process param table > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processParamTable(&$sStr) { > > // Treat > __^^... > > >__^^ // Each tag will be recognized at the begin of a line only! > // This tag can not be nested. > $sStr = preg_replace_callback( > '=^<table +([^>]*)>\n(.+)\n</table>(\s|$)=Umsi', > array(&$this, 'tokenizeParamTable'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Treat (block-)quote > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function processQuote(&$sStr) { > > // Treat " ... " > // Each tag will be recognized at the begin of a line only! > // This tag can not be nested. > $sStr = preg_replace_callback( > '=^<q>(.+)\n+</q>(\s|$)=Umsi', > array(&$this, 'tokenizeQuote'), > $sStr > ); > > return $sStr; > } > > // -------------------------------------------------------------------- > > /** > * Collect referenced nodes to where the document is linking to > * > * @access protected > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > protected function addReferencedNode($Obj) { > $this->RefNodes->add($Obj); > } > > // -------------------------------------------------------------------- > > /** > * Get referenced nodes > * > * @access public > * > * @author Daniel T. Gorski, > * @since coWiki 0.3.0 > */ > public function getReferencedNodes() { > return $this->RefNodes; > } > >} // of class > >/* > Prospero: That cross you wear around your neck; is it only a decoration, > or are you a true Christian believer? > > Francesca: Yes, I believe - truly. > > Prospero: Then I want you to remove it at once! - and never to wear it > within this castle again! Do you know how a falcon is trained > my dear? Her eyes are sown shut. Blinded temporarily she > suffers the whims of her God patiently, until her will is > submerged and she learns to serve - as your God taught and > blinded you with crosses. > > Francesca: You had me take off my cross because it offended ... > > Prospero: It offended no-one. No - it simply appears to me to be > discourteous to ... to wear the symbol of a deity long dead. > My ancestors tried to find it. And to open the door that > seperates us from our Creator. > > Francesca: But you need no doors to find God. If you believe ... > > Prospero: Believe?! If you believe you are gullible. Can you look > around this world and believe in the goodness of a god who > rules it? Famine, Pestilence, War, Disease and Death! > They rule this world. > > Francesca: There is also love and life and hope. > > Prospero: Very little hope I assure you. No. If a god of love and life > ever did exist ... he is long since dead. Someone ... > something rules in his place. >*/ > >?> > > > >__^^ > >------------------------------------------------------------------------ >__^^ >--------------------------------------------------------------------- >To unsubscribe, e-mail: [email protected] >For additional commands, e-mail: [email protected] >