diff --git a/lib/marked.js b/lib/marked.js
index d5522afce2..6f2e39e420 100644
--- a/lib/marked.js
+++ b/lib/marked.js
@@ -21,6 +21,7 @@ var block = {
blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
+ footnote: /^ *\[\^([^\]]+)\]: /,
def: /^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
table: noop,
paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
@@ -159,6 +160,16 @@ Lexer.prototype.token = function(src, top, bq) {
, l;
while (src) {
+ if (top && this.footnote
+ && this.tokens[this.tokens.length-1].type !== 'footnote_start'
+ && this.tokens[this.tokens.length-1].type !== 'parapgraph'
+ && this.tokens[this.tokens.length-1].type !== 'newline') {
+ this.footenote = false;
+ this.tokens.push({
+ type: 'footnote_end'
+ });
+ }
+
// newline
if (cap = this.rules.newline.exec(src)) {
src = src.substring(cap[0].length);
@@ -365,6 +376,17 @@ Lexer.prototype.token = function(src, top, bq) {
continue;
}
+ // footnote
+ if ((!bq && top) && (cap = this.rules.footnote.exec(src))) {
+ src = src.substring(cap[0].length);
+ this.footnote = true;
+ this.tokens.push({
+ type: 'footnote_start',
+ text: cap[1]
+ });
+ continue;
+ }
+
// def
if ((!bq && top) && (cap = this.rules.def.exec(src))) {
src = src.substring(cap[0].length);
@@ -438,6 +460,13 @@ Lexer.prototype.token = function(src, top, bq) {
}
}
+ if (top && this.footnote) {
+ this.footenote = false;
+ this.tokens.push({
+ type: 'footnote_end'
+ });
+ }
+
return this.tokens;
};
@@ -451,6 +480,7 @@ var inline = {
url: noop,
tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
link: /^!?\[(inside)\]\(href\)/,
+ footnoteref: /^ *\[\^([^\]]+)\]/,
reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
@@ -623,6 +653,13 @@ InlineLexer.prototype.output = function(src) {
continue;
}
+ // footnote
+ if (cap = this.rules.footnoteref.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.renderer.footnoteref(escape(cap[1], true));
+ continue;
+ }
+
// reflink, nolink
if ((cap = this.rules.reflink.exec(src))
|| (cap = this.rules.nolink.exec(src))) {
@@ -859,6 +896,39 @@ Renderer.prototype.del = function(text) {
return '' + text + '';
};
+Renderer.prototype.footnoteref = function(ref) {
+ return ''
+ + '' + ref + ''
+ + '';
+};
+
+Renderer.prototype.footnote = function(ref, body) {
+ return '