Skip to content

Commit

Permalink
Add footnote parsing/rendering support
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron O'Mullan committed Aug 11, 2014
1 parent d3b356f commit e5604a6
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions lib/kramed.js
Expand Up @@ -27,6 +27,7 @@ var block = {
list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
footnote: /^\[\^([^\]]+)\]: ([^\n]+)/,
table: noop,
paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def|math))+)\n*/,
text: /^[^\n]+/,
Expand All @@ -43,6 +44,7 @@ block.list = replace(block.list)
(/bull/g, block.bullet)
('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
('def', '\\n+(?=' + block.def.source + ')')
('footnote', block.footnote)
();

block.blockquote = replace(block.blockquote)
Expand Down Expand Up @@ -205,6 +207,17 @@ Lexer.prototype.token = function(src, top, bq) {
continue;
}

// footnote
if (cap = this.rules.footnote.exec(src)) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'footnote',
refname: cap[1],
text: cap[2]
});
continue;
}

// math
if (cap = this.rules.math.exec(src)) {
src = src.substring(cap[0].length);
Expand Down Expand Up @@ -475,6 +488,7 @@ var inline = {
link: /^!?\[(inside)\]\(href\)/,
reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
reffn: /^!?\[\^(inside)\]/,
strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
Expand All @@ -496,6 +510,10 @@ inline.reflink = replace(inline.reflink)
('inside', inline._inside)
();

inline.reffn = replace(inline.reffn)
('inside', inline._inside)
();

/**
* Normal Inline Grammar
*/
Expand Down Expand Up @@ -651,6 +669,13 @@ InlineLexer.prototype.output = function(src) {
continue;
}

// reffn
if ((cap = this.rules.reffn.exec(src))) {
src = src.substring(cap[0].length);
out += this.renderer.reffn(cap[1]);
continue;
}

// reflink, nolink
if ((cap = this.rules.reflink.exec(src))
|| (cap = this.rules.nolink.exec(src))) {
Expand Down Expand Up @@ -899,6 +924,19 @@ Renderer.prototype.del = function(text) {
return '<del>' + text + '</del>';
};

Renderer.prototype.reffn = function(refname) {
return '<sup><a href="#fn_' + refname + '" id="reffn_' + refname + '">' + refname + '</a></sup>'
}

Renderer.prototype.footnote = function(refname, text) {
return '<blockquote id="fn_' + refname + '">\n'
+ '<sup>' + refname + '</sup>. '
+ text
+ '<a href="#reffn_' + refname + '" title="Jump back to footnote [' + refname + '] in the text."> &#8617;</a>\n'
+ '</blockquote>\n';
}


Renderer.prototype.link = function(href, title, text) {
if (this.options.sanitize) {
try {
Expand Down Expand Up @@ -1018,6 +1056,11 @@ Parser.prototype.tok = function() {
this.token.depth,
this.token.text);
}
case 'footnote': {
return this.renderer.footnote(
this.token.refname,
this.inline.output(this.token.text));
}
case 'code': {
return this.renderer.code(this.token.text,
this.token.lang,
Expand Down

1 comment on commit e5604a6

@paolocasarini
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @AaronO, this is exactly what I needed on chjj/marked with my pull request (#431).

Please sign in to comment.