Comparing version 0.2.6 to 0.2.7
/** | ||
* marked - A markdown parser (https://github.com/chjj/marked) | ||
* Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed) | ||
* marked - a markdown parser | ||
* Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) | ||
* https://github.com/chjj/marked | ||
*/ | ||
@@ -18,2 +19,3 @@ | ||
heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, | ||
nptable: noop, | ||
lheading: /^([^\n]+)\n *(=|-){3,} *\n*/, | ||
@@ -24,2 +26,3 @@ blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/, | ||
def: /^ *\[([^\]]+)\]: *([^\s]+)(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, | ||
table: noop, | ||
paragraph: /^([^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+\n*/, | ||
@@ -40,2 +43,7 @@ text: /^[^\n]+/ | ||
block._tag = '(?!(?:' | ||
+ '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' | ||
+ '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b'; | ||
block.html = replace(block.html) | ||
@@ -45,3 +53,3 @@ ('comment', /<!--[\s\S]*?-->/) | ||
('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/) | ||
(/tag/g, tag()) | ||
(/tag/g, block._tag) | ||
(); | ||
@@ -54,15 +62,20 @@ | ||
('blockquote', block.blockquote) | ||
('tag', '<' + tag()) | ||
('tag', '<' + block._tag) | ||
('def', block.def) | ||
(); | ||
block.normal = { | ||
fences: block.fences, | ||
paragraph: block.paragraph | ||
}; | ||
/** | ||
* Normal Block Grammar | ||
*/ | ||
block.gfm = { | ||
fences: /^ *(```|~~~) *(\w+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, | ||
block.normal = merge({}, block); | ||
/** | ||
* GFM Block Grammar | ||
*/ | ||
block.gfm = merge({}, block.normal, { | ||
fences: /^ *(`{3,}|~{3,}) *(\w+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, | ||
paragraph: /^/ | ||
}; | ||
}); | ||
@@ -74,18 +87,63 @@ block.gfm.paragraph = replace(block.paragraph) | ||
/** | ||
* GFM + Tables Block Grammar | ||
*/ | ||
block.tables = merge({}, block.gfm, { | ||
nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, | ||
table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ | ||
}); | ||
/** | ||
* Block Lexer | ||
*/ | ||
block.lexer = function(src) { | ||
var tokens = []; | ||
function Lexer(options) { | ||
this.tokens = []; | ||
this.tokens.links = {}; | ||
this.options = options || marked.defaults; | ||
this.rules = block.normal; | ||
tokens.links = {}; | ||
if (this.options.gfm) { | ||
if (this.options.tables) { | ||
this.rules = block.tables; | ||
} else { | ||
this.rules = block.gfm; | ||
} | ||
} | ||
} | ||
/** | ||
* Expose Block Rules | ||
*/ | ||
Lexer.rules = block; | ||
/** | ||
* Static Lex Method | ||
*/ | ||
Lexer.lex = function(src, options) { | ||
var lexer = new Lexer(options); | ||
return lexer.lex(src); | ||
}; | ||
/** | ||
* Preprocessing | ||
*/ | ||
Lexer.prototype.lex = function(src) { | ||
src = src | ||
.replace(/\r\n|\r/g, '\n') | ||
.replace(/\t/g, ' '); | ||
.replace(/\t/g, ' ') | ||
.replace(/\u00a0/g, ' ') | ||
.replace(/\u2424/g, '\n'); | ||
return block.token(src, tokens, true); | ||
return this.token(src, true); | ||
}; | ||
block.token = function(src, tokens, top) { | ||
/** | ||
* Lexing | ||
*/ | ||
Lexer.prototype.token = function(src, top) { | ||
var src = src.replace(/^ +$/gm, '') | ||
@@ -102,6 +160,6 @@ , next | ||
// newline | ||
if (cap = block.newline.exec(src)) { | ||
if (cap = this.rules.newline.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
if (cap[0].length > 1) { | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'space' | ||
@@ -113,8 +171,8 @@ }); | ||
// code | ||
if (cap = block.code.exec(src)) { | ||
if (cap = this.rules.code.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
cap = cap[0].replace(/^ {4}/gm, ''); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'code', | ||
text: !options.pedantic | ||
text: !this.options.pedantic | ||
? cap.replace(/\n+$/, '') | ||
@@ -127,5 +185,5 @@ : cap | ||
// fences (gfm) | ||
if (cap = block.fences.exec(src)) { | ||
if (cap = this.rules.fences.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'code', | ||
@@ -139,5 +197,5 @@ lang: cap[2], | ||
// heading | ||
if (cap = block.heading.exec(src)) { | ||
if (cap = this.rules.heading.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'heading', | ||
@@ -150,6 +208,38 @@ depth: cap[1].length, | ||
// table no leading pipe (gfm) | ||
if (top && (cap = this.rules.nptable.exec(src))) { | ||
src = src.substring(cap[0].length); | ||
item = { | ||
type: 'table', | ||
header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), | ||
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), | ||
cells: cap[3].replace(/\n$/, '').split('\n') | ||
}; | ||
for (i = 0; i < item.align.length; i++) { | ||
if (/^ *-+: *$/.test(item.align[i])) { | ||
item.align[i] = 'right'; | ||
} else if (/^ *:-+: *$/.test(item.align[i])) { | ||
item.align[i] = 'center'; | ||
} else if (/^ *:-+ *$/.test(item.align[i])) { | ||
item.align[i] = 'left'; | ||
} else { | ||
item.align[i] = null; | ||
} | ||
} | ||
for (i = 0; i < item.cells.length; i++) { | ||
item.cells[i] = item.cells[i].split(/ *\| */); | ||
} | ||
this.tokens.push(item); | ||
continue; | ||
} | ||
// lheading | ||
if (cap = block.lheading.exec(src)) { | ||
if (cap = this.rules.lheading.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'heading', | ||
@@ -163,5 +253,5 @@ depth: cap[2] === '=' ? 1 : 2, | ||
// hr | ||
if (cap = block.hr.exec(src)) { | ||
if (cap = this.rules.hr.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'hr' | ||
@@ -173,6 +263,6 @@ }); | ||
// blockquote | ||
if (cap = block.blockquote.exec(src)) { | ||
if (cap = this.rules.blockquote.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'blockquote_start' | ||
@@ -186,5 +276,5 @@ }); | ||
// how markdown.pl works. | ||
block.token(cap, tokens, top); | ||
this.token(cap, top); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'blockquote_end' | ||
@@ -197,6 +287,6 @@ }); | ||
// list | ||
if (cap = block.list.exec(src)) { | ||
if (cap = this.rules.list.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'list_start', | ||
@@ -207,3 +297,3 @@ ordered: isFinite(cap[2]) | ||
// Get each top-level item. | ||
cap = cap[0].match(block.item); | ||
cap = cap[0].match(this.rules.item); | ||
@@ -226,3 +316,3 @@ next = false; | ||
space -= item.length; | ||
item = !options.pedantic | ||
item = !this.options.pedantic | ||
? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') | ||
@@ -241,3 +331,3 @@ : item.replace(/^ {1,4}/gm, ''); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: loose | ||
@@ -249,5 +339,5 @@ ? 'loose_item_start' | ||
// Recurse. | ||
block.token(item, tokens); | ||
this.token(item, false); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'list_item_end' | ||
@@ -257,3 +347,3 @@ }); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'list_end' | ||
@@ -266,6 +356,6 @@ }); | ||
// html | ||
if (cap = block.html.exec(src)) { | ||
if (cap = this.rules.html.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
type: options.sanitize | ||
this.tokens.push({ | ||
type: this.options.sanitize | ||
? 'paragraph' | ||
@@ -280,5 +370,5 @@ : 'html', | ||
// def | ||
if (top && (cap = block.def.exec(src))) { | ||
if (top && (cap = this.rules.def.exec(src))) { | ||
src = src.substring(cap[0].length); | ||
tokens.links[cap[1].toLowerCase()] = { | ||
this.tokens.links[cap[1].toLowerCase()] = { | ||
href: cap[2], | ||
@@ -290,6 +380,40 @@ title: cap[3] | ||
// table (gfm) | ||
if (top && (cap = this.rules.table.exec(src))) { | ||
src = src.substring(cap[0].length); | ||
item = { | ||
type: 'table', | ||
header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), | ||
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), | ||
cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') | ||
}; | ||
for (i = 0; i < item.align.length; i++) { | ||
if (/^ *-+: *$/.test(item.align[i])) { | ||
item.align[i] = 'right'; | ||
} else if (/^ *:-+: *$/.test(item.align[i])) { | ||
item.align[i] = 'center'; | ||
} else if (/^ *:-+ *$/.test(item.align[i])) { | ||
item.align[i] = 'left'; | ||
} else { | ||
item.align[i] = null; | ||
} | ||
} | ||
for (i = 0; i < item.cells.length; i++) { | ||
item.cells[i] = item.cells[i] | ||
.replace(/^ *\| *| *\| *$/g, '') | ||
.split(/ *\| */); | ||
} | ||
this.tokens.push(item); | ||
continue; | ||
} | ||
// top-level paragraph | ||
if (top && (cap = block.paragraph.exec(src))) { | ||
if (top && (cap = this.rules.paragraph.exec(src))) { | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'paragraph', | ||
@@ -302,6 +426,6 @@ text: cap[0] | ||
// text | ||
if (cap = block.text.exec(src)) { | ||
if (cap = this.rules.text.exec(src)) { | ||
// Top-level should never reach here. | ||
src = src.substring(cap[0].length); | ||
tokens.push({ | ||
this.tokens.push({ | ||
type: 'text', | ||
@@ -312,13 +436,18 @@ text: cap[0] | ||
} | ||
if (src) { | ||
throw new | ||
Error('Infinite loop on byte: ' + src.charCodeAt(0)); | ||
} | ||
} | ||
return tokens; | ||
return this.tokens; | ||
}; | ||
/** | ||
* Inline Processing | ||
* Inline-Level Grammar | ||
*/ | ||
var inline = { | ||
escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, | ||
escape: /^\\([\\`*{}\[\]()#+\-.!_>|])/, | ||
autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, | ||
@@ -334,41 +463,102 @@ url: noop, | ||
br: /^ {2,}\n(?!\s*$)/, | ||
del: noop, | ||
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/ | ||
}; | ||
inline._linkInside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/; | ||
inline._linkHref = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/; | ||
inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/; | ||
inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/; | ||
inline.link = replace(inline.link) | ||
('inside', inline._linkInside) | ||
('href', inline._linkHref) | ||
('inside', inline._inside) | ||
('href', inline._href) | ||
(); | ||
inline.reflink = replace(inline.reflink) | ||
('inside', inline._linkInside) | ||
('inside', inline._inside) | ||
(); | ||
inline.normal = { | ||
url: inline.url, | ||
strong: inline.strong, | ||
em: inline.em, | ||
text: inline.text | ||
}; | ||
/** | ||
* Normal Inline Grammar | ||
*/ | ||
inline.pedantic = { | ||
inline.normal = merge({}, inline); | ||
/** | ||
* Pedantic Inline Grammar | ||
*/ | ||
inline.pedantic = merge({}, inline.normal, { | ||
strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, | ||
em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ | ||
}; | ||
}); | ||
inline.gfm = { | ||
/** | ||
* GFM Inline Grammar | ||
*/ | ||
inline.gfm = merge({}, inline.normal, { | ||
escape: replace(inline.escape)('])', '~])')(), | ||
url: /^(https?:\/\/[^\s]+[^.,:;"')\]\s])/, | ||
text: /^[\s\S]+?(?=[\\<!\[_*`]|https?:\/\/| {2,}\n|$)/ | ||
del: /^~{2,}([\s\S]+?)~{2,}/, | ||
text: replace(inline.text) | ||
(']|', '~]|') | ||
('|', '|https?://|') | ||
() | ||
}); | ||
/** | ||
* GFM + Line Breaks Inline Grammar | ||
*/ | ||
inline.breaks = merge({}, inline.gfm, { | ||
br: replace(inline.br)('{2,}', '*')(), | ||
text: replace(inline.gfm.text)('{2,}', '*')() | ||
}); | ||
/** | ||
* Inline Lexer & Compiler | ||
*/ | ||
function InlineLexer(links, options) { | ||
this.options = options || marked.defaults; | ||
this.links = links; | ||
this.rules = inline.normal; | ||
if (!this.links) { | ||
throw new | ||
Error('Tokens array requires a `links` property.'); | ||
} | ||
if (this.options.gfm) { | ||
if (this.options.breaks) { | ||
this.rules = inline.breaks; | ||
} else { | ||
this.rules = inline.gfm; | ||
} | ||
} else if (this.options.pedantic) { | ||
this.rules = inline.pedantic; | ||
} | ||
} | ||
/** | ||
* Expose Inline Rules | ||
*/ | ||
InlineLexer.rules = inline; | ||
/** | ||
* Static Lexing/Compiling Method | ||
*/ | ||
InlineLexer.output = function(src, links, opt) { | ||
var inline = new InlineLexer(links, opt); | ||
return inline.output(src); | ||
}; | ||
/** | ||
* Inline Lexer | ||
* Lexing/Compiling | ||
*/ | ||
inline.lexer = function(src) { | ||
InlineLexer.prototype.output = function(src) { | ||
var out = '' | ||
, links = tokens.links | ||
, link | ||
@@ -381,3 +571,3 @@ , text | ||
// escape | ||
if (cap = inline.escape.exec(src)) { | ||
if (cap = this.rules.escape.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
@@ -389,9 +579,9 @@ out += cap[1]; | ||
// autolink | ||
if (cap = inline.autolink.exec(src)) { | ||
if (cap = this.rules.autolink.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
if (cap[2] === '@') { | ||
text = cap[1][6] === ':' | ||
? mangle(cap[1].substring(7)) | ||
: mangle(cap[1]); | ||
href = mangle('mailto:') + text; | ||
? this.mangle(cap[1].substring(7)) | ||
: this.mangle(cap[1]); | ||
href = this.mangle('mailto:') + text; | ||
} else { | ||
@@ -410,3 +600,3 @@ text = escape(cap[1]); | ||
// url (gfm) | ||
if (cap = inline.url.exec(src)) { | ||
if (cap = this.rules.url.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
@@ -424,5 +614,5 @@ text = escape(cap[1]); | ||
// tag | ||
if (cap = inline.tag.exec(src)) { | ||
if (cap = this.rules.tag.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
out += options.sanitize | ||
out += this.options.sanitize | ||
? escape(cap[0]) | ||
@@ -434,5 +624,5 @@ : cap[0]; | ||
// link | ||
if (cap = inline.link.exec(src)) { | ||
if (cap = this.rules.link.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
out += outputLink(cap, { | ||
out += this.outputLink(cap, { | ||
href: cap[2], | ||
@@ -445,7 +635,7 @@ title: cap[3] | ||
// reflink, nolink | ||
if ((cap = inline.reflink.exec(src)) | ||
|| (cap = inline.nolink.exec(src))) { | ||
if ((cap = this.rules.reflink.exec(src)) | ||
|| (cap = this.rules.nolink.exec(src))) { | ||
src = src.substring(cap[0].length); | ||
link = (cap[2] || cap[1]).replace(/\s+/g, ' '); | ||
link = links[link.toLowerCase()]; | ||
link = this.links[link.toLowerCase()]; | ||
if (!link || !link.href) { | ||
@@ -456,3 +646,3 @@ out += cap[0][0]; | ||
} | ||
out += outputLink(cap, link); | ||
out += this.outputLink(cap, link); | ||
continue; | ||
@@ -462,6 +652,6 @@ } | ||
// strong | ||
if (cap = inline.strong.exec(src)) { | ||
if (cap = this.rules.strong.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
out += '<strong>' | ||
+ inline.lexer(cap[2] || cap[1]) | ||
+ this.output(cap[2] || cap[1]) | ||
+ '</strong>'; | ||
@@ -472,6 +662,6 @@ continue; | ||
// em | ||
if (cap = inline.em.exec(src)) { | ||
if (cap = this.rules.em.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
out += '<em>' | ||
+ inline.lexer(cap[2] || cap[1]) | ||
+ this.output(cap[2] || cap[1]) | ||
+ '</em>'; | ||
@@ -482,3 +672,3 @@ continue; | ||
// code | ||
if (cap = inline.code.exec(src)) { | ||
if (cap = this.rules.code.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
@@ -492,3 +682,3 @@ out += '<code>' | ||
// br | ||
if (cap = inline.br.exec(src)) { | ||
if (cap = this.rules.br.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
@@ -499,4 +689,13 @@ out += '<br>'; | ||
// del (gfm) | ||
if (cap = this.rules.del.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
out += '<del>' | ||
+ this.output(cap[1]) | ||
+ '</del>'; | ||
continue; | ||
} | ||
// text | ||
if (cap = inline.text.exec(src)) { | ||
if (cap = this.rules.text.exec(src)) { | ||
src = src.substring(cap[0].length); | ||
@@ -506,2 +705,7 @@ out += escape(cap[0]); | ||
} | ||
if (src) { | ||
throw new | ||
Error('Infinite loop on byte: ' + src.charCodeAt(0)); | ||
} | ||
} | ||
@@ -512,3 +716,7 @@ | ||
function outputLink(cap, link) { | ||
/** | ||
* Compile Link | ||
*/ | ||
InlineLexer.prototype.outputLink = function(cap, link) { | ||
if (cap[0][0] !== '!') { | ||
@@ -524,3 +732,3 @@ return '<a href="' | ||
+ '>' | ||
+ inline.lexer(cap[1]) | ||
+ this.output(cap[1]) | ||
+ '</a>'; | ||
@@ -540,17 +748,96 @@ } else { | ||
} | ||
} | ||
}; | ||
/** | ||
* Parsing | ||
* Mangle Links | ||
*/ | ||
var tokens | ||
, token; | ||
InlineLexer.prototype.mangle = function(text) { | ||
var out = '' | ||
, l = text.length | ||
, i = 0 | ||
, ch; | ||
function next() { | ||
return token = tokens.pop(); | ||
for (; i < l; i++) { | ||
ch = text.charCodeAt(i); | ||
if (Math.random() > 0.5) { | ||
ch = 'x' + ch.toString(16); | ||
} | ||
out += '&#' + ch + ';'; | ||
} | ||
return out; | ||
}; | ||
/** | ||
* Parsing & Compiling | ||
*/ | ||
function Parser(options) { | ||
this.tokens = []; | ||
this.token = null; | ||
this.options = options || marked.defaults; | ||
} | ||
function tok() { | ||
switch (token.type) { | ||
/** | ||
* Static Parse Method | ||
*/ | ||
Parser.parse = function(src, options) { | ||
var parser = new Parser(options); | ||
return parser.parse(src); | ||
}; | ||
/** | ||
* Parse Loop | ||
*/ | ||
Parser.prototype.parse = function(src) { | ||
this.inline = new InlineLexer(src.links, this.options); | ||
this.tokens = src.reverse(); | ||
var out = ''; | ||
while (this.next()) { | ||
out += this.tok(); | ||
} | ||
return out; | ||
}; | ||
/** | ||
* Next Token | ||
*/ | ||
Parser.prototype.next = function() { | ||
return this.token = this.tokens.pop(); | ||
}; | ||
/** | ||
* Preview Next Token | ||
*/ | ||
Parser.prototype.peek = function() { | ||
return this.tokens[this.tokens.length-1] || 0; | ||
}; | ||
/** | ||
* Parse Text Tokens | ||
*/ | ||
Parser.prototype.parseText = function() { | ||
var body = this.token.text; | ||
while (this.peek().type === 'text') { | ||
body += '\n' + this.next().text; | ||
} | ||
return this.inline.output(body); | ||
}; | ||
/** | ||
* Parse Current Token | ||
*/ | ||
Parser.prototype.tok = function() { | ||
switch (this.token.type) { | ||
case 'space': { | ||
@@ -564,37 +851,74 @@ return ''; | ||
return '<h' | ||
+ token.depth | ||
+ this.token.depth | ||
+ '>' | ||
+ inline.lexer(token.text) | ||
+ this.inline.output(this.token.text) | ||
+ '</h' | ||
+ token.depth | ||
+ this.token.depth | ||
+ '>\n'; | ||
} | ||
case 'code': { | ||
if (options.highlight) { | ||
token.code = options.highlight(token.text, token.lang); | ||
if (token.code != null && token.code !== token.text) { | ||
token.escaped = true; | ||
token.text = token.code; | ||
if (this.options.highlight) { | ||
var code = this.options.highlight(this.token.text, this.token.lang); | ||
if (code != null && code !== this.token.text) { | ||
this.token.escaped = true; | ||
this.token.text = code; | ||
} | ||
} | ||
if (!token.escaped) { | ||
token.text = escape(token.text, true); | ||
if (!this.token.escaped) { | ||
this.token.text = escape(this.token.text, true); | ||
} | ||
return '<pre><code' | ||
+ (token.lang | ||
+ (this.token.lang | ||
? ' class="lang-' | ||
+ token.lang | ||
+ this.token.lang | ||
+ '"' | ||
: '') | ||
+ '>' | ||
+ token.text | ||
+ this.token.text | ||
+ '</code></pre>\n'; | ||
} | ||
case 'table': { | ||
var body = '' | ||
, heading | ||
, i | ||
, row | ||
, cell | ||
, j; | ||
// header | ||
body += '<thead>\n<tr>\n'; | ||
for (i = 0; i < this.token.header.length; i++) { | ||
heading = this.inline.output(this.token.header[i]); | ||
body += this.token.align[i] | ||
? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n' | ||
: '<th>' + heading + '</th>\n'; | ||
} | ||
body += '</tr>\n</thead>\n'; | ||
// body | ||
body += '<tbody>\n' | ||
for (i = 0; i < this.token.cells.length; i++) { | ||
row = this.token.cells[i]; | ||
body += '<tr>\n'; | ||
for (j = 0; j < row.length; j++) { | ||
cell = this.inline.output(row[j]); | ||
body += this.token.align[j] | ||
? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n' | ||
: '<td>' + cell + '</td>\n'; | ||
} | ||
body += '</tr>\n'; | ||
} | ||
body += '</tbody>\n'; | ||
return '<table>\n' | ||
+ body | ||
+ '</table>\n'; | ||
} | ||
case 'blockquote_start': { | ||
var body = ''; | ||
while (next().type !== 'blockquote_end') { | ||
body += tok(); | ||
while (this.next().type !== 'blockquote_end') { | ||
body += this.tok(); | ||
} | ||
@@ -607,7 +931,7 @@ | ||
case 'list_start': { | ||
var type = token.ordered ? 'ol' : 'ul' | ||
var type = this.token.ordered ? 'ol' : 'ul' | ||
, body = ''; | ||
while (next().type !== 'list_end') { | ||
body += tok(); | ||
while (this.next().type !== 'list_end') { | ||
body += this.tok(); | ||
} | ||
@@ -626,6 +950,6 @@ | ||
while (next().type !== 'list_item_end') { | ||
body += token.type === 'text' | ||
? parseText() | ||
: tok(); | ||
while (this.next().type !== 'list_item_end') { | ||
body += this.token.type === 'text' | ||
? this.parseText() | ||
: this.tok(); | ||
} | ||
@@ -640,4 +964,4 @@ | ||
while (next().type !== 'list_item_end') { | ||
body += tok(); | ||
while (this.next().type !== 'list_item_end') { | ||
body += this.tok(); | ||
} | ||
@@ -650,9 +974,9 @@ | ||
case 'html': { | ||
return !token.pre && !options.pedantic | ||
? inline.lexer(token.text) | ||
: token.text; | ||
return !this.token.pre && !this.options.pedantic | ||
? this.inline.output(this.token.text) | ||
: this.token.text; | ||
} | ||
case 'paragraph': { | ||
return '<p>' | ||
+ inline.lexer(token.text) | ||
+ this.inline.output(this.token.text) | ||
+ '</p>\n'; | ||
@@ -662,34 +986,8 @@ } | ||
return '<p>' | ||
+ parseText() | ||
+ this.parseText() | ||
+ '</p>\n'; | ||
} | ||
} | ||
} | ||
}; | ||
function parseText() { | ||
var body = token.text | ||
, top; | ||
while ((top = tokens[tokens.length-1]) | ||
&& top.type === 'text') { | ||
body += '\n' + next().text; | ||
} | ||
return inline.lexer(body); | ||
} | ||
function parse(src) { | ||
tokens = src.reverse(); | ||
var out = ''; | ||
while (next()) { | ||
out += tok(); | ||
} | ||
tokens = null; | ||
token = null; | ||
return out; | ||
} | ||
/** | ||
@@ -708,28 +1006,2 @@ * Helpers | ||
function mangle(text) { | ||
var out = '' | ||
, l = text.length | ||
, i = 0 | ||
, ch; | ||
for (; i < l; i++) { | ||
ch = text.charCodeAt(i); | ||
if (Math.random() > 0.5) { | ||
ch = 'x' + ch.toString(16); | ||
} | ||
out += '&#' + ch + ';'; | ||
} | ||
return out; | ||
} | ||
function tag() { | ||
var tag = '(?!(?:' | ||
+ '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' | ||
+ '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b'; | ||
return tag; | ||
} | ||
function replace(regex, opt) { | ||
@@ -750,2 +1022,19 @@ regex = regex.source; | ||
function merge(obj) { | ||
var i = 1 | ||
, target | ||
, key; | ||
for (; i < arguments.length; i++) { | ||
target = arguments[i]; | ||
for (key in target) { | ||
if (Object.prototype.hasOwnProperty.call(target, key)) { | ||
obj[key] = target[key]; | ||
} | ||
} | ||
} | ||
return obj; | ||
} | ||
/** | ||
@@ -756,4 +1045,11 @@ * Marked | ||
function marked(src, opt) { | ||
setOptions(opt); | ||
return parse(block.lexer(src)); | ||
try { | ||
return Parser.parse(Lexer.lex(src, opt), opt); | ||
} catch (e) { | ||
e.message += '\nPlease report this to https://github.com/chjj/marked.'; | ||
if ((opt || marked.defaults).silent) { | ||
return 'An error occured:\n' + e.message; | ||
} | ||
throw e; | ||
} | ||
} | ||
@@ -765,44 +1061,17 @@ | ||
var options | ||
, defaults; | ||
function setOptions(opt) { | ||
if (!opt) opt = defaults; | ||
if (options === opt) return; | ||
options = opt; | ||
if (options.gfm) { | ||
block.fences = block.gfm.fences; | ||
block.paragraph = block.gfm.paragraph; | ||
inline.text = inline.gfm.text; | ||
inline.url = inline.gfm.url; | ||
} else { | ||
block.fences = block.normal.fences; | ||
block.paragraph = block.normal.paragraph; | ||
inline.text = inline.normal.text; | ||
inline.url = inline.normal.url; | ||
} | ||
if (options.pedantic) { | ||
inline.em = inline.pedantic.em; | ||
inline.strong = inline.pedantic.strong; | ||
} else { | ||
inline.em = inline.normal.em; | ||
inline.strong = inline.normal.strong; | ||
} | ||
} | ||
marked.options = | ||
marked.setOptions = function(opt) { | ||
defaults = opt; | ||
setOptions(opt); | ||
marked.defaults = opt; | ||
return marked; | ||
}; | ||
marked.setOptions({ | ||
marked.defaults = { | ||
gfm: true, | ||
tables: true, | ||
breaks: false, | ||
pedantic: false, | ||
sanitize: false, | ||
silent: false, | ||
highlight: null | ||
}); | ||
}; | ||
@@ -813,12 +1082,11 @@ /** | ||
marked.parser = function(src, opt) { | ||
setOptions(opt); | ||
return parse(src); | ||
}; | ||
marked.Parser = Parser; | ||
marked.parser = Parser.parse; | ||
marked.lexer = function(src, opt) { | ||
setOptions(opt); | ||
return block.lexer(src); | ||
}; | ||
marked.Lexer = Lexer; | ||
marked.lexer = Lexer.lex; | ||
marked.InlineLexer = InlineLexer; | ||
marked.inlineLexer = InlineLexer.output; | ||
marked.parse = marked; | ||
@@ -828,2 +1096,4 @@ | ||
module.exports = marked; | ||
} else if (typeof define === 'function' && define.amd) { | ||
define(function() { return marked; }); | ||
} else { | ||
@@ -830,0 +1100,0 @@ this.marked = marked; |
@@ -5,13 +5,13 @@ { | ||
"author": "Christopher Jeffrey", | ||
"version": "0.2.6", | ||
"version": "0.2.7", | ||
"main": "./lib/marked.js", | ||
"bin": "./bin/marked", | ||
"man": "./man/marked.1", | ||
"preferGlobal": false, | ||
"preferGlobal": true, | ||
"repository": "git://github.com/chjj/marked.git", | ||
"homepage": "https://github.com/chjj/marked", | ||
"bugs": { "url": "http://github.com/chjj/marked/issues" }, | ||
"keywords": [ "markdown", "markup", "html" ], | ||
"tags": [ "markdown", "markup", "html" ], | ||
"keywords": ["markdown", "markup", "html"], | ||
"tags": ["markdown", "markup", "html"], | ||
"scripts": { "test": "node test", "bench": "node test --bench" } | ||
} |
@@ -65,3 +65,3 @@ # marked | ||
marked has 4 different switches which change behavior. | ||
marked has a few different switches which change behavior. | ||
@@ -73,5 +73,6 @@ - __pedantic__: Conform to obscure parts of `markdown.pl` as much as possible. | ||
- __highlight__: A callback to highlight code blocks. | ||
- __tables__: Enable GFM tables. This is enabled by default. (Requires the | ||
`gfm` option in order to be enabled). | ||
- __breaks__: Enable GFM line breaks. Disabled by default. | ||
None of the above are mutually exclusive/inclusive. | ||
## Usage | ||
@@ -83,8 +84,9 @@ | ||
gfm: true, | ||
tables: true, | ||
breaks: false, | ||
pedantic: false, | ||
sanitize: true, | ||
// callback for code highlighter | ||
highlight: function(code, lang) { | ||
if (lang === 'js') { | ||
return javascriptHighlighter(code); | ||
return highlighter.javascript(code); | ||
} | ||
@@ -100,6 +102,13 @@ return code; | ||
``` js | ||
var tokens = marked.lexer(text); | ||
var tokens = marked.lexer(text, options); | ||
console.log(marked.parser(tokens)); | ||
``` | ||
``` js | ||
var lexer = new marked.Lexer(options); | ||
var tokens = lexer.lex(text); | ||
console.log(tokens); | ||
console.log(lexer.rules); | ||
``` | ||
``` bash | ||
@@ -127,4 +136,4 @@ $ node | ||
Copyright (c) 2011-2012, Christopher Jeffrey. (MIT License) | ||
Copyright (c) 2011-2013, Christopher Jeffrey. (MIT License) | ||
See LICENSE for more info. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
32210
889
135