From 4a48b4648ce2066c755775ed74c0ed93f1433c89 Mon Sep 17 00:00:00 2001 From: Corey Worrell Date: Fri, 13 Jan 2012 15:51:49 -0800 Subject: [PATCH 1/6] Fixing fenced code blocks to allow classes to be added. Also the newline callback regex seemed to not be working, so I removed the ^ character from before \n. --- markdown.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/markdown.php b/markdown.php index f548fc2..d296dfd 100644 --- a/markdown.php +++ b/markdown.php @@ -2552,9 +2552,13 @@ class MarkdownExtra_Parser extends Markdown_Parser { ( ~{3,} # Marker: three tilde or more. ) + + # 2: CSS classes + \s?(\.[^\n]+)? + [ ]* \n # Whitespace and newline following marker. - # 2: Content + # 3: Content ( (?> (?!\1 [ ]* \n) # Not a closing marker. @@ -2563,18 +2567,26 @@ class MarkdownExtra_Parser extends Markdown_Parser { ) # Closing marker. - \1 [ ]* \n + \1 + + # 4: CSS classes + \s?(\.[^\n]+)? + + # End of line + [ ]* \n }xm', array(&$this, '_doFencedCodeBlocks_callback'), $text); return $text; } function _doFencedCodeBlocks_callback($matches) { - $codeblock = $matches[2]; + $codeblock = $matches[3]; $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); - $codeblock = preg_replace_callback('/^\n+/', + $codeblock = preg_replace_callback('/\n+/', array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); - $codeblock = "
$codeblock
"; + $class = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); + $class = ! empty($class) ? ' class="'.trim($class, '.').'"' : ''; + $codeblock = "$codeblock"; return "\n\n".$this->hashBlock($codeblock)."\n\n"; } function _doFencedCodeBlocks_newlines($matches) { From 9983ec342fee8de41ffa56ea9b6116271770a8d3 Mon Sep 17 00:00:00 2001 From: Corey Worrell Date: Sat, 14 Jan 2012 18:59:13 -0800 Subject: [PATCH 2/6] Fixing CSS class regex. --- markdown.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/markdown.php b/markdown.php index d296dfd..fb4527f 100644 --- a/markdown.php +++ b/markdown.php @@ -2554,7 +2554,7 @@ class MarkdownExtra_Parser extends Markdown_Parser { ) # 2: CSS classes - \s?(\.[^\n]+)? + [ ]*(\.[^\n]+)? [ ]* \n # Whitespace and newline following marker. @@ -2570,7 +2570,7 @@ class MarkdownExtra_Parser extends Markdown_Parser { \1 # 4: CSS classes - \s?(\.[^\n]+)? + [ ]*(\.[^\n]+)? # End of line [ ]* \n @@ -2582,6 +2582,12 @@ class MarkdownExtra_Parser extends Markdown_Parser { function _doFencedCodeBlocks_callback($matches) { $codeblock = $matches[3]; $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + /* + Newlines must be replaced with
's because otherwise extra tabs and spaces will + be shown depending on where the Markdown'ed content appears in the HTML source. This + ensures that code blocks are only a single line in the HTML source and no extra + spaces can appear. + */ $codeblock = preg_replace_callback('/\n+/', array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); $class = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); From c7beca6a4f8a7a3d9b36fafce5905d02a9059486 Mon Sep 17 00:00:00 2001 From: Corey Worrell Date: Sat, 14 Jan 2012 20:53:58 -0800 Subject: [PATCH 3/6] Restoring newline callback to correct original format. --- markdown.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/markdown.php b/markdown.php index fb4527f..e5b2896 100644 --- a/markdown.php +++ b/markdown.php @@ -2582,13 +2582,7 @@ class MarkdownExtra_Parser extends Markdown_Parser { function _doFencedCodeBlocks_callback($matches) { $codeblock = $matches[3]; $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); - /* - Newlines must be replaced with
's because otherwise extra tabs and spaces will - be shown depending on where the Markdown'ed content appears in the HTML source. This - ensures that code blocks are only a single line in the HTML source and no extra - spaces can appear. - */ - $codeblock = preg_replace_callback('/\n+/', + $codeblock = preg_replace_callback('/^\n+/', array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); $class = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); $class = ! empty($class) ? ' class="'.trim($class, '.').'"' : ''; From c50fa5ff5c51681aeb57193bdc1ec29ba62d6d27 Mon Sep 17 00:00:00 2001 From: Corey Worrell Date: Mon, 16 Jan 2012 11:15:05 -0800 Subject: [PATCH 4/6] Adding ability to add attributes to code blocks. See function comment for syntax. --- markdown.php | 63 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/markdown.php b/markdown.php index e5b2896..bef4277 100644 --- a/markdown.php +++ b/markdown.php @@ -2543,6 +2543,14 @@ class MarkdownExtra_Parser extends Markdown_Parser { # ~~~ # Code block # ~~~ + # + # ~~~ #id-here.classname.anotherclass[lang=php] + # Code block + # ~~~ + # + # ~~~ classname anotherclass + # Code block + # ~~~ # $less_than_tab = $this->tab_width; @@ -2553,8 +2561,8 @@ class MarkdownExtra_Parser extends Markdown_Parser { ~{3,} # Marker: three tilde or more. ) - # 2: CSS classes - [ ]*(\.[^\n]+)? + # 2: Attributes + [ ]*([^\n]+)? [ ]* \n # Whitespace and newline following marker. @@ -2569,8 +2577,8 @@ class MarkdownExtra_Parser extends Markdown_Parser { # Closing marker. \1 - # 4: CSS classes - [ ]*(\.[^\n]+)? + # 4: Attributes + [ ]*([^\n]+)? # End of line [ ]* \n @@ -2584,15 +2592,56 @@ class MarkdownExtra_Parser extends Markdown_Parser { $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); $codeblock = preg_replace_callback('/^\n+/', array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); - $class = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); - $class = ! empty($class) ? ' class="'.trim($class, '.').'"' : ''; - $codeblock = "$codeblock"; + $attrs = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); + $attrs = $this->_doFencedCodeBlocks_parseAttrs($attrs); + $codeblock = "$codeblock"; return "\n\n".$this->hashBlock($codeblock)."\n\n"; } function _doFencedCodeBlocks_newlines($matches) { return str_repeat("empty_element_suffix", strlen($matches[0])); } + function _doFencedCodeBlocks_parseAttrs($attrs) { + preg_match_all('/([#\.\[][^#\.\[]+)/', $attrs, $matches); + + if (isset($matches[0]) AND ! empty($matches[0])) { + $list = array(); + $list['class'] = ''; + + foreach ($matches[0] as $match) { + switch($match[0]) { + case '#': + $list['id'] = trim($match, '#'); + break; + + case '.': + $list['class'] .= trim($match, '.').' '; + break; + + case '[': + list($key, $value) = explode('=', trim($match, '[]"\'')); + $list[trim($key)] = trim($value, ' "\''); + break; + } + } + + $attrs = ''; + + foreach ($list as $attr => $value) { + if ( ! empty($value)) { + $attrs .= $attr.'="'.trim($value).'" '; + } + } + + if ( ! empty($attrs)) { + $attrs = ' '.trim($attrs); + } + } elseif ( ! empty($attrs)) { + $attrs = ' class="'.$attrs.'"'; + } + + return $attrs; + } # From 8d00ff92c16e9d5580def87175c631fbeedf65fe Mon Sep 17 00:00:00 2001 From: Corey Worrell Date: Fri, 27 Jan 2012 17:37:43 -0800 Subject: [PATCH 5/6] Updating fenced code blocks as per discussion in issue #7. --- markdown.php | 71 ++++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/markdown.php b/markdown.php index bef4277..81787f5 100644 --- a/markdown.php +++ b/markdown.php @@ -34,6 +34,13 @@ define( 'MARKDOWNEXTRA_VERSION', "1.2.5" ); # Sun 8 Jan 2012 @define( 'MARKDOWN_FN_LINK_CLASS', "" ); @define( 'MARKDOWN_FN_BACKLINK_CLASS', "" ); +# Fenced code block class prefix +@define( 'MARKDOWN_CODE_CLASS_PREFIX', "" ); + +# User-specified class attribute for code blocks goes on the "code" tag, +# but setting this to true will put attributes on the "pre" tag instead +@define( 'MARKDOWN_ATTR_ON_PRE', false ); + # # WordPress settings: @@ -2543,14 +2550,6 @@ class MarkdownExtra_Parser extends Markdown_Parser { # ~~~ # Code block # ~~~ - # - # ~~~ #id-here.classname.anotherclass[lang=php] - # Code block - # ~~~ - # - # ~~~ classname anotherclass - # Code block - # ~~~ # $less_than_tab = $this->tab_width; @@ -2561,15 +2560,15 @@ class MarkdownExtra_Parser extends Markdown_Parser { ~{3,} # Marker: three tilde or more. ) - # 2: Attributes - [ ]*([^\n]+)? + # 2: Attributes or whitespace + ([^\n]*) - [ ]* \n # Whitespace and newline following marker. + \n # Newline following marker. # 3: Content ( (?> - (?!\1 [ ]* \n) # Not a closing marker. + (?!\1 [^\n]* \n) # Not a closing marker. .*\n+ )+ ) @@ -2577,11 +2576,11 @@ class MarkdownExtra_Parser extends Markdown_Parser { # Closing marker. \1 - # 4: Attributes - [ ]*([^\n]+)? + # 4: Attributes or whitespace + ([^\n]*) # End of line - [ ]* \n + \n }xm', array(&$this, '_doFencedCodeBlocks_callback'), $text); @@ -2592,9 +2591,13 @@ class MarkdownExtra_Parser extends Markdown_Parser { $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); $codeblock = preg_replace_callback('/^\n+/', array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); - $attrs = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); - $attrs = $this->_doFencedCodeBlocks_parseAttrs($attrs); - $codeblock = "$codeblock"; + + $attrs = ! empty($matches[2]) ? $matches[2] : ( ! empty($matches[4]) ? $matches[4] : ''); + $attrs = $this->_doFencedCodeBlocks_parseAttrs($attrs); + $pre_attrs = MARKDOWN_ATTR_ON_PRE ? $attrs : ''; + $code_attrs = MARKDOWN_ATTR_ON_PRE ? '' : $attrs; + $codeblock = "$codeblock"; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; } function _doFencedCodeBlocks_newlines($matches) { @@ -2602,45 +2605,43 @@ class MarkdownExtra_Parser extends Markdown_Parser { strlen($matches[0])); } function _doFencedCodeBlocks_parseAttrs($attrs) { - preg_match_all('/([#\.\[][^#\.\[]+)/', $attrs, $matches); + $attrs = trim($attrs, ' {}'); + + if ( ! preg_match_all('/([#\.][^#\.]+)/', $attrs, $matches) AND ! empty($attrs)) + return ' class="'.MARKDOWN_CODE_CLASS_PREFIX.$attrs.'"'; if (isset($matches[0]) AND ! empty($matches[0])) { $list = array(); $list['class'] = ''; foreach ($matches[0] as $match) { - switch($match[0]) { + switch ($match[0]) { case '#': - $list['id'] = trim($match, '#'); + $list['id'] = trim($match, ' #'); break; - case '.': - $list['class'] .= trim($match, '.').' '; - break; - - case '[': - list($key, $value) = explode('=', trim($match, '[]"\'')); - $list[trim($key)] = trim($value, ' "\''); + $list['class'] .= trim($match, ' .').' '; break; } } + if ( ! empty($list['class'])) { + $list['class'] = MARKDOWN_CODE_CLASS_PREFIX.$list['class']; + } + $attrs = ''; foreach ($list as $attr => $value) { if ( ! empty($value)) { - $attrs .= $attr.'="'.trim($value).'" '; + $attrs .= $attr.'="'.trim($this->encodeAttribute($value)).'" '; } } - if ( ! empty($attrs)) { - $attrs = ' '.trim($attrs); - } - } elseif ( ! empty($attrs)) { - $attrs = ' class="'.$attrs.'"'; + if ( ! empty($attrs)) + return ' '.trim($attrs); } - return $attrs; + return ''; } From e90b9127ab79f78a4359a87757d5221ffd6c77e5 Mon Sep 17 00:00:00 2001 From: Corey Worrell Date: Mon, 20 Feb 2012 13:49:34 -0800 Subject: [PATCH 6/6] Updating HTML hashing for fenced code blocks. --- markdown.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown.php b/markdown.php index 81787f5..7984423 100644 --- a/markdown.php +++ b/markdown.php @@ -1892,7 +1892,7 @@ class MarkdownExtra_Parser extends Markdown_Parser { | # Fenced code block marker (?> ^ | \n ) - [ ]{0,'.($indent).'}~~~+[ ]*\n + [ ]{0,'.($indent).'}~~~+[^\n]*\n ' : '' ). ' # End (if not is span). ) }xs';