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|noscript|form|fieldset|iframe|math|ins|del'; $block_tags_b = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|'. 'script|noscript|form|fieldset|iframe|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]*
( # $4
(['\"]) # quote char = $5
(.*?) # Title = $6
\\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: ![alt text](url "optional title")
# 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("{
(?:\\n\\n|\\A)
( # $1 = 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) {
$codeblock = $matches[1];
$codeblock = _EncodeCode(_Outdent($codeblock));
$codeblock = _Detab($codeblock);
# trim leading newlines and trailing whitespace
$codeblock = preg_replace(array('/\A\n+/', '/\s+\z/'), '', $codeblock);
$result = "\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', " ", $bq);
# These leading spaces screw with
\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("@
(`+) # $1 = Opening run of `
(.+?) # $2 = The code block
(?$c content, so we need to fix that:
$bq = preg_replace_callback('{(\s*
.+?
)}sx',
'_DoBlockQuotes_callback2', $bq);
return "\n$bq\n
\n\n";
}
function _DoBlockQuotes_callback2($matches) {
$pre = $matches[1];
$pre = preg_replace('/^ /m', '', $pre);
return $pre;
}
function _FormParagraphs($text) {
#
# Params:
# $text - string to process with html as well).
For more information about Markdown's syntax, see:
` tags inside `
` are no longer
indented in the HTML output.
* PHP Markdown can now be used as a modifier by the Smarty
templating engine. Rename the file to "modifier.markdown.php"
and put it in your smarty plugins folder.
* Now works as a bBlog formatter. Rename the file to
"modifier.markdown.php" and place it in the "bBlog_plugins"
folder.
1.0fc1: Wed 8 Jul 2004
* Greatly simplified the rules for code blocks. No more colons
necessary; if it's indented (4 spaces or 1 tab), it's a code block.
* Unordered list items can now be denoted by any of the following
bullet markers: [*+-]
* Replacing `"` with `"` to fix literal quotes within title
attributes.
1.0b9: Sun 27 Jun 2004
* Replacing `"` with `"` to fix literal quotes within img alt
attributes.
1.0b8: Wed 23 Jun 2004
* In WordPress, solved a bug where PHP Markdown did not deactivate
the paragraph filter, converting all returns to a line break.
The "texturize" filter was being disabled instead.
* Added 'math' tags to block-level tag patterns in `_HashHTMLBlocks()`.
Please disregard all the 'math'-tag related items in 1.0b7.
* Commented out some vestigial code in `_EscapeSpecialChars()`
1.0b7: Sat 12 Jun 2004
* Added 'math' to `$tags_to_skip` pattern, for MathML users.
* Tweaked regex for identifying HTML entities in
`_EncodeAmpsAndAngles()`, so as to allow for the very long entity
names used by MathML. (Thanks to Jacques Distler for the patch.)
* Changed the internals of `_TokenizeHTML` to lower the PHP version
requirement to PHP 4.0.5.
1.0b6: Sun 6 Jun 2004
* Added a WordPress plugin interface. This means that you can
directly put the "markdown.php" file into the "wp-content/plugins"
directory and then activate it from the administrative interface.
* Added a Textile compatibility interface. Rename this file to
"classTextile.php" and it can replace Textile anywhere.
* The title attribute of reference-style links were ignored.
This is now fixed.
* Changed internal variables names so that they begin with `md_`
instead of `g_`. This should reduce the risk of name collision with
other programs.
1.0b5: Sun 2 May 2004
* Workaround for supporting `` and `
` 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:
`