Vitaly Puzrin
10 years ago
11 changed files with 1 additions and 526 deletions
@ -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; |
|
||||
}; |
|
@ -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 |
|
||||
}); |
|
||||
}; |
|
@ -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; |
|
||||
}; |
|
@ -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; |
|
||||
}; |
|
@ -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> |
|
||||
. |
|
Loading…
Reference in new issue