2013-06-03 15:32:55 +02:00
< ?
2013-06-04 19:26:14 +02:00
/*
TM Docs
==================
Description
-----------
This is a tool for auto - generating documentation based on markdown files
located in the / docs folder of the project . To see all of the available
options and to read more about how to use the library , visit the github
repo page :
https :// github . com / justinwalsh / tm - docs
Author
------
Justin Walsh ( Todaymade ) : justin @ todaymade . com , @ justin_walsh
Bugs
----
To file bug reports please create an issue using the github issue tracker :
https :// github . com / justinwalsh / tm - docs / issues
Please include with your report : ( 1 ) the example input ; ( 2 ) the output you
expected ; ( 3 ) the output Markdown actually produced .
Copyright and License
---------------------
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are
met :
* Redistributions of source code must retain the above copyright notice ,
this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
This software is provided by the copyright holders and contributors " as
is " and any express or implied warranties, including, but not limited
to , the implied warranties of merchantability and fitness for a
particular purpose are disclaimed . In no event shall the copyright owner
or contributors be liable for any direct , indirect , incidental , special ,
exemplary , or consequential damages ( including , but not limited to ,
procurement of substitute goods or services ; loss of use , data , or
profits ; or business interruption ) however caused and on any theory of
liability , whether in contract , strict liability , or tort ( including
negligence or otherwise ) arising in any way out of the use of this
software , even if advised of the possibility of such damage .
*/
// Start of Markdown Class *************************************
//////////////////////////////////////////////////////////////
#
# Markdown Extra - A text-to-HTML conversion tool for web writers
#
# PHP Markdown & Extra
# Copyright (c) 2004-2009 Michel Fortin
# <http://michelf.com/projects/php-markdown/>
#
# Original Markdown
# Copyright (c) 2004-2006 John Gruber
# <http://daringfireball.net/projects/markdown/>
#
define ( 'MARKDOWN_VERSION' , " 1.0.1n " ); define ( 'MARKDOWNEXTRA_VERSION' , " 1.2.4 " ); define ( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX' , " /> " ); define ( 'MARKDOWN_TAB_WIDTH' , 4 ); define ( 'MARKDOWN_FN_LINK_TITLE' , " " ); define ( 'MARKDOWN_FN_BACKLINK_TITLE' , " " ); define ( 'MARKDOWN_FN_LINK_CLASS' , " " ); define ( 'MARKDOWN_FN_BACKLINK_CLASS' , " " ); define ( 'MARKDOWN_WP_POSTS' , true ); define ( 'MARKDOWN_WP_COMMENTS' , true ); define ( 'MARKDOWN_PARSER_CLASS' , 'MarkdownExtra_Parser' ); function Markdown ( $text ){ static $parser ; if ( ! isset ( $parser )){ $parser_class = MARKDOWN_PARSER_CLASS ; $parser = new $parser_class ;} return $parser -> transform ( $text );} class Markdown_Parser { var $nested_brackets_depth = 6 ; var $nested_brackets_re ; var $nested_url_parenthesis_depth = 4 ; var $nested_url_parenthesis_re ; var $escape_chars = '\`*_{}[]()>#+-.!' ; var $escape_chars_re ; var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX ; var $tab_width = MARKDOWN_TAB_WIDTH ; var $no_markup = false ; var $no_entities = false ; var $predef_urls = array (); var $predef_titles = array (); function Markdown_Parser (){ $this -> _initDetab (); $this -> prepareItalicsAndBold (); $this -> nested_brackets_re = str_repeat ( '(?>[^\[\]]+|\[' , $this -> nested_brackets_depth ) . str_repeat ( '\])*' , $this -> nested_brackets_depth ); $this -> nested_url_parenthesis_re = str_repeat ( '(?>[^()\s]+|\(' , $this -> nested_url_parenthesis_depth ) . str_repeat ( '(?>\)))*' , $this -> nested_url_parenthesis_depth ); $this -> escape_chars_re = '[' . preg_quote ( $this -> escape_chars ) . ']' ; asort ( $this -> document_gamut ); asort ( $this -> block_gamut ); asort ( $this -> span_gamut );} var $urls = array (); var $titles = array (); var $html_hashes = array (); var $in_anchor = false ; function setup (){ $this -> urls = $this -> predef_urls ; $this -> titles = $this -> predef_titles ; $this -> html_hashes = array (); $in_anchor = false ;} function teardown (){ $this -> urls = array (); $this -> titles = array (); $this -> html_hashes = array ();} function transform ( $text ){ $this -> setup (); $text = preg_replace ( '{^\xEF\xBB\xBF|\x1A}' , '' , $text ); $text = preg_replace ( '{\r\n?}' , " \n " , $text ); $text .= " \n \n " ; $text = $this -> detab ( $text ); $text = $this -> hashHTMLBlocks ( $text ); $text = preg_replace ( '/^[ ]+$/m' , '' , $text ); foreach ( $this -> document_gamut as $method => $priority ){ $text = $this -> $method ( $text );} $this -> teardown (); return $text . " \n " ;} var $document_gamut = array ( " stripLinkDefinitions " => 20 , " runBasicBlockGamut " => 30 ,); function stripLinkDefinitions ( $text ){ $less_than_tab = $this -> tab_width - 1 ; $text = preg_replace_callback ( ' {
^ [ ]{ 0 , '.$less_than_tab.' } \ [( .+ ) \ ][ ] ? : # id = $1
[ ] *
\n ? # maybe *one* newline
[ ] *
( ? :
< ( .+ ? ) > # url = $2
|
( \S + ? ) # url = $3
)
[ ] *
\n ? # maybe one newline
[ ] *
( ? :
( ? <= \s ) # lookbehind for whitespace
[ " (]
( .* ? ) # title = $4
[ " )]
[ ] *
) ? # title is optional
( ? : \n +| \Z )
} xm ',array(&$this,' _stripLinkDefinitions_callback '),$text);return $text;}function _stripLinkDefinitions_callback($matches){$link_id=strtolower($matches[1]);$url=$matches[2]==' '?$matches[3]:$matches[2];$this->urls[$link_id]=$url;$this->titles[$link_id]=&$matches[4];return ' ';}function hashHTMLBlocks($text){if($this->no_markup)return $text;$less_than_tab=$this->tab_width-1;$block_tags_a_re=' ins | del ';$block_tags_b_re=' p | div | h [ 1 - 6 ] | blockquote | pre | table | dl | ol | ul | address | '.' script | noscript | form | fieldset | iframe | math ';$nested_tags_level=4;$attr='
( ?> # optional tag attributes
\s # starts with whitespace
( ?>
[ ^> " /]+ # text outside quotes
|
/+ ( ? !> ) # slash not followed by ">"
|
" [^ " ] * " # text inside double quotes (tolerate " > " )
|
\ ' [ ^ \ ' ] * \ ' # text inside single quotes (tolerate ">")
) *
) ?
';$content=str_repeat('
( ?>
[ ^< ] + # content without tag
|
< \2 # nested opening tag
'.$attr.' # attributes
( ?>
/>
|
> ',$nested_tags_level).' .* ? '.str_repeat('
</ \2\s *> # closing nested tag
)
|
< ( ? !/ \2\s *> # other tags with a different name
)
) * ',$nested_tags_level);$content2=str_replace(' \2 ',' \3 ',$content);$text=preg_replace_callback(' {( ?>
( ?>
( ? <= \n\n ) # Starting after a blank line
| # or
\A\n ? # the beginning of the doc
)
( # save in $1
# Match from `\n<tag>` to `</tag>\n`, handling nested tags
# in between.
[ ]{ 0 , '.$less_than_tab.' }
< ( '.$block_tags_b_re.' ) # start tag = $2
'.$attr.' > # attributes followed by > and \n
'.$content.' # content, support nesting
</ \2 > # the matching end tag
[ ] * # trailing spaces/tabs
( ? = \n +| \Z ) # followed by a newline or end of document
| # Special version for tags of group a.
[ ]{ 0 , '.$less_than_tab.' }
< ( '.$block_tags_a_re.' ) # start tag = $3
'.$attr.' > [ ] * \n # attributes followed by >
'.$content2.' # content, support nesting
</ \3 > # the matching end tag
[ ] * # trailing spaces/tabs
( ? = \n +| \Z ) # followed by a newline or end of document
| # Special case just for <hr />. It was easier to make a special
# case than to make the other regex more complicated.
[ ]{ 0 , '.$less_than_tab.' }
< ( hr ) # start tag = $2
'.$attr.' # attributes
/ ?> # the matching end tag
[ ] *
( ? = \n { 2 ,} | \Z ) # followed by a blank line or end of document
| # Special case for standalone HTML comments:
[ ]{ 0 , '.$less_than_tab.' }
( ? s :
<!-- .* ? -->
)
[ ] *
( ? = \n { 2 ,} | \Z ) # followed by a blank line or end of document
| # PHP and ASP-style processor instructions (<? and <%)
[ ]{ 0 , '.$less_than_tab.' }
( ? s :
< ([ ? % ]) # $2
.* ?
\2 >
)
[ ] *
( ? = \n { 2 ,} | \Z ) # followed by a blank line or end of document
)
)} Sxmi ',array(&$this,' _hashHTMLBlocks_callback '),$text);return $text;}function _hashHTMLBlocks_callback($matches){$text=$matches[1];$key=$this->hashBlock($text);return "\n\n$key\n\n";}function hashPart($text,$boundary=' X '){$text=$this->unhash($text);static $i=0;$key="$boundary\x1A".++$i.$boundary;$this->html_hashes[$key]=$text;return $key;}function hashBlock($text){return $this->hashPart($text,' B ');}var $block_gamut=array("doHeaders"=>10,"doHorizontalRules"=>20,"doLists"=>40,"doCodeBlocks"=>50,"doBlockQuotes"=>60,);function runBlockGamut($text){$text=$this->hashHTMLBlocks($text);return $this->runBasicBlockGamut($text);}function runBasicBlockGamut($text){foreach($this->block_gamut as $method=>$priority){$text=$this->$method($text);}$text=$this->formParagraphs($text);return $text;}function doHorizontalRules($text){return preg_replace(' {
^ [ ]{ 0 , 3 } # Leading space
([ -* _ ]) # $1: First marker
( ?> # Repeated marker group
[ ]{ 0 , 2 } # Zero, one, or two spaces.
\1 # Marker character
){ 2 ,} # Group repeated at least twice
[ ] * # Tailing spaces
$ # End of line.
} mx ',"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",$text);}var $span_gamut=array("parseSpan"=>-30,"doImages"=>10,"doAnchors"=>20,"doAutoLinks"=>30,"encodeAmpsAndAngles"=>40,"doItalicsAndBold"=>50,"doHardBreaks"=>60,);function runSpanGamut($text){foreach($this->span_gamut as $method=>$priority){$text=$this->$method($text);}return $text;}function doHardBreaks($text){return preg_replace_callback(' / { 2 ,} \n / ',array(&$this,' _doHardBreaks_callback '),$text);}function _doHardBreaks_callback($matches){return $this->hashPart("<br$this->empty_element_suffix\n");}function doAnchors($text){if($this->in_anchor)return $text;$this->in_anchor=true;$text=preg_replace_callback(' {
( # wrap whole match in $1
\ [
( '.$this->nested_brackets_re.' ) # link text = $2
\ ]
[ ] ? # one optional space
( ? : \n [ ] * ) ? # one optional newline followed by spaces
\ [
( .* ? ) # id = $3
\ ]
)
} xs ',array(&$this,' _doAnchors_reference_callback '),$text);$text=preg_replace_callback(' {
( # wrap whole match in $1
\ [
( '.$this->nested_brackets_re.' ) # link text = $2
\ ]
\ ( # literal paren
[ \n ] *
( ? :
< ( .+ ? ) > # href = $3
|
( '.$this->nested_url_parenthesis_re.' ) # href = $4
)
[ \n ] *
( # $5
([ \ ' " ]) # quote char = $ 6
( .* ? ) # Title = $7
\6 # matching quote
[ \n ] * # ignore any spaces/tabs between closing quote and )
) ? # title is optional
\ )
)
} xs ',array(&$this,' _doAnchors_inline_callback '),$text);$text=preg_replace_callback(' {
( # wrap whole match in $1
\ [
([ ^ \ [ \ ]] + ) # link text = $2; can\'t contain [ or ]
\ ]
)
} xs ',array(&$this,' _doAnchors_reference_callback '),$text);$this->in_anchor=false;return $text;}function _doAnchors_reference_callback($matches){$whole_match=$matches[1];$link_text=$matches[2];$link_id=&$matches[3];if($link_id==""){$link_id=$link_text;}$link_id=strtolower($link_id);$link_id=preg_replace(' {[ ] ? \n } ',' ',$link_id);if(isset($this->urls[$link_id])){$url=$this->urls[$link_id];$url=$this->encodeAttribute($url);$result="<a href=\"$url\"";if(isset($this->titles[$link_id])){$title=$this->titles[$link_id];$title=$this->encodeAttribute($title);$result.=" title=\"$title\"";}$link_text=$this->runSpanGamut($link_text);$result.=">$link_text</a>";$result=$this->hashPart($result);}else {$result=$whole_match;}return $result;}function _doAnchors_inline_callback($matches){$whole_match=$matches[1];$link_text=$this->runSpanGamut($matches[2]);$url=$matches[3]==' '?$matches[4]:$matches[3];$title=&$matches[7];$url=$this->encodeAttribute($url);$result="<a href=\"$url\"";if(isset($title)){$title=$this->encodeAttribute($title);$result.=" title=\"$title\"";}$link_text=$this->runSpanGamut($link_text);$result.=">$link_text</a>";return $this->hashPart($result);}function doImages($text){$text=preg_replace_callback(' {
( # wrap whole match in $1
! \ [
( '.$this->nested_brackets_re.' ) # alt text = $2
\ ]
[ ] ? # one optional space
( ? : \n [ ] * ) ? # one optional newline followed by spaces
\ [
( .* ? ) # id = $3
\ ]
)
} xs ',array(&$this,' _doImages_reference_callback '),$text);$text=preg_replace_callback(' {
( # wrap whole match in $1
! \ [
( '.$this->nested_brackets_re.' ) # alt text = $2
\ ]
\s ? # One optional whitespace character
\ ( # literal paren
[ \n ] *
( ? :
< ( \S * ) > # src url = $3
|
( '.$this->nested_url_parenthesis_re.' ) # src url = $4
)
[ \n ] *
( # $5
([ \ ' " ]) # quote char = $ 6
( .* ? ) # title = $7
\6 # matching quote
[ \n ] *
) ? # title is optional
\ )
)
} xs ',array(&$this,' _doImages_inline_callback '),$text);return $text;}function _doImages_reference_callback($matches){$whole_match=$matches[1];$alt_text=$matches[2];$link_id=strtolower($matches[3]);if($link_id==""){$link_id=strtolower($alt_text);}$alt_text=$this->encodeAttribute($alt_text);if(isset($this->urls[$link_id])){$url=$this->encodeAttribute($this->urls[$link_id]);$result="<img src=\"$url\" alt=\"$alt_text\"";if(isset($this->titles[$link_id])){$title=$this->titles[$link_id];$title=$this->encodeAttribute($title);$result.=" title=\"$title\"";}$result.=$this->empty_element_suffix;$result=$this->hashPart($result);}else {$result=$whole_match;}return $result;}function _doImages_inline_callback($matches){$whole_match=$matches[1];$alt_text=$matches[2];$url=$matches[3]==' '?$matches[4]:$matches[3];$title=&$matches[7];$alt_text=$this->encodeAttribute($alt_text);$url=$this->encodeAttribute($url);$result="<img src=\"$url\" alt=\"$alt_text\"";if(isset($title)){$title=$this->encodeAttribute($title);$result.=" title=\"$title\"";}$result.=$this->empty_element_suffix;return $this->hashPart($result);}function doHeaders($text){$text=preg_replace_callback(' { ^ ( .+ ? )[ ] * \n ( =+|-+ )[ ] * \n + } mx ',array(&$this,' _doHeaders_callback_setext '),$text);$text=preg_replace_callback(' {
^ ( \ #{1,6}) # $1 = string of #\'s
[ ] *
( .+ ? ) # $2 = Header text
[ ] *
\ #* # optional closing #\'s (not counted)
\n +
} xm ',array(&$this,' _doHeaders_callback_atx '),$text);return $text;}function _doHeaders_callback_setext($matches){if($matches[2]==' - '&&preg_match(' { ^- ( ? : | $ )} ',$matches[1]))return $matches[0];$level=$matches[2]{0}==' = '?1:2;$block="<h$level>".$this->runSpanGamut($matches[1])."</h$level>";return "\n".$this->hashBlock($block)."\n\n";}function _doHeaders_callback_atx($matches){$level=strlen($matches[1]);$block="<h$level>".$this->runSpanGamut($matches[2])."</h$level>";return "\n".$this->hashBlock($block)."\n\n";}function doLists($text){$less_than_tab=$this->tab_width-1;$marker_ul_re=' [ *+- ] ';$marker_ol_re=' \d + [ . ] ';$marker_any_re="(?:$marker_ul_re|$marker_ol_re)";$markers_relist=array($marker_ul_re=>$marker_ol_re,$marker_ol_re=>$marker_ul_re,);foreach($markers_relist as $marker_re=>$other_marker_re){$whole_list_re='
( # $1 = whole list
( # $2
([ ]{ 0 , '.$less_than_tab.' }) # $3 = number of spaces
( '.$marker_re.' ) # $4 = first list item marker
[ ] +
)
( ? s :.+ ? )
( # $5
\z
|
\n { 2 ,}
( ? = \S )
( ? ! # Negative lookahead for another list item marker
[ ] *
'.$marker_re.' [ ] +
)
|
( ? = # Lookahead for another kind of list
\n
\3 # Must have the same indentation
'.$other_marker_re.' [ ] +
)
)
)
';if($this->list_level){$text=preg_replace_callback(' {
^
'.$whole_list_re.'
} mx ',array(&$this,' _doLists_callback '),$text);}else {$text=preg_replace_callback(' {
( ? : ( ? <= \n ) \n | \A\n ? ) # Must eat the newline
'.$whole_list_re.'
} mx ',array(&$this,' _doLists_callback '),$text);}}return $text;}function _doLists_callback($matches){$marker_ul_re=' [ *+- ] ';$marker_ol_re=' \d + [ . ] ';$marker_any_re="(?:$marker_ul_re|$marker_ol_re)";$list=$matches[1];$list_type=preg_match("/$marker_ul_re/",$matches[4])?"ul":"ol";$marker_any_re=($list_type=="ul"?$marker_ul_re:$marker_ol_re);$list.="\n";$result=$this->processListItems($list,$marker_any_re);$result=$this->hashBlock("<$list_type>\n".$result."</$list_type>");return "\n".$result."\n\n";}var $list_level=0;function processListItems($list_str,$marker_any_re){$this->list_level++;$list_str=preg_replace("/\n{2,}\\z/","\n",$list_str);$list_str=preg_replace_callback(' {
( \n ) ? # leading line = $1
( ^ [ ] * ) # leading whitespace = $2
( '.$marker_any_re.' # list marker and space = $3
( ? : [ ] +| ( ? = \n )) # space only required if item is not empty
)
(( ? s :.* ? )) # list item text = $4
( ? : ( \n + ( ? = \n )) | \n ) # tailing blank line = $5
( ? = \n * ( \z | \2 ( '.$marker_any_re.' ) ( ? : [ ] +| ( ? = \n ))))
} xm ',array(&$this,' _processListItems_callback '),$list_str);$this->list_level--;return $list_str;}function _processListItems_callback($matches){$item=$matches[4];$leading_line=&$matches[1];$leading_space=&$matches[2];$marker_space=$matches[3];$tailing_blank_line=&$matches[5];if($leading_line||$tailing_blank_line||preg_match(' / \n { 2 ,} / ',$item)){$item=$leading_space.str_repeat(' ',strlen($marker_space)).$item;$item=$this->runBlockGamut($this->outdent($item)."\n");}else {$item=$this->doLists($this->outdent($item));$item=preg_replace(' / \n + $ / ',' ',$item);$item=$this->runSpanGamut($item);}return "<li>".$item."</li>\n";}function doCodeBlocks($text){$text=preg_replace_callback(' {
( ? : \n\n | \A\n ? )
( # $1 = the code block -- one or more lines, starting with a space/tab
( ?>
[ ]{ '.$this->tab_width.' } # Lines must start with a tab or a tab-width of spaces
.* \n +
) +
)
(( ? =^ [ ]{ 0 , '.$this->tab_width.' } \S ) | \Z ) # Lookahead for non-space at line-start, or end of doc
} xm ',array(&$this,' _doCodeBlocks_callback '),$text);return $text;}function _doCodeBlocks_callback($matches){$codeblock=$matches[1];$codeblock=$this->outdent($codeblock);$codeblock=htmlspecialchars($codeblock,ENT_NOQUOTES);$codeblock=preg_replace(' / \A\n +| \n + \z / ',' ',$codeblock);$codeblock="<pre><code>$codeblock\n</code></pre>";return "\n\n".$this->hashBlock($codeblock)."\n\n";}function makeCodeSpan($code){$code=htmlspecialchars(trim($code),ENT_NOQUOTES);return $this->hashPart("<code>$code</code>");}var $em_relist=array(' '=>' ( ? : ( ? <! \ * ) \ * ( ? ! \ * ) | ( ? <! _ ) _ ( ? ! _ ))( ? = \S | $ )( ? ! [ . , : ;] \s ) ',' * '=>' ( ? <= \S |^ )( ? <! \ * ) \ * ( ? ! \ * ) ',' _ '=>' ( ? <= \S |^ )( ? <! _ ) _ ( ? ! _ ) ',);var $strong_relist=array(' '=>' ( ? : ( ? <! \ * ) \ * \ * ( ? ! \ * ) | ( ? <! _ ) __ ( ? ! _ ))( ? = \S | $ )( ? ! [ . , : ;] \s ) ',' ** '=>' ( ? <= \S |^ )( ? <! \ * ) \ * \ * ( ? ! \ * ) ',' __ '=>' ( ? <= \S |^ )( ? <! _ ) __ ( ? ! _ ) ',);var $em_strong_relist=array(' '=>' ( ? : ( ? <! \ * ) \ * \ * \ * ( ? ! \ * ) | ( ? <! _ ) ___ ( ? ! _ ))( ? = \S | $ )( ? ! [ . , : ;] \s ) ',' *** '=>' ( ? <= \S |^ )( ? <! \ * ) \ * \ * \ * ( ? ! \ * ) ',' ___ '=>' ( ? <= \S |^ )( ? <! _ ) ___ ( ? ! _ ) ',);var $em_strong_prepared_relist;function prepareItalicsAndBold(){foreach($this->em_relist as $em=>$em_re){foreach($this->strong_relist as $strong=>$strong_re){$token_relist=array();if(isset($this->em_strong_relist["$em$strong"])){$token_relist[]=$this->em_strong_relist["$em$strong"];}$token_relist[]=$em_re;$token_relist[]=$strong_re;$token_re=' {( '.implode(' | ',$token_relist).' )} ';$this->em_strong_prepared_relist["$em$strong"]=$token_re;}}}function doItalicsAndBold($text){$token_stack=array(' ');$text_stack=array(' ');$em=' ';$strong=' ';$tree_char_em=false;while(1){$token_re=$this->em_strong_prepared_relist["$em$strong"];$parts=preg_split($token_re,$text,2,PREG_SPLIT_DELIM_CAPTURE);$text_stack[0].=$parts[0];$token=&$parts[1];$text=&$parts[2];if(empty($token)){while($token_stack[0]){$text_stack[1].=array_shift($token_stack);$text_stack[0].=array_shift($text_stack);}break;}$token_len=strlen($token);if($tree_char_em){if($token_len==3){array_shift($token_stack);$span=array_shift($text_stack);$span=$this->runSpanGamut($span);$span="<strong><em>$span</em></strong>";$text_stack[0].=$this->hashPart($span);$em=' ';$strong=' ';}else {$token_stack[0]=str_repeat($token{0},3-$token_len);$tag=$token_len==2?"strong":"em";$span=$text_stack[0];$span=$this->runSpanGamut($span);$span="<$tag>$span</$tag>";$text_stack[0]=$this->hashPart($span);$$tag=' ';}$tree_char_em=false;}else if($token_len==3){if($em){for($i=0;$i<2;++$i){$shifted_token=array_shift($token_stack);$tag=strlen($shifted_token)==2?"strong":"em";$span=array_shift($text_stack);$span=$this->runSpanGamut($span);$span="<$tag>$span</$tag>";$text_stack[0].=$this->hashPart($span);$$tag=' ';}}else {$em=$token{0};$strong="$em$em";array_unshift($token_stack,$token);array_unshift($text_stack,' ');$tree_char_em=true;}}else if($token_len==2){if($strong){if(strlen($token_stack[0])==1){$text_stack[1].=array_shift($token_stack);$text_stack[0].=array_shift($text_stack);}array_shift($token_stack);$span=array_shift($text_stack);$span=$this->runSpanGamut($span);$span="<strong>$span</strong>";$text_stack[0].=$this->hashPart($span);$strong=' ';}else {array_unshift($token_stack,$token);array_unshift($text_stack,' ');$strong=$token;}}else {if($em){if(strlen($token_stack[0])==1){array_shift($token_stack);$span=array_shift($text_stack);$span=$this->runSpanGamut($span);$span="<em>$span</em>";$text_stack[0].=$this->hashPart($span);$em=' ';}else {$text_stack[0].=$token;}}else {array_unshift($token_stack,$token);array_unshift($text_stack,' ');$em=$token;}}}return $text_stack[0];}function doBlockQuotes($text){$text=preg_replace_callback(' /
( # Wrap whole match in $1
( ?>
^ [ ] *> [ ] ? # ">" at the start of a line
.+ \n # rest of the first line
( .+ \n ) * # subsequent consecutive lines
\n * # blanks
) +
)
/ xm ',array(&$this,' _doBlockQuotes_callback '),$text);return $text;}function _doBlockQuotes_callback($matches){$bq=$matches[1];$bq=preg_replace(' /^ [ ] *> [ ] ? |^ [ ] + $ / m ',' ',$bq);$bq=$this->runBlockGamut($bq);$bq=preg_replace(' /^/ m '," ",$bq);$bq=preg_replace_callback(' {( \s *< pre >.+ ? </ pre > )} sx ',array(&$this,' _doBlockQuotes_callback2 '),$bq);return "\n".$this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";}function _doBlockQuotes_callback2($matches){$pre=$matches[1];$pre=preg_replace(' /^ / m ',' ',$pre);return $pre;}function formParagraphs($text){$text=preg_replace(' / \A\n +| \n + \z / ',' ',$text);$grafs=preg_split(' / \n { 2 ,} / ',$text,-1,PREG_SPLIT_NO_EMPTY);foreach($grafs as $key=>$value){if(!preg_match(' /^ B\x1A [ 0 - 9 ] + B $ / ',$value)){$value=$this->runSpanGamut($value);$value=preg_replace(' /^ ([ ] * ) / ',"<p>",$value);$value.="</p>";$grafs[$key]=$this->unhash($value);}else {$graf=$value;$block=$this->html_hashes[$graf];$graf=$block;$grafs[$key]=$graf;}}return implode("\n\n",$grafs);}function encodeAttribute($text){$text=$this->encodeAmpsAndAngles($text);$text=str_replace(' " ','"', $text );return $text ;}function encodeAmpsAndAngles( $text ) { if( $this->no_entities ) { $text = str_replace ( '&' , '&' , $text ); } else { $text = preg_replace ( '/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/' , '&' , $text );; } $text =str_replace('<','<', $text );return $text ;}function doAutoLinks( $text ) { $text = preg_replace_callback ( ' { < (( https ? | ftp | dict ) : [ ^ \ ' " > \ s]+)> } i',array(& $this ,'_doAutoLinks_url_callback'), $text ); $text =preg_replace_callback(' {
<
( ? : mailto : ) ?
(
( ? :
[ -! #$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
|
" .*? "
)
\ @
( ? :
[ - a - z0 - 9 \x80 - \xFF ] + ( \ . [ - a - z0 - 9 \x80 - \xFF ] + ) * \ . [ a - z ] +
|
\ [[ \d . a - fA - F : ] + \ ] # IPv4 & IPv6
)
)
>
} xi ',array(&$this,' _doAutoLinks_email_callback '),$text);return $text;}function _doAutoLinks_url_callback($matches){$url=$this->encodeAttribute($matches[1]);$link="<a href=\"$url\">$url</a>";return $this->hashPart($link);}function _doAutoLinks_email_callback($matches){$address=$matches[1];$link=$this->encodeEmailAddress($address);return $this->hashPart($link);}function encodeEmailAddress($addr){$addr="mailto:".$addr;$chars=preg_split(' / ( ? <!^ )( ? ! $ ) / ',$addr);$seed=(int)abs(crc32($addr)/strlen($addr));foreach($chars as $key=>$char){$ord=ord($char);if($ord<128){$r=($seed*(1+$key))%100;if($r>90&&$char!=' @ ');else if($r<45)$chars[$key]=' & #x'.dechex($ord).';';else $chars[$key]='&#'.$ord.';';}}$addr=implode('',$chars);$text=implode('',array_slice($chars,7));$addr="<a href=\"$addr\">$text</a>";return $addr;}function parseSpan($str){$output='';$span_re='{
(
\\\\ '.$this->escape_chars_re.'
|
( ? <! [ ` \\\\ ])
` + # code span marker
'.($this->no_markup?' ':'
|
<!-- .* ? --> # comment
|
< \ ? .* ? \ ?> | <%.*?%> # processing instruction
|
< [ /! $ ] ? [ - a - zA - Z0 - 9 : _ ] + # regular tags
( ?>
\s
( ?> [^"\'>]+|"[^"]*"|\'[^\']*\')*
) ?
>
').'
)
} xs ';while(1){$parts=preg_split($span_re,$str,2,PREG_SPLIT_DELIM_CAPTURE);if($parts[0]!=""){$output.=$parts[0];}if(isset($parts[1])){$output.=$this->handleSpanToken($parts[1],$parts[2]);$str=$parts[2];}else {break;}}return $output;}function handleSpanToken($token,&$str){switch($token{0}){case "\\":return $this->hashPart("&#".ord($token{1}).";");case "`":if(preg_match(' /^ ( .* ? [ ^ `])'.preg_quote($token).'(?!` )( .* ) $ / sm ',$str,$matches)){$str=$matches[2];$codespan=$this->makeCodeSpan($matches[1]);return $this->hashPart($codespan);}return $token;default:return $this->hashPart($token);}}function outdent($text){return preg_replace(' /^ ( \t | [ ]{ 1 , '.$this->tab_width.' }) / m ',' ',$text);}var $utf8_strlen=' mb_strlen ';function detab($text){$text=preg_replace_callback(' /^.* \t .* $ / m ',array(&$this,' _detab_callback '),$text);return $text;}function _detab_callback($matches){$line=$matches[0];$strlen=$this->utf8_strlen;$blocks=explode("\t",$line);$line=$blocks[0];unset($blocks[0]);foreach($blocks as $block){$amount=$this->tab_width-$strlen($line,' UTF - 8 ')%$this->tab_width;$line.=str_repeat(" ",$amount).$block;}return $line;}function _initDetab(){if(function_exists($this->utf8_strlen))return;$this->utf8_strlen=create_function(' $text ',' return preg_match_all (
" /[ \\ \\ x00- \\ \\ xBF]|[ \\ \\ xC0- \\ \\ xFF][ \\ \\ x80- \\ \\ xBF]*/ " ,
$text , $m ); ');}function unhash($text){return preg_replace_callback(' / ( . ) \x1A [ 0 - 9 ] + \1 / ',array(&$this,' _unhash_callback '),$text);}function _unhash_callback($matches){return $this->html_hashes[$matches[0]];}}class MarkdownExtra_Parser extends Markdown_Parser{var $fn_id_prefix="";var $fn_link_title=MARKDOWN_FN_LINK_TITLE;var $fn_backlink_title=MARKDOWN_FN_BACKLINK_TITLE;var $fn_link_class=MARKDOWN_FN_LINK_CLASS;var $fn_backlink_class=MARKDOWN_FN_BACKLINK_CLASS;var $predef_abbr=array();function MarkdownExtra_Parser(){$this->escape_chars.=' :| ';$this->document_gamut+=array("doFencedCodeBlocks"=>5,"stripFootnotes"=>15,"stripAbbreviations"=>25,"appendFootnotes"=>50,);$this->block_gamut+=array("doFencedCodeBlocks"=>5,"doTables"=>15,"doDefLists"=>45,);$this->span_gamut+=array("doFootnotes"=>5,"doAbbreviations"=>70,);parent::Markdown_Parser();}var $footnotes=array();var $footnotes_ordered=array();var $abbr_desciptions=array();var $abbr_word_re=' ';var $footnote_counter=1;function setup(){parent::setup();$this->footnotes=array();$this->footnotes_ordered=array();$this->abbr_desciptions=array();$this->abbr_word_re=' ';$this->footnote_counter=1;foreach($this->predef_abbr as $abbr_word=>$abbr_desc){if($this->abbr_word_re)$this->abbr_word_re.=' | ';$this->abbr_word_re.=preg_quote($abbr_word);$this->abbr_desciptions[$abbr_word]=trim($abbr_desc);}}function teardown(){$this->footnotes=array();$this->footnotes_ordered=array();$this->abbr_desciptions=array();$this->abbr_word_re=' ';parent::teardown();}var $block_tags_re=' p | div | h [ 1 - 6 ] | blockquote | pre | table | dl | ol | ul | address | form | fieldset | iframe | hr | legend ';var $context_block_tags_re=' script | noscript | math | ins | del ';var $contain_span_tags_re=' p | h [ 1 - 6 ] | li | dd | dt | td | th | legend | address ';var $clean_tags_re=' script | math ';var $auto_close_tags_re=' hr | img ';function hashHTMLBlocks($text){list($text,)=$this->_hashHTMLBlocks_inMarkdown($text);return $text;}function _hashHTMLBlocks_inMarkdown($text,$indent=0,$enclosing_tag_re=' ',$span=false){if($text===' ')return array(' ',' ');$newline_before_re=' / ( ? :^ \n ? | \n\n ) * $ / ';$newline_after_re=' {
^ # Start of text following the tag.
( ?> [ ]*<!--.*?-->)? # Optional comment.
[ ] * \n # Must be followed by newline.
} xs ';$block_tag_re=' {
( # $2: Capture hole tag.
</ ? # Any opening or closing tag.
( ?> # Tag name.
'.$this->block_tags_re.' |
'.$this->context_block_tags_re.' |
'.$this->clean_tags_re.' |
( ? ! \s ) '.$enclosing_tag_re.'
)
( ? :
( ? = [ \s " \ '/a-zA-Z0-9]) # Allowed characters after tag name.
( ?>
" .*? " | # Double quotes (can contain `>`)
\ ' .* ? \ ' | # Single quotes (can contain `>`)
.+ ? # Anything but quotes and `>`.
) * ?
) ?
> # End of tag.
|
<!-- .* ? --> # HTML Comment
|
< \ ? .* ? \ ?> | <%.*?%> # Processing instruction
|
<! \ [ CDATA\ [ .* ? \ ] \ ] > # CData Block
|
# Code span marker
` +
'.(!$span?' # If not in span.
|
# Indented code block
( ? : ^ [ ] * \n | ^ | \n [ ] * \n )
[ ]{ '.($indent+4).' }[ ^ \n ] * \n
( ?>
( ? : [ ]{ '.($indent+4).' }[ ^ \n ] * | [ ] * ) \n
) *
|
# Fenced code block marker
( ?> ^ | \n )
[ ]{ '.($indent).' } ~~~+ [ ] * \n
':' ').' # End (if not is span).
)
} xs ';$depth=0;$parsed="";do{$parts=preg_split($block_tag_re,$text,2,PREG_SPLIT_DELIM_CAPTURE);if($span){$void=$this->hashPart("",' : ');$newline="$void\n";$parts[0]=$void.str_replace("\n",$newline,$parts[0]).$void;}$parsed.=$parts[0];if(count($parts)<3){$text="";break;}$tag=$parts[1];$text=$parts[2];$tag_re=preg_quote($tag);if($tag{0}=="`"){$tag_re=preg_quote($tag);if(preg_match(' { ^ ( ?> .+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',$text,$matches)){$parsed.=$tag.$matches[0];$text=substr($text,strlen($matches[0]));}else {$parsed.=$tag;}}else if($tag{0}=="\n"||$tag{0}==" "){$parsed.=$tag;}else if($tag{0}=="~"){$tag_re=preg_quote(trim($tag));if(preg_match('{^(?>.*\n)+?'.$tag_re.' *\n}',$text,$matches)){$parsed.=$tag.$matches[0];$text=substr($text,strlen($matches[0]));}else {$parsed.=$tag;}}else if(preg_match('{^<(?:'.$this->block_tags_re.')\b}',$tag)||(preg_match('{^<(?:'.$this->context_block_tags_re.')\b}',$tag)&&preg_match($newline_before_re,$parsed)&&preg_match($newline_after_re,$text))){list($block_text,$text)=$this->_hashHTMLBlocks_inHTML($tag.$text,"hashBlock",true);$parsed.="\n\n$block_text\n\n";}else if(preg_match('{^<(?:'.$this->clean_tags_re.')\b}',$tag)||$tag{1}=='!'||$tag{1}=='?'){list($block_text,$text)=$this->_hashHTMLBlocks_inHTML($tag.$text,"hashClean",false);$parsed.=$block_text;}else if($enclosing_tag_re!==''&&preg_match('{^</?(?:'.$enclosing_tag_re.')\b}',$tag)){if($tag{1}=='/')$depth--;else if($tag{strlen($tag)-2}!='/')$depth++;if($depth<0){$text=$tag.$text;break;}$parsed.=$tag;}else {$parsed.=$tag;}}while($depth>=0);return array($parsed,$text);}function _hashHTMLBlocks_inHTML($text,$hash_method,$md_attr){if($text==='')return array('','');$markdown_attr_re='
{
\s * # Eat whitespace before the `markdown` attribute
markdown
\s *= \s *
( ?>
([ " \ ']) # $ 1: quote delimiter
( .* ? ) # $2: attribute value
\1 # matching delimiter
|
([ ^ \s > ] * ) # $3: unquoted attribute value
)
() # $4: make $3 always defined (avoid warnings)
} xs ';$tag_re=' {
( # $2: Capture hole tag.
</ ? # Any opening or closing tag.
[ \w : $ ] + # Tag name.
( ? :
( ? = [ \s " \ '/a-zA-Z0-9]) # Allowed characters after tag name.
( ?>
" .*? " | # Double quotes (can contain `>`)
\ ' .* ? \ ' | # Single quotes (can contain `>`)
.+ ? # Anything but quotes and `>`.
) * ?
) ?
> # End of tag.
|
<!-- .* ? --> # HTML Comment
|
< \ ? .* ? \ ?> | <%.*?%> # Processing instruction
|
<! \ [ CDATA\ [ .* ? \ ] \ ] > # CData Block
)
} xs ';$original_text=$text;$depth=0;$block_text="";$parsed="";if(preg_match(' /^< ([ \w : $ ] * ) \b / ',$text,$matches))$base_tag_name_re=$matches[1];do{$parts=preg_split($tag_re,$text,2,PREG_SPLIT_DELIM_CAPTURE);if(count($parts)<3){return array($original_text{0},substr($original_text,1));}$block_text.=$parts[0];$tag=$parts[1];$text=$parts[2];if(preg_match(' { ^</ ? ( ? : '.$this->auto_close_tags_re.' ) \b } ',$tag)||$tag{1}==' ! '||$tag{1}==' ? '){$block_text.=$tag;}else {if(preg_match(' { ^</ ? '.$base_tag_name_re.' \b } ',$tag)){if($tag{1}==' / ')$depth--;else if($tag{strlen($tag)-2}!=' / ')$depth++;}if($md_attr&&preg_match($markdown_attr_re,$tag,$attr_m)&&preg_match(' /^ 1 | block | span $ / ',$attr_m[2].$attr_m[3])){$tag=preg_replace($markdown_attr_re,' ',$tag);$this->mode=$attr_m[2].$attr_m[3];$span_mode=$this->mode==' span '||$this->mode!=' block '&&preg_match(' { ^< ( ? : '.$this->contain_span_tags_re.' ) \b } ',$tag);if(preg_match(' / ( ? :^| \n )( * ? )( ? ! ) .* ? $ / ',$block_text,$matches)){$strlen=$this->utf8_strlen;$indent=$strlen($matches[1],' UTF - 8 ');}else {$indent=0;}$block_text.=$tag;$parsed.=$this->$hash_method($block_text);preg_match(' /^< ([ \w : $ ] * ) \b / ',$tag,$matches);$tag_name_re=$matches[1];list($block_text,$text)=$this->_hashHTMLBlocks_inMarkdown($text,$indent,$tag_name_re,$span_mode);if($indent>0){$block_text=preg_replace("/^[ ]{1,$indent}/m","",$block_text);}if(!$span_mode)$parsed.="\n\n$block_text\n\n";else $parsed.="$block_text";$block_text="";}else $block_text.=$tag;}}while($depth>0);$parsed.=$this->$hash_method($block_text);return array($parsed,$text);}function hashClean($text){return $this->hashPart($text,' C ');}function doHeaders($text){$text=preg_replace_callback(' {
( ^.+ ? ) # $1: Header text
( ? : [ ] + \ { \ #([-_:a-zA-Z0-9]+)\})? # $2: Id attribute
[ ] * \n ( =+|-+ )[ ] * \n + # $3: Header footer
} mx ',array(&$this,' _doHeaders_callback_setext '),$text);$text=preg_replace_callback(' {
^ ( \ #{1,6}) # $1 = string of #\'s
[ ] *
( .+ ? ) # $2 = Header text
[ ] *
\ #* # optional closing #\'s (not counted)
( ? : [ ] + \ { \ #([-_:a-zA-Z0-9]+)\})? # id attribute
[ ] *
\n +
} xm ',array(&$this,' _doHeaders_callback_atx '),$text);return $text;}function _doHeaders_attr($attr){if(empty($attr))return "";return " id=\"$attr\"";}function _doHeaders_callback_setext($matches){if($matches[3]==' - '&&preg_match(' { ^- } ',$matches[1]))return $matches[0];$level=$matches[3]{0}==' = '?1:2;$attr=$this->_doHeaders_attr($id=&$matches[2]);$block="<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";return "\n".$this->hashBlock($block)."\n\n";}function _doHeaders_callback_atx($matches){$level=strlen($matches[1]);$attr=$this->_doHeaders_attr($id=&$matches[3]);$block="<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";return "\n".$this->hashBlock($block)."\n\n";}function doTables($text){$less_than_tab=$this->tab_width-1;$text=preg_replace_callback('
{
^ # Start of a line
[ ]{ 0 , '.$less_than_tab.' } # Allowed whitespace.
[ | ] # Optional leading pipe (present)
( .+ ) \n # $1: Header row (at least one pipe)
[ ]{ 0 , '.$less_than_tab.' } # Allowed whitespace.
[ | ] ([ ] * [ -: ] + [ -| : ] * ) \n # $2: Header underline
( # $3: Cells
( ?>
[ ] * # Allowed whitespace.
[ | ] .* \n # Row content.
) *
)
( ? = \n | \Z ) # Stop at final double newline.
} xm ',array(&$this,' _doTable_leadingPipe_callback '),$text);$text=preg_replace_callback('
{
^ # Start of a line
[ ]{ 0 , '.$less_than_tab.' } # Allowed whitespace.
( \S .* [ | ] .* ) \n # $1: Header row (at least one pipe)
[ ]{ 0 , '.$less_than_tab.' } # Allowed whitespace.
([ -: ] + [ ] * [ | ][ -| : ] * ) \n # $2: Header underline
( # $3: Cells
( ?>
.* [ | ] .* \n # Row content
) *
)
( ? = \n | \Z ) # Stop at final double newline.
} xm ',array(&$this,' _DoTable_callback '),$text);return $text;}function _doTable_leadingPipe_callback($matches){$head=$matches[1];$underline=$matches[2];$content=$matches[3];$content=preg_replace(' /^ * [ | ] / m ',' ',$content);return $this->_doTable_callback(array($matches[0],$head,$underline,$content));}function _doTable_callback($matches){$head=$matches[1];$underline=$matches[2];$content=$matches[3];$head=preg_replace(' / [ | ] * $ / m ',' ',$head);$underline=preg_replace(' / [ | ] * $ / m ',' ',$underline);$content=preg_replace(' / [ | ] * $ / m ',' ',$content);$separators=preg_split(' / * [ | ] */ ',$underline);foreach($separators as $n=>$s){if(preg_match(' /^ *-+: * $ / ',$s))$attr[$n]=' align = " right " ';else if(preg_match(' /^ *:-+: * $ / ',$s))$attr[$n]=' align = " center " ';else if(preg_match(' /^ *:-+ * $ / ',$s))$attr[$n]=' align = " left " ';else $attr[$n]=' ';}$head=$this->parseSpan($head);$headers=preg_split(' / * [ | ] */ ',$head);$col_count=count($headers);$text="<table>\n";$text.="<thead>\n";$text.="<tr>\n";foreach($headers as $n=>$header)$text.=" <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";$text.="</tr>\n";$text.="</thead>\n";$rows=explode("\n",trim($content,"\n"));$text.="<tbody>\n";foreach($rows as $row){$row=$this->parseSpan($row);$row_cells=preg_split(' / * [ | ] */ ',$row,$col_count);$row_cells=array_pad($row_cells,$col_count,' ');$text.="<tr>\n";foreach($row_cells as $n=>$cell)$text.=" <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";$text.="</tr>\n";}$text.="</tbody>\n";$text.="</table>";return $this->hashBlock($text)."\n";}function doDefLists($text){$less_than_tab=$this->tab_width-1;$whole_list_re=' ( ?>
( # $1 = whole list
( # $2
[ ]{ 0 , '.$less_than_tab.' }
(( ?> .*\S.*\n)+) # $3 = defined term
\n ?
[ ]{ 0 , '.$less_than_tab.' } : [ ] + # colon starting definition
)
( ? s :.+ ? )
( # $4
\z
|
\n { 2 ,}
( ? = \S )
( ? ! # Negative lookahead for another term
[ ]{ 0 , '.$less_than_tab.' }
( ? : \S .* \n ) + ? # defined term
\n ?
[ ]{ 0 , '.$less_than_tab.' } : [ ] + # colon starting definition
)
( ? ! # Negative lookahead for another definition
[ ]{ 0 , '.$less_than_tab.' } : [ ] + # colon starting definition
)
)
)
) ';$text=preg_replace_callback(' {
( ?> \A\n?|(?<=\n\n))
'.$whole_list_re.'
} mx ',array(&$this,' _doDefLists_callback '),$text);return $text;}function _doDefLists_callback($matches){$list=$matches[1];$result=trim($this->processDefListItems($list));$result="<dl>\n".$result."\n</dl>";return $this->hashBlock($result)."\n\n";}function processDefListItems($list_str){$less_than_tab=$this->tab_width-1;$list_str=preg_replace("/\n{2,}\\z/","\n",$list_str);$list_str=preg_replace_callback(' {
( ?> \A\n?|\n\n+) # leading line
( # definition terms = $1
[ ]{ 0 , '.$less_than_tab.' } # leading whitespace
( ? ! [ : ][ ] | [ ]) # negative lookahead for a definition
# mark (colon) or more whitespace.
( ?> \S.* \n)+? # actual term (not whitespace).
)
( ? = \n ? [ ]{ 0 , 3 } : [ ]) # lookahead for following line feed
# with a definition mark.
} xm ',array(&$this,' _processDefListItems_callback_dt '),$list_str);$list_str=preg_replace_callback(' {
\n ( \n + ) ? # leading line = $1
( # marker space = $2
[ ]{ 0 , '.$less_than_tab.' } # whitespace before colon
[ : ][ ] + # definition mark (colon)
)
(( ? s :.+ ? )) # definition text = $3
( ? = \n + # stop at next definition mark,
( ? : # next term or end of text
[ ]{ 0 , '.$less_than_tab.' } [ : ][ ] |
< dt > | \z
)
)
} xm ',array(&$this,' _processDefListItems_callback_dd '),$list_str);return $list_str;}function _processDefListItems_callback_dt($matches){$terms=explode("\n",trim($matches[1]));$text=' ';foreach($terms as $term){$term=$this->runSpanGamut(trim($term));$text.="\n<dt>".$term."</dt>";}return $text."\n";}function _processDefListItems_callback_dd($matches){$leading_line=$matches[1];$marker_space=$matches[2];$def=$matches[3];if($leading_line||preg_match(' / \n { 2 ,} / ',$def)){$def=str_repeat(' ',strlen($marker_space)).$def;$def=$this->runBlockGamut($this->outdent($def."\n\n"));$def="\n".$def."\n";}else {$def=rtrim($def);$def=$this->runSpanGamut($this->outdent($def));}return "\n<dd>".$def."</dd>\n";}function doFencedCodeBlocks($text){$less_than_tab=$this->tab_width;$text=preg_replace_callback(' {
( ? : \n | \A )
# 1: Opening marker
(
~ { 3 ,} # Marker: three tilde or more.
)
[ ] * \n # Whitespace and newline following marker.
# 2: Content
(
( ?>
( ? ! \1 [ ] * \n ) # Not a closing marker.
.* \n +
) +
)
# Closing marker.
\1 [ ] * \n
} xm ',array(&$this,' _doFencedCodeBlocks_callback '),$text);return $text;}function _doFencedCodeBlocks_callback($matches){$codeblock=$matches[2];$codeblock=htmlspecialchars($codeblock,ENT_NOQUOTES);$codeblock=preg_replace_callback(' /^ \n +/ ',array(&$this,' _doFencedCodeBlocks_newlines '),$codeblock);$codeblock="<pre><code>$codeblock</code></pre>";return "\n\n".$this->hashBlock($codeblock)."\n\n";}function _doFencedCodeBlocks_newlines($matches){return str_repeat("<br$this->empty_element_suffix",strlen($matches[0]));}var $em_relist=array(' '=>' ( ? : ( ? <! \ * ) \ * ( ? ! \ * ) | ( ? <! [ a - zA - Z0 - 9_ ]) _ ( ? ! _ ))( ? = \S | $ )( ? ! [ . , : ;] \s ) ',' * '=>' ( ? <= \S |^ )( ? <! \ * ) \ * ( ? ! \ * ) ',' _ '=>' ( ? <= \S |^ )( ? <! _ ) _ ( ? ! [ a - zA - Z0 - 9_ ]) ',);var $strong_relist=array(' '=>' ( ? : ( ? <! \ * ) \ * \ * ( ? ! \ * ) | ( ? <! [ a - zA - Z0 - 9_ ]) __ ( ? ! _ ))( ? = \S | $ )( ? ! [ . , : ;] \s ) ',' ** '=>' ( ? <= \S |^ )( ? <! \ * ) \ * \ * ( ? ! \ * ) ',' __ '=>' ( ? <= \S |^ )( ? <! _ ) __ ( ? ! [ a - zA - Z0 - 9_ ]) ',);var $em_strong_relist=array(' '=>' ( ? : ( ? <! \ * ) \ * \ * \ * ( ? ! \ * ) | ( ? <! [ a - zA - Z0 - 9_ ]) ___ ( ? ! _ ))( ? = \S | $ )( ? ! [ . , : ;] \s ) ',' *** '=>' ( ? <= \S |^ )( ? <! \ * ) \ * \ * \ * ( ? ! \ * ) ',' ___ '=>' ( ? <= \S |^ )( ? <! _ ) ___ ( ? ! [ a - zA - Z0 - 9_ ]) ',);function formParagraphs($text){$text=preg_replace(' / \A\n +| \n + \z / ',' ',$text);$grafs=preg_split(' / \n { 2 ,} / ',$text,-1,PREG_SPLIT_NO_EMPTY);foreach($grafs as $key=>$value){$value=trim($this->runSpanGamut($value));$is_p=!preg_match(' /^ B\x1A [ 0 - 9 ] + B |^ C\x1A [ 0 - 9 ] + C $ / ',$value);if($is_p){$value="<p>$value</p>";}$grafs[$key]=$value;}$text=implode("\n\n",$grafs);$text=$this->unhash($text);return $text;}function stripFootnotes($text){$less_than_tab=$this->tab_width-1;$text=preg_replace_callback(' {
^ [ ]{ 0 , '.$less_than_tab.' } \ [ \ ^ ( .+ ? ) \ ][ ] ? : # note_id = $1
[ ] *
\n ? # maybe *one* newline
( # text = $2 (no blank lines allowed)
( ? :
.+ # actual text
|
\n # newlines but
( ? ! \ [ \ ^.+ ? \ ] : \s ) # negative lookahead for footnote marker.
( ? ! \n + [ ]{ 0 , 3 } \S ) # ensure line is not blank and followed
# by non-indented content
) *
)
} xm ',array(&$this,' _stripFootnotes_callback '),$text);return $text;}function _stripFootnotes_callback($matches){$note_id=$this->fn_id_prefix.$matches[1];$this->footnotes[$note_id]=$this->outdent($matches[2]);return ' ';}function doFootnotes($text){if(!$this->in_anchor){$text=preg_replace(' { \ [ \ ^ ( .+ ? ) \ ]} ',"F\x1Afn:\\1\x1A:",$text);}return $text;}function appendFootnotes($text){$text=preg_replace_callback(' { F\x1Afn : ( .* ? ) \x1A : } ',array(&$this,' _appendFootnotes_callback '),$text);if(!empty($this->footnotes_ordered)){$text.="\n\n";$text.="<div class=\"footnotes\">\n";$text.="<hr".$this->empty_element_suffix."\n";$text.="<ol>\n\n";$attr=" rev=\"footnote\"";if($this->fn_backlink_class!=""){$class=$this->fn_backlink_class;$class=$this->encodeAttribute($class);$attr.=" class=\"$class\"";}if($this->fn_backlink_title!=""){$title=$this->fn_backlink_title;$title=$this->encodeAttribute($title);$attr.=" title=\"$title\"";}$num=0;while(!empty($this->footnotes_ordered)){$footnote=reset($this->footnotes_ordered);$note_id=key($this->footnotes_ordered);unset($this->footnotes_ordered[$note_id]);$footnote.="\n";$footnote=$this->runBlockGamut("$footnote\n");$footnote=preg_replace_callback(' { F\x1Afn : ( .* ? ) \x1A : } ',array(&$this,' _appendFootnotes_callback '),$footnote);$attr=str_replace("%%",++$num,$attr);$note_id=$this->encodeAttribute($note_id);$backlink="<a href=\"#fnref:$note_id\"$attr>↩</a>";if(preg_match(' { </ p > $ } ',$footnote)){$footnote=substr($footnote,0,-4)." $backlink</p>";}else {$footnote.="\n\n<p>$backlink</p>";}$text.="<li id=\"fn:$note_id\">\n";$text.=$footnote."\n";$text.="</li>\n\n";}$text.="</ol>\n";$text.="</div>";}return $text;}function _appendFootnotes_callback($matches){$node_id=$this->fn_id_prefix.$matches[1];if(isset($this->footnotes[$node_id])){$this->footnotes_ordered[$node_id]=$this->footnotes[$node_id];unset($this->footnotes[$node_id]);$num=$this->footnote_counter++;$attr=" rel=\"footnote\"";if($this->fn_link_class!=""){$class=$this->fn_link_class;$class=$this->encodeAttribute($class);$attr.=" class=\"$class\"";}if($this->fn_link_title!=""){$title=$this->fn_link_title;$title=$this->encodeAttribute($title);$attr.=" title=\"$title\"";}$attr=str_replace("%%",$num,$attr);$node_id=$this->encodeAttribute($node_id);return "<sup id=\"fnref:$node_id\">"."<a href=\"#fn:$node_id\"$attr>$num</a>"."</sup>";}return "[^".$matches[1]."]";}function stripAbbreviations($text){$less_than_tab=$this->tab_width-1;$text=preg_replace_callback(' {
^ [ ]{ 0 , '.$less_than_tab.' } \ * \ [( .+ ? ) \ ][ ] ? : # abbr_id = $1
( .* ) # text = $2 (no blank lines allowed)
} xm ',array(&$this,' _stripAbbreviations_callback '),$text);return $text;}function _stripAbbreviations_callback($matches){$abbr_word=$matches[1];$abbr_desc=$matches[2];if($this->abbr_word_re)$this->abbr_word_re.=' | ';$this->abbr_word_re.=preg_quote($abbr_word);$this->abbr_desciptions[$abbr_word]=trim($abbr_desc);return ' ';}function doAbbreviations($text){if($this->abbr_word_re){$text=preg_replace_callback(' { '.' ( ? <! [ \w\x1A ]) '.' ( ? : '.$this->abbr_word_re.' ) '.' ( ? ! [ \w\x1A ]) '.' } ',array(&$this,' _doAbbreviations_callback '),$text);}return $text;}function _doAbbreviations_callback($matches){$abbr=$matches[0];if(isset($this->abbr_desciptions[$abbr])){$desc=$this->abbr_desciptions[$abbr];if(empty($desc)){return $this->hashPart("<abbr>$abbr</abbr>");}else {$desc=$this->encodeAttribute($desc);return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");}}else {return $matches[0];}}}define(' MARKDOWNEXTRAEXTENDED_VERSION ',"0.3");function MarkdownExtended($text,$default_claases=array()){$parser=new MarkdownExtraExtended_Parser($default_claases);return $parser->transform($text);}class MarkdownExtraExtended_Parser extends MarkdownExtra_Parser{var $block_tags_re=' figure | figcaption | p | div | h [ 1 - 6 ] | blockquote | pre | table | dl | ol | ul | address | form | fieldset | iframe | hr | legend ';var $default_classes;function MarkdownExtraExtended_Parser($default_classes=array()){$default_classes=$default_classes;$this->block_gamut+=array("doFencedFigures"=>7,);parent::MarkdownExtra_Parser();}function transform($text){$text=parent::transform($text);return $text;}function doHardBreaks($text){return preg_replace_callback(' / * \n / ',array(&$this,' _doHardBreaks_callback '),$text);}function doBlockQuotes($text){$text=preg_replace_callback(' /
( ?> ^[ ]*>[ ]?
( ? : \ (( .+ ? ) \ )) ?
[ ] * ( .+ \n ( ? :.+ \n ) * )
) +
/ xm ',array(&$this,' _doBlockQuotes_callback '),$text);return $text;}function _doBlockQuotes_callback($matches){$cite=$matches[1];$bq=' > '.$matches[2];$bq=preg_replace(' /^ [ ] *> [ ] ? |^ [ ] + $ / m ',' ',$bq);$bq=$this->runBlockGamut($bq);$bq=preg_replace(' /^/ m '," ",$bq);$bq=preg_replace_callback(' {( \s *< pre >.+ ? </ pre > )} sx ',array(&$this,' _doBlockQuotes_callback2 '),$bq);$res="<blockquote";$res.=empty($cite)?">":" cite=\"$cite\">";$res.="\n$bq\n</blockquote>";return "\n".$this->hashBlock($res)."\n\n";}function doFencedCodeBlocks($text){$less_than_tab=$this->tab_width;$text=preg_replace_callback(' {
( ? : \n | \A )
# 1: Opening marker
(
~ { 3 ,} | ` { 3 ,} # Marker: three tilde or more.
)
[ ] ? ( \w + ) ? ( ? : ,[ ] ? ( \d + )) ? [ ] * \n # Whitespace and newline following marker.
# 3: Content
(
( ?>
( ? ! \1 [ ] * \n ) # Not a closing marker.
.* \n +
) +
)
# Closing marker.
\1 [ ] * \n
} xm ',array(&$this,' _doFencedCodeBlocks_callback '),$text);return $text;}function _doFencedCodeBlocks_callback($matches){$codeblock=$matches[4];$codeblock=htmlspecialchars($codeblock,ENT_NOQUOTES);$codeblock=preg_replace_callback(' /^ \n +/ ',array(&$this,' _doFencedCodeBlocks_newlines '),$codeblock);$cb=empty($matches[3])?"<pre><code":"<pre class=\"linenums:$matches[3]\"><code";$cb.=empty($matches[2])?">":" class=\"language-$matches[2]\">";$cb.="$codeblock</code></pre>";return "\n\n".$this->hashBlock($cb)."\n\n";}function doFencedFigures($text){$text=preg_replace_callback(' {
( ? : \n | \A )
# 1: Opening marker
(
= { 3 ,} # Marker: equal sign.
)
[ ] ? ( ? : \ [([ ^ \ ]] + ) \ ]) ? [ ] * \n # Whitespace and newline following marker.
# 3: Content
(
( ?>
( ? ! \1 [ ] ? ( ? : \ [([ ^ \ ]] + ) \ ]) ? [ ] * \n ) # Not a closing marker.
.* \n +
) +
)
# Closing marker.
\1 [ ] ? ( ? : \ [([ ^ \ ]] + ) \ ]) ? [ ] * \n
} xm ',array(&$this,' _doFencedFigures_callback '),$text);return $text;}function _doFencedFigures_callback($matches){$topcaption=empty($matches[2])?null:$this->runBlockGamut($matches[2]);$bottomcaption=empty($matches[5])?null:$this->runBlockGamut($matches[5]);$figure=$matches[3];$figure=$this->runBlockGamut($figure);$figure=preg_replace(' /^/ m '," ",$figure);$figure=preg_replace_callback(' {( \s *< pre >.+ ? </ pre > )} sx ',array(&$this,' _doBlockQuotes_callback2 ' ), $figure ); $res = " <figure> " ; if ( ! empty ( $topcaption )){ $res .= " \n <figcaption> $topcaption </figcaption> " ;} $res .= " \n $figure\n " ; if ( ! empty ( $bottomcaption ) && empty ( $topcaption )){ $res .= " <figcaption> $bottomcaption </figcaption> " ;} $res .= " </figure> " ; return " \n " . $this -> hashBlock ( $res ) . " \n \n " ;}}
// End of Markdown Class *************************************
//////////////////////////////////////////////////////////////
$version = '1.0' ;
// TM-Docs Functions
function get_options () {
$options = array (
'title' => " Documentation " ,
'homepage' => false ,
'theme' => 'spacelab' ,
'hightlight' => 'github' ,
'repo' => false ,
'twitter' => array (),
'links' => array ()
);
// Load User Config
$config_file = './docs/config.json' ;
if ( file_exists ( $config_file )) {
$config = json_decode ( file_get_contents ( $config_file ), true );
$options = array_merge ( $options , $config );
}
// Homepage Redirect?
$path = url_path ();
if ( $path === '/' ) {
// Custom Homepage?
if ( $options [ 'homepage' ]) {
header ( 'Location: ' . $options [ 'homepage' ]);
}
}
return $options ;
}
function load_page ( $tree ) {
$branch = find_branch ( $tree );
if ( isset ( $branch [ 'type' ]) && $branch [ 'type' ] == 'file' ) {
$html = '<div class="page-header"><h1>' . $branch [ 'title' ] . '</h1></div>' ;
$html .= MarkdownExtended ( file_get_contents ( $branch [ 'path' ]));
return $html ;
} else {
return " Oh No. That page dosn't exist " ;
}
}
function find_branch ( $tree ) {
$path = url_params ();
foreach ( $path as $peice ) {
if ( isset ( $tree [ $peice ])) {
if ( $tree [ $peice ][ 'type' ] == 'folder' ) {
$tree = $tree [ $peice ][ 'tree' ];
} else {
$tree = $tree [ $peice ];
}
} else {
return false ;
}
}
return $tree ;
}
function url_path () {
$url = parse_url ( $_SERVER [ 'REQUEST_URI' ]);
$url = $url [ 'path' ];
return $url ;
}
function url_params () {
$url = url_path ();
$params = explode ( '/' , trim ( $url , '/' ));
return $params ;
}
function clean_sort ( $text ) {
// Remove .md file extension
$text = str_replace ( '.md' , '' , $text );
// Remove sort placeholder
$parts = explode ( '_' , $text );
if ( isset ( $parts [ 0 ]) && is_numeric ( $parts [ 0 ])) {
unset ( $parts [ 0 ]);
}
$text = implode ( '_' , $parts );
return $text ;
}
function clean_name ( $text ) {
$text = str_replace ( '_' , ' ' , $text );
return $text ;
}
function build_nav ( $tree , $url_params = false ) {
if ( ! is_array ( $url_params )) {
$url_params = url_params ();
}
$url_path = url_path ();
$html = '<ul class="nav nav-list">' ;
foreach ( $tree as $key => $val ) {
// Active Tree Node
if ( isset ( $url_params [ 0 ]) && $url_params [ 0 ] == $val [ 'clean' ]) {
array_shift ( $url_params );
// Final Node
if ( $url_path == $val [ 'url' ]) {
$html .= '<li class="active">' ;
} else {
$html .= '<li class="open">' ;
}
} else {
$html .= '<li>' ;
}
if ( $val [ 'type' ] == 'folder' ) {
$html .= '<a href="#" class="aj-nav folder">' . $val [ 'name' ] . '</a>' ;
$html .= build_nav ( $val [ 'tree' ], $url_params );
} else {
$html .= '<a href="' . $val [ 'url' ] . '">' . $val [ 'name' ] . '</a>' ;
}
$html .= '</li>' ;
}
$html .= '</ul>' ;
return $html ;
}
function get_tree ( $path = '.' , $clean_path = '' , $title = '' ){
$tree = array ();
$ignore = array ( 'config.json' , 'cgi-bin' , '.' , '..' );
$dh = @ opendir ( $path );
$index = 0 ;
// Loop through the directory
while ( false !== ( $file = readdir ( $dh ))){
// Check that this file is not to be ignored
if ( ! in_array ( $file , $ignore )) {
$full_path = " $path / $file " ;
$clean_sort = clean_sort ( $file );
$url = $clean_path . '/' . $clean_sort ;
$clean_name = clean_name ( $clean_sort );
// Title
if ( empty ( $title )) {
$full_title = $clean_name ;
} else {
$full_title = $title . ': ' . $clean_name ;
}
if ( is_dir ( " $path / $file " )) {
// Directory
$tree [ $clean_sort ] = array (
'type' => 'folder' ,
'name' => $clean_name ,
'title' => $full_title ,
'path' => $full_path ,
'clean' => $clean_sort ,
'url' => $url ,
'tree' => get_tree ( $full_path , $url , $full_title )
);
} else {
// File
$tree [ $clean_sort ] = array (
'type' => 'file' ,
'name' => $clean_name ,
'title' => $full_title ,
'path' => $full_path ,
'clean' => $clean_sort ,
'url' => $url ,
);
}
}
$index ++ ;
}
// Close the directory handle
closedir ( $dh );
return $tree ;
}
// App Code
2013-06-03 15:32:55 +02:00
$options = get_options ();
$tree = get_tree ( " docs " );
?>
<! DOCTYPE html >
< html >
< head >
<!-- Bootstrap -->
2013-06-04 19:26:14 +02:00
< link rel = " stylesheet " href = " https://s3.amazonaws.com/todaymade/tools/tm-docs/themes/<?= $options['theme'] ;?>.css " >
2013-06-03 15:32:55 +02:00
< style type = " text/css " >
html , body {
margin : 0 ;
padding : 0 ;
height : 100 % ;
}
. container - fluid {
margin : 0 auto ;
height : 100 % ;
padding : 0 ;
- moz - box - sizing : border - box ;
- webkit - box - sizing : border - box ;
box - sizing : border - box ;
}
. columns {
height : 100 % ;
}
. content - area , . article - tree {
overflow : auto ;
height : 100 % ;
}
li ul {
display : none ;
}
li . open > ul {
display : block ;
}
a . folder {
font - weight : bold ;
}
pre {
padding : 0 ;
}
. footer {
position : fixed ;
bottom : 0 ;
left : 0 ;
padding : 15 px ;
}
2013-06-04 19:26:14 +02:00
#github-ribbon {
position : absolute ;
top : 0 ;
right : 0 ;
}
2013-06-03 15:32:55 +02:00
</ style >
<!-- hightlight . js -->
< link rel = " stylesheet " href = " http://yandex.st/highlightjs/7.3/styles/<?= $options['hightlight'] ;?>.min.css " >
< script src = " http://yandex.st/highlightjs/7.3/highlight.min.js " ></ script >
< script > hljs . initHighlightingOnLoad (); </ script >
<!-- Navigation -->
< script src = " //ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js " ></ script >
< script type = 'text/javascript' >
$ ( function () {
$ ( '.aj-nav' ) . click ( function ( e ) {
e . preventDefault ();
$ ( this ) . parent () . siblings () . find ( 'ul' ) . slideUp ();
$ ( this ) . next () . slideToggle ();
});
2013-06-06 22:20:28 +02:00
// Bootstrap Table Class
$ ( 'table' ) . addClass ( 'table' );
2013-06-03 15:32:55 +02:00
});
</ script >
</ head >
< body >
2013-06-04 19:26:14 +02:00
< ? if ( $options [ 'repo' ]) { ?>
< a href = " https://github.com/<?= $options['repo'] ; ?> " target = " _blank " id = " github-ribbon " >< img src = " https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png " alt = " Fork me on GitHub " ></ a >
< ? } ?>
2013-06-03 15:32:55 +02:00
< div class = " container-fluid wrapper " >
< div class = " navbar navbar-static-top " >
< div class = " navbar-inner " >
< a class = " brand " href = " / " >< ? = $options [ 'title' ]; ?> </a>
</ div >
</ div >
< div class = " row-fluid columns content " >
< div class = " span2 article-tree " >
2013-06-04 19:26:14 +02:00
<!-- Navigation -->
2013-06-03 15:32:55 +02:00
< ? echo build_nav ( $tree ); ?>
2013-06-04 19:26:14 +02:00
<!-- Links -->
< ? if ( ! empty ( $options [ 'links' ])) { ?>
< div class = " well " >
< ? foreach ( $options [ 'links' ] as $name => $url ) { ?>
< a href = " <?= $url ;?> " target = " _blank " >< ? = $name ; ?> </a><br>
< ? } ?>
</ div >
< ? } ?>
<!-- Twitter -->
< ? if ( ! empty ( $options [ 'twitter' ])) { ?>
< ? foreach ( $options [ 'twitter' ] as $handle ) { ?>
< div class = " extra twitter " >
< iframe allowtransparency = " true " frameborder = " 0 " scrolling = " no " style = " width:162px; height:20px; " src = " https://platform.twitter.com/widgets/follow_button.html?screen_name=<?= $handle ;?>&show_count=false " ></ iframe >
</ div >
< ? } ?>
< ? } ?>
2013-06-06 22:20:28 +02:00
<!-- Footer -->
2013-06-03 15:32:55 +02:00
< div class = " footer " > Generate by < a href = " https://github.com/justinwalsh/tm-docs " > TM - Docs </ a ></ div >
</ div >
< div class = " span10 content-area " >
< ? echo load_page ( $tree ); ?>
</ div >
</ div >
</ div >
</ body >
</ html >