diff --git a/lib/coffeescript/helpers.js b/lib/coffeescript/helpers.js index 7027a43f99..dcbb5bed37 100644 --- a/lib/coffeescript/helpers.js +++ b/lib/coffeescript/helpers.js @@ -1,8 +1,8 @@ // Generated by CoffeeScript 2.0.0-alpha1 (function() { - var buildLocationData, extend, flatten, marked, ref, repeat, syntaxErrorToString; + var buildLocationData, extend, flatten, md, ref, repeat, syntaxErrorToString; - marked = require('marked'); + md = require('markdown-it')(); exports.starts = function(string, literal, start) { return literal === string.substr(start, literal.length); @@ -28,10 +28,10 @@ }; exports.compact = function(array) { - var i, item, len1, results; + var item, j, len1, results; results = []; - for (i = 0, len1 = array.length; i < len1; i++) { - item = array[i]; + for (j = 0, len1 = array.length; j < len1; j++) { + item = array[j]; if (item) { results.push(item); } @@ -65,10 +65,10 @@ }; exports.flatten = flatten = function(array) { - var element, flattened, i, len1; + var element, flattened, j, len1; flattened = []; - for (i = 0, len1 = array.length; i < len1; i++) { - element = array[i]; + for (j = 0, len1 = array.length; j < len1; j++) { + element = array[j]; if ('[object Array]' === Object.prototype.toString.call(element)) { flattened = flattened.concat(flatten(element)); } else { @@ -86,10 +86,10 @@ }; exports.some = (ref = Array.prototype.some) != null ? ref : function(fn) { - var e, i, len1, ref1; + var e, j, len1, ref1; ref1 = this; - for (i = 0, len1 = ref1.length; i < len1; i++) { - e = ref1[i]; + for (j = 0, len1 = ref1.length; j < len1; j++) { + e = ref1[j]; if (fn(e)) { return true; } @@ -98,24 +98,23 @@ }; exports.invertLiterate = function(code) { - var generateRandomToken, i, item, len1, out, ref1, token; - generateRandomToken = function() { - return `${Math.random() * Date.now()}`; - }; - while (token === void 0 || code.indexOf(token) !== -1) { - token = generateRandomToken(); - } - code = code.replace("\t", token); - out = ""; - ref1 = marked.lexer(code, {}); - for (i = 0, len1 = ref1.length; i < len1; i++) { - item = ref1[i]; - if (item.type === 'code') { - out += `${item.text}\n`; + var out; + out = []; + md.renderer.rules = { + code_block: function(tokens, idx) { + var i, j, len1, line, lines, results, startLine; + startLine = tokens[idx].map[0]; + lines = tokens[idx].content.split('\n'); + results = []; + for (i = j = 0, len1 = lines.length; j < len1; i = ++j) { + line = lines[i]; + results.push(out[startLine + i] = line); + } + return results; } - } - out.replace(token, "\t"); - return out; + }; + md.render(code); + return out.join('\n'); }; buildLocationData = function(first, last) { diff --git a/package.json b/package.json index 1c12a0fb88..d6e63245e6 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,6 @@ "underscore": "~1.8.3" }, "dependencies": { - "marked": "~0.3.6" + "markdown-it": "^8.3.1" } } diff --git a/src/helpers.coffee b/src/helpers.coffee index 2c2d823a57..8485e6f01b 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -2,16 +2,7 @@ # the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten # arrays, count characters, that sort of thing. -marked = require 'marked' -# marked.setOptions -# renderer: new marked.Renderer() -# gfm: true -# tables: true -# breaks: false -# pedantic: false -# sanitize: true -# smartLists: true -# smartypants: false +md = require('markdown-it')() # Peek at the beginning of a given string to see if it matches a sequence. exports.starts = (string, literal, start) -> @@ -80,23 +71,18 @@ exports.some = Array::some ? (fn) -> # Simple function for extracting code from Literate CoffeeScript by stripping # out all non-code blocks, producing a string of CoffeeScript code that can -# be compiled “normally.” +# be compiled “normally.” Uses [MarkdownIt](https://markdown-it.github.io/) +# to tell the difference between Markdown and code blocks. exports.invertLiterate = (code) -> - # Create a placeholder for tabs, that isn’t used anywhere in `code`, and then - # re-insert the tabs after code extraction. - generateRandomToken = -> - "#{Math.random() * Date.now()}" - while token is undefined or code.indexOf(token) isnt -1 - token = generateRandomToken() - - code = code.replace "\t", token - # Parse as markdown, discard everything except code blocks. - out = "" - for item in marked.lexer code, {} - out += "#{item.text}\n" if item.type is 'code' - # Put the tabs back in. - out.replace token, "\t" - out + out = [] + md.renderer.rules = + code_block: (tokens, idx) -> + startLine = tokens[idx].map[0] + lines = tokens[idx].content.split '\n' + for line, i in lines + out[startLine + i] = line + md.render code + out.join '\n' # Merge two jison-style location data objects together. # If `last` is not provided, this will simply return `first`. diff --git a/test/literate.litcoffee b/test/literate.litcoffee index df40dff858..5d1f3c5fdd 100644 --- a/test/literate.litcoffee +++ b/test/literate.litcoffee @@ -1,19 +1,18 @@ -Literate CoffeeScript Test --------------------------- +# Literate CoffeeScript Test comment comment test "basic literate CoffeeScript parsing", -> ok yes - + now with a... - + test "broken up indentation", -> - + ... broken up ... do -> - + ... nested block. ok yes @@ -25,36 +24,36 @@ Code must be separated from text by a blank line. The next line is part of the text and will not be executed. fail() - ok yes - + ok yes + Code in `backticks is not parsed` and... test "comments in indented blocks work", -> do -> do -> # Regular comment. - + ### Block comment. ### - + ok yes - -Regular [Markdown](http://example.com/markdown) features, like links + +Regular [Markdown](http://example.com/markdown) features, like links and unordered lists, are fine: - * I - + * I + * Am - + * A - + * List Tabs work too: - test "tabbed code", -> - ok yes + test "tabbed code", -> + ok yes --- @@ -63,11 +62,12 @@ Tabs work too:

