Lets say I have a word that I want to make bold if I put a * in front of it. Therefore, "*word" would turn into "<b>world</b>".
Any suggestions? I'm really bad with parsing characters with PHP.
making a * turn a whole word bold
Moderator: General Moderators
Also, on the same line but maybe more complicated, how would I go about making something like "word|http://www.blabla.com" become "<a href="http://www.blabla.com">word</a>"?
These are gonna be lifesavers if anybody can help me out.
These are gonna be lifesavers if anybody can help me out.
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
I wrote this a long time ago as a wiki-based parser. It's not exactly perfect, but it works fairly well.
bbCoCode.php
wikicode.php
wikiForums.php
You can see it in action here: http://tatzu.net/examples/wikicode.php
bbCoCode.php
Code: Select all
<?php
/*
parse a given string into token keys
returns an array of the tokens and their contents
*/
function bbTokenize($text)
{
//$text = func_get_arg(0);
// used to store the final tree of the document
$tree = array();
// first, break out the singular entities
$elements = preg_split( '@((?si:<noop>.*?</noop>|<code>.*?</code>|<pre>.*?</pre>)|(?m:^-{3,}|^\+{1,6}\s+.*?$))@m', $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE );
//print var_export($elements,true)."\n\n\n";
// pieces of the wonky elements
$complex = array(
'\/'=>'i',
'\-'=>'s',
'\='=>'tt',
'\_'=>'u',
'\^'=>'sup',
'\*'=>'b',
'\%'=>'sub');
// analyze each element for further processing
for($i = 0, $j = count($elements); $i < $j; $i++)
{
$element =& $elements[$i];
if(preg_match('@^<(noop|code|pre)>@i', $element, $match) and preg_match('@^<('.$match[1].')>(.*?)</'.$match[1].'>$@si',$element,$match))
{ // no processing area, preformatted text or code area
$tree[] = array('element'=>$match[1],'type'=>'start');
$tree[] = array('element'=>'done','content'=>(strcasecmp($match[1],'noop')==0 ? nl2br($match[2]) : $match[2]));
$tree[] = array('element'=>$match[1],'type'=>'stop');
}
elseif(preg_match('@^-{3,}@', $element))
{ // horizontal rule element
$tree[] = array('element'=>'hr');
//print "%%%%%%%%%%%%%%%%%%%%\nhr in\n%%%%%%%%%%%%%%%%%%%%\n";
}
elseif(preg_match('@^(\+{1,6})\s+(.*?)\s*$@s', $element, $match))
{ // heading element
$tree[] = array('element'=>'h'.strlen($match[1]),'type'=>'start');
$more = bbTokenize($match[2]);
array_splice($tree, count($tree), 0, $more);
$tree[] = array('element'=>'h'.strlen($match[1]),'type'=>'stop');
}
elseif(preg_match('@(?m:^)(?s:([#\*])\s.*?(?:\n\n|$))@',$element,$match))
{ // list nesting
$type = ($match[1] == '*' ? 'ul' : 'ol');
$tree[] = array('element'=>$type,'type'=>'start');
//$more = preg_split( '@(?m:^)(?s:([#\*])\s.*?(?:\n\n|$))@', $element, -1, PREG_SPLIT_DELIM_CAPTURE );
$more = preg_split( '@\s*^(\s*[#\*])\s+@m', $element, -1, PREG_SPLIT_DELIM_CAPTURE );
array_shift($more);
$last = 0;
$lastType = $type;
$end = array();
for($k = 0; $k < count($more); $k+=2)
{
$depth = strlen($more[$k])-1;
//var_dump($depth,$more[$k]);
$type = ($more[$k]{$depth} == '*' ? 'ul' : 'ol');
if($depth < $last)
{
array_splice($tree, count($tree), 0, $end);
$end = array();
$tree[] = array('element'=>$type,'type'=>'start');
array_unshift($end, array('element'=>$type,'type'=>'stop'));
$tree[] = array('element'=>'li','type'=>'start');
array_unshift($end, array('element'=>'li','type'=>'stop'));
$evenmore = bbTokenize($more[$k+1]);
array_splice($tree, count($tree), 0, $evenmore);
}
elseif($depth > $last)
{ // nested
$tree[] = array('element'=>$type,'type'=>'start');
array_unshift($end, array('element'=>$type,'type'=>'stop'));
$tree[] = array('element'=>'li','type'=>'start');
array_unshift($end, array('element'=>'li','type'=>'stop'));
$evenmore = bbTokenize($more[$k+1]);
array_splice($tree, count($tree), 0, $evenmore);
}
elseif($type != $lastType)
{
array_splice($tree, count($tree), 0, $end);
$end = array();
$tree[] = array('element'=>$type,'type'=>'start');
array_unshift($end, array('element'=>$type,'type'=>'stop'));
$tree[] = array('element'=>'li','type'=>'start');
array_unshift($end, array('element'=>'li','type'=>'stop'));
$evenmore = bbTokenize($more[$k+1]);
array_splice($tree, count($tree), 0, $evenmore);
}
else
{
$tree[] = array('element'=>'li','type'=>'start');
$evenmore = bbTokenize($more[$k+1]);
array_splice($tree, count($tree), 0, $evenmore);
$tree[] = array('element'=>'li','type'=>'stop');
}
}
array_splice($tree, count($tree), 0, $end);
//var_dump($more);
//array_splice($tree, count($tree), 0, $more);
$tree[] = array('element'=>$type,'type'=>'stop');
}
elseif(preg_match("@(((?:https?|ftps?)://)?(?:(?:25[0-5]|2[0-4][0-9]". "|[0-1]?[0-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|[0-1]?". "[0-9]?[0-9])){3}|(?:[a-z0-9-]{2,}\.)+[a-z]{2,})[^ \n\r\t\?\"'\|]*).*?(?:\|([^\]]+))?@i",$element))
{ // web links are available
//print "%%%%%%%%%%%%%%%%%%%%\nlinks in\n%%%%%%%%%%%%%%%%%%%%\n";
$more = preg_split( "@\[?((?:(?:https?|ftps?)://)?(?:(?:25[0-5]|2[0-4][0-9]". "|[0-1]?[0-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|[0-1]?". "[0-9]?[0-9])){3}|(?:[a-z0-9-]{2,}\.)+[a-z]{2,})[^ \n\r\t\?\"'\|]*.*?(?:\|[^\]]+)?)\]?@i", $element, -1, PREG_SPLIT_DELIM_CAPTURE );
for($k = 0; $k < count($more); $k++)
{
if(preg_match("@(((?:https?|ftps?)://)?(?:(?:25[0-5]|2[0-4][0-9]". "|[0-1]?[0-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|[0-1]?". "[0-9]?[0-9])){3}|(?:[a-z0-9-]{2,}\.)+[a-z]{2,})[^ \n\r\t\?\"'\|\]]*).*?(?:\|([^\]]+))?@i",$more[$k],$match))
{
$tree[] = array('element'=>'link','url'=>$match[1],'text'=>(empty($match[3]) ? $match[1] : $match[3]));
//var_dump($match);
}
else
{
$evenmore = bbTokenize($more[$k]);
array_splice($tree, count($tree), 0, $evenmore);
}
}
}
/*
elseif(preg_match())
{ // emails
;
}
*/
elseif(preg_match('@^(\s*)$@s',$element))
{ // element is entirely white space.. ignore it.
}
else
{ // final content format processing
$element = htmlentities((substr($element,0,1) == ' ' ? $element : ' '.$element),ENT_QUOTES);
//var_dump($element);
foreach($complex as $c => $tag)
{
//var_dump('@'.$c.'((?:'.$c.$c.'){0,}(?=[a-z]).*?(?<=[a-z]))'.$c.'(?:'.$c.$c.'){0,}(?![a-z])@si');
$element = preg_replace( '@'.$c.'((?:'.$c.$c.'){0,}(?=[\S]).*?(?<=[\S]))'.$c.'(?:'.$c.$c.'){0,}(?![\w\d])@si', '<'.$tag.'>\\1</'.$tag.'>', $element );
//$element = preg_replace( '@(?<=\s)([^\w\d]*)'.$c.'((?:'.$c.$c.'){0,}(?=[\S]).*?(?<=[\S]))'.$c.'(?:'.$c.$c.'){0,}(?![\w\d])([^\w\d]*)(?=\s)@si', '\\1<'.$tag.'>\\2</'.$tag.'>\\3', $element );
}
//var_dump($element);
foreach($complex as $c => $tag)
{
$element = str_replace($c.$c,$c,$element);
}
$element = nl2br($element);
//var_dump($element);
//$element = preg_replace('@(?<=\[)\[(?:https?|ftps?)://(?:
$tree[] = array('element'=>'done','content'=>substr($element,1));
}
}
return $tree;
}
function bbMessageProcess($text, $options)
{
if(isset($options['cocode']) and $options['cocode'])
{
// first we tokenize if we are doing CoCode
$tree = bbTokenize($text);
// what elements to map where.. (specialty ones only)
$elements = array(
'noop'=>'',
'done'=>'',
);
$text = '';
// now we create the document using your options
foreach($tree as $key => $v)
{
$branch =& $tree[$key];
//var_dump($branch);
if(isset($branch['element']))
{
$element = (isset($elements[$branch['element']]) ? $elements[$branch['element']] : $branch['element']);
if($element == 'link')
{
if($branch['text'] == $branch['url'])
{
$tooltip = $branch['text'];
$parse = parse_url($branch['url']);
$txt = isset($parse['host']) ? $parse['host'] : 'localhost';
$url = $branch['url'];
$pre = '[';
$post = ']';
}
else
{
$tooltip = '';
$txt = $branch['text'];
$parse = parse_url($branch['url']);
$url = $branch['url'];
$pre = '';
$post = ' ['.$parse['host'].']';
}
$text .= $pre.bbClickable(array('text'=>$txt,'tooltip'=>$tooltip,'data'=>array('url'=>$url))).$post;
}
elseif(isset($branch['type']))
{
if($branch['type'] == 'start')
{
$text .= (empty($element) ? '' : '<'.$element.'>');
}
elseif($branch['type'] == 'stop')
{
$text .= (empty($element) ? '' : '</'.$element.'>');
}
}
elseif($element == 'done')
{ // do nothing
}
elseif(!empty($element))
{
$text .= '<'.$element.' />';
}
if(isset($branch['content']))
{
$text .= $branch['content'];
}
}
}
}
else
{ // basic conversion so no one can post malicious code.
$text = nl2br(htmlentities($text,ENT_QUOTES));
if(isset($options['smilies']) and $options['smilies'])
{
$text = bbDoSmilies($text);
}
}
// this must return an array for use in the appcreate platform :/
return array('processed'=>$text);
}
?>Code: Select all
<?php
include 'wikiForums.php';
include 'bbCoCode.php';
// testing section
$text = "these are *bold*, -strike-through-, =monospace=, /italics/, _underline_, ^superscript^ and %subscript% texts.
If /*you* want/ to /you *=can=*/ =mix= *the =styles=*.
http://link1.com
[http://link2.com/]
[http://link3.com/|link 3 text]
[[http://link4.com/]]
[[[http://link5.com]]]
[[http://link6.com/|link 6 text]]
[[[http://link7.com|link 7 text]]]
---
horizontal rule
---
not a horizontal rule<noop>
* unprocessed unordered list item
* another unprocessed unordered
* second tier unprocessed unordered</noOP>
# ordered list item
# another ordered
# second tier ordered
# ordered 1
# ordered 2
* unordered 1
* unordered 2
# ordered 3
* unordered 3
* second order unordered
# try this
# ordered 4
+ heading 1
++ heading 2
+++ heading 3
++++ heading 4
+++++ heading 5
++++++ heading 6
+++++++ heading 7?";
//echo bbCoCode($text);
$processed = bbMessageProcess($text,array('cocode'=>true));
$processed = array_shift($processed);
echo $processed;
?>Code: Select all
<?php
/*
make a clickable link or button
parameters:
text [required] Syntax: any string. (entities are automatically processed)
the text you wish to display in the link
data [optional] Default: none
A php array that should be converted to javascript.
type [optional] Default: new
helps tell the system where to send the clickable. Valid values are:
new open a new (normal) browser window. Useful for external links like those posted.
tab open a new tab.
win open a popup window
self or page open in the existing document page
none do nothing. (Used mostly for options, but works with links and buttons)
style [optional] Default: text/link
tell the system what kind of clickable to create. Valid values are:
text or link create a textual link
button create a form button
option generate a select-box option
*/
function bbClickable($pArray, $state = null)
{
$pop = $supplement = $type = $url = $text = $tooltip = $style = '';
extract($pArray);
if(strtolower($state) == 'debug')
{
$debug = 'yes';
}
$params = bbMakeJavascript(array('name'=>'params','data'=>$data));
switch(strtolower($type))
{
case 'tab':
$pop = 'popTab';
$url = 'bbTab';
$supplement = ',params';
break;
case 'win':
$pop = 'popWin';
$url = 'bbWin';
$supplement = ',params';
break;
case 'self':
case 'page':
$pop = 'popPage';
$url = 'bbPage';
$supplement = ',params';
break;
case 'none':
$pop = '';
$url = '';
$supplement = '';
case 'new':
default:
$pop = 'popNew';
$supplement = '';
break;
}
bbUseJavascript(array('function'=>$pop));
$vArray = array(
'text'=>$text,
'tooltip'=>(empty($tooltip) ? $text : $tooltip),
'onclick'=>(empty($pop) ? '' : "{$params}{$pop}('{$url}'{$supplement});"),
);
switch(strtolower($style))
{
case 'button':
$func = 'bbMakeButton';
break;
case 'option':
$func = 'bbMakeOption';
$vArray['value'] = $vArray['text'];
$vArray['link'] = $vArray['onclick'];
unset($vArray['onclick'],$vArray['tooltip']);
break;
case 'text':
case 'link':
default:
$func = 'bbMakeLink';
break;
}
return $func($vArray);
}
/*
store up the page's list of javascript functions to include
*/
function bbUseJavascript($pArray, $state = null)
{
global $_USER;
extract($pArray);
if(strtolower($state) == 'debug')
{
$debug = 'yes';
}
static $FUNCTIONLIST = null;
if($FUNCTIONLIST === null)
{
$FUNCTIONLIST = array();
}
if(!empty($function))
{
$r = $FUNCTIONLIST[$function] = true;
}
if(!isset($pArray['function']))
{
$r = $FUNCTIONLIST;
}
return $r;
}
/*
Flatten a PHP variable into a Javascript array or variable.
*/
function bbMakeJavascript($pArray, $state = null)
{
global $_USER;
extract($pArray);
if(strtolower($state) == 'debug')
{
$debug = 'yes';
}
$ret = '';
if(is_array($data) or is_object($data))
{
$ret .= $name.'=new Array();';
foreach($data as $key => $value)
{
$newName = $name.'['.var_export($key,true).']';
$ret .= bbMakeJavascript(array('name'=>$newName,'data'=>$value));
}
}
elseif(!empty($data) or is_numeric($data))
{
$ret .= $name.'='.var_export($data,true).';';
}
else
{
$ret .= $name.'="";';
}
return $ret;
}
?>