s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded: + $block_tags_a = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|math|ins|del'; + $block_tags_b = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|math'; + + # First, look for nested blocks, e.g.: + #
tags around block-level tags.
+ $text = _HashHTMLBlocks($text);
+
+ $text = _FormParagraphs($text);
+
+ return $text;
+}
+
+
+function _RunSpanGamut($text) {
+#
+# These are all the transformations that occur *within* block-level
+# tags like paragraphs, headers, and list items.
+#
+ global $md_empty_element_suffix;
+ $text = _DoCodeSpans($text);
+
+ # Fix unencoded ampersands and <'s:
+ $text = _EncodeAmpsAndAngles($text);
+
+ # Process anchor and image tags. Images must come first,
+ # because ![foo][f] looks like an anchor.
+ $text = _DoImages($text);
+ $text = _DoAnchors($text);
+
+
+ $text = _DoItalicsAndBold($text);
+
+ # Do hard breaks:
+ $text = preg_replace('/ {2,}\n/', " Just type tags
+#
+ global $md_html_blocks;
+
+ # Strip leading and trailing lines:
+ $text = preg_replace(array('/\A\n+/', '/\n+\z/'), '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+ $count = count($grafs);
+
+ #
+ # Wrap tags.
+ #
+ foreach ($grafs as $key => $value) {
+ if (!isset( $md_html_blocks[$value] )) {
+ $value = _RunSpanGamut($value);
+ $value = preg_replace('/^([ \t]*)/', ' ', $value);
+ $value .= "
or tags.
+# $tags_to_skip = "!<(/?)(?:pre|code|kbd|script|math)[\s>]!";
+
+ foreach ($tokens as $cur_token) {
+ if ($cur_token[0] == 'tag') {
+ # Within tags, encode * and _ so they don't conflict
+ # with their use in Markdown for italics and strong.
+ # We're replacing each such character with its
+ # corresponding MD5 checksum value; this is likely
+ # overkill, but it should prevent us from colliding
+ # with the escape values by accident.
+ $cur_token[1] = str_replace(array('*', '_'),
+ array($md_escape_table['*'], $md_escape_table['_']),
+ $cur_token[1]);
+ $text .= $cur_token[1];
+ } else {
+ $t = $cur_token[1];
+ $t = _EncodeBackslashEscapes($t);
+ $text .= $t;
+ }
+ }
+ return $text;
+}
+
+
+function _DoAnchors($text) {
+#
+# Turn Markdown link shortcuts into XHTML tags.
+#
+ global $md_nested_brackets;
+ #
+ # First, handle reference-style links: [link text] [id]
+ #
+ $text = preg_replace_callback("{
+ ( # wrap whole match in $1
+ \\[
+ ($md_nested_brackets) # link text = $2
+ \\]
+
+ [ ]? # one optional space
+ (?:\\n[ ]*)? # one optional newline followed by spaces
+
+ \\[
+ (.*?) # id = $3
+ \\]
+ )
+ }xs",
+ '_DoAnchors_reference_callback', $text);
+
+ #
+ # Next, inline-style links: [link text](url "optional title")
+ #
+ $text = preg_replace_callback("{
+ ( # wrap whole match in $1
+ \\[
+ ($md_nested_brackets) # link text = $2
+ \\]
+ \\( # literal paren
+ [ \\t]*
+ (.+?)>? # href = $3
+ [ \\t]*
+ ( # title = $4
+ (['\"]) # quote char = $5
+ .*?
+ \\5 # matching quote
+ )? # title is optional
+ \\)
+ )
+ }xs",
+ '_DoAnchors_inline_callback', $text);
+
+ return $text;
+}
+function _DoAnchors_reference_callback($matches) {
+ global $md_urls, $md_titles, $md_escape_table;
+ $whole_match = $matches[1];
+ $link_text = $matches[2];
+ $link_id = strtolower($matches[3]);
+
+ if ($link_id == "") {
+ $link_id = strtolower($link_text); # for shortcut links like [this][].
+ }
+
+ if (isset($md_urls[$link_id])) {
+ $url = $md_urls[$link_id];
+ # We've got to encode these to avoid conflicting with italics/bold.
+ $url = str_replace(array('*', '_'),
+ array($md_escape_table['*'], $md_escape_table['_']),
+ $url);
+ $result = " tags.
+#
+ #
+ # First, handle reference-style labeled images: ![alt text][id]
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ (.*?) # alt text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+
+ )
+ }xs',
+ '_DoImages_reference_callback', $text);
+
+ #
+ # Next, handle inline images: 
+ # Don't forget: encode * and _
+
+ $text = preg_replace_callback("{
+ ( # wrap whole match in $1
+ !\\[
+ (.*?) # alt text = $2
+ \\]
+ \\( # literal paren
+ [ \\t]*
+ (\S+?)>? # src url = $3
+ [ \\t]*
+ ( # $4
+ (['\"]) # quote char = $5
+ (.*?) # title = $6
+ \\5 # matching quote
+ [ \\t]*
+ )? # title is optional
+ \\)
+ )
+ }xs",
+ '_DoImages_inline_callback', $text);
+
+ return $text;
+}
+function _DoImages_reference_callback($matches) {
+ global $md_urls, $md_titles, $md_empty_element_suffix, $md_escape_table;
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $link_id = strtolower($matches[3]);
+
+ if ($link_id == "") {
+ $link_id = strtolower($alt_text); # for shortcut links like ![this][].
+ }
+
+ $alt_text = str_replace('"', '"', $alt_text);
+ if (isset($md_urls[$link_id])) {
+ $url = $md_urls[$link_id];
+ # We've got to encode these to avoid conflicting with italics/bold.
+ $url = str_replace(array('*', '_'),
+ array($md_escape_table['*'], $md_escape_table['_']),
+ $url);
+ $result = "'._RunSpanGamut(_UnslashQuotes('\\1')).'\n\n'",
+ "'
'._RunSpanGamut(_UnslashQuotes('\\1')).'
\n\n'"),
+ $text);
+
+ # atx-style headers:
+ # # Header 1
+ # ## Header 2
+ # ## Header 2 with closing hashes ##
+ # ...
+ # ###### Header 6
+ #
+ $text = preg_replace("{
+ ^(\\#{1,6}) # $1 = string of #'s
+ [ \\t]*
+ (.+?) # $2 = Header text
+ [ \\t]*
+ \\#* # optional closing #'s (not counted)
+ \\n+
+ }xme",
+ "'` blocks.
+#
+ global $md_tab_width;
+ $text = preg_replace_callback("{
+ (.?) # $1 = preceding character
+ (:) # $2 = colon delimiter
+ (\\n+) # $3 = newlines after colon
+ ( # $4 = the code block -- one or more lines, starting with a space/tab
+ (?:
+ (?:[ ]\{$md_tab_width} | \\t) # Lines must start with a tab or a tab-width of spaces
+ .*\\n+
+ )+
+ )
+ ((?=^[ ]{0,$md_tab_width}\\S)|\\Z) # Lookahead for non-space at line-start, or end of doc
+ }xm",
+ '_DoCodeBlocks_callback', $text);
+
+ return $text;
+}
+function _DoCodeBlocks_callback($matches) {
+ $prevchar = $matches[1];
+ $newlines = $matches[2];
+ $codeblock = $matches[4];
+
+ #
+ # Check the preceding character before the ":". If it's not
+ # whitespace, then the ":" remains; if it is whitespace,
+ # the ":" disappears completely, along with the space character.
+ #
+ $prefix = "";
+ if (!(preg_match('/\s/', $prevchar) || ($prevchar == ""))) {
+ $prefix = "$prevchar:";
+ }
+ $codeblock = _EncodeCode(_Outdent($codeblock));
+ $codeblock = _Detab($codeblock);
+ # trim leading newlines and trailing whitespace
+ $codeblock = preg_replace(array('/\A\n+/', '/\s+\z/'), '', $codeblock);
+
+ $result = $prefix . "\n\n";
+}
+
+
+function _EncodeCode($_) {
+#
+# Encode/escape certain characters inside Markdown code runs.
+# The point is that in code, these characters are literals,
+# and lose their special Markdown meanings.
+#
+ global $md_escape_table;
+
+ # Encode all ampersands; HTML entities are not
+ # entities within a Markdown code span.
+ $_ = str_replace('&', '&', $_);
+
+ # Do the angle bracket song and dance:
+ $_ = str_replace(array('<', '>'),
+ array('<', '>'), $_);
+
+ # Now, escape characters that are magic in Markdown:
+ $_ = str_replace(array_keys($md_escape_table),
+ array_values($md_escape_table), $_);
+
+ return $_;
+}
+
+
+function _DoItalicsAndBold($text) {
+ # must go first:
+ $text = preg_replace('{ (\*\*|__) (?=\S) (.+?) (?<=\S) \1 }sx',
+ '\2', $text);
+ # Then :
+ $text = preg_replace('{ (\*|_) (?=\S) (.+?) (?<=\S) \1 }sx',
+ '\2', $text);
+
+ return $text;
+}
+
+
+function _DoBlockQuotes($text) {
+ $text = preg_replace_callback('/
+ ( # Wrap whole match in $1
+ (
+ ^[ \t]*>[ \t]? # ">" at the start of a line
+ .+\n # rest of the first line
+ (.+\n)* # subsequent consecutive lines
+ \n* # blanks
+ )+
+ )
+ /xm',
+ '_DoBlockQuotes_callback', $text);
+
+ return $text;
+}
+function _DoBlockQuotes_callback($matches) {
+ $bq = $matches[1];
+ # trim one level of quoting - trim whitespace-only lines
+ $bq = preg_replace(array('/^[ \t]*>[ \t]?/m', '/^[ \t]+$/m'), '', $bq);
+ $bq = _RunBlockGamut($bq); # recurse
+ $bq = preg_replace('/^/m', "\t", $bq);
+
+ return "
\n\n";
+
+ return $result;
+}
+
+
+function _DoCodeSpans($text) {
+#
+# * Backtick quotes are used for " . $codeblock . "\n spans.
+#
+# * You can use multiple backticks as the delimiters if you want to
+# include literal backticks in the code span. So, this input:
+#
+# Just type ``foo `bar` baz`` at the prompt.
+#
+# Will translate to:
+#
+# foo `bar` baz at the prompt.`bar` ...
+#
+ $text = preg_replace_callback("@
+ (`+) # Opening run of `
+ (.+?) # the code block
+ (?$c\n$bq\n
\n\n";
+}
+
+
+function _FormParagraphs($text) {
+#
+# Params:
+# $text - string to process with html as well).
+
+For more information about Markdown's syntax, see:
+
+
` as block-level tags.
+ This only works if the start and end tags are on lines by
+ themselves.
+
+* Three or more underscores can now be used for horizontal rules.
+
+* Lines containing only whitespace are trimmed from blockquotes.
+
+* You can now optionally wrap URLs with angle brackets -- like so:
+ `