Page 1 of 1

making a * turn a whole word bold

Posted: Mon Jul 09, 2007 6:20 pm
by treymon
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.

Posted: Mon Jul 09, 2007 6:21 pm
by treymon
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.

Posted: Mon Jul 09, 2007 6:33 pm
by vigge89
Check out the PCRE Regular Expression support in PHP:
http://php.net/pcre
*Hint: preg_replace()

Posted: Mon Jul 09, 2007 7:13 pm
by feyd
I wrote this a long time ago as a wiki-based parser. It's not exactly perfect, but it works fairly well.

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);
}

?>
wikicode.php

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;

?>
wikiForums.php

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;
}


?>
You can see it in action here: http://tatzu.net/examples/wikicode.php