fix(HTMLParser): fix ghCodeBlocks being parsed inside code tags

When using html pre/code tags to wrap github's fenced code block syntax,
showdown would parsed them instead of treating them like plain code.

Closes #229
This commit is contained in:
Estevão Soares dos Santos 2016-01-25 01:04:06 +00:00
parent e8852a83bb
commit 7d0436d210
14 changed files with 131 additions and 27 deletions

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.js.map vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

Binary file not shown.

View File

@ -242,7 +242,8 @@ showdown.Converter = function (converterOptions) {
hashLinkCounts: {}, hashLinkCounts: {},
langExtensions: langExtensions, langExtensions: langExtensions,
outputModifiers: outputModifiers, outputModifiers: outputModifiers,
converter: this converter: this,
ghCodeBlocks: []
}; };
// attacklab: Replace ~ with ~T // attacklab: Replace ~ with ~T

View File

@ -23,6 +23,7 @@ showdown.subParser('githubCodeBlocks', function (text, options, globals) {
text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, language, codeblock) { text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, language, codeblock) {
var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n'; var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
// First parse the github code block
codeblock = showdown.subParser('encodeCode')(codeblock); codeblock = showdown.subParser('encodeCode')(codeblock);
codeblock = showdown.subParser('detab')(codeblock); codeblock = showdown.subParser('detab')(codeblock);
codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
@ -30,13 +31,16 @@ showdown.subParser('githubCodeBlocks', function (text, options, globals) {
codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>'; codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
return showdown.subParser('hashBlock')(codeblock, options, globals); codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
// Since GHCodeblocks can be false positives, we need to
// store the primitive text and the parsed text in a global var,
// and then return a token
return '\n\n~G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
}); });
// attacklab: strip sentinel // attacklab: strip sentinel
text = text.replace(/~0/, ''); text = text.replace(/~0/, '');
text = globals.converter._dispatch('githubCodeBlocks.after', text, options); return globals.converter._dispatch('githubCodeBlocks.after', text, options);
return text;
}); });

View File

@ -15,11 +15,10 @@ showdown.subParser('paragraphs', function (text, options, globals) {
for (var i = 0; i < end; i++) { for (var i = 0; i < end; i++) {
var str = grafs[i]; var str = grafs[i];
// if this is an HTML marker, copy it // if this is an HTML marker, copy it
if (str.search(/~K(\d+)K/g) >= 0) { if (str.search(/~(K|G)(\d+)\1/g) >= 0) {
grafsOut.push(str); grafsOut.push(str);
} else if (str.search(/\S/) >= 0) { } else {
str = showdown.subParser('spanGamut')(str, options, globals); str = showdown.subParser('spanGamut')(str, options, globals);
str = str.replace(/^([ \t]*)/g, '<p>'); str = str.replace(/^([ \t]*)/g, '<p>');
str += '</p>'; str += '</p>';
@ -29,16 +28,37 @@ showdown.subParser('paragraphs', function (text, options, globals) {
/** Unhashify HTML blocks */ /** Unhashify HTML blocks */
end = grafsOut.length; end = grafsOut.length;
console.log(text);
for (i = 0; i < end; i++) { for (i = 0; i < end; i++) {
var blockText = ''; var blockText = '',
grafsOutIt = grafsOut[i],
child = false,
codeFlag = false;
// if this is a marker for an html block... // if this is a marker for an html block...
while (grafsOut[i].search(/~K(\d+)K/) >= 0) { while (grafsOutIt.search(/~(K|G)(\d+)\1/) >= 0) {
blockText = globals.gHtmlBlocks[RegExp.$1]; var delim = RegExp.$1,
blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs num = RegExp.$2;
grafsOut[i] = grafsOut[i].replace(/~K\d+K/, blockText);
}
}
text = globals.converter._dispatch('paragraphs.after', text, options); if (delim === 'K') {
return grafsOut.join('\n\n'); blockText = globals.gHtmlBlocks[num];
} else {
// we need to check if ghBlock is a false positive
blockText = (codeFlag) ? globals.ghCodeBlocks[num].text : globals.ghCodeBlocks[num].codeblock;
}
blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
grafsOutIt = grafsOutIt.replace(/(\n\n)?~(K|G)\d+\2(\n\n)?/, blockText);
// Check if grafsOutIt is a pre->code
if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
codeFlag = true;
}
child = true;
}
grafsOut[i] = grafsOutIt;
}
text = grafsOut.join('\n\n');
// Strip leading and trailing lines:
text = text.replace(/^\n+/g, '');
text = text.replace(/\n+$/g, '');
return globals.converter._dispatch('paragraphs.after', text, options);
}); });

View File

@ -2,6 +2,5 @@
<li><p>A list item with code:</p> <li><p>A list item with code:</p>
<pre><code>alert('Hello world!'); <pre><code>alert('Hello world!');
</code></pre> </code></pre></li>
</li>
</ul> </ul>

View File

@ -5,14 +5,12 @@
<pre><code class="sh language-sh">$ git clone thing.git <pre><code class="sh language-sh">$ git clone thing.git
dfgdfg dfgdfg
</code></pre> </code></pre></li>
</li>
<li> <li>
<p>I am another thing!</p> <p>I am another thing!</p>
<pre><code class="sh language-sh">$ git clone other-thing.git <pre><code class="sh language-sh">$ git clone other-thing.git
foobar foobar
</code></pre> </code></pre></li>
</li>
</ol> </ol>

View File

@ -0,0 +1,25 @@
<pre lang="no-highlight"><code>
foo
```javascript
var s = "JavaScript syntax highlighting";
alert(s);
```
bar
</code></pre>
<p>this is a long paragraph</p>
<p>this is another long paragraph</p>
<pre lang="no-highlight"><code>```javascript
var s = "JavaScript syntax highlighting";
alert(s);
```
```python
s = "Python syntax highlighting"
print s
```
</code></pre>

View File

@ -0,0 +1,25 @@
<pre lang="no-highlight"><code>
foo
```javascript
var s = "JavaScript syntax highlighting";
alert(s);
```
bar
</code></pre>
this is a long paragraph
this is another long paragraph
<pre lang="no-highlight"><code>```javascript
var s = "JavaScript syntax highlighting";
alert(s);
```
```python
s = "Python syntax highlighting"
print s
```
</code></pre>

View File

@ -0,0 +1,16 @@
<pre lang="no-highlight"><code>
```javascript
var s = "JavaScript syntax highlighting";
alert(s);
```
```python
s = "Python syntax highlighting"
print s
```
```
No language indicated, so no syntax highlighting.
But let's throw in a <b>tag</b>.
```
</code></pre>

View File

@ -0,0 +1,16 @@
<pre lang="no-highlight"><code>
```javascript
var s = "JavaScript syntax highlighting";
alert(s);
```
```python
s = "Python syntax highlighting"
print s
```
```
No language indicated, so no syntax highlighting.
But let's throw in a <b>tag</b>.
```
</code></pre>

View File

@ -1,8 +1,8 @@
<ul> <ul>
<li><p>a list containing a block of code</p> <li>
<p>a list containing a block of code</p>
<pre><code>10 PRINT HELLO INFINITE <pre><code>10 PRINT HELLO INFINITE
20 GOTO 10 20 GOTO 10
</code></pre> </code></pre></li>
</li>
</ul> </ul>