transform($text); } // ################################################################### /** * Resets the parser */ public function __construct() { $this->htmlBlockMap = array(); $this->text = ''; } // ################################################################### /** * Transforms the Markdown text into XHTML with the parser's set options * * @param string Text to transform * * @return string HTML output */ public function transform($text) { // reset the data arrays $this->__construct(); // convert line breaks and remove empty lines of whitespace $this->text = BSFunctions::ConvertLineBreaks($text); $this->text = preg_replace('/^\s*?$/m', '', $this->text); $this->_extractHtmlBlocks(); $this->_convertHardLineBreaks(); $this->_convertAtxHeaders(); $this->_convertSetextHeaders(); $this->_convertHorizontalRules(); $this->_formatParagraphs(); $this->text = $this->_expandHtmlBlocks($this->text); // convert entitites $this->_convertFloatingEntities(); return $this->text; } // ################################################################### /** * Description of the function * * @param string A string param * * @return integer Return value */ private function _extractHtmlBlocks() { $start = -1; $blockStart = 0; $nest = array(); $matches = array(); // find the first insance of a block tag $regex = implode('|', $this->htmlBockTags); while ($start <= strlen($this->text)) { $start++; if (preg_match("/^<($regex)/i", substr($this->text, $start)) === 1) { if (sizeof($nest) == 0) { $blockStart = $start; } array_push($nest, $start); } else if (preg_match("#^#i", substr($this->text, $start), $matches) === 1) { array_pop($nest); if (sizeof($nest) == 0) { $block = substr($this->text, $blockStart, $start - $blockStart + strlen($matches[0])); $hash = md5($block . microtime()); $this->htmlBlockMap[$hash] = $block; $this->text = substr_replace($this->text, $hash, $blockStart, strlen($block)); $start = $blockStart; } } } } // ################################################################### /** * Expands the hashed HTML blocks back into their originial form */ private function _expandHtmlBlocks($text) { return str_replace(array_keys($this->htmlBlockMap), array_values($this->htmlBlockMap), $text); } // ################################################################### /** * Converts text surrounded by #sings to headers (## Heading 2) */ private function _convertAtxHeaders() { $this->text = preg_replace_callback('/^(\#{1,6})\s*(.+)(\s*\#+)?$/', array(&$this, '_convertAtxHeadersCallback'), $this->text); } // ################################################################### /** * Callback function for preg_replace() in _convertAtxHeaders() * * @param array Matches */ private function _convertAtxHeadersCallback($matches) { var_dump($matches); $html = '' . $this->_expandHtmlBlocks($matches[2]) . ''; $hash = md5($html . microtime()); $this->htmlBlockMap[$hash] = $html; return $hash; } // ################################################################### /** * Converts headers that are formed by underlines into headings */ private function _convertSetextHeaders() { $this->text = preg_replace_callback('/(.+)\n(-|=){1,}$/m', array(&$this, '_convertSetextHeadersCallback'), $this->text); } // ################################################################### /** * Callback function for _convertSetextHeaders(). This does the actual * conversion and then hashes it into a block * * @param array Matches from the preg_replace_callback() */ private function _convertSetextHeadersCallback($matches) { $text = $this->_expandHtmlBlocks($matches[1]); if ($matches[2][0] == '=') { $text = '

' . $text . '

'; } else { $text = '

' . $text . '

'; } $hash = md5($text . microtime()); $this->htmlBlockMap[$hash] = $text; return $hash; } // ################################################################### /** * Converts three stars or dashes (optionally separated by spaces) into * a horizontal rule. */ private function _convertHorizontalRules() { $hash = md5('
' . microtime()); $count = 0; $this->text = preg_replace('/((-|\*) ?){3,}/', $hash, $this->text, -1, $count); if ($count > 0) { $this->htmlBlockMap[$hash] = '
'; } } // ################################################################### /** * Wraps blocks into paragraphs */ private function _formatParagraphs() { $blocks = preg_split('/\n{2,}/', $this->text, -1, PREG_SPLIT_NO_EMPTY); foreach ($blocks AS $key => $value) { if (!isset($this->htmlBlockMap[$value])) { $blocks[$key] = "

$value

"; } } $this->text = implode("\n\n", $blocks); } // ################################################################### /** * Converts two spaces followed by a new line with text on it to * a hard line break (
) */ private function _convertHardLineBreaks() { $this->text = preg_replace('/ {2,}\n/m', "
\n", $this->text); } // ################################################################### /** * Converts all angle brackets and ampersands that are floating into * HTML entities */ private function _convertFloatingEntities() { // encode ampersands $this->text = preg_replace('/&(?!#?x?[0-9a-z]+;)/i', '&', $this->text); // encode brackets who aren't followed by text $this->text = preg_replace('#<(?![/?a-z])#i', '<', $this->text); } } /*=====================================================================*\ || ################################################################### || # $HeadURL$ || # $Id$ || ################################################################### \*=====================================================================*/ ?>