Browse Source

Removed footnote rules (move to plugin)

pull/25/head
Vitaly Puzrin 10 years ago
parent
commit
57d56c43fb
  1. 1
      lib/parser_block.js
  2. 1
      lib/parser_core.js
  3. 2
      lib/parser_inline.js
  4. 4
      lib/presets/default.js
  5. 33
      lib/renderer.js
  6. 66
      lib/rules_block/footnote.js
  7. 95
      lib/rules_core/footnote_tail.js
  8. 50
      lib/rules_inline/footnote_inline.js
  9. 61
      lib/rules_inline/footnote_ref.js
  10. 185
      test/fixtures/markdown-it/footnotes.txt
  11. 29
      test/fixtures/markdown-it/proto.txt

1
lib/parser_block.js

@ -15,7 +15,6 @@ var _rules = [
[ 'blockquote', require('./rules_block/blockquote'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ], [ 'blockquote', require('./rules_block/blockquote'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
[ 'hr', require('./rules_block/hr'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ], [ 'hr', require('./rules_block/hr'), [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
[ 'list', require('./rules_block/list'), [ 'paragraph', 'reference', 'blockquote' ] ], [ 'list', require('./rules_block/list'), [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'footnote', require('./rules_block/footnote'), [ 'paragraph', 'reference' ] ],
[ 'reference', require('./rules_block/reference'), [ 'reference' ] ], [ 'reference', require('./rules_block/reference'), [ 'reference' ] ],
[ 'heading', require('./rules_block/heading'), [ 'paragraph', 'reference', 'blockquote' ] ], [ 'heading', require('./rules_block/heading'), [ 'paragraph', 'reference', 'blockquote' ] ],
[ 'lheading', require('./rules_block/lheading') ], [ 'lheading', require('./rules_block/lheading') ],

1
lib/parser_core.js

@ -13,7 +13,6 @@ var Ruler = require('./ruler');
var _rules = [ var _rules = [
[ 'block', require('./rules_core/block') ], [ 'block', require('./rules_core/block') ],
[ 'inline', require('./rules_core/inline') ], [ 'inline', require('./rules_core/inline') ],
[ 'footnote_tail', require('./rules_core/footnote_tail') ],
[ 'replacements', require('./rules_core/replacements') ], [ 'replacements', require('./rules_core/replacements') ],
[ 'smartquotes', require('./rules_core/smartquotes') ], [ 'smartquotes', require('./rules_core/smartquotes') ],
[ 'linkify', require('./rules_core/linkify') ] [ 'linkify', require('./rules_core/linkify') ]

2
lib/parser_inline.js

@ -21,8 +21,6 @@ var _rules = [
[ 'emphasis', require('./rules_inline/emphasis') ], [ 'emphasis', require('./rules_inline/emphasis') ],
[ 'link', require('./rules_inline/link') ], [ 'link', require('./rules_inline/link') ],
[ 'image', require('./rules_inline/image') ], [ 'image', require('./rules_inline/image') ],
[ 'footnote_inline', require('./rules_inline/footnote_inline') ],
[ 'footnote_ref', require('./rules_inline/footnote_ref') ],
[ 'autolink', require('./rules_inline/autolink') ], [ 'autolink', require('./rules_inline/autolink') ],
[ 'htmltag', require('./rules_inline/htmltag') ], [ 'htmltag', require('./rules_inline/htmltag') ],
[ 'entity', require('./rules_inline/entity') ] [ 'entity', require('./rules_inline/entity') ]

4
lib/presets/default.js

@ -36,8 +36,7 @@ module.exports = {
'inline', 'inline',
'replacements', 'replacements',
'linkify', 'linkify',
'smartquotes', 'smartquotes'
'footnote_tail'
] ]
}, },
@ -65,7 +64,6 @@ module.exports = {
'emphasis', 'emphasis',
'entity', 'entity',
'escape', 'escape',
'footnote_ref',
'htmltag', 'htmltag',
'image', 'image',
'link', 'link',

33
lib/renderer.js

@ -231,39 +231,6 @@ rules.htmltag = function (tokens, idx /*, options, env */) {
}; };
rules.footnote_ref = function (tokens, idx) {
var n = Number(tokens[idx].id + 1).toString();
var id = 'fnref' + n;
if (tokens[idx].subId > 0) {
id += ':' + tokens[idx].subId;
}
return '<sup class="footnote-ref"><a href="#fn' + n + '" id="' + id + '">[' + n + ']</a></sup>';
};
rules.footnote_block_open = function (tokens, idx, options) {
return (options.xhtmlOut ? '<hr class="footnotes-sep" />\n' : '<hr class="footnotes-sep">\n') +
'<section class="footnotes">\n' +
'<ol class="footnotes-list">\n';
};
rules.footnote_block_close = function () {
return '</ol>\n</section>\n';
};
rules.footnote_open = function (tokens, idx) {
var id = Number(tokens[idx].id + 1).toString();
return '<li id="fn' + id + '" class="footnote-item">';
};
rules.footnote_close = function () {
return '</li>\n';
};
rules.footnote_anchor = function (tokens, idx) {
var n = Number(tokens[idx].id + 1).toString();
var id = 'fnref' + n;
if (tokens[idx].subId > 0) {
id += ':' + tokens[idx].subId;
}
return ' <a href="#' + id + '" class="footnote-backref">\u21a9</a>'; /* ↩ */
};
rules.dl_open = function() { rules.dl_open = function() {
return '<dl>\n'; return '<dl>\n';
}; };

66
lib/rules_block/footnote.js

@ -1,66 +0,0 @@
// Process footnote reference list
'use strict';
module.exports = function footnote(state, startLine, endLine, silent) {
var oldBMark, oldTShift, oldParentType, pos, label,
start = state.bMarks[startLine] + state.tShift[startLine],
max = state.eMarks[startLine];
// line should be at least 5 chars - "[^x]:"
if (start + 4 > max) { return false; }
if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }
if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }
for (pos = start + 2; pos < max; pos++) {
if (state.src.charCodeAt(pos) === 0x20) { return false; }
if (state.src.charCodeAt(pos) === 0x5D /* ] */) {
break;
}
}
if (pos === start + 2) { return false; } // no empty footnote labels
if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x3A /* : */) { return false; }
if (silent) { return true; }
pos++;
if (!state.env.footnotes) { state.env.footnotes = {}; }
if (!state.env.footnotes.refs) { state.env.footnotes.refs = {}; }
label = state.src.slice(start + 2, pos - 2);
state.env.footnotes.refs[':' + label] = -1;
state.tokens.push({
type: 'footnote_reference_open',
label: label,
level: state.level++
});
oldBMark = state.bMarks[startLine];
oldTShift = state.tShift[startLine];
oldParentType = state.parentType;
state.tShift[startLine] = state.skipSpaces(pos) - pos;
state.bMarks[startLine] = pos;
state.blkIndent += 4;
state.parentType = 'footnote';
if (state.tShift[startLine] < state.blkIndent) {
state.tShift[startLine] += state.blkIndent;
state.bMarks[startLine] -= state.blkIndent;
}
state.md.block.tokenize(state, startLine, endLine, true);
state.parentType = oldParentType;
state.blkIndent -= 4;
state.tShift[startLine] = oldTShift;
state.bMarks[startLine] = oldBMark;
state.tokens.push({
type: 'footnote_reference_close',
level: --state.level
});
return true;
};

95
lib/rules_core/footnote_tail.js

@ -1,95 +0,0 @@
'use strict';
module.exports = function footnote_block(state) {
var i, l, j, t, lastParagraph, list, tokens, current, currentLabel,
level = 0,
insideRef = false,
refTokens = {};
if (!state.env.footnotes) { return; }
state.tokens = state.tokens.filter(function(tok) {
if (tok.type === 'footnote_reference_open') {
insideRef = true;
current = [];
currentLabel = tok.label;
return false;
}
if (tok.type === 'footnote_reference_close') {
insideRef = false;
// prepend ':' to avoid conflict with Object.prototype members
refTokens[':' + currentLabel] = current;
return false;
}
if (insideRef) { current.push(tok); }
return !insideRef;
});
if (!state.env.footnotes.list) { return; }
list = state.env.footnotes.list;
state.tokens.push({
type: 'footnote_block_open',
level: level++
});
for (i = 0, l = list.length; i < l; i++) {
state.tokens.push({
type: 'footnote_open',
id: i,
level: level++
});
if (list[i].tokens) {
tokens = [];
tokens.push({
type: 'paragraph_open',
tight: false,
level: level++
});
tokens.push({
type: 'inline',
content: '',
level: level,
children: list[i].tokens
});
tokens.push({
type: 'paragraph_close',
tight: false,
level: --level
});
} else if (list[i].label) {
tokens = refTokens[':' + list[i].label];
}
state.tokens = state.tokens.concat(tokens);
if (state.tokens[state.tokens.length - 1].type === 'paragraph_close') {
lastParagraph = state.tokens.pop();
} else {
lastParagraph = null;
}
t = list[i].count > 0 ? list[i].count : 1;
for (j = 0; j < t; j++) {
state.tokens.push({
type: 'footnote_anchor',
id: i,
subId: j,
level: level
});
}
if (lastParagraph) {
state.tokens.push(lastParagraph);
}
state.tokens.push({
type: 'footnote_close',
level: --level
});
}
state.tokens.push({
type: 'footnote_block_close',
level: --level
});
};

50
lib/rules_inline/footnote_inline.js

@ -1,50 +0,0 @@
// Process inline footnotes (^[...])
'use strict';
var parseLinkLabel = require('../helpers/parse_link_label');
module.exports = function footnote_inline(state, silent) {
var labelStart,
labelEnd,
footnoteId,
oldLength,
max = state.posMax,
start = state.pos;
if (start + 2 >= max) { return false; }
if (state.src.charCodeAt(start) !== 0x5E/* ^ */) { return false; }
if (state.src.charCodeAt(start + 1) !== 0x5B/* [ */) { return false; }
labelStart = start + 2;
labelEnd = parseLinkLabel(state, start + 1);
// parser failed to find ']', so it's not a valid note
if (labelEnd < 0) { return false; }
// We found the end of the link, and know for a fact it's a valid link;
// so all that's left to do is to call tokenizer.
//
if (!silent) {
if (!state.env.footnotes) { state.env.footnotes = {}; }
if (!state.env.footnotes.list) { state.env.footnotes.list = []; }
footnoteId = state.env.footnotes.list.length;
state.pos = labelStart;
state.posMax = labelEnd;
state.push({
type: 'footnote_ref',
id: footnoteId,
level: state.level
});
oldLength = state.tokens.length;
state.md.inline.tokenize(state);
state.env.footnotes.list[footnoteId] = { tokens: state.tokens.splice(oldLength) };
}
state.pos = labelEnd + 1;
state.posMax = max;
return true;
};

61
lib/rules_inline/footnote_ref.js

@ -1,61 +0,0 @@
// Process footnote references ([^...])
'use strict';
module.exports = function footnote_ref(state, silent) {
var label,
pos,
footnoteId,
footnoteSubId,
max = state.posMax,
start = state.pos;
// should be at least 4 chars - "[^x]"
if (start + 3 > max) { return false; }
if (!state.env.footnotes || !state.env.footnotes.refs) { return false; }
if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }
if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }
for (pos = start + 2; pos < max; pos++) {
if (state.src.charCodeAt(pos) === 0x20) { return false; }
if (state.src.charCodeAt(pos) === 0x0A) { return false; }
if (state.src.charCodeAt(pos) === 0x5D /* ] */) {
break;
}
}
if (pos === start + 2) { return false; } // no empty footnote labels
if (pos >= max) { return false; }
pos++;
label = state.src.slice(start + 2, pos - 1);
if (typeof state.env.footnotes.refs[':' + label] === 'undefined') { return false; }
if (!silent) {
if (!state.env.footnotes.list) { state.env.footnotes.list = []; }
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;
} else {
footnoteId = state.env.footnotes.refs[':' + label];
}
footnoteSubId = state.env.footnotes.list[footnoteId].count;
state.env.footnotes.list[footnoteId].count++;
state.push({
type: 'footnote_ref',
id: footnoteId,
subId: footnoteSubId,
level: state.level
});
}
state.pos = pos;
state.posMax = max;
return true;
};

185
test/fixtures/markdown-it/footnotes.txt

@ -1,185 +0,0 @@
Pandoc example:
.
Here is a footnote reference,[^1] and another.[^longnote]
[^1]: Here is the footnote.
[^longnote]: Here's one with multiple blocks.
Subsequent paragraphs are indented to show that they
belong to the previous footnote.
{ some.code }
The whole paragraph can be indented, or just the first
line. In this way, multi-paragraph footnotes work like
multi-paragraph list items.
This paragraph won't be part of the note, because it
isn't indented.
.
<p>Here is a footnote reference,<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> and another.<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup></p>
<p>This paragraph won’t be part of the note, because it
isn’t indented.</p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Here is the footnote. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Here’s one with multiple blocks.</p>
<p>Subsequent paragraphs are indented to show that they
belong to the previous footnote.</p>
<pre><code>{ some.code }
</code></pre>
<p>The whole paragraph can be indented, or just the first
line. In this way, multi-paragraph footnotes work like
multi-paragraph list items. <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
They could terminate each other:
.
[^1][^2][^3]
[^1]: foo
[^2]: bar
[^3]: baz
.
<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup><sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>foo <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2" class="footnote-item"><p>bar <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
<li id="fn3" class="footnote-item"><p>baz <a href="#fnref3" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
They could be inside blockquotes, and are lazy:
.
[^foo]
> [^foo]: bar
baz
.
<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<blockquote>
</blockquote>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>bar
baz <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
Their labels could not contain spaces or newlines:
.
[^ foo]: bar baz
[^foo
]: bar baz
.
<p>[^ foo]: bar baz</p>
<p>[^foo
]: bar baz</p>
.
We support inline notes too (pandoc example):
.
Here is an inline note.^[Inlines notes are easier to write, since
you don't have to pick an identifier and move down to type the
note.]
.
<p>Here is an inline note.<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Inlines notes are easier to write, since
you don’t have to pick an identifier and move down to type the
note. <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
They could have arbitrary markup:
.
foo^[ *bar* ]
.
<p>foo<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p> <em>bar</em> <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
Indents:
.
[^xxxxx] [^yyyyy]
[^xxxxx]: foo
---
[^yyyyy]: foo
---
.
<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> <sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup></p>
<hr>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><h2>foo</h2>
<a href="#fnref1" class="footnote-backref">↩</a></li>
<li id="fn2" class="footnote-item"><p>foo <a href="#fnref2" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
Indents for the first line:
.
[^xxxxx] [^yyyyy]
[^xxxxx]: foo
[^yyyyy]: foo
.
<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> <sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>foo <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
<li id="fn2" class="footnote-item"><pre><code>foo
</code></pre>
<a href="#fnref2" class="footnote-backref">↩</a></li>
</ol>
</section>
.

29
test/fixtures/markdown-it/proto.txt

@ -7,20 +7,6 @@
<p><a href="blah"><strong>proto</strong></a></p> <p><a href="blah"><strong>proto</strong></a></p>
. .
.
[^__proto__]
[^__proto__]: blah
.
<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>blah <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.
. .
[hasOwnProperty] [hasOwnProperty]
@ -29,18 +15,3 @@
. .
<p><a href="blah">hasOwnProperty</a></p> <p><a href="blah">hasOwnProperty</a></p>
. .
.
[^hasOwnProperty]
[^hasOwnProperty]: blah
.
<p><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></p>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>blah <a href="#fnref1" class="footnote-backref">↩</a></p>
</li>
</ol>
</section>
.

Loading…
Cancel
Save