diff --git a/Michelf/Markdown.php b/Michelf/Markdown.php index 5585d3c..405b9e2 100644 --- a/Michelf/Markdown.php +++ b/Michelf/Markdown.php @@ -64,6 +64,9 @@ class Markdown implements MarkdownInterface { # Optional header id="" generation callback function. public $header_id_func = null; + + # Optional function for converting code block content to HTML + public $code_block_content_func = null; # Class attribute to toggle "enhanced ordered list" behaviour # setting this to true will allow ordered lists to start from the index @@ -1024,7 +1027,11 @@ class Markdown implements MarkdownInterface { $codeblock = $matches[1]; $codeblock = $this->outdent($codeblock); - $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + if ($this->code_block_content_func) { + $codeblock = call_user_func($this->code_block_content_func, $codeblock, ""); + } else { + $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + } # trim leading newlines and trailing newlines $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock); diff --git a/Michelf/MarkdownExtra.php b/Michelf/MarkdownExtra.php index 09b0c5a..a6b568f 100644 --- a/Michelf/MarkdownExtra.php +++ b/Michelf/MarkdownExtra.php @@ -42,9 +42,6 @@ class MarkdownExtra extends \Michelf\Markdown { # Class attribute for code blocks goes on the `code` tag; # setting this to true will put attributes on the `pre` tag instead. public $code_attr_on_pre = false; - - # Optional content function for code blocks - public $code_block_content_func = null; # Predefined abbreviations. public $predef_abbr = array(); @@ -138,7 +135,7 @@ class MarkdownExtra extends \Michelf\Markdown { # Expression to use when parsing in a context when no capture is desired protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}'; - protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null) { + protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) { # # Parse attributes caught by the $this->id_class_attr_catch_re expression # and return the HTML-formatted list of attributes. @@ -148,14 +145,13 @@ class MarkdownExtra extends \Michelf\Markdown { # In addition, this method also supports supplying a default Id value, # which will be used to populate the id attribute in case it was not # overridden. - if (empty($attr) && !$defaultIdValue) return ""; + if (empty($attr) && !$defaultIdValue && empty($classes)) return ""; # Split on components preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches); $elements = $matches[0]; # handle classes and ids (only first id taken into account) - $classes = array(); $attributes = array(); $id = false; foreach ($elements as $element) { @@ -352,12 +348,10 @@ class MarkdownExtra extends \Michelf\Markdown { # Fenced code block marker (?<= ^ | \n ) [ ]{0,'.($indent+3).'}(?:~{3,}|`{3,}) - [ ]* - (?: - \.?[-_:a-zA-Z0-9]+ # standalone class name - | - '.$this->id_class_attr_nocatch_re.' # extra attributes - )? + [ ]* + (?: \.?[-_:a-zA-Z0-9]+ )? # standalone class name + [ ]* + (?: '.$this->id_class_attr_nocatch_re.' )? # extra attributes [ ]* (?= \n ) ' : '' ). ' # End (if not is span). @@ -413,7 +407,7 @@ class MarkdownExtra extends \Michelf\Markdown { # Note: need to recheck the whole tag to disambiguate backtick # fences from code spans # - if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) { + if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) { # Fenced code block marker: find matching end marker. $fence_indent = strlen($capture[1]); # use captured indent in re $fence_re = $capture[2]; # use captured fence in re @@ -1333,13 +1327,13 @@ class MarkdownExtra extends \Michelf\Markdown { $codeblock = preg_replace_callback('/^\n+/', array($this, '_doFencedCodeBlocks_newlines'), $codeblock); + $classes = array(); if ($classname != "") { if ($classname{0} == '.') $classname = substr($classname, 1); - $attr_str = ' class="'.$this->code_class_prefix.$classname.'"'; - } else { - $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs); + $classes[] = $this->code_class_prefix.$classname; } + $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes); $pre_attr_str = $this->code_attr_on_pre ? $attr_str : ''; $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str; $codeblock = "
$codeblock";
diff --git a/Readme.md b/Readme.md
index fa7fe58..130874e 100644
--- a/Readme.md
+++ b/Readme.md
@@ -174,6 +174,20 @@ PHP Markdown, please visit [michelf.ca/donate] or send Bitcoin to
Version History
---------------
+Current Version
+
+* For fenced code blocks in Markdown Extra, can now set a class name for the
+ code block's language before the special attribute block. Previously, this
+ class name was only allowed in the absence of the special attribute block.
+
+* Added a `code_block_content_func` configuration variable which takes a
+ function that will convert the content of the code block to HTML. This is
+ most useful for syntax highlighting. For fenced code blocks in Markdown
+ Extra, the function has access to the language class name (the one outside
+ of the special attribute block). Credits to Mario Konrad for providing the
+ implementation.
+
+
PHP Markdown Lib 1.5.0 (1 Mar 2015)
* Added the ability start ordered lists with a number different from 1 and