Skip to content

Commit

Permalink
fix(encodeAmpsAndAngles): fix > and < encoding
Browse files Browse the repository at this point in the history
In some circumstances, > and < were not being encoded properly.

Closes #236
  • Loading branch information
tivie committed Feb 6, 2017
1 parent 3172e06 commit 7f43b79
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 22 deletions.
72 changes: 64 additions & 8 deletions dist/showdown.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/showdown.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions dist/showdown.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/showdown.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/converter.js
Expand Up @@ -302,7 +302,7 @@ showdown.Converter = function (converterOptions) {
text = showdown.subParser('hashPreCodeTags')(text, options, globals);
text = showdown.subParser('githubCodeBlocks')(text, options, globals);
text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
text = showdown.subParser('hashHTMLSpans')(text, options, globals);
text = showdown.subParser('hashCodeTags')(text, options, globals);
text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
text = showdown.subParser('blockGamut')(text, options, globals);
text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
Expand Down
6 changes: 6 additions & 0 deletions src/subParsers/encodeAmpsAndAngles.js
Expand Up @@ -12,6 +12,12 @@ showdown.subParser('encodeAmpsAndAngles', function (text, options, globals) {
// Encode naked <'s
text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');

// Encode <
text = text.replace(/</g, '&lt;');

// Encode >
text = text.replace(/>/g, '&gt;');

text = globals.converter._dispatch('encodeAmpsAndAngles.after', text, options, globals);
return text;
});
42 changes: 37 additions & 5 deletions src/subParsers/hashHTMLSpans.js
Expand Up @@ -5,12 +5,32 @@ showdown.subParser('hashHTMLSpans', function (text, options, globals) {
'use strict';
text = globals.converter._dispatch('hashHTMLSpans.before', text, options, globals);

var matches = showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');

for (var i = 0; i < matches.length; ++i) {
text = text.replace(matches[i][0], '¨C' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'C');
function hashHTMLSpan (html) {
return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
}

// Hash Self Closing tags
text = text.replace(/<[^>]+?\/>/gi, function (wm) {
return hashHTMLSpan(wm);
});

// Hash tags without properties
text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
return hashHTMLSpan(wm);
});

// Hash tags with properties
text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
return hashHTMLSpan(wm);
});

// Hash self closing tags without />
text = text.replace(/<[^>]+?>/gi, function (wm) {
return hashHTMLSpan(wm);
});

/*showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');*/

text = globals.converter._dispatch('hashHTMLSpans.after', text, options, globals);
return text;
});
Expand All @@ -23,7 +43,19 @@ showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);

for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
text = text.replace('¨C' + i + 'C', globals.gHtmlSpans[i]);
var repText = globals.gHtmlSpans[i],
// limiter to prevent infinite loop (assume 10 as limit for recurse)
limit = 0;

while (/¨C(\d+)C/.test(repText)) {
var num = RegExp.$1;
repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
if (limit === 10) {
break;
}
++limit;
}
text = text.replace('¨C' + i + 'C', repText);
}

text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
Expand Down
13 changes: 13 additions & 0 deletions src/subParsers/hashPreCodeTags.js
Expand Up @@ -11,8 +11,21 @@ showdown.subParser('hashPreCodeTags', function (text, options, globals) {
return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
};

// Hash <pre><code>
text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');

text = globals.converter._dispatch('hashPreCodeTags.after', text, options, globals);
return text;
});

showdown.subParser('hashCodeTags', function (text, options, globals) {
'use strict';
text = globals.converter._dispatch('hashCodeTags.before', text, options, globals);
// Hash naked <code>
var matches = showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');
for (var i = 0; i < matches.length; ++i) {
text = text.replace(matches[i][0], '¨C' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'C');
}
text = globals.converter._dispatch('hashCodeTags.after', text, options, globals);
return text;
});
7 changes: 6 additions & 1 deletion src/subParsers/spanGamut.js
Expand Up @@ -19,10 +19,15 @@ showdown.subParser('spanGamut', function (text, options, globals) {
// Must come after _DoAnchors(), because you can use < and >
// delimiters in inline links like [this](<url>).
text = showdown.subParser('autoLinks')(text, options, globals);
text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
text = showdown.subParser('italicsAndBold')(text, options, globals);
text = showdown.subParser('strikethrough')(text, options, globals);

// we need to hash HTML tags inside spans
text = showdown.subParser('hashHTMLSpans')(text, options, globals);

// now we encode amps and angles
text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);

// Do hard breaks
if (options.simpleLineBreaks) {
// GFM style hard breaks
Expand Down
@@ -1,3 +1,3 @@
<h1 id="some-header">some header</h1>
<h1 id="some-header-with--chars">some header with &amp;+$,/:;=?@\"#{}|^~[]`\*()%.!' chars</h1>
<h1 id="another-header--with--chars">another header > with &lt; chars</h1>
<h1 id="another-header--with--chars">another header &gt; with &lt; chars</h1>
5 changes: 5 additions & 0 deletions test/issues/#236.wrong-lt-parsing-when-attached-to-word.html
@@ -0,0 +1,5 @@
<p>this should be <parsed></parsed></p>
<p>this should be <parsed></p>
<p>this should be <parsed/></p>
<p>this should&gt; appear</p>
<p>this text &lt;should appear</p>
9 changes: 9 additions & 0 deletions test/issues/#236.wrong-lt-parsing-when-attached-to-word.md
@@ -0,0 +1,9 @@
this should be <parsed></parsed>

this should be <parsed>

this should be <parsed/>

this should> appear

this text <should appear
2 changes: 1 addition & 1 deletion test/karlcow/ampersand-uri.html
@@ -1 +1 @@
<p>There is an <a href="http://validator.w3.org/check?uri=http://www.w3.org/&amp;verbose=1">ampersand</a> in the URI.</p>
<p>There is an <a href="http://validator.w3.org/check?uri=http://www.w3.org/&verbose=1">ampersand</a> in the URI.</p>

0 comments on commit 7f43b79

Please sign in to comment.