Skip to content

Commit 79fd772

Browse files
committed
Fixed some issues with fenced code blocks.
HTML block parser was confusing backtick fenced code blocks with code spans, which has no consequence most of the time but could be problematic if you're writing code spans inside of the code block. Code span markers are now matched only when backtick fence matching has failed. Fixed an issue were two consecutive fenced code blocks with no blank line between them which was causing the next paragraph to become a code block (with both tilde and backtick fences).
1 parent 85ead87 commit 79fd772

File tree

1 file changed

+30
-24
lines changed

1 file changed

+30
-24
lines changed

markdown.php

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,9 +1996,6 @@ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
19961996
<\?.*?\?> | <%.*?%> # Processing instruction
19971997
|
19981998
<!\[CDATA\[.*?\]\]> # CData Block
1999-
|
2000-
# Code span marker
2001-
`+
20021999
'. ( !$span ? ' # If not in span.
20032000
|
20042001
# Indented code block
@@ -2018,8 +2015,14 @@ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
20182015
'.$this->id_class_attr_nocatch_re.' # extra attributes
20192016
)?
20202017
[ ]*
2021-
\n
2018+
(?= \n )
20222019
' : '' ). ' # End (if not is span).
2020+
|
2021+
# Code span marker
2022+
# Note, this regex needs to go after backtick fenced
2023+
# code blocks but it should also be kept outside of the
2024+
# "if not in span" condition adding backticks to the parser
2025+
`+
20232026
)
20242027
}xs';
20252028

@@ -2061,28 +2064,12 @@ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
20612064
$text = $parts[2]; # Remaining text after current tag.
20622065
$tag_re = preg_quote($tag); # For use in a regular expression.
20632066

2064-
#
2065-
# Check for: Code span marker
2066-
#
2067-
if ($tag{0} == "`") {
2068-
# Find corresponding end marker.
2069-
$tag_re = preg_quote($tag);
2070-
if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
2071-
$text, $matches))
2072-
{
2073-
# End marker found: pass text unchanged until marker.
2074-
$parsed .= $tag . $matches[0];
2075-
$text = substr($text, strlen($matches[0]));
2076-
}
2077-
else {
2078-
# Unmatched marker: just skip it.
2079-
$parsed .= $tag;
2080-
}
2081-
}
20822067
#
20832068
# Check for: Fenced code block marker.
2069+
# Note: need to recheck the whole tag to disambiguate backtick
2070+
# fences from code spans
20842071
#
2085-
else if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~+|`+)}', $tag, $capture)) {
2072+
if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) {
20862073
# Fenced code block marker: find matching end marker.
20872074
$fence_indent = strlen($capture[1]); # use captured indent in re
20882075
$fence_re = $capture[2]; # use captured fence in re
@@ -2107,6 +2094,25 @@ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
21072094
$parsed .= $tag;
21082095
}
21092096
#
2097+
# Check for: Code span marker
2098+
# Note: need to check this after backtick fenced code blocks
2099+
#
2100+
else if ($tag{0} == "`") {
2101+
# Find corresponding end marker.
2102+
$tag_re = preg_quote($tag);
2103+
if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
2104+
$text, $matches))
2105+
{
2106+
# End marker found: pass text unchanged until marker.
2107+
$parsed .= $tag . $matches[0];
2108+
$text = substr($text, strlen($matches[0]));
2109+
}
2110+
else {
2111+
# Unmatched marker: just skip it.
2112+
$parsed .= $tag;
2113+
}
2114+
}
2115+
#
21102116
# Check for: Opening Block level tag or
21112117
# Opening Context Block tag (like ins and del)
21122118
# used as a block tag (tag is alone on it's line).
@@ -2938,7 +2944,7 @@ function doFencedCodeBlocks($text) {
29382944
)
29392945
29402946
# Closing marker.
2941-
\1 [ ]* \n
2947+
\1 [ ]* (?= \n )
29422948
}xm',
29432949
array(&$this, '_doFencedCodeBlocks_callback'), $text);
29442950

0 commit comments

Comments
 (0)