remarkable
Advanced tools
Comparing version
@@ -50,7 +50,7 @@ #!/usr/bin/env node | ||
readFile(options.file, 'utf8', function (error, input) { | ||
readFile(options.file, 'utf8', function (err, input) { | ||
var output, md; | ||
if (error) { | ||
if (error.code === 'ENOENT') { | ||
if (err) { | ||
if (err.code === 'ENOENT') { | ||
console.error('File not found: ' + options.file); | ||
@@ -60,3 +60,3 @@ process.exit(2); | ||
console.error(error.stack || error.message || String(error)); | ||
console.error(err.stack || err.message || String(err)); | ||
@@ -76,4 +76,4 @@ process.exit(1); | ||
} catch (error) { | ||
console.error(error.stack || error.message || String(error)); | ||
} catch (e) { | ||
console.error(e.stack || e.message || String(e)); | ||
@@ -80,0 +80,0 @@ process.exit(1); |
@@ -0,1 +1,12 @@ | ||
1.5.0 / 2014-12-12 | ||
------------------ | ||
- Added Demo sync scroll, to show how lines mapping can be used. | ||
- Improved IE8 support. Now you need only es5-shim, without es5-sham. | ||
- Fixed errors on refs/attrs/footnoted with special names like `__proto__`. | ||
- Renamed Ruler() private properties, to show those should not be accessed | ||
directly. | ||
- Fixed Makefile OSX compatibility. | ||
1.4.2 / 2014-11-29 | ||
@@ -2,0 +13,0 @@ ------------------ |
'use strict'; | ||
module.exports = function normalizeReference(str) { | ||
return str.trim().replace(/\s+/g, ' ').toLowerCase(); | ||
// use .toUpperCase() instead of .toLowerCase() | ||
// here to avoid a conflict with Object.prototype | ||
// members (most notably, `__proto__`) | ||
return str.trim().replace(/\s+/g, ' ').toUpperCase(); | ||
}; |
125
lib/ruler.js
@@ -22,3 +22,3 @@ // Ruler is helper class to build responsibility chains from parse rules. | ||
// | ||
this.rules = []; | ||
this.__rules__ = []; | ||
@@ -30,11 +30,14 @@ // Cached rule chains. | ||
// | ||
this.cache = null; | ||
this.__cache__ = null; | ||
} | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// Helper methods, should not be used directly | ||
// Find rule index by name | ||
// | ||
Ruler.prototype.find = function (name) { | ||
for (var i = 0; i < this.rules.length; i++) { | ||
if (this.rules[i].name === name) { | ||
Ruler.prototype.__find__ = function (name) { | ||
for (var i = 0; i < this.__rules__.length; i++) { | ||
if (this.__rules__[i].name === name) { | ||
return i; | ||
@@ -47,6 +50,42 @@ } | ||
// Build rules lookup cache | ||
// | ||
Ruler.prototype.__compile__ = function () { | ||
var self = this; | ||
var chains = [ '' ]; | ||
// collect unique names | ||
self.__rules__.forEach(function (rule) { | ||
if (!rule.enabled) { return; } | ||
rule.alt.forEach(function (altName) { | ||
if (chains.indexOf(altName) < 0) { | ||
chains.push(altName); | ||
} | ||
}); | ||
}); | ||
self.__cache__ = {}; | ||
chains.forEach(function (chain) { | ||
self.__cache__[chain] = []; | ||
self.__rules__.forEach(function (rule) { | ||
if (!rule.enabled) { return; } | ||
if (chain && rule.alt.indexOf(chain) < 0) { return; } | ||
self.__cache__[chain].push(rule.fn); | ||
}); | ||
}); | ||
}; | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// Public methods | ||
// Replace rule function | ||
// | ||
Ruler.prototype.at = function (name, fn, options) { | ||
var index = this.find(name); | ||
var index = this.__find__(name); | ||
var opt = options || {}; | ||
@@ -56,5 +95,5 @@ | ||
this.rules[index].fn = fn; | ||
this.rules[index].alt = opt.alt || []; | ||
this.cache = null; | ||
this.__rules__[index].fn = fn; | ||
this.__rules__[index].alt = opt.alt || []; | ||
this.__cache__ = null; | ||
}; | ||
@@ -66,3 +105,3 @@ | ||
Ruler.prototype.before = function (beforeName, ruleName, fn, options) { | ||
var index = this.find(beforeName); | ||
var index = this.__find__(beforeName); | ||
var opt = options || {}; | ||
@@ -72,3 +111,3 @@ | ||
this.rules.splice(index, 0, { | ||
this.__rules__.splice(index, 0, { | ||
name: ruleName, | ||
@@ -80,3 +119,3 @@ enabled: true, | ||
this.cache = null; | ||
this.__cache__ = null; | ||
}; | ||
@@ -88,3 +127,3 @@ | ||
Ruler.prototype.after = function (afterName, ruleName, fn, options) { | ||
var index = this.find(afterName); | ||
var index = this.__find__(afterName); | ||
var opt = options || {}; | ||
@@ -94,3 +133,3 @@ | ||
this.rules.splice(index + 1, 0, { | ||
this.__rules__.splice(index + 1, 0, { | ||
name: ruleName, | ||
@@ -102,3 +141,3 @@ enabled: true, | ||
this.cache = null; | ||
this.__cache__ = null; | ||
}; | ||
@@ -111,3 +150,3 @@ | ||
this.rules.push({ | ||
this.__rules__.push({ | ||
name: ruleName, | ||
@@ -119,3 +158,3 @@ enabled: true, | ||
this.cache = null; | ||
this.__cache__ = null; | ||
}; | ||
@@ -134,3 +173,3 @@ | ||
if (strict) { | ||
this.rules.forEach(function (rule) { | ||
this.__rules__.forEach(function (rule) { | ||
rule.enabled = false; | ||
@@ -142,10 +181,10 @@ }); | ||
list.forEach(function (name) { | ||
var idx = this.find(name); | ||
var idx = this.__find__(name); | ||
if (idx < 0) { throw new Error('Rules manager: invalid rule name ' + name); } | ||
this.rules[idx].enabled = true; | ||
this.__rules__[idx].enabled = true; | ||
}, this); | ||
this.cache = null; | ||
this.__cache__ = null; | ||
}; | ||
@@ -163,55 +202,23 @@ | ||
list.forEach(function (name) { | ||
var idx = this.find(name); | ||
var idx = this.__find__(name); | ||
if (idx < 0) { throw new Error('Rules manager: invalid rule name ' + name); } | ||
this.rules[idx].enabled = false; | ||
this.__rules__[idx].enabled = false; | ||
}, this); | ||
this.cache = null; | ||
this.__cache__ = null; | ||
}; | ||
// Build rules lookup cache | ||
// | ||
Ruler.prototype.compile = function () { | ||
var self = this; | ||
var chains = [ '' ]; | ||
// collect unique names | ||
self.rules.forEach(function (rule) { | ||
if (!rule.enabled) { return; } | ||
rule.alt.forEach(function (altName) { | ||
if (chains.indexOf(altName) < 0) { | ||
chains.push(altName); | ||
} | ||
}); | ||
}); | ||
self.cache = {}; | ||
chains.forEach(function (chain) { | ||
self.cache[chain] = []; | ||
self.rules.forEach(function (rule) { | ||
if (!rule.enabled) { return; } | ||
if (chain && rule.alt.indexOf(chain) < 0) { return; } | ||
self.cache[chain].push(rule.fn); | ||
}); | ||
}); | ||
}; | ||
// Get rules list as array of functions. | ||
// | ||
Ruler.prototype.getRules = function (chainName) { | ||
if (this.cache === null) { | ||
this.compile(); | ||
if (this.__cache__ === null) { | ||
this.__compile__(); | ||
} | ||
return this.cache[chainName]; | ||
return this.__cache__[chainName]; | ||
}; | ||
module.exports = Ruler; |
@@ -31,5 +31,5 @@ // Process footnote reference list | ||
if (!state.env.footnotes) { state.env.footnotes = {}; } | ||
if (!state.env.footnotes.refs) { state.env.footnotes.refs = Object.create(null); } | ||
if (!state.env.footnotes.refs) { state.env.footnotes.refs = {}; } | ||
label = state.src.slice(start + 2, pos - 2); | ||
state.env.footnotes.refs[label] = -1; | ||
state.env.footnotes.refs[':' + label] = -1; | ||
@@ -36,0 +36,0 @@ state.tokens.push({ |
@@ -31,4 +31,4 @@ // heading (#, ##, ...) | ||
max = state.skipCharsBack(max, 0x20/* space */, pos); | ||
tmp = state.skipCharsBack(max, 0x23/* # */, pos); | ||
max = state.skipCharsBack(max, 0x20, pos); // space | ||
tmp = state.skipCharsBack(max, 0x23, pos); // # | ||
if (tmp > pos && state.src.charCodeAt(tmp - 1) === 0x20/* space */) { | ||
@@ -35,0 +35,0 @@ max = tmp; |
@@ -185,4 +185,2 @@ // Lists | ||
//nextLine++; | ||
oldIndent = state.blkIndent; | ||
@@ -189,0 +187,0 @@ oldTight = state.tight; |
@@ -35,3 +35,6 @@ // Parse abbreviation definitions, i.e. `*[abbr]: description` | ||
if (!env.abbreviations) { env.abbreviations = {}; } | ||
env.abbreviations[label] = env.abbreviations[label] || title; | ||
// prepend ':' to avoid conflict with Object.prototype members | ||
if (typeof env.abbreviations[':' + label] === 'undefined') { | ||
env.abbreviations[':' + label] = title; | ||
} | ||
@@ -38,0 +41,0 @@ return pos; |
@@ -23,3 +23,5 @@ // Enclose abbreviations in <abbr> tags | ||
regText = '(^|[' + PUNCT_CHARS.split('').map(regEscape).join('') + '])' | ||
+ '(' + Object.keys(state.env.abbreviations).sort(function (a, b) { | ||
+ '(' + Object.keys(state.env.abbreviations).map(function (x) { | ||
return x.substr(1); | ||
}).sort(function (a, b) { | ||
return b.length - a.length; | ||
@@ -58,3 +60,3 @@ }).map(regEscape).join('|') + ')' | ||
type: 'abbr_open', | ||
title: state.env.abbreviations[m[2]], | ||
title: state.env.abbreviations[':' + m[2]], | ||
level: level++ | ||
@@ -61,0 +63,0 @@ }); |
@@ -8,3 +8,3 @@ 'use strict'; | ||
insideRef = false, | ||
refTokens = Object.create(null); | ||
refTokens = {}; | ||
@@ -22,3 +22,4 @@ if (!state.env.footnotes) { return; } | ||
insideRef = false; | ||
refTokens[currentLabel] = current; | ||
// prepend ':' to avoid conflict with Object.prototype members | ||
refTokens[':' + currentLabel] = current; | ||
return false; | ||
@@ -63,3 +64,3 @@ } | ||
} else if (list[i].label) { | ||
tokens = refTokens[list[i].label]; | ||
tokens = refTokens[':' + list[i].label]; | ||
} | ||
@@ -66,0 +67,0 @@ |
@@ -61,3 +61,5 @@ 'use strict'; | ||
label = normalizeReference(str.slice(1, labelEnd)); | ||
env.references[label] = env.references[label] || { title: title, href: href }; | ||
if (typeof env.references[label] === 'undefined') { | ||
env.references[label] = { title: title, href: href }; | ||
} | ||
@@ -64,0 +66,0 @@ return pos; |
@@ -32,3 +32,3 @@ // Parse backticks | ||
content: state.src.slice(pos, matchStart) | ||
.replace(/[ \n]+/g,' ') | ||
.replace(/[ \n]+/g, ' ') | ||
.trim(), | ||
@@ -35,0 +35,0 @@ block: false, |
@@ -53,3 +53,3 @@ // Process ~~deleted text~~ | ||
// // standalone ' ~~ ' indented with spaces | ||
//} | ||
// } | ||
if (stack <= 0) { | ||
@@ -56,0 +56,0 @@ found = true; |
@@ -35,3 +35,3 @@ // Process footnote references ([^...]) | ||
label = state.src.slice(start + 2, pos - 1); | ||
if (state.env.footnotes.refs[label] === undefined) { return false; } | ||
if (typeof state.env.footnotes.refs[':' + label] === 'undefined') { return false; } | ||
@@ -41,8 +41,8 @@ if (!silent) { | ||
if (state.env.footnotes.refs[label] < 0) { | ||
if (state.env.footnotes.refs[':' + label] < 0) { | ||
footnoteId = state.env.footnotes.list.length; | ||
state.env.footnotes.list[footnoteId] = { label: label, count: 0 }; | ||
state.env.footnotes.refs[label] = footnoteId; | ||
state.env.footnotes.refs[':' + label] = footnoteId; | ||
} else { | ||
footnoteId = state.env.footnotes.refs[label]; | ||
footnoteId = state.env.footnotes.refs[':' + label]; | ||
} | ||
@@ -49,0 +49,0 @@ |
@@ -53,3 +53,3 @@ // Process ++inserted text++ | ||
// // standalone ' ++ ' indented with spaces | ||
//} | ||
// } | ||
if (stack <= 0) { | ||
@@ -56,0 +56,0 @@ found = true; |
@@ -53,3 +53,3 @@ // Process ==highlighted text== | ||
// // standalone ' == ' indented with spaces | ||
//} | ||
// } | ||
if (stack <= 0) { | ||
@@ -56,0 +56,0 @@ found = true; |
{ | ||
"name": "remarkable", | ||
"version": "1.4.2", | ||
"version": "1.5.0", | ||
"description": "Markdown parser, done right.", | ||
@@ -34,3 +34,3 @@ "keywords": [ | ||
"coveralls": "^2.11.2", | ||
"eslint": "0.9.1", | ||
"eslint": "0.10.1", | ||
"eslint-plugin-nodeca": "^1.0.0", | ||
@@ -37,0 +37,0 @@ "istanbul": "*", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
546886
0.4%14691
0.2%