diff --git a/lib/lexer_block/fences.js b/lib/lexer_block/fences.js index 8bd246a..4cba9ab 100644 --- a/lib/lexer_block/fences.js +++ b/lib/lexer_block/fences.js @@ -3,11 +3,13 @@ 'use strict'; -var skipEmptyLines = require('../helpers').skipEmptyLines; +var skipEmptyLines = require('../helpers').skipEmptyLines; +var skipSpaces = require('../helpers').skipSpaces; +var skipChars = require('../helpers').skipChars; module.exports =function fences(state, startLine, endLine, silent) { - var marker, len, params, nextLine, + var marker, len, params, nextLine, mem, pos = state.bMarks[startLine] + state.tShift[startLine], max = state.eMarks[startLine]; @@ -20,43 +22,41 @@ module.exports =function fences(state, startLine, endLine, silent) { } // scan marker length - len = 1; - while (state.src.charCodeAt(++pos) === marker) { - len++; - } + mem = pos; + pos = skipChars(state, pos, marker); + + len = pos - mem; if (len < 3) { return false; } params = state.src.slice(pos, max).trim(); - if (!/\S/.test(params)) { return false; } - // search end of block nextLine = startLine; do { nextLine++; - if (nextLine > endLine) { return false; } + if (nextLine >= endLine) { + // unclosed block should be autoclosed by end of document. + if (state.blkLevel === 0) { + break; + } + return false; + } - pos = state.bMarks[nextLine] + state.tShift[nextLine]; + pos = mem = state.bMarks[nextLine] + state.tShift[nextLine]; max = state.eMarks[nextLine]; - if (pos + 3 > max) { continue; } + if (state.src.charCodeAt(pos) !== marker) { continue; } - // check markers - if (state.src.charCodeAt(pos) !== marker && - state.src.charCodeAt(pos + 1) !== marker && - state.src.charCodeAt(pos + 2) !== marker) { - continue; - } + pos = skipChars(state, pos, marker); - pos += 3; + // closing code fence must be at least as long as the opening one + if (pos - mem < len) { continue; } // make sure tail has spaces only - //pos = pos < max ? skipSpaces(state, pos) : pos; - - // stmd allow any combonation of markers and spaces in tail + pos = skipSpaces(state, pos); if (pos < max) { continue; } @@ -69,7 +69,7 @@ module.exports =function fences(state, startLine, endLine, silent) { state.tokens.push({ type: 'fence', - params: params.split(/\s+/g), + params: params ? params.split(/\s+/g) : [], startLine: startLine + 1, endLine: nextLine }); diff --git a/lib/renderer.js b/lib/renderer.js index 4cf477f..a1ab94d 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -1,13 +1,16 @@ 'use strict'; -function escapeHTML(str) { - return str.replace(/&/g, '&').replace(//g, '>'); +function escapeHtml(str) { + return str.replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); } var MD_UNESCAPE_RE = /\\([!"#$%&\'()*+,.\/:;<=>?@[\\\]^_`{|}~-])/g; -function unescapeMD(str) { +function unescapeMd(str) { return str.replace(MD_UNESCAPE_RE, '$1'); } @@ -40,19 +43,20 @@ rules.bullet_list_close = function (state, token) { rules.code = function (state, token) { var content = joinLines(state, token.startLine, token.endLine).replace(/^ {4}/gm, ''); - state.result += '
' + escapeHTML(content) + '
\n';
+ state.result += '' + escapeHtml(content) + '
\n';
};
rules.fence = function (state, token) {
var content = joinLines(state, token.startLine, token.endLine);
var langMark = '';
+ var langPrefix = state.options.codeLangPrefix || '';
if (token.params.length) {
- langMark = ' class="language-' + escapeHTML(token.params[0]) + '"';
+ langMark = ' class="' + langPrefix + escapeHtml(token.params[0]) + '"';
}
- state.result += '' + escapeHTML(content) + '
\n';
+ state.result += '' + escapeHtml(content) + '
\n';
};
@@ -86,7 +90,7 @@ rules.paragraph_close = function (state, token) {
rules.text = function (state, token) {
- state.result += escapeHTML(unescapeMD(state.src.slice(token.begin, token.end)));
+ state.result += escapeHtml(unescapeMd(state.src.slice(token.begin, token.end)));
};
diff --git a/test/fixtures/remarkable/code/fence_matching.html b/test/fixtures/remarkable/code/fence_matching.html
new file mode 100644
index 0000000..5c8833a
--- /dev/null
+++ b/test/fixtures/remarkable/code/fence_matching.html
@@ -0,0 +1,8 @@
+```
+
+
+`````
+
+````
+
+
diff --git a/test/fixtures/stmd_pending/Code/FenceMatching.markdown b/test/fixtures/remarkable/code/fence_matching.md
similarity index 100%
rename from test/fixtures/stmd_pending/Code/FenceMatching.markdown
rename to test/fixtures/remarkable/code/fence_matching.md
diff --git a/test/fixtures/remarkable/code/fenced_code_blocks.html b/test/fixtures/remarkable/code/fenced_code_blocks.html
new file mode 100644
index 0000000..5452844
--- /dev/null
+++ b/test/fixtures/remarkable/code/fenced_code_blocks.html
@@ -0,0 +1,24 @@
+This is a fenced code block:
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+
+Here is one with tildes:
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+
+More metadata:
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+
+More backticks:
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+
+backticks :: String
+backticks = "`````"
+
+Without an end:
+code with
+no end
+
+
diff --git a/test/fixtures/stmd_pending/Code/FencedCodeBlocks.markdown b/test/fixtures/remarkable/code/fenced_code_blocks.md
similarity index 100%
rename from test/fixtures/stmd_pending/Code/FencedCodeBlocks.markdown
rename to test/fixtures/remarkable/code/fenced_code_blocks.md
diff --git a/test/fixtures/remarked_pending/gfm_code.html b/test/fixtures/remarked_conflicting/code/gfm_code.html
similarity index 100%
rename from test/fixtures/remarked_pending/gfm_code.html
rename to test/fixtures/remarked_conflicting/code/gfm_code.html
diff --git a/test/fixtures/remarked_pending/gfm_code.md b/test/fixtures/remarked_conflicting/code/gfm_code.md
similarity index 100%
rename from test/fixtures/remarked_pending/gfm_code.md
rename to test/fixtures/remarked_conflicting/code/gfm_code.md
diff --git a/test/fixtures/stmd_pending/Code/FenceMatching.html b/test/fixtures/stmd_conflicting/Code/FenceMatching.html
similarity index 100%
rename from test/fixtures/stmd_pending/Code/FenceMatching.html
rename to test/fixtures/stmd_conflicting/Code/FenceMatching.html
diff --git a/test/fixtures/stmd_conflicting/Code/FenceMatching.markdown b/test/fixtures/stmd_conflicting/Code/FenceMatching.markdown
new file mode 100644
index 0000000..d86169a
--- /dev/null
+++ b/test/fixtures/stmd_conflicting/Code/FenceMatching.markdown
@@ -0,0 +1,10 @@
+````abc
+```
+````
+``````blah
+
+`````
+
+````
+
+```````````
diff --git a/test/fixtures/stmd_pending/Code/FencedCodeBlocks.html b/test/fixtures/stmd_conflicting/Code/FencedCodeBlocks.html
similarity index 100%
rename from test/fixtures/stmd_pending/Code/FencedCodeBlocks.html
rename to test/fixtures/stmd_conflicting/Code/FencedCodeBlocks.html
diff --git a/test/fixtures/stmd_conflicting/Code/FencedCodeBlocks.markdown b/test/fixtures/stmd_conflicting/Code/FencedCodeBlocks.markdown
new file mode 100644
index 0000000..6ccc6be
--- /dev/null
+++ b/test/fixtures/stmd_conflicting/Code/FencedCodeBlocks.markdown
@@ -0,0 +1,35 @@
+This is a fenced code block:
+```haskell
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+```
+Here is one with tildes:
+
+~~~ haskell
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+~~~
+
+More metadata:
+
+```haskell numberLines start=50
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+```
+
+More backticks:
+
+```````` haskell
+pairs :: [(Int,Char)]
+pairs = [(x,y) | x <- [0..10], y <- ['a'..'z']]
+
+backticks :: String
+backticks = "`````"
+`````````````
+
+Without an end:
+
+```
+code with
+no end
+
diff --git a/test/remarked.js b/test/remarked.js
index 3a5634c..9a21f30 100644
--- a/test/remarked.js
+++ b/test/remarked.js
@@ -12,6 +12,11 @@ var Remarked = require('../');
describe('remarked', function () {
var md = new Remarked();
+ // Set options, to give output more close to remarked
+ md.set({
+ codeLangPrefix: 'lang-'
+ });
+
utils.addTests(path.join(__dirname, 'fixtures/remarked_ok'), md);
});
diff --git a/test/utils.js b/test/utils.js
index 8ece3cb..b32a63a 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -41,11 +41,11 @@ function addTests(dir, md, skip) {
if (!skip) {
it(base, function () {
- assert.strictEqual(right, md.render(src));
+ assert.strictEqual(md.render(src), right);
});
} else {
it.skip(base, function () {
- assert.strictEqual(right, md.render(src));
+ assert.strictEqual(md.render(src), right);
});
}
}