Merge branch 'master' into update-templates
This commit is contained in:
commit
a14ac2e2d0
27
.eslintrc.json
Normal file
27
.eslintrc.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"extends": "standard",
|
||||||
|
"plugins": [
|
||||||
|
"standard"
|
||||||
|
],
|
||||||
|
"parserOptions": { "ecmaVersion": 5 },
|
||||||
|
"rules": {
|
||||||
|
"semi": "off",
|
||||||
|
"indent": ["warn", 2, {
|
||||||
|
"VariableDeclarator": { "var": 2 },
|
||||||
|
"SwitchCase": 1,
|
||||||
|
"outerIIFEBody": 0
|
||||||
|
}],
|
||||||
|
"space-before-function-paren": "off",
|
||||||
|
"operator-linebreak": ["error", "before", { "overrides": { "=": "after" } }],
|
||||||
|
"no-cond-assign": "off",
|
||||||
|
"no-useless-escape": "off",
|
||||||
|
"no-return-assign": "off",
|
||||||
|
"one-var": "off",
|
||||||
|
"no-control-regex": "off"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"browser": true,
|
||||||
|
"amd": true
|
||||||
|
}
|
||||||
|
}
|
15
.travis.yml
15
.travis.yml
@ -1,5 +1,16 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "0.10"
|
- "0.10"
|
||||||
- "0.8"
|
- "4"
|
||||||
- "0.6"
|
- "lts/*"
|
||||||
|
- "node"
|
||||||
|
script: |
|
||||||
|
if [ `node --version | cut -d . -f 1,2` = "v0.10" ]; then
|
||||||
|
sed -i s/0o755/0755/ test/index.js;
|
||||||
|
npm test;
|
||||||
|
else
|
||||||
|
npm run lint && npm test;
|
||||||
|
fi
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
||||||
|
245
lib/marked.js
245
lib/marked.js
@ -4,7 +4,7 @@
|
|||||||
* https://github.com/chjj/marked
|
* https://github.com/chjj/marked
|
||||||
*/
|
*/
|
||||||
|
|
||||||
;(function() {
|
;(function(root) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,45 +30,45 @@ var block = {
|
|||||||
|
|
||||||
block._label = /(?:\\[\[\]]|[^\[\]])+/;
|
block._label = /(?:\\[\[\]]|[^\[\]])+/;
|
||||||
block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/;
|
block._title = /(?:"(?:\\"|[^"]|"[^"\n]*")*"|'\n?(?:[^'\n]+\n?)*'|\([^()]*\))/;
|
||||||
block.def = replace(block.def)
|
block.def = edit(block.def)
|
||||||
('label', block._label)
|
.replace('label', block._label)
|
||||||
('title', block._title)
|
.replace('title', block._title)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
block.bullet = /(?:[*+-]|\d+\.)/;
|
block.bullet = /(?:[*+-]|\d+\.)/;
|
||||||
block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
|
block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
|
||||||
block.item = replace(block.item, 'gm')
|
block.item = edit(block.item, 'gm')
|
||||||
(/bull/g, block.bullet)
|
.replace(/bull/g, block.bullet)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
block.list = replace(block.list)
|
block.list = edit(block.list)
|
||||||
(/bull/g, block.bullet)
|
.replace(/bull/g, block.bullet)
|
||||||
('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
|
.replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))')
|
||||||
('def', '\\n+(?=' + block.def.source + ')')
|
.replace('def', '\\n+(?=' + block.def.source + ')')
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
block._tag = '(?!(?:'
|
block._tag = '(?!(?:'
|
||||||
+ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
|
+ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
|
||||||
+ '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
|
+ '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
|
||||||
+ '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b';
|
+ '|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b';
|
||||||
|
|
||||||
block.html = replace(block.html)
|
block.html = edit(block.html)
|
||||||
('comment', /<!--[\s\S]*?-->/)
|
.replace('comment', /<!--[\s\S]*?-->/)
|
||||||
('closed', /<(tag)[\s\S]+?<\/\1>/)
|
.replace('closed', /<(tag)[\s\S]+?<\/\1>/)
|
||||||
('closing', /<tag(?:"[^"]*"|'[^']*'|\s[^'"\/>]*)*?\/?>/)
|
.replace('closing', /<tag(?:"[^"]*"|'[^']*'|\s[^'"\/>]*)*?\/?>/)
|
||||||
(/tag/g, block._tag)
|
.replace(/tag/g, block._tag)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
block.paragraph = replace(block.paragraph)
|
block.paragraph = edit(block.paragraph)
|
||||||
('hr', block.hr)
|
.replace('hr', block.hr)
|
||||||
('heading', block.heading)
|
.replace('heading', block.heading)
|
||||||
('lheading', block.lheading)
|
.replace('lheading', block.lheading)
|
||||||
('tag', '<' + block._tag)
|
.replace('tag', '<' + block._tag)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
block.blockquote = replace(block.blockquote)
|
block.blockquote = edit(block.blockquote)
|
||||||
('paragraph', block.paragraph)
|
.replace('paragraph', block.paragraph)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normal Block Grammar
|
* Normal Block Grammar
|
||||||
@ -86,11 +86,11 @@ block.gfm = merge({}, block.normal, {
|
|||||||
heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
|
heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
|
||||||
});
|
});
|
||||||
|
|
||||||
block.gfm.paragraph = replace(block.paragraph)
|
block.gfm.paragraph = edit(block.paragraph)
|
||||||
('(?!', '(?!'
|
.replace('(?!', '(?!'
|
||||||
+ block.gfm.fences.source.replace('\\1', '\\2') + '|'
|
+ block.gfm.fences.source.replace('\\1', '\\2') + '|'
|
||||||
+ block.list.source.replace('\\1', '\\3') + '|')
|
+ block.list.source.replace('\\1', '\\3') + '|')
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GFM + Tables Block Grammar
|
* GFM + Tables Block Grammar
|
||||||
@ -154,17 +154,17 @@ Lexer.prototype.lex = function(src) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Lexer.prototype.token = function(src, top) {
|
Lexer.prototype.token = function(src, top) {
|
||||||
var src = src.replace(/^ +$/gm, '')
|
src = src.replace(/^ +$/gm, '');
|
||||||
, next
|
var next,
|
||||||
, loose
|
loose,
|
||||||
, cap
|
cap,
|
||||||
, bull
|
bull,
|
||||||
, b
|
b,
|
||||||
, item
|
item,
|
||||||
, space
|
space,
|
||||||
, i
|
i,
|
||||||
, tag
|
tag,
|
||||||
, l;
|
l;
|
||||||
|
|
||||||
while (src) {
|
while (src) {
|
||||||
// newline
|
// newline
|
||||||
@ -366,7 +366,7 @@ Lexer.prototype.token = function(src, top) {
|
|||||||
// def
|
// def
|
||||||
if (top && (cap = this.rules.def.exec(src))) {
|
if (top && (cap = this.rules.def.exec(src))) {
|
||||||
src = src.substring(cap[0].length);
|
src = src.substring(cap[0].length);
|
||||||
if (cap[3]) cap[3] = cap[3].substring(1,cap[3].length-1);
|
if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
|
||||||
tag = cap[1].toLowerCase();
|
tag = cap[1].toLowerCase();
|
||||||
if (!this.tokens.links[tag]) {
|
if (!this.tokens.links[tag]) {
|
||||||
this.tokens.links[tag] = {
|
this.tokens.links[tag] = {
|
||||||
@ -446,8 +446,7 @@ Lexer.prototype.token = function(src, top) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
throw new
|
throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
||||||
Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,22 +476,22 @@ var inline = {
|
|||||||
inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
|
inline._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
|
||||||
inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
|
inline._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
|
||||||
|
|
||||||
inline.autolink = replace(inline.autolink)
|
inline.autolink = edit(inline.autolink)
|
||||||
('scheme', inline._scheme)
|
.replace('scheme', inline._scheme)
|
||||||
('email', inline._email)
|
.replace('email', inline._email)
|
||||||
()
|
.getRegex()
|
||||||
|
|
||||||
inline._inside = /(?:\[[^\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/;
|
inline._inside = /(?:\[[^\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/;
|
||||||
inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
|
inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
|
||||||
|
|
||||||
inline.link = replace(inline.link)
|
inline.link = edit(inline.link)
|
||||||
('inside', inline._inside)
|
.replace('inside', inline._inside)
|
||||||
('href', inline._href)
|
.replace('href', inline._href)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
inline.reflink = replace(inline.reflink)
|
inline.reflink = edit(inline.reflink)
|
||||||
('inside', inline._inside)
|
.replace('inside', inline._inside)
|
||||||
();
|
.getRegex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normal Inline Grammar
|
* Normal Inline Grammar
|
||||||
@ -514,16 +513,16 @@ inline.pedantic = merge({}, inline.normal, {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
inline.gfm = merge({}, inline.normal, {
|
inline.gfm = merge({}, inline.normal, {
|
||||||
escape: replace(inline.escape)('])', '~|])')(),
|
escape: edit(inline.escape).replace('])', '~|])').getRegex(),
|
||||||
url: replace(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/)
|
url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/)
|
||||||
('email', inline._email)
|
.replace('email', inline._email)
|
||||||
(),
|
.getRegex(),
|
||||||
_backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
|
_backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
|
||||||
del: /^~~(?=\S)([\s\S]*?\S)~~/,
|
del: /^~~(?=\S)([\s\S]*?\S)~~/,
|
||||||
text: replace(inline.text)
|
text: edit(inline.text)
|
||||||
(']|', '~]|')
|
.replace(']|', '~]|')
|
||||||
('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|')
|
.replace('|', '|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&\'*+/=?^_`{\\|}~-]+@|')
|
||||||
()
|
.getRegex()
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -531,8 +530,8 @@ inline.gfm = merge({}, inline.normal, {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
inline.breaks = merge({}, inline.gfm, {
|
inline.breaks = merge({}, inline.gfm, {
|
||||||
br: replace(inline.br)('{2,}', '*')(),
|
br: edit(inline.br).replace('{2,}', '*').getRegex(),
|
||||||
text: replace(inline.gfm.text)('{2,}', '*')()
|
text: edit(inline.gfm.text).replace('{2,}', '*').getRegex()
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -543,12 +542,11 @@ function InlineLexer(links, options) {
|
|||||||
this.options = options || marked.defaults;
|
this.options = options || marked.defaults;
|
||||||
this.links = links;
|
this.links = links;
|
||||||
this.rules = inline.normal;
|
this.rules = inline.normal;
|
||||||
this.renderer = this.options.renderer || new Renderer;
|
this.renderer = this.options.renderer || new Renderer();
|
||||||
this.renderer.options = this.options;
|
this.renderer.options = this.options;
|
||||||
|
|
||||||
if (!this.links) {
|
if (!this.links) {
|
||||||
throw new
|
throw new Error('Tokens array requires a `links` property.');
|
||||||
Error('Tokens array requires a `links` property.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.gfm) {
|
if (this.options.gfm) {
|
||||||
@ -582,11 +580,11 @@ InlineLexer.output = function(src, links, options) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
InlineLexer.prototype.output = function(src) {
|
InlineLexer.prototype.output = function(src) {
|
||||||
var out = ''
|
var out = '',
|
||||||
, link
|
link,
|
||||||
, text
|
text,
|
||||||
, href
|
href,
|
||||||
, cap;
|
cap;
|
||||||
|
|
||||||
while (src) {
|
while (src) {
|
||||||
// escape
|
// escape
|
||||||
@ -717,8 +715,7 @@ InlineLexer.prototype.output = function(src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
throw new
|
throw new Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
||||||
Error('Infinite loop on byte: ' + src.charCodeAt(0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,8 +727,8 @@ InlineLexer.prototype.output = function(src) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
InlineLexer.prototype.outputLink = function(cap, link) {
|
InlineLexer.prototype.outputLink = function(cap, link) {
|
||||||
var href = escape(link.href)
|
var href = escape(link.href),
|
||||||
, title = link.title ? escape(link.title) : null;
|
title = link.title ? escape(link.title) : null;
|
||||||
|
|
||||||
return cap[0].charAt(0) !== '!'
|
return cap[0].charAt(0) !== '!'
|
||||||
? this.renderer.link(href, title, this.output(cap[1]))
|
? this.renderer.link(href, title, this.output(cap[1]))
|
||||||
@ -767,10 +764,10 @@ InlineLexer.prototype.smartypants = function(text) {
|
|||||||
|
|
||||||
InlineLexer.prototype.mangle = function(text) {
|
InlineLexer.prototype.mangle = function(text) {
|
||||||
if (!this.options.mangle) return text;
|
if (!this.options.mangle) return text;
|
||||||
var out = ''
|
var out = '',
|
||||||
, l = text.length
|
l = text.length,
|
||||||
, i = 0
|
i = 0,
|
||||||
, ch;
|
ch;
|
||||||
|
|
||||||
for (; i < l; i++) {
|
for (; i < l; i++) {
|
||||||
ch = text.charCodeAt(i);
|
ch = text.charCodeAt(i);
|
||||||
@ -970,7 +967,7 @@ function Parser(options) {
|
|||||||
this.tokens = [];
|
this.tokens = [];
|
||||||
this.token = null;
|
this.token = null;
|
||||||
this.options = options || marked.defaults;
|
this.options = options || marked.defaults;
|
||||||
this.options.renderer = this.options.renderer || new Renderer;
|
this.options.renderer = this.options.renderer || new Renderer();
|
||||||
this.renderer = this.options.renderer;
|
this.renderer = this.options.renderer;
|
||||||
this.renderer.options = this.options;
|
this.renderer.options = this.options;
|
||||||
}
|
}
|
||||||
@ -991,7 +988,10 @@ Parser.parse = function(src, options) {
|
|||||||
Parser.prototype.parse = function(src) {
|
Parser.prototype.parse = function(src) {
|
||||||
this.inline = new InlineLexer(src.links, this.options);
|
this.inline = new InlineLexer(src.links, this.options);
|
||||||
// use an InlineLexer with a TextRenderer to extract pure text
|
// use an InlineLexer with a TextRenderer to extract pure text
|
||||||
this.inlineText = new InlineLexer(src.links, merge({}, this.options, {renderer: new TextRenderer}));
|
this.inlineText = new InlineLexer(
|
||||||
|
src.links,
|
||||||
|
merge({}, this.options, {renderer: new TextRenderer()})
|
||||||
|
);
|
||||||
this.tokens = src.reverse();
|
this.tokens = src.reverse();
|
||||||
|
|
||||||
var out = '';
|
var out = '';
|
||||||
@ -1056,12 +1056,12 @@ Parser.prototype.tok = function() {
|
|||||||
this.token.escaped);
|
this.token.escaped);
|
||||||
}
|
}
|
||||||
case 'table': {
|
case 'table': {
|
||||||
var header = ''
|
var header = '',
|
||||||
, body = ''
|
body = '',
|
||||||
, i
|
i,
|
||||||
, row
|
row,
|
||||||
, cell
|
cell,
|
||||||
, j;
|
j;
|
||||||
|
|
||||||
// header
|
// header
|
||||||
cell = '';
|
cell = '';
|
||||||
@ -1089,7 +1089,7 @@ Parser.prototype.tok = function() {
|
|||||||
return this.renderer.table(header, body);
|
return this.renderer.table(header, body);
|
||||||
}
|
}
|
||||||
case 'blockquote_start': {
|
case 'blockquote_start': {
|
||||||
var body = '';
|
body = '';
|
||||||
|
|
||||||
while (this.next().type !== 'blockquote_end') {
|
while (this.next().type !== 'blockquote_end') {
|
||||||
body += this.tok();
|
body += this.tok();
|
||||||
@ -1098,8 +1098,8 @@ Parser.prototype.tok = function() {
|
|||||||
return this.renderer.blockquote(body);
|
return this.renderer.blockquote(body);
|
||||||
}
|
}
|
||||||
case 'list_start': {
|
case 'list_start': {
|
||||||
var body = ''
|
body = '';
|
||||||
, ordered = this.token.ordered;
|
var ordered = this.token.ordered;
|
||||||
|
|
||||||
while (this.next().type !== 'list_end') {
|
while (this.next().type !== 'list_end') {
|
||||||
body += this.tok();
|
body += this.tok();
|
||||||
@ -1108,7 +1108,7 @@ Parser.prototype.tok = function() {
|
|||||||
return this.renderer.list(body, ordered);
|
return this.renderer.list(body, ordered);
|
||||||
}
|
}
|
||||||
case 'list_item_start': {
|
case 'list_item_start': {
|
||||||
var body = '';
|
body = '';
|
||||||
|
|
||||||
while (this.next().type !== 'list_item_end') {
|
while (this.next().type !== 'list_item_end') {
|
||||||
body += this.token.type === 'text'
|
body += this.token.type === 'text'
|
||||||
@ -1119,7 +1119,7 @@ Parser.prototype.tok = function() {
|
|||||||
return this.renderer.listitem(body);
|
return this.renderer.listitem(body);
|
||||||
}
|
}
|
||||||
case 'loose_item_start': {
|
case 'loose_item_start': {
|
||||||
var body = '';
|
body = '';
|
||||||
|
|
||||||
while (this.next().type !== 'list_item_end') {
|
while (this.next().type !== 'list_item_end') {
|
||||||
body += this.tok();
|
body += this.tok();
|
||||||
@ -1156,7 +1156,7 @@ function escape(html, encode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function unescape(html) {
|
function unescape(html) {
|
||||||
// explicitly match decimal, hex, and named HTML entities
|
// explicitly match decimal, hex, and named HTML entities
|
||||||
return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) {
|
return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, function(_, n) {
|
||||||
n = n.toLowerCase();
|
n = n.toLowerCase();
|
||||||
if (n === 'colon') return ':';
|
if (n === 'colon') return ':';
|
||||||
@ -1169,15 +1169,19 @@ function unescape(html) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function replace(regex, opt) {
|
function edit(regex, opt) {
|
||||||
regex = regex.source;
|
regex = regex.source;
|
||||||
opt = opt || '';
|
opt = opt || '';
|
||||||
return function self(name, val) {
|
return {
|
||||||
if (!name) return new RegExp(regex, opt);
|
replace: function(name, val) {
|
||||||
val = val.source || val;
|
val = val.source || val;
|
||||||
val = val.replace(/(^|[^\[])\^/g, '$1');
|
val = val.replace(/(^|[^\[])\^/g, '$1');
|
||||||
regex = regex.replace(name, val);
|
regex = regex.replace(name, val);
|
||||||
return self;
|
return this;
|
||||||
|
},
|
||||||
|
getRegex: function() {
|
||||||
|
return new RegExp(regex, opt);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1209,9 +1213,9 @@ function noop() {}
|
|||||||
noop.exec = noop;
|
noop.exec = noop;
|
||||||
|
|
||||||
function merge(obj) {
|
function merge(obj) {
|
||||||
var i = 1
|
var i = 1,
|
||||||
, target
|
target,
|
||||||
, key;
|
key;
|
||||||
|
|
||||||
for (; i < arguments.length; i++) {
|
for (; i < arguments.length; i++) {
|
||||||
target = arguments[i];
|
target = arguments[i];
|
||||||
@ -1225,19 +1229,19 @@ function merge(obj) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marked
|
* Marked
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function marked(src, opt, callback) {
|
function marked(src, opt, callback) {
|
||||||
// throw error in case of non string input
|
// throw error in case of non string input
|
||||||
if (typeof src == 'undefined' || src === null)
|
if (typeof src === 'undefined' || src === null) {
|
||||||
throw new Error('marked(): input parameter is undefined or null');
|
throw new Error('marked(): input parameter is undefined or null');
|
||||||
if (typeof src != 'string')
|
}
|
||||||
throw new Error('marked(): input parameter is of type ' +
|
if (typeof src !== 'string') {
|
||||||
Object.prototype.toString.call(src) + ', string expected');
|
throw new Error('marked(): input parameter is of type '
|
||||||
|
+ Object.prototype.toString.call(src) + ', string expected');
|
||||||
|
}
|
||||||
|
|
||||||
if (callback || typeof opt === 'function') {
|
if (callback || typeof opt === 'function') {
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
@ -1247,10 +1251,10 @@ function marked(src, opt, callback) {
|
|||||||
|
|
||||||
opt = merge({}, marked.defaults, opt || {});
|
opt = merge({}, marked.defaults, opt || {});
|
||||||
|
|
||||||
var highlight = opt.highlight
|
var highlight = opt.highlight,
|
||||||
, tokens
|
tokens,
|
||||||
, pending
|
pending,
|
||||||
, i = 0;
|
i = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tokens = Lexer.lex(src, opt)
|
tokens = Lexer.lex(src, opt)
|
||||||
@ -1346,7 +1350,7 @@ marked.defaults = {
|
|||||||
langPrefix: 'lang-',
|
langPrefix: 'lang-',
|
||||||
smartypants: false,
|
smartypants: false,
|
||||||
headerPrefix: '',
|
headerPrefix: '',
|
||||||
renderer: new Renderer,
|
renderer: new Renderer(),
|
||||||
xhtml: false,
|
xhtml: false,
|
||||||
baseUrl: null
|
baseUrl: null
|
||||||
};
|
};
|
||||||
@ -1374,9 +1378,6 @@ if (typeof module !== 'undefined' && typeof exports === 'object') {
|
|||||||
} else if (typeof define === 'function' && define.amd) {
|
} else if (typeof define === 'function' && define.amd) {
|
||||||
define(function() { return marked; });
|
define(function() { return marked; });
|
||||||
} else {
|
} else {
|
||||||
this.marked = marked;
|
root.marked = marked;
|
||||||
}
|
}
|
||||||
|
})(this || (typeof window !== 'undefined' ? window : global));
|
||||||
}).call(function() {
|
|
||||||
return this || (typeof window !== 'undefined' ? window : global);
|
|
||||||
}());
|
|
||||||
|
2
marked.min.js
vendored
2
marked.min.js
vendored
File diff suppressed because one or more lines are too long
1544
package-lock.json
generated
1544
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -23,17 +23,27 @@
|
|||||||
"html"
|
"html"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"markdown": "*",
|
"eslint": "^4.15.0",
|
||||||
"showdown": "*",
|
"eslint-config-standard": "^11.0.0-beta.0",
|
||||||
"markdown-it": "*",
|
"eslint-plugin-import": "^2.8.0",
|
||||||
|
"eslint-plugin-node": "^5.2.1",
|
||||||
|
"eslint-plugin-promise": "^3.6.0",
|
||||||
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
"front-matter": "^2.3.0",
|
"front-matter": "^2.3.0",
|
||||||
"glob-to-regexp": "0.3.0",
|
"glob-to-regexp": "0.3.0",
|
||||||
|
"markdown": "*",
|
||||||
|
"markdown-it": "*",
|
||||||
|
"showdown": "*",
|
||||||
"uglify-js": "^3.3.10"
|
"uglify-js": "^3.3.10"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node test",
|
"test": "node test",
|
||||||
"bench": "node test --bench",
|
"bench": "node test --bench",
|
||||||
|
"lint": "eslint --fix lib/marked.js test/index.js",
|
||||||
"build": "uglifyjs lib/marked.js -cm --comments /Copyright/ -o marked.min.js",
|
"build": "uglifyjs lib/marked.js -cm --comments /Copyright/ -o marked.min.js",
|
||||||
"preversion": "npm run build && (git diff --quiet || git commit -am 'minify')"
|
"preversion": "npm run build && (git diff --quiet || git commit -am 'minify')"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
var fs = require('fs');
|
var fs = require('fs'),
|
||||||
|
path = require('path');
|
||||||
|
|
||||||
var test = require('../')
|
var testMod = require('../'),
|
||||||
, runTests = test.runTests
|
load = testMod.load;
|
||||||
, load = test.load;
|
|
||||||
|
|
||||||
var express = require('express')
|
var express = require('express'),
|
||||||
, app = express();
|
app = express();
|
||||||
|
|
||||||
|
var files = load();
|
||||||
|
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
var setHeader = res.setHeader;
|
var setHeader = res.setHeader;
|
||||||
@ -21,21 +23,17 @@ app.use(function(req, res, next) {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
var dir = __dirname + '/../tests'
|
|
||||||
, files = {};
|
|
||||||
|
|
||||||
app.get('/test.js', function(req, res, next) {
|
app.get('/test.js', function(req, res, next) {
|
||||||
var test = fs.readFileSync(__dirname + '/test.js', 'utf8')
|
var test = fs.readFileSync(path.join(__dirname, 'test.js'), 'utf8');
|
||||||
, files = load();
|
var testScript = test.replace('__TESTS__', JSON.stringify(files))
|
||||||
|
.replace('__MAIN__', testMod.runTests + '')
|
||||||
test = test.replace('__TESTS__', JSON.stringify(files));
|
.replace('__LIBS__', testMod.testFile + '');
|
||||||
test = test.replace('__MAIN__', runTests + '');
|
|
||||||
|
|
||||||
res.contentType('.js');
|
res.contentType('.js');
|
||||||
res.send(test);
|
res.send(testScript);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(express.static(__dirname + '/../../lib'));
|
app.use(express.static(path.join(__dirname, '/../../lib'))) ;
|
||||||
app.use(express.static(__dirname));
|
app.use(express.static(__dirname));
|
||||||
|
|
||||||
app.listen(8080);
|
app.listen(8080);
|
||||||
|
@ -57,6 +57,8 @@ function escape(html, encode) {
|
|||||||
.replace(/'/g, ''');
|
.replace(/'/g, ''');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__LIBS__;
|
||||||
|
|
||||||
(__MAIN__)();
|
(__MAIN__)();
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
249
test/index.js
vendored
249
test/index.js
vendored
@ -10,30 +10,28 @@
|
|||||||
* Modules
|
* Modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fs = require('fs')
|
var fs = require('fs'),
|
||||||
, path = require('path')
|
path = require('path'),
|
||||||
, fm = require('front-matter')
|
fm = require('front-matter'),
|
||||||
, g2r = require('glob-to-regexp')
|
g2r = require('glob-to-regexp'),
|
||||||
, marked = require('../')
|
marked = require('../'),
|
||||||
, markedMin = require('../marked.min.js');
|
markedMin = require('../marked.min.js');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load Tests
|
* Load Tests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function load(options) {
|
function load(options) {
|
||||||
var dir = __dirname + '/compiled_tests'
|
options = options || {};
|
||||||
, files = {}
|
var dir = path.join(__dirname, 'compiled_tests'),
|
||||||
, list
|
files = {},
|
||||||
, file
|
list,
|
||||||
, name
|
file,
|
||||||
, content
|
name,
|
||||||
, regex
|
content,
|
||||||
, skip
|
glob = g2r(options.glob || '*', { extended: true }),
|
||||||
, glob = g2r(options.glob || "*", { extended: true })
|
i,
|
||||||
, i
|
l;
|
||||||
, j
|
|
||||||
, l;
|
|
||||||
|
|
||||||
list = fs
|
list = fs
|
||||||
.readdirSync(dir)
|
.readdirSync(dir)
|
||||||
@ -45,7 +43,7 @@ function load(options) {
|
|||||||
l = list.length;
|
l = list.length;
|
||||||
|
|
||||||
for (i = 0; i < l; i++) {
|
for (i = 0; i < l; i++) {
|
||||||
name = path.basename(list[i], ".md");
|
name = path.basename(list[i], '.md');
|
||||||
if (glob.test(name)) {
|
if (glob.test(name)) {
|
||||||
file = path.join(dir, list[i]);
|
file = path.join(dir, list[i]);
|
||||||
content = fm(fs.readFileSync(file, 'utf8'));
|
content = fm(fs.readFileSync(file, 'utf8'));
|
||||||
@ -62,7 +60,7 @@ function load(options) {
|
|||||||
if (!options.glob) {
|
if (!options.glob) {
|
||||||
// Change certain tests to allow
|
// Change certain tests to allow
|
||||||
// comparison to older benchmark times.
|
// comparison to older benchmark times.
|
||||||
fs.readdirSync(__dirname + '/new').forEach(function(name) {
|
fs.readdirSync(path.join(__dirname, 'new')).forEach(function(name) {
|
||||||
if (path.extname(name) === '.html') return;
|
if (path.extname(name) === '.html') return;
|
||||||
if (name === 'main.md') return;
|
if (name === 'main.md') return;
|
||||||
delete files[name];
|
delete files[name];
|
||||||
@ -93,112 +91,118 @@ function runTests(engine, options) {
|
|||||||
engine = null;
|
engine = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var engine = engine || marked
|
engine = engine || marked;
|
||||||
, options = options || {}
|
options = options || {};
|
||||||
, files = options.files || load(options)
|
var succeeded = 0,
|
||||||
, complete = 0
|
failed = 0,
|
||||||
, failed = 0
|
files = options.files || load(options),
|
||||||
, failures = []
|
filenames = Object.keys(files),
|
||||||
, keys = Object.keys(files)
|
len = filenames.length,
|
||||||
, i = 0
|
success,
|
||||||
, len = keys.length
|
i,
|
||||||
, filename
|
filename,
|
||||||
, file
|
file;
|
||||||
, opts
|
|
||||||
, text
|
|
||||||
, html
|
|
||||||
, j
|
|
||||||
, l;
|
|
||||||
|
|
||||||
if (options.marked) {
|
if (options.marked) {
|
||||||
marked.setOptions(options.marked);
|
marked.setOptions(options.marked);
|
||||||
}
|
}
|
||||||
|
|
||||||
main:
|
for (i = 0; i < len; i++) {
|
||||||
for (; i < len; i++) {
|
filename = filenames[i];
|
||||||
filename = keys[i];
|
|
||||||
file = files[filename];
|
file = files[filename];
|
||||||
opts = Object.keys(file.options);
|
success = testFile(engine, file, filename, i + 1);
|
||||||
|
if (success) {
|
||||||
if (marked._original) {
|
succeeded++;
|
||||||
marked.defaults = marked._original;
|
} else {
|
||||||
delete marked._original;
|
failed++;
|
||||||
}
|
if (options.stop) {
|
||||||
|
break;
|
||||||
if (opts.length) {
|
|
||||||
marked._original = marked.defaults;
|
|
||||||
marked.defaults = {};
|
|
||||||
Object.keys(marked._original).forEach(function(key) {
|
|
||||||
marked.defaults[key] = marked._original[key];
|
|
||||||
});
|
|
||||||
opts.forEach(function(key) {
|
|
||||||
if (marked.defaults.hasOwnProperty(key)) {
|
|
||||||
marked.defaults[key] = file.options[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
text = engine(file.text).replace(/\s/g, '');
|
|
||||||
html = file.html.replace(/\s/g, '');
|
|
||||||
} catch (e) {
|
|
||||||
console.log('%s failed.', filename);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
l = html.length;
|
|
||||||
|
|
||||||
for (; j < l; j++) {
|
|
||||||
if (text[j] !== html[j]) {
|
|
||||||
failed++;
|
|
||||||
failures.push(filename);
|
|
||||||
|
|
||||||
text = text.substring(
|
|
||||||
Math.max(j - 30, 0),
|
|
||||||
Math.min(j + 30, text.length));
|
|
||||||
|
|
||||||
html = html.substring(
|
|
||||||
Math.max(j - 30, 0),
|
|
||||||
Math.min(j + 30, html.length));
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
'\n#%d. %s failed at offset %d. Near: "%s".\n',
|
|
||||||
i + 1, filename, j, text);
|
|
||||||
|
|
||||||
console.log('\nGot:\n%s\n', text.trim() || text);
|
|
||||||
console.log('\nExpected:\n%s\n', html.trim() || html);
|
|
||||||
|
|
||||||
if (options.stop) {
|
|
||||||
break main;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue main;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
complete++;
|
|
||||||
console.log('#%d. %s completed.', i + 1, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('%d/%d tests completed successfully.', complete, len);
|
console.log('%d/%d tests completed successfully.', succeeded, len);
|
||||||
if (failed) console.log('%d/%d tests failed.', failed, len);
|
if (failed) console.log('%d/%d tests failed.', failed, len);
|
||||||
|
|
||||||
return !failed;
|
return !failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a file
|
||||||
|
*/
|
||||||
|
|
||||||
|
function testFile(engine, file, filename, index) {
|
||||||
|
var opts = Object.keys(file.options),
|
||||||
|
text,
|
||||||
|
html,
|
||||||
|
j,
|
||||||
|
l;
|
||||||
|
|
||||||
|
if (marked._original) {
|
||||||
|
marked.defaults = marked._original;
|
||||||
|
delete marked._original;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.length) {
|
||||||
|
marked._original = marked.defaults;
|
||||||
|
marked.defaults = {};
|
||||||
|
Object.keys(marked._original).forEach(function(key) {
|
||||||
|
marked.defaults[key] = marked._original[key];
|
||||||
|
});
|
||||||
|
opts.forEach(function(key) {
|
||||||
|
if (marked.defaults.hasOwnProperty(key)) {
|
||||||
|
marked.defaults[key] = file.options[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
text = engine(file.text).replace(/\s/g, '');
|
||||||
|
html = file.html.replace(/\s/g, '');
|
||||||
|
} catch (e) {
|
||||||
|
console.log('%s failed.', filename);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = html.length;
|
||||||
|
|
||||||
|
for (j = 0; j < l; j++) {
|
||||||
|
if (text[j] !== html[j]) {
|
||||||
|
text = text.substring(
|
||||||
|
Math.max(j - 30, 0),
|
||||||
|
Math.min(j + 30, text.length));
|
||||||
|
|
||||||
|
html = html.substring(
|
||||||
|
Math.max(j - 30, 0),
|
||||||
|
Math.min(j + 30, l));
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'\n#%d. %s failed at offset %d. Near: "%s".\n',
|
||||||
|
index, filename, j, text);
|
||||||
|
|
||||||
|
console.log('\nGot:\n%s\n', text.trim() || text);
|
||||||
|
console.log('\nExpected:\n%s\n', html.trim() || html);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('#%d. %s completed.', index, filename);
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Benchmark a function
|
* Benchmark a function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function bench(name, files, func) {
|
function bench(name, files, func) {
|
||||||
var start = Date.now()
|
var start = Date.now(),
|
||||||
, times = 1000
|
times = 1000,
|
||||||
, keys = Object.keys(files)
|
keys = Object.keys(files),
|
||||||
, i
|
i,
|
||||||
, l = keys.length
|
l = keys.length,
|
||||||
, filename
|
filename,
|
||||||
, file;
|
file;
|
||||||
|
|
||||||
while (times--) {
|
while (times--) {
|
||||||
for (i = 0; i < l; i++) {
|
for (i = 0; i < l; i++) {
|
||||||
@ -216,8 +220,8 @@ function bench(name, files, func) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function runBench(options) {
|
function runBench(options) {
|
||||||
var options = options || {}
|
options = options || {};
|
||||||
, files = load(options);
|
var files = load(options);
|
||||||
|
|
||||||
// Non-GFM, Non-pedantic
|
// Non-GFM, Non-pedantic
|
||||||
marked.setOptions({
|
marked.setOptions({
|
||||||
@ -314,8 +318,8 @@ function runBench(options) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function time(options) {
|
function time(options) {
|
||||||
var options = options || {}
|
options = options || {};
|
||||||
, files = load(options);
|
var files = load(options);
|
||||||
if (options.marked) {
|
if (options.marked) {
|
||||||
marked.setOptions(options.marked);
|
marked.setOptions(options.marked);
|
||||||
}
|
}
|
||||||
@ -360,13 +364,13 @@ function fix() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// node fix.js
|
// node fix.js
|
||||||
var dir = __dirname + '/compiled_tests';
|
var dir = path.join(__dirname, 'compiled_tests');
|
||||||
|
|
||||||
fs.readdirSync(dir).filter(function(file) {
|
fs.readdirSync(dir).filter(function(file) {
|
||||||
return path.extname(file) === '.html';
|
return path.extname(file) === '.html';
|
||||||
}).forEach(function(file) {
|
}).forEach(function(file) {
|
||||||
var file = path.join(dir, file)
|
file = path.join(dir, file);
|
||||||
, html = fs.readFileSync(file, 'utf8');
|
var html = fs.readFileSync(file, 'utf8');
|
||||||
|
|
||||||
// fix unencoded quotes
|
// fix unencoded quotes
|
||||||
html = html
|
html = html
|
||||||
@ -386,7 +390,7 @@ function fix() {
|
|||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/&/g, '&');
|
.replace(/&/g, '&');
|
||||||
|
|
||||||
id = id.toLowerCase().replace(/[^\w]+/g, '-');
|
id = id.toLowerCase().replace(/[^\w]+/g, '-');
|
||||||
|
|
||||||
return '<' + h + ' id="' + id + '">' + text + '</' + h + '>';
|
return '<' + h + ' id="' + id + '">' + text + '</' + h + '>';
|
||||||
});
|
});
|
||||||
@ -396,8 +400,8 @@ function fix() {
|
|||||||
|
|
||||||
// turn <hr /> into <hr>
|
// turn <hr /> into <hr>
|
||||||
fs.readdirSync(dir).forEach(function(file) {
|
fs.readdirSync(dir).forEach(function(file) {
|
||||||
var file = path.join(dir, file)
|
file = path.join(dir, file);
|
||||||
, text = fs.readFileSync(file, 'utf8');
|
var text = fs.readFileSync(file, 'utf8');
|
||||||
|
|
||||||
text = text.replace(/(<|<)hr\s*\/(>|>)/g, '$1hr$2');
|
text = text.replace(/(<|<)hr\s*\/(>|>)/g, '$1hr$2');
|
||||||
|
|
||||||
@ -425,12 +429,12 @@ function fix() {
|
|||||||
* Argument Parsing
|
* Argument Parsing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function parseArg(argv) {
|
function parseArg() {
|
||||||
var argv = process.argv.slice(2)
|
var argv = process.argv.slice(2),
|
||||||
, options = {}
|
options = {},
|
||||||
, opt = ""
|
opt = '',
|
||||||
, orphans = []
|
orphans = [],
|
||||||
, arg;
|
arg;
|
||||||
|
|
||||||
function getarg() {
|
function getarg() {
|
||||||
var arg = argv.shift();
|
var arg = argv.shift();
|
||||||
@ -571,6 +575,7 @@ if (!module.parent) {
|
|||||||
exports = main;
|
exports = main;
|
||||||
exports.main = main;
|
exports.main = main;
|
||||||
exports.runTests = runTests;
|
exports.runTests = runTests;
|
||||||
|
exports.testFile = testFile;
|
||||||
exports.runBench = runBench;
|
exports.runBench = runBench;
|
||||||
exports.load = load;
|
exports.load = load;
|
||||||
exports.bench = bench;
|
exports.bench = bench;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user