- executed = true # should not execute, this is just HTML para, not code! +if true + executed = true # should not execute, this is just HTML para, not code!

- test "should ignore indented sections inside HTML", -> + test "should ignore code blocks inside HTML", -> eq executed, false --- @@ -119,24 +119,8 @@ Tabs work too: --- -This next one probably passes because a string is inoffensive in compiled js, also, can't get `marked` to parse it correctly, and not sure if empty line is permitted between title and reference - This is [an example][id] reference-style link. -[id]: http://example.com/ - - "Optional Title Here" - ---- - - executed = no - -1986. What a great season. - executed = yes - -and test... - - test "should recognise indented code blocks in lists", -> - ok executed +[id]: http://example.com/ "Optional Title Here" --- @@ -148,7 +132,7 @@ and test... and test... - test "should recognise indented code blocks in lists with empty line as separator", -> + test "should recognize indented code blocks in lists with empty line as separator", -> ok executed --- @@ -163,3 +147,11 @@ and test... test "should ignore indented code in escaped list like number", -> eq executed, no +one last test! + + test "block quotes should render correctly", -> + quote = ''' + foo + and bar! + ''' + eq quote, 'foo\n and bar!' diff --git a/test/literate_tabbed.litcoffee b/test/literate_tabbed.litcoffee new file mode 100644 index 0000000000..b3d73e4454 --- /dev/null +++ b/test/literate_tabbed.litcoffee @@ -0,0 +1,157 @@ +# Tabbed Literate CoffeeScript Test + +comment comment + + test "basic literate CoffeeScript parsing", -> + ok yes + +now with a... + + test "broken up indentation", -> + +... broken up ... + + do -> + +... nested block. + + ok yes + +Code must be separated from text by a blank line. + + test "code blocks must be preceded by a blank line", -> + +The next line is part of the text and will not be executed. + fail() + + ok yes + +Code in `backticks is not parsed` and... + + test "comments in indented blocks work", -> + do -> + do -> + # Regular comment. + + ### + Block comment. + ### + + ok yes + +Regular [Markdown](http://example.com/markdown) features, like links +and unordered lists, are fine: + + * I + + * Am + + * A + + * List + +Spaces work too: + + test "spaced code", -> + ok yes + +--- + + # keep track of whether code blocks are executed or not + executed = false + +

+ +if true + executed = true # should not execute, this is just HTML para, not code! + +

+ + test "should ignore code blocks inside HTML", -> + eq executed, false + +--- + +* A list item with a code block: + + test "basic literate CoffeeScript parsing", -> + ok yes + +--- + +* Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + +* Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +--- + +1. This is a list item with two paragraphs. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. Aliquam hendrerit + mi posuere lectus. + + Vestibulum enim wisi, viverra nec, fringilla in, laoreet + vitae, risus. Donec sit amet nisl. Aliquam semper ipsum + sit amet velit. + +2. Suspendisse id sem consectetuer libero luctus adipiscing. + +--- + +1. This is a list item with two paragraphs. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. Aliquam hendrerit + mi posuere lectus. + + Vestibulum enim wisi, viverra nec, fringilla in, laoreet + vitae, risus. Donec sit amet nisl. Aliquam semper ipsum + sit amet velit. + +2. Suspendisse id sem consectetuer libero luctus adipiscing. + +--- + +* A list item with a blockquote: + + > This is a blockquote + > inside a list item. + +--- + +This is [an example][id] reference-style link. +[id]: http://example.com/ "Optional Title Here" + +--- + + executed = no + +1986. What a great season. + + executed = yes + +and test... + + test "should recognize indented code blocks in lists with empty line as separator", -> + ok executed + +--- + + executed = no + +1986\. What a great season. + executed = yes + +and test... + + test "should ignore indented code in escaped list like number", -> + eq executed, no + +one last test! + + test "block quotes should render correctly", -> + quote = ''' + foo + and bar! + ''' + eq quote, 'foo\n\t\tand bar!'