remarkable
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -15,11 +15,12 @@ { | ||
"**/.*", | ||
"benchmark", | ||
"bower_components", | ||
"demo", | ||
"lib", | ||
"node_modules", | ||
"bower_components", | ||
"support", | ||
"test", | ||
"Makefile", | ||
"index*", | ||
"lib", | ||
"benchmark", | ||
"demo" | ||
"index*" | ||
] | ||
} |
@@ -1,4 +0,11 @@ | ||
1.0.0 / WIP | ||
----------- | ||
1.1.0 / 2014-10-20 | ||
------------------ | ||
- Code refactoring, bugfixes, API update. | ||
- Added source lines info to block nodes. | ||
1.0.0 / 2014-10-16 | ||
------------------ | ||
- First release. |
@@ -6,4 +6,5 @@ // List of valid html blocks names, accorting to stmd spec | ||
var html_blocks = {}; | ||
module.exports = [ | ||
[ | ||
'article', | ||
@@ -59,2 +60,5 @@ 'aside', | ||
'video' | ||
]; | ||
].forEach(function (name) { html_blocks[name] = true; }); | ||
module.exports = html_blocks; |
@@ -71,7 +71,7 @@ // Main perser class | ||
// Main method that does all magic :) | ||
// Parse input string, returns tokens array. Modify `env` with | ||
// definitions data. | ||
// | ||
Remarkable.prototype.render = function (src) { | ||
var tokens, tok, i, l, env = { references: Object.create(null) }; | ||
Remarkable.prototype.parse = function (src, env) { | ||
var tokens, tok, i, l; | ||
// Parse blocks | ||
@@ -88,7 +88,14 @@ tokens = this.block.parse(src, this.options, env); | ||
// Render | ||
return this.renderer.render(tokens, this.options, env); | ||
return tokens; | ||
}; | ||
// Main method that does all magic :) | ||
// | ||
Remarkable.prototype.render = function (src) { | ||
var env = { references: {} }; | ||
return this.renderer.render(this.parse(src, env), this.options, env); | ||
}; | ||
module.exports = Remarkable; |
@@ -63,4 +63,5 @@ // Block parser | ||
// Termination condition for nested calls. | ||
// Nested calls currently used for blockquotes & lists | ||
if (state.tShift[line] < state.blkIndent) { break; } | ||
if (state.bqMarks[line] < state.bqLevel) { break; } | ||
@@ -101,3 +102,3 @@ // Try all possible rules. | ||
// two empty lines should stop the parser in list mode | ||
if (line < endLine && state.listMode && state.isEmpty(line)) { break; } | ||
if (line < endLine && state.parentType === 'list' && state.isEmpty(line)) { break; } | ||
state.line = line; | ||
@@ -104,0 +105,0 @@ } |
@@ -60,3 +60,3 @@ | ||
// ensure that the end of the line is empty | ||
pos = state.skipSpaces(pos); | ||
while (pos < max && state.src.charCodeAt(pos) === 0x20/* space */) { pos++; } | ||
if (pos < max && state.src.charCodeAt(pos) !== 0x0A) { return -1; } | ||
@@ -63,0 +63,0 @@ |
@@ -231,2 +231,13 @@ 'use strict'; | ||
Renderer.prototype.renderInline = function (tokens, options) { | ||
var result = ''; | ||
for (var i = 0, len = tokens.length; i < len; i++) { | ||
result += rules[tokens[i].type](tokens, i, options); | ||
} | ||
return result; | ||
}; | ||
Renderer.prototype.render = function (tokens, options) { | ||
@@ -276,3 +287,3 @@ var i, len, name, | ||
if (tokens[i].type === 'inline') { | ||
result += this.render(tokens[i].children, options); | ||
result += this.renderInline(tokens[i].children, options); | ||
} else { | ||
@@ -279,0 +290,0 @@ result += rules[name](tokens, i, options); |
@@ -7,3 +7,3 @@ // Block quotes | ||
module.exports = function blockquote(state, startLine, endLine, silent) { | ||
var nextLine, lastLineEmpty, oldTShift, oldBMarks, oldIndent, oldListMode, | ||
var nextLine, lastLineEmpty, oldTShift, oldBMarks, oldIndent, oldParentType, lines, | ||
terminatorRules = state.parser._rulesBlockquoteTerm, i, l, terminate, | ||
@@ -27,4 +27,2 @@ pos = state.bMarks[startLine] + state.tShift[startLine], | ||
state.bqMarks[startLine]++; | ||
state.bqLevel++; | ||
oldIndent = state.blkIndent; | ||
@@ -71,3 +69,2 @@ state.blkIndent = 0; | ||
if (state.src.charCodeAt(pos++) === 0x3E/* > */) { | ||
state.bqMarks[nextLine]++; | ||
// This line is inside the blockquote. | ||
@@ -104,10 +101,24 @@ | ||
oldTShift.push(state.tShift[nextLine]); | ||
// A negative number means that this is a paragraph continuation; | ||
// | ||
// Any negative number will do the job here, but it's better for it | ||
// to be large enough to make any bugs obvious. | ||
state.tShift[nextLine] = -1337; | ||
} | ||
oldListMode = state.listMode; | ||
state.listMode = false; | ||
state.tokens.push({ type: 'blockquote_open', level: state.level++ }); | ||
oldParentType = state.parentType; | ||
state.parentType = 'blockquote'; | ||
state.tokens.push({ | ||
type: 'blockquote_open', | ||
lines: lines = [ startLine, 0 ], | ||
level: state.level++ | ||
}); | ||
state.parser.tokenize(state, startLine, nextLine); | ||
state.tokens.push({ type: 'blockquote_close', level: --state.level }); | ||
state.listMode = oldListMode; | ||
state.tokens.push({ | ||
type: 'blockquote_close', | ||
level: --state.level | ||
}); | ||
state.parentType = oldParentType; | ||
lines[1] = state.lines; | ||
@@ -120,3 +131,2 @@ // Restore original tShift; this might not be necessary since the parser | ||
} | ||
state.bqLevel--; | ||
state.blkIndent = oldIndent; | ||
@@ -123,0 +133,0 @@ |
@@ -14,3 +14,2 @@ // Code block (4 spaces padded) | ||
while (nextLine < endLine) { | ||
if (state.bqMarks[nextLine] < state.bqLevel) { break; } | ||
if (state.isEmpty(nextLine)) { | ||
@@ -30,2 +29,3 @@ nextLine++; | ||
state.line = nextLine; | ||
state.tokens.push({ | ||
@@ -35,7 +35,7 @@ type: 'code', | ||
block: true, | ||
lines: [ startLine, state.line ], | ||
level: state.level | ||
}); | ||
state.line = nextLine; | ||
return true; | ||
}; |
@@ -55,3 +55,2 @@ // fences (``` lang, ~~~ lang) | ||
} | ||
if (pos < max && state.bqMarks[nextLine] < state.bqLevel) { break; } | ||
@@ -78,2 +77,3 @@ if (state.src.charCodeAt(pos) !== marker) { continue; } | ||
state.line = nextLine + (haveEndMarker ? 1 : 0); | ||
state.tokens.push({ | ||
@@ -83,7 +83,7 @@ type: 'fence', | ||
content: state.getLines(startLine + 1, nextLine, len, true), | ||
lines: [ startLine, state.line ], | ||
level: state.level | ||
}); | ||
state.line = nextLine + (haveEndMarker ? 1 : 0); | ||
return true; | ||
}; |
@@ -48,3 +48,10 @@ // heading (#, ##, ...) | ||
state.tokens.push({ type: 'heading_open', hLevel: level, level: state.level }); | ||
state.line = startLine + 1; | ||
state.tokens.push({ type: 'heading_open', | ||
hLevel: level, | ||
lines: [ startLine, state.line ], | ||
level: state.level | ||
}); | ||
// only if header is not empty | ||
@@ -55,3 +62,5 @@ if (pos < max) { | ||
content: state.src.slice(pos, max).trim(), | ||
level: state.level + 1 | ||
level: state.level + 1, | ||
lines: [ startLine, state.line ], | ||
children: [] | ||
}); | ||
@@ -61,4 +70,3 @@ } | ||
state.line = startLine + 1; | ||
return true; | ||
}; |
@@ -37,6 +37,10 @@ // Horizontal rule | ||
state.tokens.push({ type: 'hr', level: state.level }); | ||
state.line = startLine + 1; | ||
state.tokens.push({ | ||
type: 'hr', | ||
lines: [ startLine, state.line ], | ||
level: state.level | ||
}); | ||
state.line = startLine + 1; | ||
return true; | ||
}; |
@@ -51,3 +51,3 @@ // HTML block | ||
// Make sure tag name is valid | ||
if (block_names.indexOf(match[1].toLowerCase()) < 0) { return false; } | ||
if (block_names[match[1].toLowerCase()] !== true) { return false; } | ||
if (silent) { return true; } | ||
@@ -66,10 +66,11 @@ | ||
state.line = nextLine; | ||
state.tokens.push({ | ||
type: 'htmlblock', | ||
level: state.level, | ||
lines: [ startLine, state.line ], | ||
content: state.getLines(startLine, nextLine, 0, true) | ||
}); | ||
state.line = nextLine; | ||
return true; | ||
}; |
@@ -12,5 +12,5 @@ // lheading (---, ===) | ||
if (state.tShift[next] < state.blkIndent) { return false; } | ||
if (state.bqMarks[next] < state.bqLevel) { return false; } | ||
// Scan next line | ||
if (state.tShift[next] - state.blkIndent > 3) { return false; } | ||
@@ -21,2 +21,4 @@ | ||
if (pos >= max) { return false; } | ||
marker = state.src.charCodeAt(pos); | ||
@@ -36,5 +38,7 @@ | ||
state.line = next + 1; | ||
state.tokens.push({ | ||
type: 'heading_open', | ||
hLevel: marker === 0x3D/* = */ ? 1 : 2, | ||
lines: [ startLine, state.line ], | ||
level: state.level | ||
@@ -45,3 +49,5 @@ }); | ||
content: state.src.slice(pos, state.eMarks[startLine]).trim(), | ||
level: state.level + 1 | ||
level: state.level + 1, | ||
lines: [ startLine, state.line - 1 ], | ||
children: [] | ||
}); | ||
@@ -54,4 +60,3 @@ state.tokens.push({ | ||
state.line = next + 1; | ||
return true; | ||
}; |
@@ -78,3 +78,3 @@ // Lists | ||
oldTight, | ||
oldListMode, | ||
oldParentType, | ||
start, | ||
@@ -90,2 +90,4 @@ posAfterMarker, | ||
prevEmptyEnd, | ||
listLines, | ||
itemLines, | ||
terminatorRules = state.parser._rulesListTerm, i, l, terminate; | ||
@@ -121,2 +123,3 @@ | ||
tight: true, | ||
lines: listLines = [ startLine, 0 ], | ||
level: state.level++ | ||
@@ -129,2 +132,3 @@ }); | ||
tight: true, | ||
lines: listLines = [ startLine, 0 ], | ||
level: state.level++ | ||
@@ -165,3 +169,7 @@ }); | ||
// Run subparser & write tokens | ||
state.tokens.push({ type: 'list_item_open', level: state.level++ }); | ||
state.tokens.push({ | ||
type: 'list_item_open', | ||
lines: itemLines = [ startLine, 0 ], | ||
level: state.level++ | ||
}); | ||
@@ -173,7 +181,7 @@ //nextLine++; | ||
oldTShift = state.tShift[startLine]; | ||
oldListMode = state.listMode; | ||
oldParentType = state.parentType; | ||
state.tShift[startLine] = contentStart - state.bMarks[startLine]; | ||
state.blkIndent = indent; | ||
state.tight = true; | ||
state.listMode = true; | ||
state.parentType = 'list'; | ||
@@ -193,3 +201,3 @@ state.parser.tokenize(state, startLine, endLine, true); | ||
state.tight = oldTight; | ||
state.listMode = oldListMode; | ||
state.parentType = oldParentType; | ||
@@ -199,2 +207,3 @@ state.tokens.push({ type: 'list_item_close', level: --state.level }); | ||
nextLine = startLine = state.line; | ||
itemLines[1] = nextLine; | ||
contentStart = state.bMarks[startLine]; | ||
@@ -212,3 +221,2 @@ | ||
if (state.tShift[nextLine] < state.blkIndent) { break; } | ||
if (state.bqMarks[nextLine] < state.bqLevel) { break; } | ||
@@ -243,2 +251,3 @@ // fail if terminating block found | ||
} | ||
listLines[1] = nextLine; | ||
@@ -245,0 +254,0 @@ state.line = nextLine; |
@@ -41,14 +41,23 @@ // Paragraph | ||
state.line = nextLine; | ||
if (content.length) { | ||
state.tokens.push({ type: 'paragraph_open', level: state.level }); | ||
state.tokens.push({ | ||
type: 'paragraph_open', | ||
lines: [ startLine, state.line ], | ||
level: state.level | ||
}); | ||
state.tokens.push({ | ||
type: 'inline', | ||
content: content, | ||
level: state.level + 1 | ||
level: state.level + 1, | ||
lines: [ startLine, state.line ], | ||
children: [] | ||
}); | ||
state.tokens.push({ type: 'paragraph_close', level: state.level }); | ||
state.tokens.push({ | ||
type: 'paragraph_close', | ||
level: state.level | ||
}); | ||
} | ||
state.line = nextLine; | ||
return true; | ||
}; |
@@ -6,3 +6,3 @@ // Parser state class | ||
function State(src, parser, tokens, options, env) { | ||
function StateBlock(src, parser, tokens, options, env) { | ||
var ch, s, start, pos, len, indent, indent_found; | ||
@@ -33,11 +33,10 @@ | ||
this.tShift = []; // indent for each line | ||
this.bqMarks = []; // lines shifts in blockquotes (calculated on bq enter) | ||
// block parser variables | ||
this.blkIndent = 0; | ||
this.blkIndent = 0; // required block content indent | ||
// (for example, if we are in list) | ||
this.line = 0; // line index in src | ||
this.lineMax = 0; // lines count | ||
this.tight = false; // loose/tight mode for lists | ||
this.listMode = false; // if true, block parser stops on two newlines | ||
this.bqLevel = 0; // blockquote nesting level | ||
this.tight = false; // loose/tight mode for lists | ||
this.parentType = 'root'; // if `list`, block parser stops on two newlines | ||
@@ -68,3 +67,3 @@ this.level = 0; | ||
if (ch === 0x0A || ch === 0x0D) { | ||
if (ch === 0x0A) { | ||
this.bMarks.push(start); | ||
@@ -75,10 +74,5 @@ this.eMarks.push(pos); | ||
start = pos + 1; | ||
if (ch === 0x0D && pos + 1 < len && s.charCodeAt(pos + 1) === 0x0A) { | ||
pos++; | ||
start++; | ||
} | ||
} | ||
} | ||
if (ch !== 0x0D || ch !== 0x0A) { | ||
if (ch !== 0x0A) { | ||
this.bMarks.push(start); | ||
@@ -95,13 +89,9 @@ this.eMarks.push(len); | ||
this.lineMax = this.bMarks.length - 1; // don't count last fake line | ||
for (start = this.bMarks.length; start > 0; start--) { | ||
this.bqMarks.push(0); | ||
} | ||
} | ||
State.prototype.isEmpty = function isEmpty(line) { | ||
StateBlock.prototype.isEmpty = function isEmpty(line) { | ||
return this.bMarks[line] + this.tShift[line] >= this.eMarks[line]; | ||
}; | ||
State.prototype.skipEmptyLines = function skipEmptyLines(from) { | ||
StateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) { | ||
for (var max = this.lineMax; from < max; from++) { | ||
@@ -116,3 +106,3 @@ if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) { | ||
// Skip spaces from given position. | ||
State.prototype.skipSpaces = function skipSpaces(pos) { | ||
StateBlock.prototype.skipSpaces = function skipSpaces(pos) { | ||
for (var max = this.src.length; pos < max; pos++) { | ||
@@ -125,3 +115,3 @@ if (this.src.charCodeAt(pos) !== 0x20/* space */) { break; } | ||
// Skip char codes from given position | ||
State.prototype.skipChars = function skipChars(pos, code) { | ||
StateBlock.prototype.skipChars = function skipChars(pos, code) { | ||
for (var max = this.src.length; pos < max; pos++) { | ||
@@ -134,3 +124,3 @@ if (this.src.charCodeAt(pos) !== code) { break; } | ||
// Skip char codes reverse from given position - 1 | ||
State.prototype.skipCharsBack = function skipCharsBack(pos, code, min) { | ||
StateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) { | ||
if (pos <= min) { return pos; } | ||
@@ -145,4 +135,4 @@ | ||
// cut lines range from source. | ||
State.prototype.getLines = function getLines(begin, end, indent, keepLastLF) { | ||
var i, first, last, queue, | ||
StateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) { | ||
var i, first, last, queue, shift, | ||
line = begin; | ||
@@ -164,4 +154,8 @@ | ||
for (i = 0; line < end; line++, i++) { | ||
first = this.bMarks[line] + Math.min(this.tShift[line], indent); | ||
shift = this.tShift[line]; | ||
if (shift > indent) { shift = indent; } | ||
if (shift < 0) { shift = 0; } | ||
first = this.bMarks[line] + shift; | ||
if (line + 1 < end || keepLastLF) { | ||
@@ -181,4 +175,4 @@ // No need for bounds check because we have fake entry on tail. | ||
// Create shadow clone of curent state with new input data | ||
State.prototype.clone = function clone(src) { | ||
return new State( | ||
StateBlock.prototype.clone = function clone(src) { | ||
return new StateBlock( | ||
src, | ||
@@ -191,2 +185,2 @@ this.parser, | ||
module.exports = State; | ||
module.exports = StateBlock; |
@@ -15,4 +15,4 @@ // GFM table, non-standard | ||
module.exports = function table(state, startLine, endLine, silent) { | ||
var ch, firstLineMatch, secondLineMatch, i, nextLine, m, rows, | ||
aligns, t; | ||
var ch, firstLineMatch, secondLineMatch, pos, i, nextLine, m, rows, | ||
aligns, t, tableLines, tbodyLines; | ||
@@ -22,8 +22,12 @@ // should have at least three lines | ||
if (state.tShift[startLine + 1] < state.blkIndent) { return false; } | ||
if (state.bqMarks[startLine + 1] < state.bqLevel) { return false; } | ||
nextLine = startLine + 1; | ||
if (state.tShift[nextLine] < state.blkIndent) { return false; } | ||
// first character of the second line should be '|' or '-' | ||
ch = state.src.charCodeAt(state.bMarks[startLine + 1] | ||
+ state.tShift[startLine + 1]); | ||
pos = state.bMarks[nextLine] + state.tShift[nextLine]; | ||
if (pos >= state.eMarks[nextLine]) { return false; } | ||
ch = state.src.charCodeAt(pos); | ||
if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */) { return false; } | ||
@@ -55,12 +59,31 @@ | ||
state.tokens.push({ type: 'table_open', level: state.level++ }); | ||
state.tokens.push({ type: 'thead_open', level: state.level++ }); | ||
state.tokens.push({ | ||
type: 'table_open', | ||
lines: tableLines = [ startLine, 0 ], | ||
level: state.level++ | ||
}); | ||
state.tokens.push({ | ||
type: 'thead_open', | ||
lines: [ startLine, startLine + 1 ], | ||
level: state.level++ | ||
}); | ||
state.tokens.push({ type: 'tr_open', level: state.level++ }); | ||
state.tokens.push({ | ||
type: 'tr_open', | ||
lines: [ startLine, startLine + 1 ], | ||
level: state.level++ | ||
}); | ||
for (i = 0; i < rows.length; i++) { | ||
state.tokens.push({ type: 'th_open', align: aligns[i], level: state.level++ }); | ||
state.tokens.push({ | ||
type: 'th_open', | ||
align: aligns[i], | ||
lines: [ startLine, startLine + 1 ], | ||
level: state.level++ | ||
}); | ||
state.tokens.push({ | ||
type: 'inline', | ||
content: rows[i].trim(), | ||
level: state.level | ||
lines: [ startLine, startLine + 1 ], | ||
level: state.level, | ||
children: [] | ||
}); | ||
@@ -71,7 +94,11 @@ state.tokens.push({ type: 'th_close', level: --state.level }); | ||
state.tokens.push({ type: 'thead_close', level: --state.level }); | ||
state.tokens.push({ type: 'tbody_open', level: state.level++ }); | ||
state.tokens.push({ | ||
type: 'tbody_open', | ||
lines: tbodyLines = [ startLine + 2, 0 ], | ||
level: state.level++ | ||
}); | ||
for (nextLine = startLine + 2; nextLine < endLine; nextLine++) { | ||
if (state.tShift[nextLine] < state.blkIndent) { break; } | ||
if (state.bqMarks[nextLine] < state.bqLevel) { break; } | ||
@@ -87,3 +114,5 @@ m = lineMatch(state, nextLine, /^ *\|?(.*?\|.*?)\|? *$/); | ||
type: 'inline', | ||
content: rows[i].replace(/^\|? *| *\|?$/g, '') | ||
content: rows[i].replace(/^\|? *| *\|?$/g, ''), | ||
level: state.level, | ||
children: [] | ||
}); | ||
@@ -97,4 +126,5 @@ state.tokens.push({ type: 'td_close', level: --state.level }); | ||
tableLines[1] = tbodyLines[1] = nextLine; | ||
state.line = nextLine; | ||
return true; | ||
}; |
// Parse backticks | ||
var END_RE = /`+/g; | ||
module.exports = function backticks(state) { | ||
var start, code, max, marker, match, | ||
var start, max, marker, matchStart, matchEnd, | ||
pos = state.pos, | ||
@@ -20,18 +18,19 @@ ch = state.src.charCodeAt(pos); | ||
END_RE = /`+/g; | ||
END_RE.lastIndex = pos; | ||
matchStart = matchEnd = pos; | ||
while ((match = END_RE.exec(state.src)) !== null) { | ||
if (match[0].length === marker.length) { | ||
code = state.src.slice(pos, END_RE.lastIndex - marker.length); | ||
while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) { | ||
matchEnd = matchStart + 1; | ||
while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; } | ||
if (matchEnd - matchStart === marker.length) { | ||
state.push({ | ||
type: 'code', | ||
content: code | ||
.replace(/[ \n]+/g,' ') | ||
.trim(), | ||
content: state.src.slice(pos, matchStart) | ||
.replace(/[ \n]+/g,' ') | ||
.trim(), | ||
block: false, | ||
level: state.level | ||
}); | ||
state.pos += marker.length * 2 + code.length; | ||
state.pos = matchEnd; | ||
return true; | ||
@@ -38,0 +37,0 @@ } |
@@ -18,10 +18,8 @@ // Process *this* and _that_ | ||
function parseStart(state, start) { | ||
var pos = start, lastChar, count, | ||
var pos = start, lastChar, nextChar, count, | ||
max = state.posMax, | ||
marker = state.src.charCodeAt(start); | ||
lastChar = state.pending.length !== 0 ? state.pending.charCodeAt(state.pending.length - 1) : -1; | ||
lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1; | ||
if (lastChar === marker) { return -1; } | ||
while (pos < max && state.src.charCodeAt(pos) === marker) { pos++; } | ||
@@ -46,3 +44,4 @@ if (pos >= max) { return -1; } | ||
// check condition 2, marker followed by whitespace | ||
if (state.src.charCodeAt(pos) === 0x20) { return -1; } | ||
nextChar = state.src.charCodeAt(pos); | ||
if (nextChar === 0x20 || nextChar === 0x0A) { return -1; } | ||
@@ -68,3 +67,3 @@ if (marker === 0x5F /* _ */) { | ||
lastChar = state.pending.length !== 0 ? state.pending.charCodeAt(state.pending.length - 1) : -1; | ||
lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1; | ||
@@ -88,3 +87,3 @@ while (pos < max && state.src.charCodeAt(pos) === marker) { pos++; } | ||
// check condition 2, marker preceded by whitespace | ||
if (lastChar === 0x20) { return -1; } | ||
if (lastChar === 0x20 || lastChar === 0x0A) { return -1; } | ||
@@ -110,3 +109,2 @@ if (marker === 0x5F) { | ||
stack, | ||
breakOutOfOuterLoop, | ||
max = state.posMax, | ||
@@ -150,16 +148,4 @@ start = state.pos, | ||
while (oldCount !== newCount) { | ||
if (oldCount === 3) { | ||
// e.g. `***foo*` | ||
stack.push(3 - newCount); | ||
break; | ||
} | ||
if (newCount < oldCount) { | ||
// assert(oldCount == 2 && newCount == 1) | ||
// i.e. `**foo* bar*` | ||
// not valid for now, but might be in the future | ||
// eslint is misconfigured, so it doesn't accept "break MAIN;" | ||
// here is a crappy workaround | ||
breakOutOfOuterLoop = true; | ||
stack.push(oldCount - newCount); | ||
break; | ||
@@ -176,4 +162,2 @@ } | ||
if (breakOutOfOuterLoop) { break; } | ||
if (stack.length === 0) { | ||
@@ -180,0 +164,0 @@ startCount = oldCount; |
// Proceess escaped chars and hardbreaks | ||
var ESCAPED = '\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-' | ||
.split('') | ||
.map(function(ch) { return ch.charCodeAt(0); }); | ||
var ESCAPED = {}; | ||
'\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-' | ||
.split('').forEach(function(ch) { ESCAPED[ch.charCodeAt(0)] = true; }); | ||
module.exports = function escape(state) { | ||
@@ -17,3 +18,3 @@ var ch, pos = state.pos, max = state.posMax; | ||
if (ESCAPED.indexOf(ch) >= 0) { | ||
if (typeof ESCAPED[ch] !== 'undefined') { | ||
// escape html chars if needed | ||
@@ -20,0 +21,0 @@ if (ch === 0x26/* & */) { |
@@ -13,10 +13,11 @@ // Inline parser state | ||
this.pos = 0; | ||
this.posMax = this.src.length; | ||
this.level = 0; | ||
this.pending = ''; | ||
this.posMax = this.src.length; | ||
this.pendingLevel = 0; | ||
this.validateInsideEm = false; | ||
this.validateInsideLink = false; | ||
this.linkLevel = 0; | ||
this.level = 0; | ||
this.link_content = ''; | ||
this.pendingLevel = 0; | ||
this.label_nest_level = 0; // for stmd-like backtrack optimization | ||
@@ -27,7 +28,5 @@ } | ||
StateInline.prototype.pushPending = function () { | ||
var pending = this.pending; | ||
this.tokens.push({ | ||
type: 'text', | ||
content: pending, | ||
content: this.pending, | ||
level: this.pendingLevel | ||
@@ -47,9 +46,3 @@ }); | ||
StateInline.prototype.skipSpaces = function skipSpaces(pos) { | ||
for (var max = this.src.length; pos < max; pos++) { | ||
if (this.src.charCodeAt(pos) !== 0x20/* space */) { break; } | ||
} | ||
return pos; | ||
}; | ||
module.exports = StateInline; |
@@ -26,5 +26,5 @@ // Process ~~strike through~~ | ||
if (state.level >= state.options.level) { return false; } | ||
if (state.level >= state.options.maxNesting) { return false; } | ||
lastChar = state.pending.length !== 0 ? state.pending.charCodeAt(state.pending.length - 1) : -1; | ||
lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1; | ||
nextChar = state.src.charCodeAt(start + 2); | ||
@@ -34,3 +34,3 @@ | ||
if (nextChar === 0x7E/* */) { return false; } | ||
if (nextChar === 0x20/* */) { return false; } | ||
if (nextChar === 0x20 || nextChar === 0x0A) { return false; } | ||
@@ -57,9 +57,9 @@ pos = start + 2; | ||
if (state.src.charCodeAt(state.pos + 1) === 0x7E/* ~ */) { | ||
lastChar = state.pending.length !== 0 ? state.pending.charCodeAt(state.pending.length - 1) : -1; | ||
lastChar = state.src.charCodeAt(state.pos - 1); | ||
nextChar = state.pos + 2 < max ? state.src.charCodeAt(state.pos + 2) : -1; | ||
if (nextChar !== 0x7E/* ~ */ && lastChar !== 0x7E/* ~ */) { | ||
if (lastChar !== 0x20) { | ||
if (lastChar !== 0x20 && lastChar !== 0x0A) { | ||
// closing '~~' | ||
stack--; | ||
} else if (nextChar !== 0x20) { | ||
} else if (nextChar !== 0x20 && nextChar !== 0x0A) { | ||
// opening '~~' | ||
@@ -66,0 +66,0 @@ stack++; |
@@ -23,2 +23,4 @@ // Class of typographic replacements rules | ||
function Typographer() { | ||
this._rules = []; | ||
this.options = assign({}, defaults); | ||
@@ -47,4 +49,2 @@ | ||
if (!state.options.typographer) { return; } | ||
rules = this._rules; | ||
@@ -51,0 +51,0 @@ |
{ | ||
"name": "remarkable", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Markdown parser, done right. Commonmark support, extensions, syntax plugins, high speed - all in one.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -1,3 +0,1 @@ | ||
cooming soon | ||
remarkable | ||
@@ -33,3 +31,5 @@ ========== | ||
CDNs for browser: [jsDeliver](http://www.jsdelivr.com/#!remarkable "jsDelivr CDN") | ||
## Usage | ||
@@ -54,3 +54,3 @@ | ||
console.log(md.parse('# Remarkable rulezz!')); | ||
console.log(md.render('# Remarkable rulezz!')); | ||
// => <h1>Remarkable rulezz!</h1> | ||
@@ -71,5 +71,5 @@ ``` | ||
__Note.__ To acheive best performance, don't modify `Remarkable` instance on | ||
__Note.__ To acheive best performance, don't modify the `Remarkable` instance on | ||
the fly. If you need several configurations - create multiple instances and | ||
setup each appropriately. | ||
initialise each appropriately. | ||
@@ -91,3 +91,3 @@ You can also reset parser to strict [CommonMark](http://commonmark.org/) mode: | ||
// This values are default | ||
// These values are default | ||
var md = new Remarkable({ | ||
@@ -110,5 +110,5 @@ highlight: function (str, lang) { | ||
### Typorgapher | ||
### Typographer | ||
Though full weigh typograpic replacements are language specific, `remarkable` | ||
Though full-weight typograpic replacements are language specific, `remarkable` | ||
provides the most common and universal case coverage: | ||
@@ -120,3 +120,3 @@ | ||
// This values are default | ||
// These values are default | ||
md.typographer.set({ | ||
@@ -136,3 +136,3 @@ singleQuotes: '‘’', // set empty to disable | ||
Of cause, you can add your own rules or replace default one with something | ||
Of course, you can add your own rules or replace default ones with something | ||
more advanced, specific for your language. | ||
@@ -142,3 +142,3 @@ | ||
This extentions are enabled by default: | ||
These extensions are enabled by default: | ||
@@ -151,5 +151,5 @@ - [Strikethrough](https://help.github.com/articles/github-flavored-markdown/#strikethrough) | ||
Big thanks to [John MacFarlane](https://github.com/jgm) for his work on | ||
Big thanks to [John MacFarlane](https://github.com/jgm) for his work on the | ||
CommonMark spec and reference implementations. His work saved us a lot of time | ||
during this project development. | ||
during this project's development. | ||
@@ -156,0 +156,0 @@ Links: |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
5
0
446672
53
12452