*/ /** Convert the Markdown text to html format */ class markdown { /** To debug the markdown analyzer, activate the option */ public $debug = false; private $blockid = array ("
"; // Titre2 // ------ $search[] = "/(.+)\\n--+$/Um"; $replace[] = "
"; // SEPARATORS : *** --- ___ * * * - - - _ _ _ // Must be placed before EMPHASIS $search[] = "/^[*_-] ?[*_-] ?[*_-]$/Um"; $replace[] = "
"; $markdown = preg_replace ($search, $replace, $markdown); $textArray = explode ("\n", $markdown); $pos = 0; $html = $this->detectBlock ($textArray, 0, $pos); $html = str_replace ("
", "", $html); $html = str_replace ("", "", $html); $html = trim ($html); return $html; } /** Search and replace in the paragraph on one line */ private function searchReplace ($line) { if ($this->debug) echo "CALL searchReplace ($line)\n"; $search = array (); $replace = array (); // Titles short // == TITRE1 $search[] = "/^==+ (.+)( ==+)?$/Um"; $replace[] = "\n
"; // -- TITRE2 $search[] = "/^--+ (.+)( --+)?$/Um"; $replace[] = "
\n";
// EMPHASIS : _ or * for normal, __ or ** for strong
$search[] = "/__(.+)__/U"; $replace[] = "\\1";
$search[] = "/_(.+)_/U"; $replace[] = "\\1";
$search[] = "/\*\*(.+)\*\*/U"; $replace[] = "\\1";
$search[] = "/\*(.+)\*/U"; $replace[] = "\\1";
// CODE : `code` ->
$search[] = "/\\n?\`((\\n|.)+)\`/Um";
$replace[] = "\\1";
// LINKS (can be relative)
// images
$search[] = "(!\[(.+)\]\((.+)\))";
$replace[] = "";
// [Google Site](http://google.fr/ "With help bubble")
$search[] = "(\[(.+)\]\((.+) \"(.+)\"\))";
$replace[] = "\\1";
// [Google Site](http://google.fr/)
$search[] = "(\[(.+)\]\((.+)\))"; $replace[] = "\\1";
// Automatics links :
//
"; // ##### Title5 $search[] = "/^##### (.+)( +#+)?$/Um"; $replace[] = "
"; // #### Title4 $search[] = "/^#### (.+)( +#+)?$/Um"; $replace[] = "
"; // ### Title3 $search[] = "/^### (.+)( +#+)?$/Um"; $replace[] = "
"; // ## Title2 $search[] = "/^## (.+)( +#+)?$/Um"; $replace[] = "
"; // # Title1 $search[] = "/^# (.+)( +#+)?$/Um"; $replace[] = "
"; return preg_replace ($search, $replace, $line); } /** Return HTML code corresponding to the code block @param array $text The Markdown text to translate split by \n @param integer $depth The depth of current bloc (in number of space) @param integer $pos The start line number of the bloc */ private function typeCode ($text, $depth, &$pos) { if ($this->debug) echo "CALL typeCode (\$text, $depth, $pos)\n"; $posStart = $pos; $content = ""; // End of code block : end of markdown text / depth lighter than $depth while (isset ($text[$pos]) && $this->depth($text[$pos]) >= $depth) { // The Code blocks can't be imbricated if ($pos > $posStart) $content .= "\n"; $content .= substr ($text[$pos], $depth); $pos++; } // Insert Geshi on $content if ($this->debug) echo "RETURN typeCode :
$content\n";
return "$content\n";
}
/** Return HTML code corresponding to the OL block
@param array $text The Markdown text to translate split by \n
@param integer $depth The depth of current bloc (in number of space)
@param integer $pos The start line number of the bloc */
private function typeOL ($text, $depth, &$pos)
{
if ($this->debug) echo "CALL typeOL (\$text, $depth, $pos)\n";
$content = $this->typeOLUL ($text, $depth, $pos, "ol");
if ($this->debug) echo "RETURN typeOL : $content\n";
return $content;
}
/** Return HTML code corresponding to the UL block
@param array $text The Markdown text to translate split by \n
@param integer $depth The depth of current bloc (in number of space)
@param integer $pos The start line number of the bloc */
private function typeUL ($text, $depth, &$pos)
{
if ($this->debug) echo "CALL typeUL (\$text, $depth, $pos)\n";
$content = $this->typeOLUL ($text, $depth, $pos, "ul");
if ($this->debug) echo "RETURN typeUL : $content\n";
return $content;
}
private function typeOLUL ($text, $depth, &$pos, $type)
{
if ($this->debug) echo "CALL typeOLUL (\$text, $depth, $pos, $type)\n";
$content = "";
// End of OL/UL block : end of markdown text / depth lighter than $depth /
// linetype changed
$blockStart = $pos;
$blockContent = "";
while (isset ($text[$pos]) &&
$this->depth($text[$pos]) >= $depth &&
$this->lineType ($text[$pos]) === $type)
{
if ($this->debug)
echo "Start while $pos\n";
if (1)
{
$content .= str_repeat (" ", ($depth+2))."$content
\n"; return "$content
\n"; } /** Detect the type of the text and call the appropriate function * @param array $text The Markdown text to translate split by \n @param integer $depth The depth of current bloc (in number of space) @param integer $pos The start line number of the bloc @return the HTML code */ private function detectBlock ($text, $depth, &$pos) { if ($this->debug) echo "CALL detectBlock (\$text, $depth, $pos)\n"; $content = ""; $blockContent = ""; // detect the type and call the right type function while (isset ($text[$pos])) { if ($this->depth ($text[$pos]) > $depth && $depth === 0) { // New block code if ($this->debug) echo "New block code\n"; $content .= $this->typeCode ($text, $this->depth ($text[$pos]), $pos); continue; } elseif ($this->depth ($text[$pos]) > $depth) { if ($this->debug) echo "CALL DEPTH > MINDEPTH (".$this->depth ($text[$pos]). " > $depth)\n"; $content .= $this->detectBlock ($text, $this->depth ($text[$pos]), $pos); continue; } elseif ($this->depth ($text[$pos]) < $depth) { if ($this->debug) echo "CALL DEPTH > MINDEPTH (".$this->depth ($text[$pos]). " < $depth)\n"; return $content; } $type = $this->lineType ($text[$pos]); $func = "type$type"; if ($this->debug) echo "FROM DETECT : CALL $func (line=".$text[$pos].")\n"; $content .= str_repeat (" ", $depth). $this->$func ($text, $depth, $pos); } return $content; } /** Return the Type of object in the provided line p, ul, ol, code */ private function lineType ($line) { if (! isset ($line{0})) return "NONE"; if (preg_match ("/^[ \t]*[+*-] /", $line) === 1) return "ul"; if (preg_match ("/^[ \t]*[0-9]+\. /", $line) === 1) return "ol"; if (preg_match ("/^( |\t)+/", $line) === 1) return "code"; return "p"; } /** Return the depth of the provided line @param string $line Line to analyze @return the depth of the line */ private function depth ($line) { return strspn ($line, " "); } }