commonmark
Advanced tools
Comparing version 0.24.0 to 0.25.0
@@ -0,1 +1,21 @@ | ||
[0.25.0] | ||
* [API change] Added abstract renderer; adjusted HTML renderer to use | ||
its prototype (muji, jgm). | ||
* Fix tabs in list indentation (#86). This fixes `advanceOffset` | ||
to better handle cases where a list indent doesn't consume all of | ||
the virtual spaces represented by a tab. | ||
* Proper tab handling with blockquotes, fenced code, lists. | ||
* Fixed handling of partially consumed tabs. | ||
* Fixed logic bug with blank line after empty list item (#78). | ||
* Ensured render directory is installed by npm (muji). | ||
* Better ECMAScript 5 style inheritance (muji). | ||
* Don't require sudo for make bench. | ||
* Added command line usage (Daniel Baird). | ||
* Brought CLI options in line with cmark. Now you say `-t xml` | ||
instead of `--xml`. | ||
* Use minima for cli option parsing, add `--help` (#81). | ||
* Tweaked description of commonmark program. Now that we have `--help` | ||
we can forego a detailed description of options. | ||
[0.24.0] | ||
@@ -2,0 +22,0 @@ |
@@ -64,2 +64,6 @@ "use strict"; | ||
var isSpaceOrTab = function(c) { | ||
return c === C_SPACE || c === C_TAB; | ||
}; | ||
var peek = function(ln, pos) { | ||
@@ -85,3 +89,3 @@ if (pos < ln.length) { | ||
var t = block.type; | ||
if (t === 'List' || t === 'Item') { | ||
if (t === 'list' || t === 'item') { | ||
block = block._lastChild; | ||
@@ -103,3 +107,3 @@ } else { | ||
do { | ||
if (b.type === 'List') { | ||
if (b.type === 'list') { | ||
last_list = b; | ||
@@ -123,2 +127,8 @@ } | ||
var addLine = function() { | ||
if (this.partiallyConsumedTab) { | ||
this.offset += 1; // skip over tab | ||
// add space characters: | ||
var charsToTab = 4 - (this.column % 4); | ||
this.tip._string_content += (' '.repeat(charsToTab)); | ||
} | ||
this.tip._string_content += this.currentLine.slice(this.offset) + '\n'; | ||
@@ -159,7 +169,7 @@ }; | ||
if ((match = rest.match(reBulletListMarker))) { | ||
data.type = 'Bullet'; | ||
data.type = 'bullet'; | ||
data.bulletChar = match[0][0]; | ||
} else if ((match = rest.match(reOrderedListMarker))) { | ||
data.type = 'Ordered'; | ||
data.type = 'ordered'; | ||
data.start = parseInt(match[1]); | ||
@@ -185,3 +195,3 @@ data.delimiter = match[2]; | ||
} while (parser.column - spacesStartCol < 5 && | ||
(nextc === C_SPACE || nextc === C_TAB)); | ||
isSpaceOrTab(nextc)); | ||
var blank_item = peek(parser.currentLine, parser.offset) === -1; | ||
@@ -195,3 +205,3 @@ var spaces_after_marker = parser.column - spacesStartCol; | ||
parser.offset = spacesStartOffset; | ||
if (peek(parser.currentLine, parser.offset) === C_SPACE) { | ||
if (isSpaceOrTab(peek(parser.currentLine, parser.offset))) { | ||
parser.advanceOffset(1, true); | ||
@@ -233,9 +243,9 @@ } | ||
var blocks = { | ||
Document: { | ||
document: { | ||
continue: function() { return 0; }, | ||
finalize: function() { return; }, | ||
canContain: function(t) { return (t !== 'Item'); }, | ||
canContain: function(t) { return (t !== 'item'); }, | ||
acceptsLines: false | ||
}, | ||
List: { | ||
list: { | ||
continue: function() { return 0; }, | ||
@@ -264,6 +274,6 @@ finalize: function(parser, block) { | ||
}, | ||
canContain: function(t) { return (t === 'Item'); }, | ||
canContain: function(t) { return (t === 'item'); }, | ||
acceptsLines: false | ||
}, | ||
BlockQuote: { | ||
block_quote: { | ||
continue: function(parser) { | ||
@@ -275,4 +285,4 @@ var ln = parser.currentLine; | ||
parser.advanceOffset(1, false); | ||
if (peek(ln, parser.offset) === C_SPACE) { | ||
parser.offset++; | ||
if (isSpaceOrTab(peek(ln, parser.offset))) { | ||
parser.advanceOffset(1, true); | ||
} | ||
@@ -285,9 +295,14 @@ } else { | ||
finalize: function() { return; }, | ||
canContain: function(t) { return (t !== 'Item'); }, | ||
canContain: function(t) { return (t !== 'item'); }, | ||
acceptsLines: false | ||
}, | ||
Item: { | ||
item: { | ||
continue: function(parser, container) { | ||
if (parser.blank && container._firstChild !== null) { | ||
parser.advanceNextNonspace(); | ||
if (parser.blank) { | ||
if (container._firstChild == null) { | ||
// Blank line after empty list item | ||
return 1; | ||
} else { | ||
parser.advanceNextNonspace(); | ||
} | ||
} else if (parser.indent >= | ||
@@ -304,6 +319,6 @@ container._listData.markerOffset + | ||
finalize: function() { return; }, | ||
canContain: function(t) { return (t !== 'Item'); }, | ||
canContain: function(t) { return (t !== 'item'); }, | ||
acceptsLines: false | ||
}, | ||
Heading: { | ||
heading: { | ||
continue: function() { | ||
@@ -317,3 +332,3 @@ // a heading can never container > 1 line, so fail to match: | ||
}, | ||
ThematicBreak: { | ||
thematic_break: { | ||
continue: function() { | ||
@@ -327,3 +342,3 @@ // a thematic break can never container > 1 line, so fail to match: | ||
}, | ||
CodeBlock: { | ||
code_block: { | ||
continue: function(parser, container) { | ||
@@ -343,4 +358,4 @@ var ln = parser.currentLine; | ||
var i = container._fenceOffset; | ||
while (i > 0 && peek(ln, parser.offset) === C_SPACE) { | ||
parser.advanceOffset(1, false); | ||
while (i > 0 && isSpaceOrTab(peek(ln, parser.offset))) { | ||
parser.advanceOffset(1, true); | ||
i--; | ||
@@ -377,3 +392,3 @@ } | ||
}, | ||
HtmlBlock: { | ||
html_block: { | ||
continue: function(parser, container) { | ||
@@ -391,3 +406,3 @@ return ((parser.blank && | ||
}, | ||
Paragraph: { | ||
paragraph: { | ||
continue: function(parser) { | ||
@@ -429,7 +444,7 @@ return (parser.blank ? 1 : 0); | ||
// optional following space | ||
if (peek(parser.currentLine, parser.offset) === C_SPACE) { | ||
parser.advanceOffset(1, false); | ||
if (isSpaceOrTab(peek(parser.currentLine, parser.offset))) { | ||
parser.advanceOffset(1, true); | ||
} | ||
parser.closeUnmatchedBlocks(); | ||
parser.addChild('BlockQuote', parser.nextNonspace); | ||
parser.addChild('block_quote', parser.nextNonspace); | ||
return 1; | ||
@@ -449,3 +464,3 @@ } else { | ||
parser.closeUnmatchedBlocks(); | ||
var container = parser.addChild('Heading', parser.nextNonspace); | ||
var container = parser.addChild('heading', parser.nextNonspace); | ||
container.level = match[0].trim().length; // number of #s | ||
@@ -469,3 +484,3 @@ // remove trailing ###s: | ||
parser.closeUnmatchedBlocks(); | ||
var container = parser.addChild('CodeBlock', parser.nextNonspace); | ||
var container = parser.addChild('code_block', parser.nextNonspace); | ||
container._isFenced = true; | ||
@@ -493,7 +508,7 @@ container._fenceLength = fenceLength; | ||
(blockType < 7 || | ||
container.type !== 'Paragraph')) { | ||
container.type !== 'paragraph')) { | ||
parser.closeUnmatchedBlocks(); | ||
// We don't adjust parser.offset; | ||
// spaces are part of the HTML block: | ||
var b = parser.addChild('HtmlBlock', | ||
var b = parser.addChild('html_block', | ||
parser.offset); | ||
@@ -514,6 +529,6 @@ b._htmlBlockType = blockType; | ||
if (!parser.indented && | ||
container.type === 'Paragraph' && | ||
container.type === 'paragraph' && | ||
((match = parser.currentLine.slice(parser.nextNonspace).match(reSetextHeadingLine)))) { | ||
parser.closeUnmatchedBlocks(); | ||
var heading = new Node('Heading', container.sourcepos); | ||
var heading = new Node('heading', container.sourcepos); | ||
heading.level = match[0][0] === '=' ? 1 : 2; | ||
@@ -536,3 +551,3 @@ heading._string_content = container._string_content; | ||
parser.closeUnmatchedBlocks(); | ||
parser.addChild('ThematicBreak', parser.nextNonspace); | ||
parser.addChild('thematic_break', parser.nextNonspace); | ||
parser.advanceOffset(parser.currentLine.length - parser.offset, false); | ||
@@ -549,3 +564,3 @@ return 2; | ||
if ((!parser.indented || container.type === 'List') | ||
if ((!parser.indented || container.type === 'list') | ||
&& (data = parseListMarker(parser))) { | ||
@@ -555,5 +570,5 @@ parser.closeUnmatchedBlocks(); | ||
// add the list if needed | ||
if (parser.tip.type !== 'List' || | ||
if (parser.tip.type !== 'list' || | ||
!(listsMatch(container._listData, data))) { | ||
container = parser.addChild('List', parser.nextNonspace); | ||
container = parser.addChild('list', parser.nextNonspace); | ||
container._listData = data; | ||
@@ -563,3 +578,3 @@ } | ||
// add the list item | ||
container = parser.addChild('Item', parser.nextNonspace); | ||
container = parser.addChild('item', parser.nextNonspace); | ||
container._listData = data; | ||
@@ -575,3 +590,3 @@ return 1; | ||
if (parser.indented && | ||
parser.tip.type !== 'Paragraph' && | ||
parser.tip.type !== 'paragraph' && | ||
!parser.blank) { | ||
@@ -581,3 +596,3 @@ // indented code | ||
parser.closeUnmatchedBlocks(); | ||
parser.addChild('CodeBlock', parser.offset); | ||
parser.addChild('code_block', parser.offset); | ||
return 2; | ||
@@ -594,3 +609,3 @@ } else { | ||
var currentLine = this.currentLine; | ||
var charsToTab; | ||
var charsToTab, charsToAdvance; | ||
var c; | ||
@@ -600,6 +615,9 @@ while (count > 0 && (c = currentLine[this.offset])) { | ||
charsToTab = 4 - (this.column % 4); | ||
this.column += charsToTab; | ||
this.offset += 1; | ||
count -= (columns ? charsToTab : 1); | ||
this.partiallyConsumedTab = columns && charsToTab > count; | ||
charsToAdvance = charsToTab > count ? count : charsToTab; | ||
this.column += charsToAdvance; | ||
this.offset += this.partiallyConsumedTab ? 0 : 1; | ||
count -= (columns ? charsToAdvance : 1); | ||
} else { | ||
this.partiallyConsumedTab = false; | ||
cols += 1; | ||
@@ -698,3 +716,3 @@ this.offset += 1; | ||
var matchedLeaf = container.type !== 'Paragraph' && | ||
var matchedLeaf = container.type !== 'paragraph' && | ||
blocks[container.type].acceptsLines; | ||
@@ -742,3 +760,3 @@ var starts = this.blockStarts; | ||
if (!this.allClosed && !this.blank && | ||
this.tip.type === 'Paragraph') { | ||
this.tip.type === 'paragraph') { | ||
// lazy paragraph continuation | ||
@@ -762,5 +780,5 @@ this.addLine(); | ||
var lastLineBlank = this.blank && | ||
!(t === 'BlockQuote' || | ||
(t === 'CodeBlock' && container._isFenced) || | ||
(t === 'Item' && | ||
!(t === 'block_quote' || | ||
(t === 'code_block' && container._isFenced) || | ||
(t === 'item' && | ||
!container._firstChild && | ||
@@ -779,3 +797,3 @@ container.sourcepos[0][0] === this.lineNumber)); | ||
// if HtmlBlock, check for end condition | ||
if (t === 'HtmlBlock' && | ||
if (t === 'html_block' && | ||
container._htmlBlockType >= 1 && | ||
@@ -789,3 +807,3 @@ container._htmlBlockType <= 5 && | ||
// create paragraph container for line | ||
container = this.addChild('Paragraph', this.offset); | ||
container = this.addChild('paragraph', this.offset); | ||
this.advanceNextNonspace(); | ||
@@ -823,3 +841,3 @@ this.addLine(); | ||
t = node.type; | ||
if (!event.entering && (t === 'Paragraph' || t === 'Heading')) { | ||
if (!event.entering && (t === 'paragraph' || t === 'heading')) { | ||
this.inlineParser.parse(node); | ||
@@ -831,3 +849,3 @@ } | ||
var Document = function() { | ||
var doc = new Node('Document', [[1, 1], [0, 0]]); | ||
var doc = new Node('document', [[1, 1], [0, 0]]); | ||
return doc; | ||
@@ -887,2 +905,3 @@ }; | ||
blank: false, | ||
partiallyConsumedTab: false, | ||
allClosed: true, | ||
@@ -889,0 +908,0 @@ lastMatchedContainer: this.doc, |
@@ -79,11 +79,11 @@ "use strict"; | ||
switch (node.type) { | ||
case 'Text': | ||
case 'text': | ||
out(esc(node.literal, false)); | ||
break; | ||
case 'Softbreak': | ||
case 'softbreak': | ||
out(this.softbreak); | ||
break; | ||
case 'Hardbreak': | ||
case 'linebreak': | ||
out(tag('br', [], true)); | ||
@@ -93,11 +93,11 @@ cr(); | ||
case 'Emph': | ||
case 'emph': | ||
out(tag(entering ? 'em' : '/em')); | ||
break; | ||
case 'Strong': | ||
case 'strong': | ||
out(tag(entering ? 'strong' : '/strong')); | ||
break; | ||
case 'HtmlInline': | ||
case 'html_inline': | ||
if (options.safe) { | ||
@@ -110,3 +110,3 @@ out('<!-- raw HTML omitted -->'); | ||
case 'CustomInline': | ||
case 'custom_inline': | ||
if (entering && node.onEnter) { | ||
@@ -119,3 +119,3 @@ out(node.onEnter); | ||
case 'Link': | ||
case 'link': | ||
if (entering) { | ||
@@ -134,3 +134,3 @@ if (!(options.safe && potentiallyUnsafe(node.destination))) { | ||
case 'Image': | ||
case 'image': | ||
if (entering) { | ||
@@ -158,13 +158,13 @@ if (disableTags === 0) { | ||
case 'Code': | ||
case 'code': | ||
out(tag('code') + esc(node.literal, false) + tag('/code')); | ||
break; | ||
case 'Document': | ||
case 'document': | ||
break; | ||
case 'Paragraph': | ||
case 'paragraph': | ||
grandparent = node.parent.parent; | ||
if (grandparent !== null && | ||
grandparent.type === 'List') { | ||
grandparent.type === 'list') { | ||
if (grandparent.listTight) { | ||
@@ -183,3 +183,3 @@ break; | ||
case 'BlockQuote': | ||
case 'block_quote': | ||
if (entering) { | ||
@@ -196,3 +196,3 @@ cr(); | ||
case 'Item': | ||
case 'item': | ||
if (entering) { | ||
@@ -206,4 +206,4 @@ out(tag('li', attrs)); | ||
case 'List': | ||
tagname = node.listType === 'Bullet' ? 'ul' : 'ol'; | ||
case 'list': | ||
tagname = node.listType === 'bullet' ? 'ul' : 'ol'; | ||
if (entering) { | ||
@@ -224,3 +224,3 @@ var start = node.listStart; | ||
case 'Heading': | ||
case 'heading': | ||
tagname = 'h' + node.level; | ||
@@ -236,3 +236,3 @@ if (entering) { | ||
case 'CodeBlock': | ||
case 'code_block': | ||
info_words = node.info ? node.info.split(/\s+/) : []; | ||
@@ -249,3 +249,3 @@ if (info_words.length > 0 && info_words[0].length > 0) { | ||
case 'HtmlBlock': | ||
case 'html_block': | ||
cr(); | ||
@@ -260,3 +260,3 @@ if (options.safe) { | ||
case 'CustomBlock': | ||
case 'custom_block': | ||
cr(); | ||
@@ -271,3 +271,3 @@ if (entering && node.onEnter) { | ||
case 'ThematicBreak': | ||
case 'thematic_break': | ||
cr(); | ||
@@ -274,0 +274,0 @@ out(tag('hr', attrs, true)); |
@@ -14,6 +14,7 @@ "use strict"; | ||
module.exports.version = '0.24.0' | ||
module.exports.version = '0.25.0'; | ||
module.exports.Node = require('./node'); | ||
module.exports.Parser = require('./blocks'); | ||
module.exports.HtmlRenderer = require('./html'); | ||
// module.exports.HtmlRenderer = require('./html'); | ||
module.exports.HtmlRenderer = require('./render/html'); | ||
module.exports.XmlRenderer = require('./xml'); |
@@ -91,3 +91,3 @@ "use strict"; | ||
var text = function(s) { | ||
var node = new Node('Text'); | ||
var node = new Node('text'); | ||
node._literal = s; | ||
@@ -147,3 +147,3 @@ return node; | ||
if (matched === ticks) { | ||
node = new Node('Code'); | ||
node = new Node('code'); | ||
node._literal = this.subject.slice(afterOpenTicks, | ||
@@ -172,3 +172,3 @@ this.pos - ticks.length) | ||
this.pos += 1; | ||
node = new Node('Hardbreak'); | ||
node = new Node('linebreak'); | ||
block.appendChild(node); | ||
@@ -191,3 +191,3 @@ } else if (reEscapable.test(subj.charAt(this.pos))) { | ||
dest = m.slice(1, m.length - 1); | ||
node = new Node('Link'); | ||
node = new Node('link'); | ||
node._destination = normalizeURI('mailto:' + dest); | ||
@@ -200,3 +200,3 @@ node._title = ''; | ||
dest = m.slice(1, m.length - 1); | ||
node = new Node('Link'); | ||
node = new Node('link'); | ||
node._destination = normalizeURI(dest); | ||
@@ -218,3 +218,3 @@ node._title = ''; | ||
} else { | ||
var node = new Node('HtmlInline'); | ||
var node = new Node('html_inline'); | ||
node._literal = m; | ||
@@ -411,3 +411,3 @@ block.appendChild(node); | ||
// build contents for new emph element | ||
var emph = new Node(use_delims === 1 ? 'Emph' : 'Strong'); | ||
var emph = new Node(use_delims === 1 ? 'emph' : 'strong'); | ||
@@ -656,3 +656,3 @@ tmp = opener_inl._next; | ||
if (matched) { | ||
var node = new Node(is_image ? 'Image' : 'Link'); | ||
var node = new Node(is_image ? 'image' : 'link'); | ||
node._destination = dest; | ||
@@ -749,8 +749,8 @@ node._title = title || ''; | ||
var lastc = block._lastChild; | ||
if (lastc && lastc.type === 'Text' && lastc._literal[lastc._literal.length - 1] === ' ') { | ||
if (lastc && lastc.type === 'text' && lastc._literal[lastc._literal.length - 1] === ' ') { | ||
var hardbreak = lastc._literal[lastc._literal.length - 2] === ' '; | ||
lastc._literal = lastc._literal.replace(reFinalSpace, ''); | ||
block.appendChild(new Node(hardbreak ? 'Hardbreak' : 'Softbreak')); | ||
block.appendChild(new Node(hardbreak ? 'linebreak' : 'softbreak')); | ||
} else { | ||
block.appendChild(new Node('Softbreak')); | ||
block.appendChild(new Node('softbreak')); | ||
} | ||
@@ -757,0 +757,0 @@ this.match(reInitialSpace); // gobble leading spaces in next line |
@@ -5,14 +5,14 @@ "use strict"; | ||
switch (node._type) { | ||
case 'Document': | ||
case 'BlockQuote': | ||
case 'List': | ||
case 'Item': | ||
case 'Paragraph': | ||
case 'Heading': | ||
case 'Emph': | ||
case 'Strong': | ||
case 'Link': | ||
case 'Image': | ||
case 'CustomInline': | ||
case 'CustomBlock': | ||
case 'document': | ||
case 'block_quote': | ||
case 'list': | ||
case 'item': | ||
case 'paragraph': | ||
case 'heading': | ||
case 'emph': | ||
case 'strong': | ||
case 'link': | ||
case 'image': | ||
case 'custom_inline': | ||
case 'custom_block': | ||
return true; | ||
@@ -19,0 +19,0 @@ default: |
@@ -77,4 +77,4 @@ "use strict"; | ||
container = node.isContainer; | ||
selfClosing = nodetype === 'ThematicBreak' || nodetype === 'Hardbreak' || | ||
nodetype === 'Softbreak'; | ||
selfClosing = nodetype === 'thematic_break' || nodetype === 'linebreak' || | ||
nodetype === 'softbreak'; | ||
tagname = toTagName(nodetype); | ||
@@ -87,6 +87,6 @@ | ||
switch (nodetype) { | ||
case 'Document': | ||
case 'document': | ||
attrs.push(['xmlns', 'http://commonmark.org/xml/1.0']); | ||
break; | ||
case 'List': | ||
case 'list': | ||
if (node.listType !== null) { | ||
@@ -112,3 +112,3 @@ attrs.push(['type', node.listType.toLowerCase()]); | ||
break; | ||
case 'CodeBlock': | ||
case 'code_block': | ||
if (node.info) { | ||
@@ -118,12 +118,12 @@ attrs.push(['info', node.info]); | ||
break; | ||
case 'Heading': | ||
case 'heading': | ||
attrs.push(['level', String(node.level)]); | ||
break; | ||
case 'Link': | ||
case 'Image': | ||
case 'link': | ||
case 'image': | ||
attrs.push(['destination', node.destination]); | ||
attrs.push(['title', node.title]); | ||
break; | ||
case 'CustomInline': | ||
case 'CustomBlock': | ||
case 'custom_inline': | ||
case 'custom_block': | ||
attrs.push(['on_enter', node.onEnter]); | ||
@@ -130,0 +130,0 @@ attrs.push(['on_exit', node.onExit]); |
{ "name": "commonmark", | ||
"description": "a strongly specified, highly compatible variant of Markdown", | ||
"version": "0.24.0", | ||
"version": "0.25.0", | ||
"homepage": "http://commonmark.org", | ||
@@ -22,3 +22,4 @@ "keywords": | ||
"mdurl": "~ 1.0.1", | ||
"string.prototype.repeat": "^0.2.0" | ||
"string.prototype.repeat": "^0.2.0", | ||
"minimist": "~ 1.2.0" | ||
}, | ||
@@ -25,0 +26,0 @@ "directories": { |
@@ -57,2 +57,3 @@ commonmark.js | ||
Usage | ||
@@ -187,3 +188,3 @@ ----- | ||
node = event.node; | ||
if (event.entering && node.type === 'Text') { | ||
if (event.entering && node.type === 'text') { | ||
node.literal = node.literal.toUpperCase(); | ||
@@ -203,3 +204,3 @@ } | ||
node = event.node; | ||
if (node.type === 'Emph') { | ||
if (node.type === 'emph') { | ||
if (event.entering) { | ||
@@ -216,3 +217,3 @@ inEmph = true; | ||
} | ||
} else if (inEmph && node.type === 'Text') { | ||
} else if (inEmph && node.type === 'text') { | ||
node.literal = node.literal.toUpperCase(); | ||
@@ -233,2 +234,18 @@ } | ||
Command line | ||
------------ | ||
The command line executable parses CommonMark input from the | ||
specified files, or from stdin if no files are specified, and | ||
renders the result to stdout as HTML. If multiple input files | ||
are specified, their contents are concatenated before parsing, | ||
with newlines between them. | ||
``` | ||
commonmark inputfile.md > outputfile.html | ||
commonmark intro.md chapter1.md chapter2.md > book.html | ||
``` | ||
Use `commonmark --help` to get a summary of options. | ||
A note on security | ||
@@ -326,2 +343,4 @@ ------------------ | ||
Authors | ||
@@ -328,0 +347,0 @@ ------- |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
428614
18
6419
349
4
+ Addedminimist@~ 1.2.0
+ Addedminimist@1.2.8(transitive)