\n';
+}
+
+function generateFootnoteBackRefHtml(id, refId, renderInfo) {
+ const tok = renderInfo.tokens[renderInfo.idx];
+ assert.strict.ok(tok != null);
+ assert.strict.ok(tok.meta != null);
+ /* ↩ with escape code to prevent display as Apple Emoji on iOS */
+
+ return ` \u21a9\uFE0E`;
+}
+
+const default_plugin_options = {
+ // atDocumentEnd: false, -- obsoleted option of the original plugin
+ anchorFn: anchorFnDefault,
+ captionFn: captionFnDefault,
+ headerFn: headerFnDefault,
+ mkLabel: determine_footnote_symbol,
+ // see also https://www.editage.com/insights/footnotes-in-tables-part-1-choice-of-footnote-markers-and-their-sequence
+ // why asterisk/star is not part of the default footnote marker sequence.
+ //
+ // For similar reasons, we DO NOT include the section § symbol in this list.
+ //
+ // when numberSequnce is NULL/empty, a regular numerical numbering is assumed.
+ // Otherwise, the array is indexed; when there are more footnotes than entries in
+ // the numberSequence array, the entries are re-used, but doubled/trippled, etc.
+ //
+ // When the indexing in this array hits a NUMERIC value (as last entry), any higher
+ // footnotes are NUMBERED starting at that number.
+ //
+ // NOTE: as we can reference the same footnote from multiple spots, we do not depend
+ // on CSS counter() approaches by default, but providee this mechanism in the plugin
+ // code itself.
+ numberSequence: ['†', '‡', '††', '‡‡', '¶', 1],
+ // Overrides the footnode mode when set to one of the following:
+ //
+ // Recognized 'modes':
+ // '>': aside note (default for inline notes)
+ // ':': end node
+ // '=': section note (default for regular referenced notes)
+ //
+ // Also accepts these keywords: 'aside', 'section', 'end'
+ //
+ modeOverride: null,
+ // list section notes and endnotes in order of:
+ //
+ // 0: first *appearance* in the text
+ // 1: first *reference* in the text
+ // 2: *definition* in the text
+ // 3: sorted alphanumerically by *coded* label,
+ // i.e. *numeric* labels are sorted in numeric order (so `10` comes AFTER `7`!),
+ // while all others are sorted using `String.localeCompare()`. When labels have
+ // a *numeric leading*, e.g. `71geo` --> `71`, that part is sorted numerically first.
+ //
+ // Here 'coded label' means the label constructed from the reference ids and label overrides
+ // as used in the markdown source, using the expression
+ // labelOverride || reference || id
+ // which gives for these examples (assuming them to be the only definitions in your input):
+ // [^refA]: ... --> null || 'refA' || 1
+ // [^refB LBL]: ... --> 'LBL' || 'refB' || 2
+ // 4: sorted alphanumerically by *printed* label
+ // which is like mode 3, but now for the label as will be seen in the *output*!
+ sortOrder: 4,
+ // what to print between bunched-together footnote references, i.e. the '+' in `blabla¹⁺²`
+ refCombiner: ','
+};
+function footnote_plugin(md, plugin_options) {
+ const parseLinkLabel = md.helpers.parseLinkLabel,
+ isSpace = md.utils.isSpace;
+ plugin_options = Object.assign({}, default_plugin_options, plugin_options);
+
+ function determine_mode(mode, default_mode) {
+ let override = null;
+
+ if (plugin_options.modeOverride) {
+
+ if ('>:='.includes(plugin_options.modeOverride)) {
+ override = plugin_options.modeOverride;
+ }
+ }
+
+ if ('>:='.includes(mode)) {
+ return {
+ mode: override || mode,
+ fromInput: true
+ };
+ }
+
+ return {
+ mode: override || default_mode,
+ fromInput: false
+ };
+ }
+
+ function render_footnote_n(tokens, idx, excludeSubId) {
+ const mark = tokens[idx].meta.id;
+ assert.strict.ok(Number.isFinite(mark));
+ assert.strict.ok(mark > 0);
+ let n = '' + mark; // = mark.toString();
+
+ assert.strict.ok(n.length > 0);
+
+ if (!excludeSubId && tokens[idx].meta.subId > 0) {
+ n += '-' + tokens[idx].meta.subId;
+ }
+
+ return n;
+ }
+
+ function render_footnote_mark(renderInfo) {
+ const token = renderInfo.tokens[renderInfo.idx];
+ assert.strict.ok(token != null);
+ assert.strict.ok(renderInfo.env.footnotes != null);
+ assert.strict.ok(renderInfo.env.footnotes.list != null);
+ const info = renderInfo.env.footnotes.list[token.meta.id];
+ assert.strict.ok(info != null);
+ const mark = plugin_options.mkLabel(token.meta.id, info, renderInfo);
+ assert.strict.ok(mark.length > 0);
+ return mark;
+ }
+
+ function render_footnote_anchor_name(renderInfo) {
+ const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, true);
+ return plugin_options.anchorFn(n, true, renderInfo);
+ }
+
+ function render_footnote_anchor_nameRef(renderInfo) {
+ const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, false);
+ return plugin_options.anchorFn(n, false, renderInfo);
+ }
+
+ function render_footnote_caption(renderInfo) {
+ const n = render_footnote_mark(renderInfo);
+ return plugin_options.captionFn(n, renderInfo);
+ }
+
+ function render_footnote_ref(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const id = render_footnote_anchor_name(renderInfo);
+ const caption = render_footnote_caption(renderInfo);
+ const refId = render_footnote_anchor_nameRef(renderInfo); // check if multiple footnote references are bunched together:
+ // IFF they are, we should separate them with commas.
+ //
+ // Exception: when next token has an extra text (`meta.text`) the
+ // bunching together is not a problem as them the output will render
+ // like this: `bla1text2`, ergo a look
+ // like this: `bla¹text²` instead of bunched footnotes references ¹ and ²
+ // that would (without the extra comma injection) look like `bla¹²` instead
+ // of `x¹⁺²` (here '+' instead of ',' comma, but you get the idea -- there's no
+ // Unicode superscript-comma so that's why I used unicode superscript-plus
+ // in this 'ascii art' example).
+ //
+
+ const next_token = tokens[idx + 1] || {};
+ const next_token_meta = next_token.meta || {};
+ const bunched_footnote_ref_mode = next_token.type === 'footnote_ref' ? !next_token_meta.text ? 1 : 2 : 0;
+ return generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo);
+ }
+
+ function render_footnote_block_open(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ return generateFootnoteSectionStartHtml(renderInfo);
+ }
+
+ function render_footnote_block_close(tokens, idx, options, env, self) {
+ return generateFootnoteSectionEndHtml();
+ }
+
+ function render_footnote_reference_open(tokens, idx, options, env, self) {
+ return '';
+ }
+
+ function render_footnote_reference_close() {
+ return '';
+ }
+
+ function render_footnote_mark_end_of_block() {
+ return '';
+ }
+
+ function render_footnote_open(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const id = render_footnote_anchor_name(renderInfo);
+ const caption = render_footnote_caption(renderInfo); // allow both a JavaScript --> CSS approach via `data-footnote-caption`
+ // and a classic CSS approach while a display:inline-block SUP presenting
+ // the LI 'button' instead:
+
+ return generateFootnoteStartHtml(id, caption);
+ }
+
+ function render_footnote_close(tokens, idx, options, env, self) {
+ return generateFootnoteEndHtml();
+ }
+
+ function render_footnote_anchor_backref(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const tok = tokens[idx];
+ assert.strict.ok(tok != null);
+ assert.strict.ok(tok.meta != null);
+ const id = render_footnote_anchor_name(renderInfo);
+ let refId = render_footnote_n(tokens, idx, false);
+ refId = plugin_options.anchorFn(refId, false, renderInfo);
+ return generateFootnoteBackRefHtml(id, refId, renderInfo);
+ }
+
+ md.renderer.rules.footnote_ref = render_footnote_ref;
+ md.renderer.rules.footnote_block_open = render_footnote_block_open;
+ md.renderer.rules.footnote_block_close = render_footnote_block_close;
+ md.renderer.rules.footnote_reference_open = render_footnote_reference_open;
+ md.renderer.rules.footnote_reference_close = render_footnote_reference_close;
+ md.renderer.rules.footnote_mark_end_of_block = render_footnote_mark_end_of_block;
+ md.renderer.rules.footnote_open = render_footnote_open;
+ md.renderer.rules.footnote_close = render_footnote_close;
+ md.renderer.rules.footnote_anchor = render_footnote_anchor_backref;
+
+ function obtain_footnote_info_slot(env, label, at_definition) {
+ // inline blocks have their own *child* environment in markdown-it v10+.
+ // As the footnotes must live beyond the lifetime of the inline block env,
+ // we must patch them into the `parentState.env` for the footnote_tail
+ // handler to be able to access them afterwards!
+ while (env.parentState) {
+ env = env.parentState.env;
+ assert.strict.ok(env != null);
+ }
+
+ if (!env.footnotes) {
+ env.footnotes = {
+ // map label tto ID:
+ refs: {},
+ // store footnote info indexed by ID
+ list: [],
+ // remap ID to re-ordered ID (determines placement order for section notes and endnotes)
+ idMap: [0],
+ idMapCounter: 0,
+ // and a counter for the generated sections (including asides); see the demo/test which
+ // uses the generated `#fnsection-DDD` identifiers to hack/fix the styling, for example.
+ sectionCounter: 0
+ };
+ } // When label is NULL, this is a request from in INLINE NOTE.
+ // NOTE: IDs are index numbers, BUT they start at 1 instead of 0 to make life easier in check code:
+
+
+ let footnoteId;
+ let infoRec; // label as index: prepend ':' to avoid conflict with Object.prototype members
+
+ if (label == null || !env.footnotes.refs[':' + label]) {
+ footnoteId = Math.max(1, env.footnotes.list.length);
+ infoRec = {
+ id: footnoteId,
+ label,
+ labelOverride: null,
+ mode: null,
+ content: null,
+ tokens: null,
+ count: 0
+ };
+ env.footnotes.list[footnoteId] = infoRec;
+
+ if (label != null) {
+ env.footnotes.refs[':' + label] = footnoteId;
+ }
+ } else {
+ footnoteId = env.footnotes.refs[':' + label];
+ infoRec = env.footnotes.list[footnoteId];
+ assert.strict.ok(!!infoRec, 'expects non-NULL footnote info record');
+ }
+
+ const idMap = env.footnotes.idMap; // now check if the idMap[] has been set up already as well. This depends on
+ // when WE are invoked (`at_definition`) and the configured `options.sortOrder`:
+
+ switch (plugin_options.sortOrder) {
+ // 0: first *appearance* in the text
+ default:
+ case 0:
+ // basically, this means: order as-is
+ if (!idMap[footnoteId]) {
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 1: first *reference* in the text
+
+ case 1:
+ if (!at_definition && !idMap[footnoteId]) {
+ // first reference is now!
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 2: *definition* in the text
+
+ case 2:
+ if (at_definition && !idMap[footnoteId]) {
+ // definition is now!
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)
+
+ case 3:
+ case 4:
+ // just note the footnoteId now; this must be re-ordered later when we have collected all footnotes.
+ //
+ // set it up when we get there...
+ break;
+ }
+
+ return infoRec;
+ }
+
+ function find_end_of_block_marker(state, startIndex) {
+ let idx, len;
+ const tokens = state.tokens;
+
+ for (idx = startIndex, len = tokens.length; idx < len; idx++) {
+ if (tokens[idx].type === 'footnote_mark_end_of_block') {
+ return idx;
+ }
+ } // Punch a slot into the token stream (at the very end)
+ // for consistency with footnote_mark_end_of_block():
+
+
+ const token = new state.Token('footnote_mark_end_of_block', '', 0);
+ token.hidden = true;
+ tokens.push(token);
+ return tokens.length - 1;
+ }
+
+ function update_end_of_block_marker(state, footnoteId) {
+ // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:
+ // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the
+ // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:
+ const parentState = state.env.parentState;
+ const parentIndex = state.env.parentTokenIndex;
+ const markerTokenIndex = find_end_of_block_marker(parentState, parentIndex + 1);
+ const token = parentState.tokens[markerTokenIndex];
+
+ if (!token.meta) {
+ token.meta = {
+ footnote_list: []
+ };
+ }
+
+ token.meta.footnote_list.push(footnoteId);
+ } // Mark end of paragraph/heading/whatever BLOCK (or rather: START of the next block!)
+
+
+ function footnote_mark_end_of_block(state, startLine, endLine, silent) {
+ if (!silent && state.tokens.length > 0) {
+ const token = state.push('footnote_mark_end_of_block', '', 0);
+ token.hidden = true;
+ }
+
+ return false;
+ } // Process footnote block definition
+
+
+ function footnote_def(state, startLine, endLine, silent) {
+ let oldBMark,
+ oldTShift,
+ oldSCount,
+ oldParentType,
+ pos,
+ token,
+ initial,
+ offset,
+ ch,
+ posAfterColon,
+ start = state.bMarks[startLine] + state.tShift[startLine],
+ max = state.eMarks[startLine]; // line should be at least 6 chars - "[^x]: " or "[^x]:> "
+
+ if (start + 5 > 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) === 0x0A
+ /* LF */
+ ) {
+ return false;
+ }
+
+ if (state.src.charCodeAt(pos) === 0x5D
+ /* ] */
+ ) {
+ break;
+ }
+ }
+
+ const labelEnd = pos;
+
+ if (pos === start + 2) {
+ return false;
+ } // no empty footnote labels
+
+
+ if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x3A
+ /* : */
+ ) {
+ return false;
+ }
+
+ const mode_rec = determine_mode(state.src[pos + 1], '='); // default mode is section_note mode.
+
+ if (mode_rec.fromInput) {
+ pos++;
+ }
+
+ const mode = mode_rec.mode;
+
+ if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x20
+ /* space */
+ ) {
+ return false;
+ }
+
+ if (silent) {
+ return true;
+ }
+
+ pos++;
+ const labelInfo = decode_label(state.src.slice(start + 2, labelEnd), true);
+
+ if (!labelInfo) {
+ return false;
+ }
+
+ assert.strict.ok(!labelInfo.extraText); // Now see if we already have a footnote ID for this footnote label:
+ // fetch it if we have one and otherwise produce a new one so everyone
+ // can use this from now on.
+ //
+ // This scenario is possible when the footnote *definition* comes BEFORE
+ // the first actual footnote *use* (*reference*). This is UNUSUAL when people
+ // write texts, but it is *not impossible*, particularly now that we have
+ // specified-by-design that endnotes can be marked as such (`[^label]:: note text`)
+ // and freely mixed with sidenotes (`[^label]:> note text`) and section
+ // notes (`[^label]:= note text` (explicit mode) or `[^label]: note text`
+ // (implicit mode)), where *section notes* will placed at the spot in the text
+ // flow where they were *defined*. Again, highly irregular, BUT someone MAY
+ // feel the need to place some section note *definitions* ABOVE their first
+ // use point.
+ //
+
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, true);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ infoRec.mode = mode;
+ infoRec.content = state.src.slice(pos, max);
+ token = state.push('footnote_reference_open', '', 1);
+ token.meta = {
+ id: infoRec.id
+ };
+ token.hidden = true;
+ oldBMark = state.bMarks[startLine];
+ oldTShift = state.tShift[startLine];
+ oldSCount = state.sCount[startLine];
+ oldParentType = state.parentType;
+ posAfterColon = pos;
+ initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);
+
+ while (pos < max) {
+ ch = state.src.charCodeAt(pos);
+
+ if (isSpace(ch)) {
+ if (ch === 0x09) {
+ offset += 4 - offset % 4;
+ } else {
+ offset++;
+ }
+ } else {
+ break;
+ }
+
+ pos++;
+ }
+
+ state.tShift[startLine] = pos - posAfterColon;
+ state.sCount[startLine] = offset - initial;
+ state.bMarks[startLine] = posAfterColon;
+ state.blkIndent += 4;
+ state.parentType = 'footnote';
+
+ if (state.sCount[startLine] < state.blkIndent) {
+ state.sCount[startLine] += state.blkIndent;
+ }
+
+ state.md.block.tokenize(state, startLine, endLine, true);
+ state.parentType = oldParentType;
+ state.blkIndent -= 4;
+ state.tShift[startLine] = oldTShift;
+ state.sCount[startLine] = oldSCount;
+ state.bMarks[startLine] = oldBMark;
+ token = state.push('footnote_reference_close', '', -1);
+ token.meta = {
+ id: infoRec.id
+ };
+ return true;
+ } // Process inline footnotes (^[...] or ^[>...])
+
+
+ function footnote_inline(state, silent) {
+ let labelStart,
+ labelEnd,
+ token,
+ tokens,
+ 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; // NOTE: inline notes are automatically considered to be ASIDE notes,
+ // UNLESS otherwise specified!
+ //
+ // Recognized 'modes':
+ // '>': aside note (default for inline notes)
+ // ':': end node
+ // '=': section note (default for regular referenced notes)
+ //
+ // (Also note https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html:
+ // our notes look like this: `[^ref]:` while Academic MarkDown references look
+ // like this: `[@Belawog2012]` i.e. no '^' in there. Hence these can safely co-exist.)
+ //
+
+ const mode_rec = determine_mode(state.src[start + 2], '>'); // default mode is aside ~ sidenote mode.
+
+ if (mode_rec.fromInput) {
+ labelStart++;
+ }
+
+ const mode = mode_rec.mode;
+ 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) {
+ // WARNING: claim our footnote slot for there MAY be nested footnotes
+ // discovered in the next inline.parse() call below!
+ const infoRec = obtain_footnote_info_slot(state.env, null, true);
+ infoRec.mode = mode;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id
+ };
+ state.md.inline.parse(state.src.slice(labelStart, labelEnd), state.md, state.env, tokens = []); // Now fill our previously claimed slot:
+
+ infoRec.content = state.src.slice(labelStart, labelEnd);
+ infoRec.tokens = tokens; // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:
+ // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the
+ // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:
+
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = labelEnd + 1;
+ state.posMax = max;
+ return true;
+ } // Check if this is a valid ffootnote reference label.
+ //
+ // Also see if there's a label OVERRIDE text or marker ('@') provided.
+ //
+ // Return the parsed label record.
+
+
+ function decode_label(label, extra_text_is_labelOverride) {
+ var _m$;
+
+ if (!label) {
+ return null;
+ }
+
+ const m = label.match(/^(@?)(\S+)(?:\s+(.+))?$/); // label with OPTIONAL override text...
+
+ if (!m) {
+ return null;
+ }
+
+ assert.strict.ok(m[2].length > 0);
+ let extraText = (_m$ = m[3]) == null ? void 0 : _m$.trim(); // label [output] override?
+
+ let override = null;
+
+ if (m[1]) {
+ override = m[2];
+ }
+
+ if (extra_text_is_labelOverride && extraText) {
+ override = extraText;
+ extraText = null;
+ }
+
+ return {
+ label: m[2],
+ labelOverride: override,
+ extraText
+ };
+ } // Process footnote references with text ([^label ...])
+
+
+ function footnote_ref_with_text(state, silent) {
+ let pos,
+ footnoteSubId,
+ token,
+ max = state.posMax,
+ start = state.pos; // should be at least 6 chars - "[^l x]"
+
+ if (start + 5 > 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) === 0x0A
+ /* linefeed */
+ ) {
+ 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++;
+ const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), false);
+
+ if (!labelInfo || !labelInfo.extraText) {
+ return false;
+ }
+
+ assert.strict.ok(labelInfo.extraText.length > 0);
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ if (!silent) {
+ footnoteSubId = infoRec.count;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id,
+ subId: footnoteSubId,
+ text: labelInfo.extraText
+ };
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = pos;
+ state.posMax = max;
+ return true;
+ } // Process footnote references ([^...])
+
+
+ function footnote_ref(state, silent) {
+ let pos,
+ footnoteSubId,
+ token,
+ max = state.posMax,
+ start = state.pos; // should be at least 4 chars - "[^x]"
+
+ if (start + 3 > 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) === 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++;
+ const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), true);
+
+ if (!labelInfo) {
+ return false;
+ }
+
+ assert.strict.ok(!labelInfo.extraText);
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ if (!silent) {
+ footnoteSubId = infoRec.count;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id,
+ subId: footnoteSubId
+ };
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = pos;
+ state.posMax = max;
+ return true;
+ }
+
+ function place_footnote_definitions_at(state, token_idx, footnote_id_list, category, baseInfo) {
+ if (footnote_id_list.length === 0) {
+ return; // nothing to inject...
+ }
+
+ let inject_tokens = [];
+ assert.strict.ok(baseInfo.env.footnotes.list != null);
+ const footnote_spec_list = baseInfo.env.footnotes.list;
+ let token = new state.Token('footnote_block_open', '', 1);
+ token.markup = plugin_options.headerFn(category, baseInfo.env, plugin_options);
+ token.meta = {
+ sectionId: ++baseInfo.env.footnotes.sectionCounter,
+ category
+ };
+ inject_tokens.push(token);
+
+ for (const id of footnote_id_list) {
+ const fn = footnote_spec_list[id];
+ token = new state.Token('footnote_open', '', 1);
+ token.meta = {
+ id,
+ category
+ };
+ inject_tokens.push(token);
+
+ if (fn.label == null) {
+ // process an inline footnote text:
+ token = new state.Token('paragraph_open', 'p', 1);
+ token.block = true;
+ inject_tokens.push(token);
+ token = new state.Token('inline', '', 0);
+ token.children = fn.tokens;
+ token.content = fn.content;
+ inject_tokens.push(token);
+ token = new state.Token('paragraph_close', 'p', -1);
+ token.block = true;
+ inject_tokens.push(token);
+ } else {
+ // process a labeled footnote:
+ inject_tokens = inject_tokens.concat(fn.tokens || []);
+ } //let lastParagraph;
+ //if (inject_tokens[inject_tokens.length - 1].type === 'paragraph_close') {
+ // lastParagraph = inject_tokens.pop();
+ //} else {
+ // lastParagraph = null;
+ //}
+
+
+ const cnt = fn.count;
+ assert.strict.ok(cnt >= 0);
+
+ for (let j = 0; j < cnt; j++) {
+ token = new state.Token('footnote_anchor', '', 0);
+ token.meta = {
+ id,
+ subId: j,
+ backrefCount: cnt,
+ category
+ };
+ inject_tokens.push(token);
+ } //if (lastParagraph) {
+ // inject_tokens.push(lastParagraph);
+ //}
+
+
+ token = new state.Token('footnote_close', '', -1);
+ token.meta = {
+ id,
+ category
+ };
+ inject_tokens.push(token);
+ }
+
+ token = new state.Token('footnote_block_close', '', -1);
+ token.meta = {
+ category
+ };
+ inject_tokens.push(token);
+ state.tokens.splice(token_idx, 0, ...inject_tokens);
+ }
+
+ function more_footnote_reference_blocks_follow_immediately(tokens, idx) {
+ let tok = tokens[idx];
+
+ while (tok && (tok.type === 'footnote_mark_end_of_block' || tok.type === 'footnote_reference_close')) {
+ idx++;
+ tok = tokens[idx];
+ }
+
+ return tok && tok.type === 'footnote_reference_open';
+ } // Glue footnote tokens into appropriate slots of token stream.
+
+
+ function footnote_tail(state, startLine, endLine, silent) {
+ let i,
+ current,
+ insideRef = false;
+
+ if (!state.env.footnotes) {
+ // no footnotes at all? --> filter out all 'footnote_mark_end_of_block' chunks:
+ state.tokens = state.tokens.filter(function (tok, idx) {
+ return tok.type !== 'footnote_mark_end_of_block';
+ });
+ return;
+ }
+
+ const idMap = state.env.footnotes.idMap;
+ const baseInfo = {
+ options: state.md.options,
+ env: state.env,
+ plugin_options,
+ self: this
+ };
+
+ function footnote_print_comparer(idA, idB) {
+ return idMap[idA] - idMap[idB];
+ } // Rewrite the tokenstream to place the aside-footnotes and section footnotes where they need to be:
+
+
+ const footnote_spec_list = state.env.footnotes.list; // extract the tokens constituting the footnote/sidenote *content* and
+ // store that bunch in `refTokens[:]` instead, to be injected back into
+ // the tokenstream at the appropriate spots.
+
+ state.tokens = state.tokens.filter(function (tok, idx) {
+ switch (tok.type) {
+ // filter out 'footnote_mark_end_of_block' tokens which follow BLOCKS that do not contain any
+ // footnote/sidenote/endnote references:
+ case 'footnote_mark_end_of_block':
+ if (!tok.meta) return false;
+ if (!tok.meta.footnote_list) return false;
+ break;
+
+ case 'footnote_reference_open':
+ insideRef = true;
+ current = [];
+ return true;
+
+ case 'footnote_reference_close':
+ insideRef = false;
+ const infoRec = footnote_spec_list[tok.meta.id];
+ infoRec.tokens = current;
+ return true;
+ }
+
+ if (insideRef) {
+ current.push(tok);
+ }
+
+ return !insideRef;
+ }); // execute configured sorting/mapping (`idMap`):
+
+ switch (plugin_options.sortOrder) {
+ // 0: first *appearance* in the text
+ default:
+ case 0: // 1: first *reference* in the text
+
+ case 1: // 2: *definition* in the text
+
+ case 2:
+ // order is specified in the `idMap` already.
+ break;
+ // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)
+
+ case 3:
+ case 4:
+ // the `idMap[]` array has not been set up and must be produced
+ // to turn this into an alphanumerically-by-label sort order, where
+ // a `footnoteId` based index will produce the order of appearance.
+ const reIdMap = [];
+
+ for (let i = 1; i < footnote_spec_list.length; i++) {
+ reIdMap[i - 1] = i;
+ }
+
+ reIdMap.sort((idA, idB) => {
+ const infoA = footnote_spec_list[idA];
+ const infoB = footnote_spec_list[idB];
+ assert.strict.ok(infoA);
+ assert.strict.ok(infoB); // is any of these an inline footnote, i.e. without any label yet? Produce a fake label for sorting then!
+ //
+ // As stated elsewhere: inline section_notes and end_notes will end up among everyone else in this sort order mode.
+
+ assert.strict.ok(infoA.id === idA);
+ assert.strict.ok(infoB.id === idB); // Split a "sort label" up into its numerical part and the tail. Note that we don't call
+ // it 'tail' but 'label', because we will need to compare the ENTIRE LABEL using string comparison
+ // when the numeric leaders are identical, so as to ensure that 'labels' such as `00000` will sort
+ // as 'higher' than `000`, both of which will be rated as numerically identical!
+
+ function to_atoms(label) {
+ // now extract number or numerical leader part.
+ //
+ // Only accept OBVIOUS, SIMPLE NUMERIC LEADERS! This is about *legibility*
+ // of those numrical leaders, not a pedantic "what is possibly legally numeric"
+ // challenge. Hence we DO NOT accept leading +/- and only a decimal dot when
+ // there's a decimal number BEFORE it, such as in `5.1hack` --> `5.1`, but NOT
+ // `.42oz`!
+ //
+ // Do not use `nmr = +lbl` as that would treat labels such as `0xf4` as hexadecimal numbers,
+ // which we DO NOT want to happen.
+ const m = label.match(/^\d+(?:\.\d+)?/) || ['x'];
+ const nmr = +m[0] || Infinity; // non-numeric labels are rated NUMEICALLY HIGHER than any numerical leader.
+
+ return {
+ label,
+ number: nmr
+ };
+ }
+
+ const labelA = plugin_options.sortOrder === 3 ? infoA.labelOverride || infoA.label || '' + infoA.id : plugin_options.mkLabel(infoA.id, infoA, baseInfo);
+ const labelB = plugin_options.sortOrder === 3 ? infoB.labelOverride || infoB.label || '' + infoB.id : plugin_options.mkLabel(infoB.id, infoB, baseInfo);
+ const atomA = to_atoms(labelA);
+ const atomB = to_atoms(labelB);
+ const diff = atomA.number - atomB.number;
+ return diff || atomA.label.localeCompare(atomB.label); // ^^^^^^^ shorthand for:
+ //
+ // if (isNaN(diff) || diff === 0) then stringcompare else numeric-difference
+ }); // Now turn this into a sort order map:
+
+ for (let prio = 0; prio < reIdMap.length; prio++) {
+ const id = reIdMap[prio];
+ idMap[id] = prio;
+ }
+
+ break;
+ }
+
+ let aside_list;
+ let section_list = new Set();
+ const section_done_list = new Set(); // once a section_note has been printed, it should never appear again!
+
+ const end_list = new Set();
+ const used_list = new Set();
+ let tokens = state.tokens;
+
+ for (i = 0; i < tokens.length; i++) {
+ const tok = tokens[i];
+
+ switch (tok.type) {
+ case 'footnote_mark_end_of_block':
+ // check the gathered list of footnotes referenced in this block:
+ // - dump the ones which are sidenotes
+ // - mark the ones which are section- or end-notes.
+ //
+ // Note: make sure we don't produce duplicates in the collect sets.
+ {
+ var _tok$meta;
+
+ aside_list = new Set();
+ const refd_notes_list = ((_tok$meta = tok.meta) == null ? void 0 : _tok$meta.footnote_list) || [];
+
+ for (const id of refd_notes_list) {
+ const footnote = footnote_spec_list[id];
+
+ switch (footnote.mode) {
+ case '>':
+ aside_list.add(id);
+ used_list.add(id);
+ break;
+
+ case '=':
+ if (!section_done_list.has(id)) {
+ section_list.add(id);
+ section_done_list.add(id);
+ used_list.add(id);
+ }
+
+ break;
+
+ default:
+ case ':':
+ end_list.add(id);
+ used_list.add(id);
+ break;
+ }
+ }
+
+ const aside_ids = [];
+
+ for (const id of aside_list.values()) {
+ aside_ids.push(id);
+ }
+
+ aside_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, i + 1, aside_ids, 'aside', baseInfo);
+ tokens = state.tokens;
+ }
+ break;
+
+ case 'footnote_reference_close':
+ // anywhere a footnote *definition* appeared in the original text is
+ // also a place to dump the section_notes gathered to date, so to speak.
+ //
+ // However, DO detect clusters of footnote definitions and MERGE them
+ // together:
+ if (more_footnote_reference_blocks_follow_immediately(tokens, i + 1)) {
+ continue;
+ } else {
+ const section_ids = [];
+
+ for (const id of section_list.values()) {
+ section_ids.push(id);
+ }
+
+ section_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, i + 1, section_ids, 'section', baseInfo);
+ tokens = state.tokens; // and reset the tracking set:
+
+ section_list = new Set();
+ }
+
+ break;
+ }
+ } // Now process the endnotes:
+
+
+ {
+ const end_ids = [];
+
+ for (const id of end_list.values()) {
+ end_ids.push(id);
+ }
+
+ end_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, tokens.length, end_ids, 'end', baseInfo);
+ tokens = state.tokens;
+ } // Now process the unused footnotes and dump them for diagnostic purposes:
+
+ {
+ const unused_ids = [];
+
+ for (let i = 1; i < footnote_spec_list.length; i++) {
+ const fn = footnote_spec_list[i];
+ const id = fn.id;
+
+ if (!used_list.has(id)) {
+ console.error(`ERROR: footnote ID ${id} is defined but never used. Footnote will be added as an ERRONEOUS ENDNOTE to the output, so the situation is easy to diagnose!`, Object.assign({}, fn, {
+ tokens: '......'
+ }));
+ unused_ids.push(id);
+ }
+ }
+
+ unused_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, tokens.length, unused_ids, 'Error::Unused', baseInfo); //tokens = state.tokens;
+ } // Update state_block too as we have rewritten & REPLACED the token array earlier in this call:
+ // the reference `state.env.state_block.tokens` is still pointing to the OLD token array!
+
+ state.env.state_block.tokens = state.tokens;
+ } // attach ourselves to the start of block handling too
+
+
+ md.block.ruler.before('table', 'footnote_mark_end_of_block', footnote_mark_end_of_block);
+ md.block.ruler.before('reference', 'footnote_def', footnote_def, {
+ alt: ['paragraph', 'reference']
+ });
+ md.inline.ruler.after('image', 'footnote_inline', footnote_inline);
+ md.inline.ruler.after('footnote_inline', 'footnote_ref_with_text', footnote_ref_with_text);
+ md.inline.ruler.after('footnote_ref_with_text', 'footnote_ref', footnote_ref);
+ md.core.ruler.after('inline', 'footnote_tail', footnote_tail);
+}
+
+module.exports = footnote_plugin;
+//# sourceMappingURL=markdownItFootnote.cjs.map
diff --git a/dist/markdownItFootnote.cjs.map b/dist/markdownItFootnote.cjs.map
new file mode 100644
index 0000000..f866f48
--- /dev/null
+++ b/dist/markdownItFootnote.cjs.map
@@ -0,0 +1 @@
+{"version":3,"file":"markdownItFootnote.cjs","sources":["../index.ts"],"sourcesContent":["// Process footnotes\n//\n\nimport { strict as assert } from 'assert';\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Renderer partials\n\n\n\ninterface FootnotePluginOptions {\n numberSequence?: Array;\n modeOverride?: string;\n sortOrder: number;\n refCombiner?: string;\n}\n\ninterface GenericInfoParameters {\n options: any; // markdown_it options object\n plugin_options: FootnotePluginOptions;\n env: any; // markdown_it environment object\n self: any; // reference to this plugin instance\n}\n\ninterface RenderInfoParameters extends GenericInfoParameters {\n tokens: Array; // array of tokens\n idx: number; // index of current token in token array\n}\n\ninterface footnoteMetaInfo {\n id: number;\n label?: string;\n labelOverride?: string;\n mode?: string;\n content?: string;\n tokens?: Array;\n count: number;\n}\n\n\n\nfunction anchorFnDefault(n: number, excludeSubId: number, baseInfo: RenderInfoParameters) {\n const env = baseInfo.env;\n assert.ok(env != null);\n let prefix = '';\n if (typeof env.docId === 'string' && env.docId.length > 0) {\n prefix = '-' + env.docId + '-';\n }\n return prefix + n;\n}\n\nfunction captionFnDefault(n, baseInfo: RenderInfoParameters) {\n //return '[' + n + ']';\n return '' + n;\n}\n\nfunction headerFnDefault(category, baseInfo: GenericInfoParameters) {\n switch (category) {\n case 'aside':\n return 'Side Notes';\n\n case 'section':\n return 'Section Notes';\n\n case 'end':\n return 'Endnotes';\n\n default: // used for error category, e.g. 'Error::Unused'\n return category;\n }\n}\n\nfunction determine_footnote_symbol(idx: number, info: footnoteMetaInfo, baseInfo: GenericInfoParameters): string {\n const plugin_options = baseInfo.plugin_options;\n assert.ok(plugin_options != null);\n\n // rule to construct the printed label:\n //\n // mark = labelOverride /* || info.label */ || idx;\n const label = info.labelOverride;\n if (label) {\n return label;\n }\n if (plugin_options.numberSequence == null || plugin_options.numberSequence.length === 0) {\n return '' + idx;\n }\n const len = plugin_options.numberSequence.length;\n if (idx >= len) {\n // is last slot numeric or alphanumerically?\n const slot = plugin_options.numberSequence[len - 1];\n if (Number.isFinite(slot)) {\n const delta = idx - len + 1;\n return '' + (slot + delta);\n }\n\n // non-numerical last slot --> duplicate, triplicate, etc.\n const dupli = (idx / len) | 0; // = int(x mod N)\n const remainder = idx % len;\n const core = plugin_options.numberSequence[remainder];\n let str = '' + core;\n for (let i = 1; i < dupli; i++) {\n str += core;\n }\n return str;\n }\n\n return '' + plugin_options.numberSequence[idx];\n}\n\n\nconst bunched_mode_classes = [ '', 'footnote-bunched-ref-ref', 'footnote-bunched-ref-text' ];\n\n\nfunction generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo: RenderInfoParameters) {\n let localOverride = renderInfo.tokens[renderInfo.idx].meta.text;\n if (localOverride) {\n localOverride = `${ localOverride }`;\n }\n return `${ localOverride || '' }${ caption }` +\n (bunched_footnote_ref_mode !== 0 ? `${ renderInfo.plugin_options.refCombiner || '' }` : '');\n}\n\nfunction generateFootnoteSectionStartHtml(renderInfo: RenderInfoParameters) {\n const tok = renderInfo.tokens[renderInfo.idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n const header = (tok.markup ? `
${ tok.markup }
` : '');\n let category = tok.meta.category;\n assert.ok(category.length > 0);\n // `category` can contain CSS class illegal characters, e.g. when category = 'Error::Unused':\n category = category.replace(/[^a-zA-Z0-9_-]+/g, '_');\n return `\\n';\n}\n\nfunction generateFootnoteStartHtml(id, caption, renderInfo: RenderInfoParameters) {\n // allow both a JavaWScript --> CSS approach via `data-footnote-caption`\n // and a classic CSS approach while a display:inline-block SUP presenting\n // the LI 'button' instead:\n return `
\\n';\n}\n\nfunction generateFootnoteBackRefHtml(id, refId, renderInfo: RenderInfoParameters) {\n const tok = renderInfo.tokens[renderInfo.idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n\n /* ↩ with escape code to prevent display as Apple Emoji on iOS */\n return ` \\u21a9\\uFE0E`;\n}\n\n\n\n\n/*\nref:\n return ``;\n\n\nopen:\n return `\\n';\n}\n\n*/\n\n\n\n\ninterface FootnotePluginOptions /* extends FootnotePluginOptions */ { // eslint-disable-line no-redeclare\n anchorFn: (n: number, excludeSubId: number, baseInfo: RenderInfoParameters) => string;\n captionFn: (n: number, baseInfo: RenderInfoParameters) => string;\n headerFn: (category: string, baseInfo: GenericInfoParameters) => string;\n mkLabel: (idx: number, info: footnoteMetaInfo, baseInfo: GenericInfoParameters) => string;\n}\n\n\n\n\nconst default_plugin_options: FootnotePluginOptions = {\n // atDocumentEnd: false, -- obsoleted option of the original plugin\n\n anchorFn: anchorFnDefault,\n captionFn: captionFnDefault,\n headerFn: headerFnDefault,\n mkLabel: determine_footnote_symbol,\n\n // see also https://www.editage.com/insights/footnotes-in-tables-part-1-choice-of-footnote-markers-and-their-sequence\n // why asterisk/star is not part of the default footnote marker sequence.\n //\n // For similar reasons, we DO NOT include the section § symbol in this list.\n //\n // when numberSequnce is NULL/empty, a regular numerical numbering is assumed.\n // Otherwise, the array is indexed; when there are more footnotes than entries in\n // the numberSequence array, the entries are re-used, but doubled/trippled, etc.\n //\n // When the indexing in this array hits a NUMERIC value (as last entry), any higher\n // footnotes are NUMBERED starting at that number.\n //\n // NOTE: as we can reference the same footnote from multiple spots, we do not depend\n // on CSS counter() approaches by default, but providee this mechanism in the plugin\n // code itself.\n numberSequence: [ '†', '‡', '††', '‡‡', '¶', 1 ],\n\n // Overrides the footnode mode when set to one of the following:\n //\n // Recognized 'modes':\n // '>': aside note (default for inline notes)\n // ':': end node\n // '=': section note (default for regular referenced notes)\n //\n // Also accepts these keywords: 'aside', 'section', 'end'\n //\n modeOverride: null,\n\n // list section notes and endnotes in order of:\n //\n // 0: first *appearance* in the text\n // 1: first *reference* in the text\n // 2: *definition* in the text\n // 3: sorted alphanumerically by *coded* label,\n // i.e. *numeric* labels are sorted in numeric order (so `10` comes AFTER `7`!),\n // while all others are sorted using `String.localeCompare()`. When labels have\n // a *numeric leading*, e.g. `71geo` --> `71`, that part is sorted numerically first.\n //\n // Here 'coded label' means the label constructed from the reference ids and label overrides\n // as used in the markdown source, using the expression\n // labelOverride || reference || id\n // which gives for these examples (assuming them to be the only definitions in your input):\n // [^refA]: ... --> null || 'refA' || 1\n // [^refB LBL]: ... --> 'LBL' || 'refB' || 2\n // 4: sorted alphanumerically by *printed* label\n // which is like mode 3, but now for the label as will be seen in the *output*!\n sortOrder: 4,\n\n // what to print between bunched-together footnote references, i.e. the '+' in `blabla¹⁺²`\n refCombiner: ','\n};\n\n\n\n\nexport default function footnote_plugin(md, plugin_options) {\n const parseLinkLabel = md.helpers.parseLinkLabel,\n isSpace = md.utils.isSpace;\n\n plugin_options = Object.assign({}, default_plugin_options, plugin_options);\n\n\n\n const modeOverrideMap = {\n aside: '>',\n section: '=',\n end: ':'\n };\n\n function determine_mode(mode: string, default_mode: string) {\n let override = null;\n if (plugin_options.modeOverride) {\n const mode = modeOverrideMap[plugin_options.modeOverride] || plugin_options.modeOverride;\n if ('>:='.includes(plugin_options.modeOverride)) {\n override = plugin_options.modeOverride;\n }\n }\n if ('>:='.includes(mode)) {\n return {\n mode: override || mode,\n fromInput: true\n };\n }\n return {\n mode: override || default_mode,\n fromInput: false\n };\n }\n\n function render_footnote_n(tokens, idx, excludeSubId) {\n const mark = tokens[idx].meta.id;\n assert.ok(Number.isFinite(mark));\n assert.ok(mark > 0);\n let n = '' + mark; // = mark.toString();\n assert.ok(n.length > 0);\n\n if (!excludeSubId && tokens[idx].meta.subId > 0) {\n n += '-' + tokens[idx].meta.subId;\n }\n\n return n;\n }\n\n function render_footnote_mark(renderInfo: RenderInfoParameters): string {\n const token = renderInfo.tokens[renderInfo.idx];\n assert.ok(token != null);\n assert.ok(renderInfo.env.footnotes != null);\n assert.ok(renderInfo.env.footnotes.list != null);\n const info = renderInfo.env.footnotes.list[token.meta.id];\n assert.ok(info != null);\n const mark: string = plugin_options.mkLabel(token.meta.id, info, renderInfo);\n assert.ok(mark.length > 0);\n return mark;\n }\n\n function render_footnote_anchor_name(renderInfo: RenderInfoParameters) {\n const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, true);\n return plugin_options.anchorFn(n, true, renderInfo);\n }\n\n function render_footnote_anchor_nameRef(renderInfo: RenderInfoParameters) {\n const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, false);\n return plugin_options.anchorFn(n, false, renderInfo);\n }\n\n function render_footnote_caption(renderInfo: RenderInfoParameters) {\n const n = render_footnote_mark(renderInfo);\n return plugin_options.captionFn(n, renderInfo);\n }\n\n function render_footnote_ref(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n const id = render_footnote_anchor_name(renderInfo);\n const caption = render_footnote_caption(renderInfo);\n const refId = render_footnote_anchor_nameRef(renderInfo);\n\n // check if multiple footnote references are bunched together:\n // IFF they are, we should separate them with commas.\n //\n // Exception: when next token has an extra text (`meta.text`) the\n // bunching together is not a problem as them the output will render\n // like this: `bla1text2`, ergo a look\n // like this: `bla¹text²` instead of bunched footnotes references ¹ and ²\n // that would (without the extra comma injection) look like `bla¹²` instead\n // of `x¹⁺²` (here '+' instead of ',' comma, but you get the idea -- there's no\n // Unicode superscript-comma so that's why I used unicode superscript-plus\n // in this 'ascii art' example).\n //\n const next_token = tokens[idx + 1] || {};\n const next_token_meta = next_token.meta || {};\n const bunched_footnote_ref_mode = (next_token.type === 'footnote_ref' ? !next_token_meta.text ? 1 : 2 : 0);\n\n return generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo);\n }\n\n function render_footnote_block_open(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n return generateFootnoteSectionStartHtml(renderInfo);\n }\n\n function render_footnote_block_close(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n return generateFootnoteSectionEndHtml(renderInfo);\n }\n\n function render_footnote_reference_open(tokens, idx, options, env, self) {\n return '';\n }\n\n function render_footnote_reference_close() {\n return '';\n }\n\n function render_footnote_mark_end_of_block() {\n return '';\n }\n\n function render_footnote_open(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n const id = render_footnote_anchor_name(renderInfo);\n const caption = render_footnote_caption(renderInfo);\n\n // allow both a JavaScript --> CSS approach via `data-footnote-caption`\n // and a classic CSS approach while a display:inline-block SUP presenting\n // the LI 'button' instead:\n return generateFootnoteStartHtml(id, caption, renderInfo);\n }\n\n function render_footnote_close(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n return generateFootnoteEndHtml(renderInfo);\n }\n\n function render_footnote_anchor_backref(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n\n const tok = tokens[idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n const id = render_footnote_anchor_name(renderInfo);\n let refId = render_footnote_n(tokens, idx, false);\n refId = plugin_options.anchorFn(refId, false, renderInfo);\n\n return generateFootnoteBackRefHtml(id, refId, renderInfo);\n }\n\n\n\n md.renderer.rules.footnote_ref = render_footnote_ref;\n md.renderer.rules.footnote_block_open = render_footnote_block_open;\n md.renderer.rules.footnote_block_close = render_footnote_block_close;\n md.renderer.rules.footnote_reference_open = render_footnote_reference_open;\n md.renderer.rules.footnote_reference_close = render_footnote_reference_close;\n md.renderer.rules.footnote_mark_end_of_block = render_footnote_mark_end_of_block;\n md.renderer.rules.footnote_open = render_footnote_open;\n md.renderer.rules.footnote_close = render_footnote_close;\n md.renderer.rules.footnote_anchor = render_footnote_anchor_backref;\n\n\n\n function obtain_footnote_info_slot(env, label: string|null, at_definition: boolean) {\n // inline blocks have their own *child* environment in markdown-it v10+.\n // As the footnotes must live beyond the lifetime of the inline block env,\n // we must patch them into the `parentState.env` for the footnote_tail\n // handler to be able to access them afterwards!\n while (env.parentState) {\n env = env.parentState.env;\n assert.ok(env != null);\n }\n\n if (!env.footnotes) {\n env.footnotes = {\n // map label tto ID:\n refs: {},\n // store footnote info indexed by ID\n list: [],\n // remap ID to re-ordered ID (determines placement order for section notes and endnotes)\n idMap: [ 0 ],\n idMapCounter: 0,\n\n // and a counter for the generated sections (including asides); see the demo/test which\n // uses the generated `#fnsection-DDD` identifiers to hack/fix the styling, for example.\n sectionCounter: 0\n };\n }\n\n // When label is NULL, this is a request from in INLINE NOTE.\n\n // NOTE: IDs are index numbers, BUT they start at 1 instead of 0 to make life easier in check code:\n let footnoteId;\n let infoRec: footnoteMetaInfo;\n // label as index: prepend ':' to avoid conflict with Object.prototype members\n if (label == null || !env.footnotes.refs[':' + label]) {\n footnoteId = Math.max(1, env.footnotes.list.length);\n infoRec = {\n id: footnoteId,\n label,\n labelOverride: null,\n mode: null,\n content: null,\n tokens: null,\n count: 0\n };\n env.footnotes.list[footnoteId] = infoRec;\n if (label != null) {\n env.footnotes.refs[':' + label] = footnoteId;\n }\n } else {\n footnoteId = env.footnotes.refs[':' + label];\n infoRec = env.footnotes.list[footnoteId];\n assert.ok(!!infoRec, 'expects non-NULL footnote info record');\n }\n\n const idMap = env.footnotes.idMap;\n\n // now check if the idMap[] has been set up already as well. This depends on\n // when WE are invoked (`at_definition`) and the configured `options.sortOrder`:\n switch (plugin_options.sortOrder) {\n // 0: first *appearance* in the text\n default:\n case 0:\n // basically, this means: order as-is\n if (!idMap[footnoteId]) {\n idMap[footnoteId] = ++env.footnotes.idMapCounter;\n }\n break;\n\n // 1: first *reference* in the text\n case 1:\n if (!at_definition && !idMap[footnoteId]) {\n // first reference is now!\n idMap[footnoteId] = ++env.footnotes.idMapCounter;\n }\n break;\n\n // 2: *definition* in the text\n case 2:\n if (at_definition && !idMap[footnoteId]) {\n // definition is now!\n idMap[footnoteId] = ++env.footnotes.idMapCounter;\n }\n break;\n\n // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)\n case 3:\n case 4:\n // just note the footnoteId now; this must be re-ordered later when we have collected all footnotes.\n //\n // set it up when we get there...\n break;\n }\n\n return infoRec;\n }\n\n function find_end_of_block_marker(state, startIndex) {\n let idx, len;\n const tokens = state.tokens;\n for (idx = startIndex, len = tokens.length; idx < len; idx++) {\n if (tokens[idx].type === 'footnote_mark_end_of_block') { return idx; }\n }\n\n // Punch a slot into the token stream (at the very end)\n // for consistency with footnote_mark_end_of_block():\n const token = new state.Token('footnote_mark_end_of_block', '', 0);\n token.hidden = true;\n tokens.push(token);\n return tokens.length - 1;\n }\n\n function update_end_of_block_marker(state, footnoteId) {\n // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:\n // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the\n // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:\n const parentState = state.env.parentState;\n const parentIndex = state.env.parentTokenIndex;\n const markerTokenIndex = find_end_of_block_marker(parentState, parentIndex + 1);\n const token = parentState.tokens[markerTokenIndex];\n if (!token.meta) {\n token.meta = {\n footnote_list: []\n };\n }\n token.meta.footnote_list.push(footnoteId);\n }\n\n // Mark end of paragraph/heading/whatever BLOCK (or rather: START of the next block!)\n function footnote_mark_end_of_block(state, startLine, endLine, silent) {\n if (!silent && state.tokens.length > 0) {\n const token = state.push('footnote_mark_end_of_block', '', 0);\n token.hidden = true;\n }\n return false;\n }\n\n\n\n // Process footnote block definition\n function footnote_def(state, startLine, endLine, silent) {\n let oldBMark, oldTShift, oldSCount, oldParentType, pos, token,\n initial, offset, ch, posAfterColon,\n start = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // line should be at least 6 chars - \"[^x]: \" or \"[^x]:> \"\n if (start + 5 > max) { return false; }\n\n if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }\n\n for (pos = start + 2; pos < max; pos++) {\n if (state.src.charCodeAt(pos) === 0x0A /* LF */) { return false; }\n if (state.src.charCodeAt(pos) === 0x5D /* ] */) {\n break;\n }\n }\n const labelEnd = pos;\n\n if (pos === start + 2) { return false; } // no empty footnote labels\n if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x3A /* : */) { return false; }\n\n const mode_rec = determine_mode(state.src[pos + 1], '='); // default mode is section_note mode.\n if (mode_rec.fromInput) { pos++; }\n const mode = mode_rec.mode;\n\n if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x20 /* space */) { return false; }\n if (silent) { return true; }\n pos++;\n\n const labelInfo = decode_label(state.src.slice(start + 2, labelEnd), true);\n if (!labelInfo) { return false; }\n assert.ok(!labelInfo.extraText);\n\n // Now see if we already have a footnote ID for this footnote label:\n // fetch it if we have one and otherwise produce a new one so everyone\n // can use this from now on.\n //\n // This scenario is possible when the footnote *definition* comes BEFORE\n // the first actual footnote *use* (*reference*). This is UNUSUAL when people\n // write texts, but it is *not impossible*, particularly now that we have\n // specified-by-design that endnotes can be marked as such (`[^label]:: note text`)\n // and freely mixed with sidenotes (`[^label]:> note text`) and section\n // notes (`[^label]:= note text` (explicit mode) or `[^label]: note text`\n // (implicit mode)), where *section notes* will placed at the spot in the text\n // flow where they were *defined*. Again, highly irregular, BUT someone MAY\n // feel the need to place some section note *definitions* ABOVE their first\n // use point.\n //\n const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, true);\n if (labelInfo.labelOverride) {\n infoRec.labelOverride = labelInfo.labelOverride;\n }\n infoRec.mode = mode;\n infoRec.content = state.src.slice(pos, max);\n\n token = state.push('footnote_reference_open', '', 1);\n token.meta = {\n id: infoRec.id\n };\n token.hidden = true;\n\n oldBMark = state.bMarks[startLine];\n oldTShift = state.tShift[startLine];\n oldSCount = state.sCount[startLine];\n oldParentType = state.parentType;\n\n posAfterColon = pos;\n initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - offset % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n state.tShift[startLine] = pos - posAfterColon;\n state.sCount[startLine] = offset - initial;\n\n state.bMarks[startLine] = posAfterColon;\n state.blkIndent += 4;\n state.parentType = 'footnote';\n\n if (state.sCount[startLine] < state.blkIndent) {\n state.sCount[startLine] += state.blkIndent;\n }\n\n state.md.block.tokenize(state, startLine, endLine, true);\n\n state.parentType = oldParentType;\n state.blkIndent -= 4;\n state.tShift[startLine] = oldTShift;\n state.sCount[startLine] = oldSCount;\n state.bMarks[startLine] = oldBMark;\n\n token = state.push('footnote_reference_close', '', -1);\n token.meta = {\n id: infoRec.id\n };\n\n return true;\n }\n\n\n\n // Process inline footnotes (^[...] or ^[>...])\n function footnote_inline(state, silent) {\n let labelStart,\n labelEnd,\n token,\n tokens,\n max = state.posMax,\n start = state.pos;\n\n if (start + 2 >= max) { return false; }\n if (state.src.charCodeAt(start) !== 0x5E/* ^ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5B/* [ */) { return false; }\n\n labelStart = start + 2;\n\n // NOTE: inline notes are automatically considered to be ASIDE notes,\n // UNLESS otherwise specified!\n //\n // Recognized 'modes':\n // '>': aside note (default for inline notes)\n // ':': end node\n // '=': section note (default for regular referenced notes)\n //\n // (Also note https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html:\n // our notes look like this: `[^ref]:` while Academic MarkDown references look\n // like this: `[@Belawog2012]` i.e. no '^' in there. Hence these can safely co-exist.)\n //\n const mode_rec = determine_mode(state.src[start + 2], '>'); // default mode is aside ~ sidenote mode.\n if (mode_rec.fromInput) {\n labelStart++;\n }\n const mode = mode_rec.mode;\n\n labelEnd = parseLinkLabel(state, start + 1);\n\n // parser failed to find ']', so it's not a valid note\n if (labelEnd < 0) { return false; }\n\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n if (!silent) {\n // WARNING: claim our footnote slot for there MAY be nested footnotes\n // discovered in the next inline.parse() call below!\n const infoRec = obtain_footnote_info_slot(state.env, null, true);\n infoRec.mode = mode;\n infoRec.count++;\n\n token = state.push('footnote_ref', '', 0);\n token.meta = {\n id: infoRec.id\n };\n\n state.md.inline.parse(\n state.src.slice(labelStart, labelEnd),\n state.md,\n state.env,\n tokens = []\n );\n\n // Now fill our previously claimed slot:\n infoRec.content = state.src.slice(labelStart, labelEnd);\n infoRec.tokens = tokens;\n\n // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:\n // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the\n // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:\n update_end_of_block_marker(state, infoRec.id);\n\n //md.block.ruler.enable('footnote_mark_end_of_block');\n }\n\n state.pos = labelEnd + 1;\n state.posMax = max;\n return true;\n }\n\n\n\n // Check if this is a valid ffootnote reference label.\n //\n // Also see if there's a label OVERRIDE text or marker ('@') provided.\n //\n // Return the parsed label record.\n function decode_label(label: string, extra_text_is_labelOverride: boolean) {\n if (!label) {\n return null;\n }\n const m = label.match(/^(@?)(\\S+)(?:\\s+(.+))?$/); // label with OPTIONAL override text...\n if (!m) {\n return null;\n }\n assert.ok(m[2].length > 0);\n let extraText = m[3]?.trim();\n // label [output] override?\n let override = null;\n if (m[1]) {\n override = m[2];\n }\n if (extra_text_is_labelOverride && extraText) {\n override = extraText;\n extraText = null;\n }\n\n return {\n label: m[2],\n labelOverride: override,\n extraText\n };\n }\n\n\n\n // Process footnote references with text ([^label ...])\n function footnote_ref_with_text(state, silent) {\n let pos,\n footnoteSubId,\n token,\n max = state.posMax,\n start = state.pos;\n\n // should be at least 6 chars - \"[^l x]\"\n if (start + 5 > max) { return false; }\n\n if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }\n\n for (pos = start + 2; pos < max; pos++) {\n if (state.src.charCodeAt(pos) === 0x0A /* linefeed */) { return false; }\n if (state.src.charCodeAt(pos) === 0x5D /* ] */) {\n break;\n }\n }\n\n if (pos === start + 2) { return false; } // no empty footnote labels\n if (pos >= max) { return false; }\n pos++;\n\n const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), false);\n if (!labelInfo || !labelInfo.extraText) { return false; }\n assert.ok(labelInfo.extraText.length > 0);\n\n const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);\n if (labelInfo.labelOverride) {\n infoRec.labelOverride = labelInfo.labelOverride;\n }\n\n if (!silent) {\n footnoteSubId = infoRec.count;\n\n infoRec.count++;\n\n token = state.push('footnote_ref', '', 0);\n token.meta = {\n id: infoRec.id,\n subId: footnoteSubId,\n text: labelInfo.extraText\n };\n\n update_end_of_block_marker(state, infoRec.id);\n\n //md.block.ruler.enable('footnote_mark_end_of_block');\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n }\n\n\n\n // Process footnote references ([^...])\n function footnote_ref(state, silent) {\n let pos,\n footnoteSubId,\n token,\n max = state.posMax,\n start = state.pos;\n\n // should be at least 4 chars - \"[^x]\"\n if (start + 3 > max) { return false; }\n\n if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }\n\n for (pos = start + 2; pos < max; pos++) {\n //if (state.src.charCodeAt(pos) === 0x20) { return false; }\n if (state.src.charCodeAt(pos) === 0x0A) { return false; }\n if (state.src.charCodeAt(pos) === 0x5D /* ] */) {\n break;\n }\n }\n\n if (pos === start + 2) { return false; } // no empty footnote labels\n if (pos >= max) { return false; }\n pos++;\n\n const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), true);\n if (!labelInfo) { return false; }\n assert.ok(!labelInfo.extraText);\n\n const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);\n if (labelInfo.labelOverride) {\n infoRec.labelOverride = labelInfo.labelOverride;\n }\n\n if (!silent) {\n footnoteSubId = infoRec.count;\n\n infoRec.count++;\n\n token = state.push('footnote_ref', '', 0);\n token.meta = {\n id: infoRec.id,\n subId: footnoteSubId\n };\n\n update_end_of_block_marker(state, infoRec.id);\n\n //md.block.ruler.enable('footnote_mark_end_of_block');\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n }\n\n\n\n function place_footnote_definitions_at(state, token_idx: number, footnote_id_list, category: string, baseInfo: GenericInfoParameters) {\n if (footnote_id_list.length === 0) {\n return; // nothing to inject...\n }\n\n let inject_tokens = [];\n assert.ok(baseInfo.env.footnotes.list != null);\n const footnote_spec_list = baseInfo.env.footnotes.list;\n\n let token = new state.Token('footnote_block_open', '', 1);\n token.markup = plugin_options.headerFn(category, baseInfo.env, plugin_options);\n token.meta = {\n sectionId: ++baseInfo.env.footnotes.sectionCounter,\n category\n };\n inject_tokens.push(token);\n\n for (const id of footnote_id_list) {\n const fn = footnote_spec_list[id];\n const inject_start_index = inject_tokens.length;\n\n token = new state.Token('footnote_open', '', 1);\n token.meta = {\n id,\n category\n };\n inject_tokens.push(token);\n\n if (fn.label == null) {\n // process an inline footnote text:\n token = new state.Token('paragraph_open', 'p', 1);\n token.block = true;\n inject_tokens.push(token);\n\n token = new state.Token('inline', '', 0);\n token.children = fn.tokens;\n token.content = fn.content;\n inject_tokens.push(token);\n\n token = new state.Token('paragraph_close', 'p', -1);\n token.block = true;\n inject_tokens.push(token);\n } else {\n // process a labeled footnote:\n inject_tokens = inject_tokens.concat(fn.tokens || []);\n }\n\n //let lastParagraph;\n //if (inject_tokens[inject_tokens.length - 1].type === 'paragraph_close') {\n // lastParagraph = inject_tokens.pop();\n //} else {\n // lastParagraph = null;\n //}\n\n const cnt = fn.count;\n assert.ok(cnt >= 0);\n for (let j = 0; j < cnt; j++) {\n token = new state.Token('footnote_anchor', '', 0);\n token.meta = {\n id,\n subId: j,\n backrefCount: cnt,\n category\n };\n inject_tokens.push(token);\n }\n\n //if (lastParagraph) {\n // inject_tokens.push(lastParagraph);\n //}\n\n token = new state.Token('footnote_close', '', -1);\n token.meta = {\n id,\n category\n };\n inject_tokens.push(token);\n }\n\n token = new state.Token('footnote_block_close', '', -1);\n token.meta = {\n category\n };\n inject_tokens.push(token);\n\n state.tokens.splice(token_idx, 0, ...inject_tokens);\n }\n\n function more_footnote_reference_blocks_follow_immediately(tokens, idx) {\n let tok = tokens[idx];\n while (tok && (tok.type === 'footnote_mark_end_of_block' || tok.type === 'footnote_reference_close')) {\n idx++;\n tok = tokens[idx];\n }\n return tok && (tok.type === 'footnote_reference_open');\n }\n\n // Glue footnote tokens into appropriate slots of token stream.\n function footnote_tail(state, startLine, endLine, silent) {\n let i, l, j, t, token, current, currentRefToken,\n insideRef = false,\n refTokens = {};\n\n if (!state.env.footnotes) {\n // no footnotes at all? --> filter out all 'footnote_mark_end_of_block' chunks:\n state.tokens = state.tokens.filter(function (tok, idx) {\n return (tok.type !== 'footnote_mark_end_of_block');\n });\n return;\n }\n\n const idMap = state.env.footnotes.idMap;\n\n const baseInfo: GenericInfoParameters = {\n options: state.md.options,\n env: state.env,\n plugin_options,\n self: this\n };\n\n function footnote_print_comparer(idA, idB) {\n return idMap[idA] - idMap[idB];\n }\n\n\n // Rewrite the tokenstream to place the aside-footnotes and section footnotes where they need to be:\n const footnote_spec_list = state.env.footnotes.list;\n\n // extract the tokens constituting the footnote/sidenote *content* and\n // store that bunch in `refTokens[:]` instead, to be injected back into\n // the tokenstream at the appropriate spots.\n state.tokens = state.tokens.filter(function (tok, idx) {\n switch (tok.type) {\n // filter out 'footnote_mark_end_of_block' tokens which follow BLOCKS that do not contain any\n // footnote/sidenote/endnote references:\n case 'footnote_mark_end_of_block':\n if (!tok.meta) return false;\n if (!tok.meta.footnote_list) return false;\n break;\n\n case 'footnote_reference_open':\n insideRef = true;\n current = [];\n currentRefToken = tok;\n return true;\n\n case 'footnote_reference_close':\n insideRef = false;\n\n const infoRec = footnote_spec_list[tok.meta.id];\n infoRec.tokens = current;\n\n return true;\n }\n if (insideRef) {\n current.push(tok);\n }\n return !insideRef;\n });\n\n\n // execute configured sorting/mapping (`idMap`):\n switch (plugin_options.sortOrder) {\n // 0: first *appearance* in the text\n default:\n case 0:\n // 1: first *reference* in the text\n case 1:\n // 2: *definition* in the text\n case 2:\n // order is specified in the `idMap` already.\n break;\n\n // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)\n case 3:\n case 4:\n // the `idMap[]` array has not been set up and must be produced\n // to turn this into an alphanumerically-by-label sort order, where\n // a `footnoteId` based index will produce the order of appearance.\n const reIdMap = [];\n for (let i = 1; i < footnote_spec_list.length; i++) {\n reIdMap[i - 1] = i;\n }\n reIdMap.sort((idA, idB) => {\n const infoA = footnote_spec_list[idA];\n const infoB = footnote_spec_list[idB];\n assert.ok(infoA);\n assert.ok(infoB);\n\n // is any of these an inline footnote, i.e. without any label yet? Produce a fake label for sorting then!\n //\n // As stated elsewhere: inline section_notes and end_notes will end up among everyone else in this sort order mode.\n assert.ok(infoA.id === idA);\n assert.ok(infoB.id === idB);\n\n // Split a \"sort label\" up into its numerical part and the tail. Note that we don't call\n // it 'tail' but 'label', because we will need to compare the ENTIRE LABEL using string comparison\n // when the numeric leaders are identical, so as to ensure that 'labels' such as `00000` will sort\n // as 'higher' than `000`, both of which will be rated as numerically identical!\n function to_atoms(label) {\n // now extract number or numerical leader part.\n //\n // Only accept OBVIOUS, SIMPLE NUMERIC LEADERS! This is about *legibility*\n // of those numrical leaders, not a pedantic \"what is possibly legally numeric\"\n // challenge. Hence we DO NOT accept leading +/- and only a decimal dot when\n // there's a decimal number BEFORE it, such as in `5.1hack` --> `5.1`, but NOT\n // `.42oz`!\n //\n // Do not use `nmr = +lbl` as that would treat labels such as `0xf4` as hexadecimal numbers,\n // which we DO NOT want to happen.\n const m = label.match(/^\\d+(?:\\.\\d+)?/) || [ 'x' ];\n const nmr = +m[0] || Infinity; // non-numeric labels are rated NUMEICALLY HIGHER than any numerical leader.\n return {\n label,\n number: nmr\n };\n }\n\n const labelA = (plugin_options.sortOrder === 3 ?\n infoA.labelOverride || infoA.label || ('' + infoA.id) :\n plugin_options.mkLabel(infoA.id, infoA, baseInfo)\n );\n const labelB = (plugin_options.sortOrder === 3 ?\n infoB.labelOverride || infoB.label || ('' + infoB.id) :\n plugin_options.mkLabel(infoB.id, infoB, baseInfo)\n );\n const atomA = to_atoms(labelA);\n const atomB = to_atoms(labelB);\n const diff = atomA.number - atomB.number;\n return diff || atomA.label.localeCompare(atomB.label);\n // ^^^^^^^ shorthand for:\n //\n // if (isNaN(diff) || diff === 0) then stringcompare else numeric-difference\n });\n\n // Now turn this into a sort order map:\n for (let prio = 0; prio < reIdMap.length; prio++) {\n const id = reIdMap[prio];\n idMap[id] = prio;\n }\n break;\n }\n\n\n const inject_tokens = [];\n\n // Now go through the token stream and place the sidenotes, section_notes and endnotes where they belong:\n let aside_list;\n let section_list = new Set();\n const section_done_list = new Set(); // once a section_note has been printed, it should never appear again!\n const end_list = new Set();\n const used_list = new Set();\n\n let tokens = state.tokens;\n\n for (i = 0; i < tokens.length; i++) {\n const tok = tokens[i];\n switch (tok.type) {\n case 'footnote_mark_end_of_block':\n // check the gathered list of footnotes referenced in this block:\n // - dump the ones which are sidenotes\n // - mark the ones which are section- or end-notes.\n //\n // Note: make sure we don't produce duplicates in the collect sets.\n {\n aside_list = new Set();\n\n const refd_notes_list = (tok.meta?.footnote_list || []);\n for (const id of refd_notes_list) {\n const footnote = footnote_spec_list[id];\n\n switch (footnote.mode) {\n case '>':\n aside_list.add(id);\n used_list.add(id);\n break;\n\n case '=':\n if (!section_done_list.has(id)) {\n section_list.add(id);\n section_done_list.add(id);\n used_list.add(id);\n }\n break;\n\n default:\n case ':':\n end_list.add(id);\n used_list.add(id);\n break;\n }\n }\n\n const aside_ids = [];\n for (const id of aside_list.values()) {\n aside_ids.push(id);\n }\n aside_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, i + 1, aside_ids, 'aside', baseInfo);\n tokens = state.tokens;\n }\n break;\n\n case 'footnote_reference_close':\n // anywhere a footnote *definition* appeared in the original text is\n // also a place to dump the section_notes gathered to date, so to speak.\n //\n // However, DO detect clusters of footnote definitions and MERGE them\n // together:\n if (more_footnote_reference_blocks_follow_immediately(tokens, i + 1)) {\n continue;\n } else {\n const section_ids = [];\n for (const id of section_list.values()) {\n section_ids.push(id);\n }\n section_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, i + 1, section_ids, 'section', baseInfo);\n tokens = state.tokens;\n\n // and reset the tracking set:\n section_list = new Set();\n }\n break;\n }\n }\n\n // Now process the endnotes:\n {\n const end_ids = [];\n for (const id of end_list.values()) {\n end_ids.push(id);\n }\n end_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, tokens.length, end_ids, 'end', baseInfo);\n tokens = state.tokens;\n }\n\n // Now process the unused footnotes and dump them for diagnostic purposes:\n {\n const unused_ids = [];\n\n for (let i = 1; i < footnote_spec_list.length; i++) {\n const fn = footnote_spec_list[i];\n const id = fn.id;\n if (!used_list.has(id)) {\n console.error(`ERROR: footnote ID ${id} is defined but never used. Footnote will be added as an ERRONEOUS ENDNOTE to the output, so the situation is easy to diagnose!`, Object.assign({}, fn, { tokens: '......' }));\n unused_ids.push(id);\n }\n }\n unused_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, tokens.length, unused_ids, 'Error::Unused', baseInfo);\n //tokens = state.tokens;\n }\n\n // Update state_block too as we have rewritten & REPLACED the token array earlier in this call:\n // the reference `state.env.state_block.tokens` is still pointing to the OLD token array!\n state.env.state_block.tokens = state.tokens;\n }\n\n\n\n\n // attach ourselves to the start of block handling too\n md.block.ruler.before('table', 'footnote_mark_end_of_block', footnote_mark_end_of_block);\n\n md.block.ruler.before('reference', 'footnote_def', footnote_def, { alt: [ 'paragraph', 'reference' ] });\n md.inline.ruler.after('image', 'footnote_inline', footnote_inline);\n md.inline.ruler.after('footnote_inline', 'footnote_ref_with_text', footnote_ref_with_text);\n md.inline.ruler.after('footnote_ref_with_text', 'footnote_ref', footnote_ref);\n md.core.ruler.after('inline', 'footnote_tail', footnote_tail);\n}\n"],"names":["anchorFnDefault","n","excludeSubId","baseInfo","env","assert","ok","prefix","docId","length","captionFnDefault","headerFnDefault","category","determine_footnote_symbol","idx","info","plugin_options","label","labelOverride","numberSequence","len","slot","Number","isFinite","delta","dupli","remainder","core","str","i","bunched_mode_classes","generateFootnoteRefHtml","id","caption","refId","bunched_footnote_ref_mode","renderInfo","localOverride","tokens","meta","text","refCombiner","generateFootnoteSectionStartHtml","tok","header","markup","replace","sectionId","options","xhtmlOut","generateFootnoteSectionEndHtml","generateFootnoteStartHtml","generateFootnoteEndHtml","generateFootnoteBackRefHtml","subId","backrefCount","default_plugin_options","anchorFn","captionFn","headerFn","mkLabel","modeOverride","sortOrder","footnote_plugin","md","parseLinkLabel","helpers","isSpace","utils","Object","assign","determine_mode","mode","default_mode","override","includes","fromInput","render_footnote_n","mark","render_footnote_mark","token","footnotes","list","render_footnote_anchor_name","render_footnote_anchor_nameRef","render_footnote_caption","render_footnote_ref","self","next_token","next_token_meta","type","render_footnote_block_open","render_footnote_block_close","render_footnote_reference_open","render_footnote_reference_close","render_footnote_mark_end_of_block","render_footnote_open","render_footnote_close","render_footnote_anchor_backref","renderer","rules","footnote_ref","footnote_block_open","footnote_block_close","footnote_reference_open","footnote_reference_close","footnote_mark_end_of_block","footnote_open","footnote_close","footnote_anchor","obtain_footnote_info_slot","at_definition","parentState","refs","idMap","idMapCounter","sectionCounter","footnoteId","infoRec","Math","max","content","count","find_end_of_block_marker","state","startIndex","Token","hidden","push","update_end_of_block_marker","parentIndex","parentTokenIndex","markerTokenIndex","footnote_list","startLine","endLine","silent","footnote_def","oldBMark","oldTShift","oldSCount","oldParentType","pos","initial","offset","ch","posAfterColon","start","bMarks","tShift","eMarks","src","charCodeAt","labelEnd","mode_rec","labelInfo","decode_label","slice","extraText","sCount","parentType","blkIndent","block","tokenize","footnote_inline","labelStart","posMax","inline","parse","extra_text_is_labelOverride","m","match","trim","footnote_ref_with_text","footnoteSubId","place_footnote_definitions_at","token_idx","footnote_id_list","inject_tokens","footnote_spec_list","fn","children","concat","cnt","j","splice","more_footnote_reference_blocks_follow_immediately","footnote_tail","current","insideRef","filter","footnote_print_comparer","idA","idB","reIdMap","sort","infoA","infoB","to_atoms","nmr","Infinity","number","labelA","labelB","atomA","atomB","diff","localeCompare","prio","aside_list","section_list","Set","section_done_list","end_list","used_list","refd_notes_list","footnote","add","has","aside_ids","values","section_ids","end_ids","unused_ids","console","error","state_block","ruler","before","alt","after"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/markdownItFootnote.mjs b/dist/markdownItFootnote.mjs
new file mode 100644
index 0000000..a369531
--- /dev/null
+++ b/dist/markdownItFootnote.mjs
@@ -0,0 +1,1298 @@
+/*! markdown-it-footnote 3.0.3-10 https://github.com//GerHobbelt/markdown-it-footnote @license MIT */
+
+import { strict } from 'assert';
+
+// Process footnotes
+
+function anchorFnDefault(n, excludeSubId, baseInfo) {
+ const env = baseInfo.env;
+ strict.ok(env != null);
+ let prefix = '';
+
+ if (typeof env.docId === 'string' && env.docId.length > 0) {
+ prefix = '-' + env.docId + '-';
+ }
+
+ return prefix + n;
+}
+
+function captionFnDefault(n, baseInfo) {
+ //return '[' + n + ']';
+ return '' + n;
+}
+
+function headerFnDefault(category, baseInfo) {
+ switch (category) {
+ case 'aside':
+ return 'Side Notes';
+
+ case 'section':
+ return 'Section Notes';
+
+ case 'end':
+ return 'Endnotes';
+
+ default:
+ // used for error category, e.g. 'Error::Unused'
+ return category;
+ }
+}
+
+function determine_footnote_symbol(idx, info, baseInfo) {
+ const plugin_options = baseInfo.plugin_options;
+ strict.ok(plugin_options != null); // rule to construct the printed label:
+ //
+ // mark = labelOverride /* || info.label */ || idx;
+
+ const label = info.labelOverride;
+
+ if (label) {
+ return label;
+ }
+
+ if (plugin_options.numberSequence == null || plugin_options.numberSequence.length === 0) {
+ return '' + idx;
+ }
+
+ const len = plugin_options.numberSequence.length;
+
+ if (idx >= len) {
+ // is last slot numeric or alphanumerically?
+ const slot = plugin_options.numberSequence[len - 1];
+
+ if (Number.isFinite(slot)) {
+ const delta = idx - len + 1;
+ return '' + (slot + delta);
+ } // non-numerical last slot --> duplicate, triplicate, etc.
+
+
+ const dupli = idx / len | 0; // = int(x mod N)
+
+ const remainder = idx % len;
+ const core = plugin_options.numberSequence[remainder];
+ let str = '' + core;
+
+ for (let i = 1; i < dupli; i++) {
+ str += core;
+ }
+
+ return str;
+ }
+
+ return '' + plugin_options.numberSequence[idx];
+}
+
+const bunched_mode_classes = ['', 'footnote-bunched-ref-ref', 'footnote-bunched-ref-text'];
+
+function generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo) {
+ let localOverride = renderInfo.tokens[renderInfo.idx].meta.text;
+
+ if (localOverride) {
+ localOverride = `${localOverride}`;
+ }
+
+ return `${localOverride || ''}${caption}` + (bunched_footnote_ref_mode !== 0 ? `${renderInfo.plugin_options.refCombiner || ''}` : '');
+}
+
+function generateFootnoteSectionStartHtml(renderInfo) {
+ const tok = renderInfo.tokens[renderInfo.idx];
+ strict.ok(tok != null);
+ strict.ok(tok.meta != null);
+ const header = tok.markup ? `
${tok.markup}
` : '';
+ let category = tok.meta.category;
+ strict.ok(category.length > 0); // `category` can contain CSS class illegal characters, e.g. when category = 'Error::Unused':
+
+ category = category.replace(/[^a-zA-Z0-9_-]+/g, '_');
+ return `\n';
+}
+
+function generateFootnoteStartHtml(id, caption, renderInfo) {
+ // allow both a JavaWScript --> CSS approach via `data-footnote-caption`
+ // and a classic CSS approach while a display:inline-block SUP presenting
+ // the LI 'button' instead:
+ return `
\n';
+}
+
+function generateFootnoteBackRefHtml(id, refId, renderInfo) {
+ const tok = renderInfo.tokens[renderInfo.idx];
+ strict.ok(tok != null);
+ strict.ok(tok.meta != null);
+ /* ↩ with escape code to prevent display as Apple Emoji on iOS */
+
+ return ` \u21a9\uFE0E`;
+}
+
+const default_plugin_options = {
+ // atDocumentEnd: false, -- obsoleted option of the original plugin
+ anchorFn: anchorFnDefault,
+ captionFn: captionFnDefault,
+ headerFn: headerFnDefault,
+ mkLabel: determine_footnote_symbol,
+ // see also https://www.editage.com/insights/footnotes-in-tables-part-1-choice-of-footnote-markers-and-their-sequence
+ // why asterisk/star is not part of the default footnote marker sequence.
+ //
+ // For similar reasons, we DO NOT include the section § symbol in this list.
+ //
+ // when numberSequnce is NULL/empty, a regular numerical numbering is assumed.
+ // Otherwise, the array is indexed; when there are more footnotes than entries in
+ // the numberSequence array, the entries are re-used, but doubled/trippled, etc.
+ //
+ // When the indexing in this array hits a NUMERIC value (as last entry), any higher
+ // footnotes are NUMBERED starting at that number.
+ //
+ // NOTE: as we can reference the same footnote from multiple spots, we do not depend
+ // on CSS counter() approaches by default, but providee this mechanism in the plugin
+ // code itself.
+ numberSequence: ['†', '‡', '††', '‡‡', '¶', 1],
+ // Overrides the footnode mode when set to one of the following:
+ //
+ // Recognized 'modes':
+ // '>': aside note (default for inline notes)
+ // ':': end node
+ // '=': section note (default for regular referenced notes)
+ //
+ // Also accepts these keywords: 'aside', 'section', 'end'
+ //
+ modeOverride: null,
+ // list section notes and endnotes in order of:
+ //
+ // 0: first *appearance* in the text
+ // 1: first *reference* in the text
+ // 2: *definition* in the text
+ // 3: sorted alphanumerically by *coded* label,
+ // i.e. *numeric* labels are sorted in numeric order (so `10` comes AFTER `7`!),
+ // while all others are sorted using `String.localeCompare()`. When labels have
+ // a *numeric leading*, e.g. `71geo` --> `71`, that part is sorted numerically first.
+ //
+ // Here 'coded label' means the label constructed from the reference ids and label overrides
+ // as used in the markdown source, using the expression
+ // labelOverride || reference || id
+ // which gives for these examples (assuming them to be the only definitions in your input):
+ // [^refA]: ... --> null || 'refA' || 1
+ // [^refB LBL]: ... --> 'LBL' || 'refB' || 2
+ // 4: sorted alphanumerically by *printed* label
+ // which is like mode 3, but now for the label as will be seen in the *output*!
+ sortOrder: 4,
+ // what to print between bunched-together footnote references, i.e. the '+' in `blabla¹⁺²`
+ refCombiner: ','
+};
+function footnote_plugin(md, plugin_options) {
+ const parseLinkLabel = md.helpers.parseLinkLabel,
+ isSpace = md.utils.isSpace;
+ plugin_options = Object.assign({}, default_plugin_options, plugin_options);
+
+ function determine_mode(mode, default_mode) {
+ let override = null;
+
+ if (plugin_options.modeOverride) {
+
+ if ('>:='.includes(plugin_options.modeOverride)) {
+ override = plugin_options.modeOverride;
+ }
+ }
+
+ if ('>:='.includes(mode)) {
+ return {
+ mode: override || mode,
+ fromInput: true
+ };
+ }
+
+ return {
+ mode: override || default_mode,
+ fromInput: false
+ };
+ }
+
+ function render_footnote_n(tokens, idx, excludeSubId) {
+ const mark = tokens[idx].meta.id;
+ strict.ok(Number.isFinite(mark));
+ strict.ok(mark > 0);
+ let n = '' + mark; // = mark.toString();
+
+ strict.ok(n.length > 0);
+
+ if (!excludeSubId && tokens[idx].meta.subId > 0) {
+ n += '-' + tokens[idx].meta.subId;
+ }
+
+ return n;
+ }
+
+ function render_footnote_mark(renderInfo) {
+ const token = renderInfo.tokens[renderInfo.idx];
+ strict.ok(token != null);
+ strict.ok(renderInfo.env.footnotes != null);
+ strict.ok(renderInfo.env.footnotes.list != null);
+ const info = renderInfo.env.footnotes.list[token.meta.id];
+ strict.ok(info != null);
+ const mark = plugin_options.mkLabel(token.meta.id, info, renderInfo);
+ strict.ok(mark.length > 0);
+ return mark;
+ }
+
+ function render_footnote_anchor_name(renderInfo) {
+ const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, true);
+ return plugin_options.anchorFn(n, true, renderInfo);
+ }
+
+ function render_footnote_anchor_nameRef(renderInfo) {
+ const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, false);
+ return plugin_options.anchorFn(n, false, renderInfo);
+ }
+
+ function render_footnote_caption(renderInfo) {
+ const n = render_footnote_mark(renderInfo);
+ return plugin_options.captionFn(n, renderInfo);
+ }
+
+ function render_footnote_ref(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const id = render_footnote_anchor_name(renderInfo);
+ const caption = render_footnote_caption(renderInfo);
+ const refId = render_footnote_anchor_nameRef(renderInfo); // check if multiple footnote references are bunched together:
+ // IFF they are, we should separate them with commas.
+ //
+ // Exception: when next token has an extra text (`meta.text`) the
+ // bunching together is not a problem as them the output will render
+ // like this: `bla1text2`, ergo a look
+ // like this: `bla¹text²` instead of bunched footnotes references ¹ and ²
+ // that would (without the extra comma injection) look like `bla¹²` instead
+ // of `x¹⁺²` (here '+' instead of ',' comma, but you get the idea -- there's no
+ // Unicode superscript-comma so that's why I used unicode superscript-plus
+ // in this 'ascii art' example).
+ //
+
+ const next_token = tokens[idx + 1] || {};
+ const next_token_meta = next_token.meta || {};
+ const bunched_footnote_ref_mode = next_token.type === 'footnote_ref' ? !next_token_meta.text ? 1 : 2 : 0;
+ return generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo);
+ }
+
+ function render_footnote_block_open(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ return generateFootnoteSectionStartHtml(renderInfo);
+ }
+
+ function render_footnote_block_close(tokens, idx, options, env, self) {
+ return generateFootnoteSectionEndHtml();
+ }
+
+ function render_footnote_reference_open(tokens, idx, options, env, self) {
+ return '';
+ }
+
+ function render_footnote_reference_close() {
+ return '';
+ }
+
+ function render_footnote_mark_end_of_block() {
+ return '';
+ }
+
+ function render_footnote_open(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const id = render_footnote_anchor_name(renderInfo);
+ const caption = render_footnote_caption(renderInfo); // allow both a JavaScript --> CSS approach via `data-footnote-caption`
+ // and a classic CSS approach while a display:inline-block SUP presenting
+ // the LI 'button' instead:
+
+ return generateFootnoteStartHtml(id, caption);
+ }
+
+ function render_footnote_close(tokens, idx, options, env, self) {
+ return generateFootnoteEndHtml();
+ }
+
+ function render_footnote_anchor_backref(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const tok = tokens[idx];
+ strict.ok(tok != null);
+ strict.ok(tok.meta != null);
+ const id = render_footnote_anchor_name(renderInfo);
+ let refId = render_footnote_n(tokens, idx, false);
+ refId = plugin_options.anchorFn(refId, false, renderInfo);
+ return generateFootnoteBackRefHtml(id, refId, renderInfo);
+ }
+
+ md.renderer.rules.footnote_ref = render_footnote_ref;
+ md.renderer.rules.footnote_block_open = render_footnote_block_open;
+ md.renderer.rules.footnote_block_close = render_footnote_block_close;
+ md.renderer.rules.footnote_reference_open = render_footnote_reference_open;
+ md.renderer.rules.footnote_reference_close = render_footnote_reference_close;
+ md.renderer.rules.footnote_mark_end_of_block = render_footnote_mark_end_of_block;
+ md.renderer.rules.footnote_open = render_footnote_open;
+ md.renderer.rules.footnote_close = render_footnote_close;
+ md.renderer.rules.footnote_anchor = render_footnote_anchor_backref;
+
+ function obtain_footnote_info_slot(env, label, at_definition) {
+ // inline blocks have their own *child* environment in markdown-it v10+.
+ // As the footnotes must live beyond the lifetime of the inline block env,
+ // we must patch them into the `parentState.env` for the footnote_tail
+ // handler to be able to access them afterwards!
+ while (env.parentState) {
+ env = env.parentState.env;
+ strict.ok(env != null);
+ }
+
+ if (!env.footnotes) {
+ env.footnotes = {
+ // map label tto ID:
+ refs: {},
+ // store footnote info indexed by ID
+ list: [],
+ // remap ID to re-ordered ID (determines placement order for section notes and endnotes)
+ idMap: [0],
+ idMapCounter: 0,
+ // and a counter for the generated sections (including asides); see the demo/test which
+ // uses the generated `#fnsection-DDD` identifiers to hack/fix the styling, for example.
+ sectionCounter: 0
+ };
+ } // When label is NULL, this is a request from in INLINE NOTE.
+ // NOTE: IDs are index numbers, BUT they start at 1 instead of 0 to make life easier in check code:
+
+
+ let footnoteId;
+ let infoRec; // label as index: prepend ':' to avoid conflict with Object.prototype members
+
+ if (label == null || !env.footnotes.refs[':' + label]) {
+ footnoteId = Math.max(1, env.footnotes.list.length);
+ infoRec = {
+ id: footnoteId,
+ label,
+ labelOverride: null,
+ mode: null,
+ content: null,
+ tokens: null,
+ count: 0
+ };
+ env.footnotes.list[footnoteId] = infoRec;
+
+ if (label != null) {
+ env.footnotes.refs[':' + label] = footnoteId;
+ }
+ } else {
+ footnoteId = env.footnotes.refs[':' + label];
+ infoRec = env.footnotes.list[footnoteId];
+ strict.ok(!!infoRec, 'expects non-NULL footnote info record');
+ }
+
+ const idMap = env.footnotes.idMap; // now check if the idMap[] has been set up already as well. This depends on
+ // when WE are invoked (`at_definition`) and the configured `options.sortOrder`:
+
+ switch (plugin_options.sortOrder) {
+ // 0: first *appearance* in the text
+ default:
+ case 0:
+ // basically, this means: order as-is
+ if (!idMap[footnoteId]) {
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 1: first *reference* in the text
+
+ case 1:
+ if (!at_definition && !idMap[footnoteId]) {
+ // first reference is now!
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 2: *definition* in the text
+
+ case 2:
+ if (at_definition && !idMap[footnoteId]) {
+ // definition is now!
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)
+
+ case 3:
+ case 4:
+ // just note the footnoteId now; this must be re-ordered later when we have collected all footnotes.
+ //
+ // set it up when we get there...
+ break;
+ }
+
+ return infoRec;
+ }
+
+ function find_end_of_block_marker(state, startIndex) {
+ let idx, len;
+ const tokens = state.tokens;
+
+ for (idx = startIndex, len = tokens.length; idx < len; idx++) {
+ if (tokens[idx].type === 'footnote_mark_end_of_block') {
+ return idx;
+ }
+ } // Punch a slot into the token stream (at the very end)
+ // for consistency with footnote_mark_end_of_block():
+
+
+ const token = new state.Token('footnote_mark_end_of_block', '', 0);
+ token.hidden = true;
+ tokens.push(token);
+ return tokens.length - 1;
+ }
+
+ function update_end_of_block_marker(state, footnoteId) {
+ // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:
+ // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the
+ // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:
+ const parentState = state.env.parentState;
+ const parentIndex = state.env.parentTokenIndex;
+ const markerTokenIndex = find_end_of_block_marker(parentState, parentIndex + 1);
+ const token = parentState.tokens[markerTokenIndex];
+
+ if (!token.meta) {
+ token.meta = {
+ footnote_list: []
+ };
+ }
+
+ token.meta.footnote_list.push(footnoteId);
+ } // Mark end of paragraph/heading/whatever BLOCK (or rather: START of the next block!)
+
+
+ function footnote_mark_end_of_block(state, startLine, endLine, silent) {
+ if (!silent && state.tokens.length > 0) {
+ const token = state.push('footnote_mark_end_of_block', '', 0);
+ token.hidden = true;
+ }
+
+ return false;
+ } // Process footnote block definition
+
+
+ function footnote_def(state, startLine, endLine, silent) {
+ let oldBMark,
+ oldTShift,
+ oldSCount,
+ oldParentType,
+ pos,
+ token,
+ initial,
+ offset,
+ ch,
+ posAfterColon,
+ start = state.bMarks[startLine] + state.tShift[startLine],
+ max = state.eMarks[startLine]; // line should be at least 6 chars - "[^x]: " or "[^x]:> "
+
+ if (start + 5 > 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) === 0x0A
+ /* LF */
+ ) {
+ return false;
+ }
+
+ if (state.src.charCodeAt(pos) === 0x5D
+ /* ] */
+ ) {
+ break;
+ }
+ }
+
+ const labelEnd = pos;
+
+ if (pos === start + 2) {
+ return false;
+ } // no empty footnote labels
+
+
+ if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x3A
+ /* : */
+ ) {
+ return false;
+ }
+
+ const mode_rec = determine_mode(state.src[pos + 1], '='); // default mode is section_note mode.
+
+ if (mode_rec.fromInput) {
+ pos++;
+ }
+
+ const mode = mode_rec.mode;
+
+ if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x20
+ /* space */
+ ) {
+ return false;
+ }
+
+ if (silent) {
+ return true;
+ }
+
+ pos++;
+ const labelInfo = decode_label(state.src.slice(start + 2, labelEnd), true);
+
+ if (!labelInfo) {
+ return false;
+ }
+
+ strict.ok(!labelInfo.extraText); // Now see if we already have a footnote ID for this footnote label:
+ // fetch it if we have one and otherwise produce a new one so everyone
+ // can use this from now on.
+ //
+ // This scenario is possible when the footnote *definition* comes BEFORE
+ // the first actual footnote *use* (*reference*). This is UNUSUAL when people
+ // write texts, but it is *not impossible*, particularly now that we have
+ // specified-by-design that endnotes can be marked as such (`[^label]:: note text`)
+ // and freely mixed with sidenotes (`[^label]:> note text`) and section
+ // notes (`[^label]:= note text` (explicit mode) or `[^label]: note text`
+ // (implicit mode)), where *section notes* will placed at the spot in the text
+ // flow where they were *defined*. Again, highly irregular, BUT someone MAY
+ // feel the need to place some section note *definitions* ABOVE their first
+ // use point.
+ //
+
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, true);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ infoRec.mode = mode;
+ infoRec.content = state.src.slice(pos, max);
+ token = state.push('footnote_reference_open', '', 1);
+ token.meta = {
+ id: infoRec.id
+ };
+ token.hidden = true;
+ oldBMark = state.bMarks[startLine];
+ oldTShift = state.tShift[startLine];
+ oldSCount = state.sCount[startLine];
+ oldParentType = state.parentType;
+ posAfterColon = pos;
+ initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);
+
+ while (pos < max) {
+ ch = state.src.charCodeAt(pos);
+
+ if (isSpace(ch)) {
+ if (ch === 0x09) {
+ offset += 4 - offset % 4;
+ } else {
+ offset++;
+ }
+ } else {
+ break;
+ }
+
+ pos++;
+ }
+
+ state.tShift[startLine] = pos - posAfterColon;
+ state.sCount[startLine] = offset - initial;
+ state.bMarks[startLine] = posAfterColon;
+ state.blkIndent += 4;
+ state.parentType = 'footnote';
+
+ if (state.sCount[startLine] < state.blkIndent) {
+ state.sCount[startLine] += state.blkIndent;
+ }
+
+ state.md.block.tokenize(state, startLine, endLine, true);
+ state.parentType = oldParentType;
+ state.blkIndent -= 4;
+ state.tShift[startLine] = oldTShift;
+ state.sCount[startLine] = oldSCount;
+ state.bMarks[startLine] = oldBMark;
+ token = state.push('footnote_reference_close', '', -1);
+ token.meta = {
+ id: infoRec.id
+ };
+ return true;
+ } // Process inline footnotes (^[...] or ^[>...])
+
+
+ function footnote_inline(state, silent) {
+ let labelStart,
+ labelEnd,
+ token,
+ tokens,
+ 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; // NOTE: inline notes are automatically considered to be ASIDE notes,
+ // UNLESS otherwise specified!
+ //
+ // Recognized 'modes':
+ // '>': aside note (default for inline notes)
+ // ':': end node
+ // '=': section note (default for regular referenced notes)
+ //
+ // (Also note https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html:
+ // our notes look like this: `[^ref]:` while Academic MarkDown references look
+ // like this: `[@Belawog2012]` i.e. no '^' in there. Hence these can safely co-exist.)
+ //
+
+ const mode_rec = determine_mode(state.src[start + 2], '>'); // default mode is aside ~ sidenote mode.
+
+ if (mode_rec.fromInput) {
+ labelStart++;
+ }
+
+ const mode = mode_rec.mode;
+ 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) {
+ // WARNING: claim our footnote slot for there MAY be nested footnotes
+ // discovered in the next inline.parse() call below!
+ const infoRec = obtain_footnote_info_slot(state.env, null, true);
+ infoRec.mode = mode;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id
+ };
+ state.md.inline.parse(state.src.slice(labelStart, labelEnd), state.md, state.env, tokens = []); // Now fill our previously claimed slot:
+
+ infoRec.content = state.src.slice(labelStart, labelEnd);
+ infoRec.tokens = tokens; // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:
+ // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the
+ // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:
+
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = labelEnd + 1;
+ state.posMax = max;
+ return true;
+ } // Check if this is a valid ffootnote reference label.
+ //
+ // Also see if there's a label OVERRIDE text or marker ('@') provided.
+ //
+ // Return the parsed label record.
+
+
+ function decode_label(label, extra_text_is_labelOverride) {
+ var _m$;
+
+ if (!label) {
+ return null;
+ }
+
+ const m = label.match(/^(@?)(\S+)(?:\s+(.+))?$/); // label with OPTIONAL override text...
+
+ if (!m) {
+ return null;
+ }
+
+ strict.ok(m[2].length > 0);
+ let extraText = (_m$ = m[3]) == null ? void 0 : _m$.trim(); // label [output] override?
+
+ let override = null;
+
+ if (m[1]) {
+ override = m[2];
+ }
+
+ if (extra_text_is_labelOverride && extraText) {
+ override = extraText;
+ extraText = null;
+ }
+
+ return {
+ label: m[2],
+ labelOverride: override,
+ extraText
+ };
+ } // Process footnote references with text ([^label ...])
+
+
+ function footnote_ref_with_text(state, silent) {
+ let pos,
+ footnoteSubId,
+ token,
+ max = state.posMax,
+ start = state.pos; // should be at least 6 chars - "[^l x]"
+
+ if (start + 5 > 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) === 0x0A
+ /* linefeed */
+ ) {
+ 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++;
+ const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), false);
+
+ if (!labelInfo || !labelInfo.extraText) {
+ return false;
+ }
+
+ strict.ok(labelInfo.extraText.length > 0);
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ if (!silent) {
+ footnoteSubId = infoRec.count;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id,
+ subId: footnoteSubId,
+ text: labelInfo.extraText
+ };
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = pos;
+ state.posMax = max;
+ return true;
+ } // Process footnote references ([^...])
+
+
+ function footnote_ref(state, silent) {
+ let pos,
+ footnoteSubId,
+ token,
+ max = state.posMax,
+ start = state.pos; // should be at least 4 chars - "[^x]"
+
+ if (start + 3 > 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) === 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++;
+ const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), true);
+
+ if (!labelInfo) {
+ return false;
+ }
+
+ strict.ok(!labelInfo.extraText);
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ if (!silent) {
+ footnoteSubId = infoRec.count;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id,
+ subId: footnoteSubId
+ };
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = pos;
+ state.posMax = max;
+ return true;
+ }
+
+ function place_footnote_definitions_at(state, token_idx, footnote_id_list, category, baseInfo) {
+ if (footnote_id_list.length === 0) {
+ return; // nothing to inject...
+ }
+
+ let inject_tokens = [];
+ strict.ok(baseInfo.env.footnotes.list != null);
+ const footnote_spec_list = baseInfo.env.footnotes.list;
+ let token = new state.Token('footnote_block_open', '', 1);
+ token.markup = plugin_options.headerFn(category, baseInfo.env, plugin_options);
+ token.meta = {
+ sectionId: ++baseInfo.env.footnotes.sectionCounter,
+ category
+ };
+ inject_tokens.push(token);
+
+ for (const id of footnote_id_list) {
+ const fn = footnote_spec_list[id];
+ token = new state.Token('footnote_open', '', 1);
+ token.meta = {
+ id,
+ category
+ };
+ inject_tokens.push(token);
+
+ if (fn.label == null) {
+ // process an inline footnote text:
+ token = new state.Token('paragraph_open', 'p', 1);
+ token.block = true;
+ inject_tokens.push(token);
+ token = new state.Token('inline', '', 0);
+ token.children = fn.tokens;
+ token.content = fn.content;
+ inject_tokens.push(token);
+ token = new state.Token('paragraph_close', 'p', -1);
+ token.block = true;
+ inject_tokens.push(token);
+ } else {
+ // process a labeled footnote:
+ inject_tokens = inject_tokens.concat(fn.tokens || []);
+ } //let lastParagraph;
+ //if (inject_tokens[inject_tokens.length - 1].type === 'paragraph_close') {
+ // lastParagraph = inject_tokens.pop();
+ //} else {
+ // lastParagraph = null;
+ //}
+
+
+ const cnt = fn.count;
+ strict.ok(cnt >= 0);
+
+ for (let j = 0; j < cnt; j++) {
+ token = new state.Token('footnote_anchor', '', 0);
+ token.meta = {
+ id,
+ subId: j,
+ backrefCount: cnt,
+ category
+ };
+ inject_tokens.push(token);
+ } //if (lastParagraph) {
+ // inject_tokens.push(lastParagraph);
+ //}
+
+
+ token = new state.Token('footnote_close', '', -1);
+ token.meta = {
+ id,
+ category
+ };
+ inject_tokens.push(token);
+ }
+
+ token = new state.Token('footnote_block_close', '', -1);
+ token.meta = {
+ category
+ };
+ inject_tokens.push(token);
+ state.tokens.splice(token_idx, 0, ...inject_tokens);
+ }
+
+ function more_footnote_reference_blocks_follow_immediately(tokens, idx) {
+ let tok = tokens[idx];
+
+ while (tok && (tok.type === 'footnote_mark_end_of_block' || tok.type === 'footnote_reference_close')) {
+ idx++;
+ tok = tokens[idx];
+ }
+
+ return tok && tok.type === 'footnote_reference_open';
+ } // Glue footnote tokens into appropriate slots of token stream.
+
+
+ function footnote_tail(state, startLine, endLine, silent) {
+ let i,
+ current,
+ insideRef = false;
+
+ if (!state.env.footnotes) {
+ // no footnotes at all? --> filter out all 'footnote_mark_end_of_block' chunks:
+ state.tokens = state.tokens.filter(function (tok, idx) {
+ return tok.type !== 'footnote_mark_end_of_block';
+ });
+ return;
+ }
+
+ const idMap = state.env.footnotes.idMap;
+ const baseInfo = {
+ options: state.md.options,
+ env: state.env,
+ plugin_options,
+ self: this
+ };
+
+ function footnote_print_comparer(idA, idB) {
+ return idMap[idA] - idMap[idB];
+ } // Rewrite the tokenstream to place the aside-footnotes and section footnotes where they need to be:
+
+
+ const footnote_spec_list = state.env.footnotes.list; // extract the tokens constituting the footnote/sidenote *content* and
+ // store that bunch in `refTokens[:]` instead, to be injected back into
+ // the tokenstream at the appropriate spots.
+
+ state.tokens = state.tokens.filter(function (tok, idx) {
+ switch (tok.type) {
+ // filter out 'footnote_mark_end_of_block' tokens which follow BLOCKS that do not contain any
+ // footnote/sidenote/endnote references:
+ case 'footnote_mark_end_of_block':
+ if (!tok.meta) return false;
+ if (!tok.meta.footnote_list) return false;
+ break;
+
+ case 'footnote_reference_open':
+ insideRef = true;
+ current = [];
+ return true;
+
+ case 'footnote_reference_close':
+ insideRef = false;
+ const infoRec = footnote_spec_list[tok.meta.id];
+ infoRec.tokens = current;
+ return true;
+ }
+
+ if (insideRef) {
+ current.push(tok);
+ }
+
+ return !insideRef;
+ }); // execute configured sorting/mapping (`idMap`):
+
+ switch (plugin_options.sortOrder) {
+ // 0: first *appearance* in the text
+ default:
+ case 0: // 1: first *reference* in the text
+
+ case 1: // 2: *definition* in the text
+
+ case 2:
+ // order is specified in the `idMap` already.
+ break;
+ // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)
+
+ case 3:
+ case 4:
+ // the `idMap[]` array has not been set up and must be produced
+ // to turn this into an alphanumerically-by-label sort order, where
+ // a `footnoteId` based index will produce the order of appearance.
+ const reIdMap = [];
+
+ for (let i = 1; i < footnote_spec_list.length; i++) {
+ reIdMap[i - 1] = i;
+ }
+
+ reIdMap.sort((idA, idB) => {
+ const infoA = footnote_spec_list[idA];
+ const infoB = footnote_spec_list[idB];
+ strict.ok(infoA);
+ strict.ok(infoB); // is any of these an inline footnote, i.e. without any label yet? Produce a fake label for sorting then!
+ //
+ // As stated elsewhere: inline section_notes and end_notes will end up among everyone else in this sort order mode.
+
+ strict.ok(infoA.id === idA);
+ strict.ok(infoB.id === idB); // Split a "sort label" up into its numerical part and the tail. Note that we don't call
+ // it 'tail' but 'label', because we will need to compare the ENTIRE LABEL using string comparison
+ // when the numeric leaders are identical, so as to ensure that 'labels' such as `00000` will sort
+ // as 'higher' than `000`, both of which will be rated as numerically identical!
+
+ function to_atoms(label) {
+ // now extract number or numerical leader part.
+ //
+ // Only accept OBVIOUS, SIMPLE NUMERIC LEADERS! This is about *legibility*
+ // of those numrical leaders, not a pedantic "what is possibly legally numeric"
+ // challenge. Hence we DO NOT accept leading +/- and only a decimal dot when
+ // there's a decimal number BEFORE it, such as in `5.1hack` --> `5.1`, but NOT
+ // `.42oz`!
+ //
+ // Do not use `nmr = +lbl` as that would treat labels such as `0xf4` as hexadecimal numbers,
+ // which we DO NOT want to happen.
+ const m = label.match(/^\d+(?:\.\d+)?/) || ['x'];
+ const nmr = +m[0] || Infinity; // non-numeric labels are rated NUMEICALLY HIGHER than any numerical leader.
+
+ return {
+ label,
+ number: nmr
+ };
+ }
+
+ const labelA = plugin_options.sortOrder === 3 ? infoA.labelOverride || infoA.label || '' + infoA.id : plugin_options.mkLabel(infoA.id, infoA, baseInfo);
+ const labelB = plugin_options.sortOrder === 3 ? infoB.labelOverride || infoB.label || '' + infoB.id : plugin_options.mkLabel(infoB.id, infoB, baseInfo);
+ const atomA = to_atoms(labelA);
+ const atomB = to_atoms(labelB);
+ const diff = atomA.number - atomB.number;
+ return diff || atomA.label.localeCompare(atomB.label); // ^^^^^^^ shorthand for:
+ //
+ // if (isNaN(diff) || diff === 0) then stringcompare else numeric-difference
+ }); // Now turn this into a sort order map:
+
+ for (let prio = 0; prio < reIdMap.length; prio++) {
+ const id = reIdMap[prio];
+ idMap[id] = prio;
+ }
+
+ break;
+ }
+
+ let aside_list;
+ let section_list = new Set();
+ const section_done_list = new Set(); // once a section_note has been printed, it should never appear again!
+
+ const end_list = new Set();
+ const used_list = new Set();
+ let tokens = state.tokens;
+
+ for (i = 0; i < tokens.length; i++) {
+ const tok = tokens[i];
+
+ switch (tok.type) {
+ case 'footnote_mark_end_of_block':
+ // check the gathered list of footnotes referenced in this block:
+ // - dump the ones which are sidenotes
+ // - mark the ones which are section- or end-notes.
+ //
+ // Note: make sure we don't produce duplicates in the collect sets.
+ {
+ var _tok$meta;
+
+ aside_list = new Set();
+ const refd_notes_list = ((_tok$meta = tok.meta) == null ? void 0 : _tok$meta.footnote_list) || [];
+
+ for (const id of refd_notes_list) {
+ const footnote = footnote_spec_list[id];
+
+ switch (footnote.mode) {
+ case '>':
+ aside_list.add(id);
+ used_list.add(id);
+ break;
+
+ case '=':
+ if (!section_done_list.has(id)) {
+ section_list.add(id);
+ section_done_list.add(id);
+ used_list.add(id);
+ }
+
+ break;
+
+ default:
+ case ':':
+ end_list.add(id);
+ used_list.add(id);
+ break;
+ }
+ }
+
+ const aside_ids = [];
+
+ for (const id of aside_list.values()) {
+ aside_ids.push(id);
+ }
+
+ aside_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, i + 1, aside_ids, 'aside', baseInfo);
+ tokens = state.tokens;
+ }
+ break;
+
+ case 'footnote_reference_close':
+ // anywhere a footnote *definition* appeared in the original text is
+ // also a place to dump the section_notes gathered to date, so to speak.
+ //
+ // However, DO detect clusters of footnote definitions and MERGE them
+ // together:
+ if (more_footnote_reference_blocks_follow_immediately(tokens, i + 1)) {
+ continue;
+ } else {
+ const section_ids = [];
+
+ for (const id of section_list.values()) {
+ section_ids.push(id);
+ }
+
+ section_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, i + 1, section_ids, 'section', baseInfo);
+ tokens = state.tokens; // and reset the tracking set:
+
+ section_list = new Set();
+ }
+
+ break;
+ }
+ } // Now process the endnotes:
+
+
+ {
+ const end_ids = [];
+
+ for (const id of end_list.values()) {
+ end_ids.push(id);
+ }
+
+ end_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, tokens.length, end_ids, 'end', baseInfo);
+ tokens = state.tokens;
+ } // Now process the unused footnotes and dump them for diagnostic purposes:
+
+ {
+ const unused_ids = [];
+
+ for (let i = 1; i < footnote_spec_list.length; i++) {
+ const fn = footnote_spec_list[i];
+ const id = fn.id;
+
+ if (!used_list.has(id)) {
+ console.error(`ERROR: footnote ID ${id} is defined but never used. Footnote will be added as an ERRONEOUS ENDNOTE to the output, so the situation is easy to diagnose!`, Object.assign({}, fn, {
+ tokens: '......'
+ }));
+ unused_ids.push(id);
+ }
+ }
+
+ unused_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, tokens.length, unused_ids, 'Error::Unused', baseInfo); //tokens = state.tokens;
+ } // Update state_block too as we have rewritten & REPLACED the token array earlier in this call:
+ // the reference `state.env.state_block.tokens` is still pointing to the OLD token array!
+
+ state.env.state_block.tokens = state.tokens;
+ } // attach ourselves to the start of block handling too
+
+
+ md.block.ruler.before('table', 'footnote_mark_end_of_block', footnote_mark_end_of_block);
+ md.block.ruler.before('reference', 'footnote_def', footnote_def, {
+ alt: ['paragraph', 'reference']
+ });
+ md.inline.ruler.after('image', 'footnote_inline', footnote_inline);
+ md.inline.ruler.after('footnote_inline', 'footnote_ref_with_text', footnote_ref_with_text);
+ md.inline.ruler.after('footnote_ref_with_text', 'footnote_ref', footnote_ref);
+ md.core.ruler.after('inline', 'footnote_tail', footnote_tail);
+}
+
+export default footnote_plugin;
+//# sourceMappingURL=markdownItFootnote.mjs.map
diff --git a/dist/markdownItFootnote.mjs.map b/dist/markdownItFootnote.mjs.map
new file mode 100644
index 0000000..4384afe
--- /dev/null
+++ b/dist/markdownItFootnote.mjs.map
@@ -0,0 +1 @@
+{"version":3,"file":"markdownItFootnote.mjs","sources":["../index.ts"],"sourcesContent":["// Process footnotes\n//\n\nimport { strict as assert } from 'assert';\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Renderer partials\n\n\n\ninterface FootnotePluginOptions {\n numberSequence?: Array;\n modeOverride?: string;\n sortOrder: number;\n refCombiner?: string;\n}\n\ninterface GenericInfoParameters {\n options: any; // markdown_it options object\n plugin_options: FootnotePluginOptions;\n env: any; // markdown_it environment object\n self: any; // reference to this plugin instance\n}\n\ninterface RenderInfoParameters extends GenericInfoParameters {\n tokens: Array; // array of tokens\n idx: number; // index of current token in token array\n}\n\ninterface footnoteMetaInfo {\n id: number;\n label?: string;\n labelOverride?: string;\n mode?: string;\n content?: string;\n tokens?: Array;\n count: number;\n}\n\n\n\nfunction anchorFnDefault(n: number, excludeSubId: number, baseInfo: RenderInfoParameters) {\n const env = baseInfo.env;\n assert.ok(env != null);\n let prefix = '';\n if (typeof env.docId === 'string' && env.docId.length > 0) {\n prefix = '-' + env.docId + '-';\n }\n return prefix + n;\n}\n\nfunction captionFnDefault(n, baseInfo: RenderInfoParameters) {\n //return '[' + n + ']';\n return '' + n;\n}\n\nfunction headerFnDefault(category, baseInfo: GenericInfoParameters) {\n switch (category) {\n case 'aside':\n return 'Side Notes';\n\n case 'section':\n return 'Section Notes';\n\n case 'end':\n return 'Endnotes';\n\n default: // used for error category, e.g. 'Error::Unused'\n return category;\n }\n}\n\nfunction determine_footnote_symbol(idx: number, info: footnoteMetaInfo, baseInfo: GenericInfoParameters): string {\n const plugin_options = baseInfo.plugin_options;\n assert.ok(plugin_options != null);\n\n // rule to construct the printed label:\n //\n // mark = labelOverride /* || info.label */ || idx;\n const label = info.labelOverride;\n if (label) {\n return label;\n }\n if (plugin_options.numberSequence == null || plugin_options.numberSequence.length === 0) {\n return '' + idx;\n }\n const len = plugin_options.numberSequence.length;\n if (idx >= len) {\n // is last slot numeric or alphanumerically?\n const slot = plugin_options.numberSequence[len - 1];\n if (Number.isFinite(slot)) {\n const delta = idx - len + 1;\n return '' + (slot + delta);\n }\n\n // non-numerical last slot --> duplicate, triplicate, etc.\n const dupli = (idx / len) | 0; // = int(x mod N)\n const remainder = idx % len;\n const core = plugin_options.numberSequence[remainder];\n let str = '' + core;\n for (let i = 1; i < dupli; i++) {\n str += core;\n }\n return str;\n }\n\n return '' + plugin_options.numberSequence[idx];\n}\n\n\nconst bunched_mode_classes = [ '', 'footnote-bunched-ref-ref', 'footnote-bunched-ref-text' ];\n\n\nfunction generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo: RenderInfoParameters) {\n let localOverride = renderInfo.tokens[renderInfo.idx].meta.text;\n if (localOverride) {\n localOverride = `${ localOverride }`;\n }\n return `${ localOverride || '' }${ caption }` +\n (bunched_footnote_ref_mode !== 0 ? `${ renderInfo.plugin_options.refCombiner || '' }` : '');\n}\n\nfunction generateFootnoteSectionStartHtml(renderInfo: RenderInfoParameters) {\n const tok = renderInfo.tokens[renderInfo.idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n const header = (tok.markup ? `
${ tok.markup }
` : '');\n let category = tok.meta.category;\n assert.ok(category.length > 0);\n // `category` can contain CSS class illegal characters, e.g. when category = 'Error::Unused':\n category = category.replace(/[^a-zA-Z0-9_-]+/g, '_');\n return `\\n';\n}\n\nfunction generateFootnoteStartHtml(id, caption, renderInfo: RenderInfoParameters) {\n // allow both a JavaWScript --> CSS approach via `data-footnote-caption`\n // and a classic CSS approach while a display:inline-block SUP presenting\n // the LI 'button' instead:\n return `
\\n';\n}\n\nfunction generateFootnoteBackRefHtml(id, refId, renderInfo: RenderInfoParameters) {\n const tok = renderInfo.tokens[renderInfo.idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n\n /* ↩ with escape code to prevent display as Apple Emoji on iOS */\n return ` \\u21a9\\uFE0E`;\n}\n\n\n\n\n/*\nref:\n return ``;\n\n\nopen:\n return `\\n';\n}\n\n*/\n\n\n\n\ninterface FootnotePluginOptions /* extends FootnotePluginOptions */ { // eslint-disable-line no-redeclare\n anchorFn: (n: number, excludeSubId: number, baseInfo: RenderInfoParameters) => string;\n captionFn: (n: number, baseInfo: RenderInfoParameters) => string;\n headerFn: (category: string, baseInfo: GenericInfoParameters) => string;\n mkLabel: (idx: number, info: footnoteMetaInfo, baseInfo: GenericInfoParameters) => string;\n}\n\n\n\n\nconst default_plugin_options: FootnotePluginOptions = {\n // atDocumentEnd: false, -- obsoleted option of the original plugin\n\n anchorFn: anchorFnDefault,\n captionFn: captionFnDefault,\n headerFn: headerFnDefault,\n mkLabel: determine_footnote_symbol,\n\n // see also https://www.editage.com/insights/footnotes-in-tables-part-1-choice-of-footnote-markers-and-their-sequence\n // why asterisk/star is not part of the default footnote marker sequence.\n //\n // For similar reasons, we DO NOT include the section § symbol in this list.\n //\n // when numberSequnce is NULL/empty, a regular numerical numbering is assumed.\n // Otherwise, the array is indexed; when there are more footnotes than entries in\n // the numberSequence array, the entries are re-used, but doubled/trippled, etc.\n //\n // When the indexing in this array hits a NUMERIC value (as last entry), any higher\n // footnotes are NUMBERED starting at that number.\n //\n // NOTE: as we can reference the same footnote from multiple spots, we do not depend\n // on CSS counter() approaches by default, but providee this mechanism in the plugin\n // code itself.\n numberSequence: [ '†', '‡', '††', '‡‡', '¶', 1 ],\n\n // Overrides the footnode mode when set to one of the following:\n //\n // Recognized 'modes':\n // '>': aside note (default for inline notes)\n // ':': end node\n // '=': section note (default for regular referenced notes)\n //\n // Also accepts these keywords: 'aside', 'section', 'end'\n //\n modeOverride: null,\n\n // list section notes and endnotes in order of:\n //\n // 0: first *appearance* in the text\n // 1: first *reference* in the text\n // 2: *definition* in the text\n // 3: sorted alphanumerically by *coded* label,\n // i.e. *numeric* labels are sorted in numeric order (so `10` comes AFTER `7`!),\n // while all others are sorted using `String.localeCompare()`. When labels have\n // a *numeric leading*, e.g. `71geo` --> `71`, that part is sorted numerically first.\n //\n // Here 'coded label' means the label constructed from the reference ids and label overrides\n // as used in the markdown source, using the expression\n // labelOverride || reference || id\n // which gives for these examples (assuming them to be the only definitions in your input):\n // [^refA]: ... --> null || 'refA' || 1\n // [^refB LBL]: ... --> 'LBL' || 'refB' || 2\n // 4: sorted alphanumerically by *printed* label\n // which is like mode 3, but now for the label as will be seen in the *output*!\n sortOrder: 4,\n\n // what to print between bunched-together footnote references, i.e. the '+' in `blabla¹⁺²`\n refCombiner: ','\n};\n\n\n\n\nexport default function footnote_plugin(md, plugin_options) {\n const parseLinkLabel = md.helpers.parseLinkLabel,\n isSpace = md.utils.isSpace;\n\n plugin_options = Object.assign({}, default_plugin_options, plugin_options);\n\n\n\n const modeOverrideMap = {\n aside: '>',\n section: '=',\n end: ':'\n };\n\n function determine_mode(mode: string, default_mode: string) {\n let override = null;\n if (plugin_options.modeOverride) {\n const mode = modeOverrideMap[plugin_options.modeOverride] || plugin_options.modeOverride;\n if ('>:='.includes(plugin_options.modeOverride)) {\n override = plugin_options.modeOverride;\n }\n }\n if ('>:='.includes(mode)) {\n return {\n mode: override || mode,\n fromInput: true\n };\n }\n return {\n mode: override || default_mode,\n fromInput: false\n };\n }\n\n function render_footnote_n(tokens, idx, excludeSubId) {\n const mark = tokens[idx].meta.id;\n assert.ok(Number.isFinite(mark));\n assert.ok(mark > 0);\n let n = '' + mark; // = mark.toString();\n assert.ok(n.length > 0);\n\n if (!excludeSubId && tokens[idx].meta.subId > 0) {\n n += '-' + tokens[idx].meta.subId;\n }\n\n return n;\n }\n\n function render_footnote_mark(renderInfo: RenderInfoParameters): string {\n const token = renderInfo.tokens[renderInfo.idx];\n assert.ok(token != null);\n assert.ok(renderInfo.env.footnotes != null);\n assert.ok(renderInfo.env.footnotes.list != null);\n const info = renderInfo.env.footnotes.list[token.meta.id];\n assert.ok(info != null);\n const mark: string = plugin_options.mkLabel(token.meta.id, info, renderInfo);\n assert.ok(mark.length > 0);\n return mark;\n }\n\n function render_footnote_anchor_name(renderInfo: RenderInfoParameters) {\n const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, true);\n return plugin_options.anchorFn(n, true, renderInfo);\n }\n\n function render_footnote_anchor_nameRef(renderInfo: RenderInfoParameters) {\n const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, false);\n return plugin_options.anchorFn(n, false, renderInfo);\n }\n\n function render_footnote_caption(renderInfo: RenderInfoParameters) {\n const n = render_footnote_mark(renderInfo);\n return plugin_options.captionFn(n, renderInfo);\n }\n\n function render_footnote_ref(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n const id = render_footnote_anchor_name(renderInfo);\n const caption = render_footnote_caption(renderInfo);\n const refId = render_footnote_anchor_nameRef(renderInfo);\n\n // check if multiple footnote references are bunched together:\n // IFF they are, we should separate them with commas.\n //\n // Exception: when next token has an extra text (`meta.text`) the\n // bunching together is not a problem as them the output will render\n // like this: `bla1text2`, ergo a look\n // like this: `bla¹text²` instead of bunched footnotes references ¹ and ²\n // that would (without the extra comma injection) look like `bla¹²` instead\n // of `x¹⁺²` (here '+' instead of ',' comma, but you get the idea -- there's no\n // Unicode superscript-comma so that's why I used unicode superscript-plus\n // in this 'ascii art' example).\n //\n const next_token = tokens[idx + 1] || {};\n const next_token_meta = next_token.meta || {};\n const bunched_footnote_ref_mode = (next_token.type === 'footnote_ref' ? !next_token_meta.text ? 1 : 2 : 0);\n\n return generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo);\n }\n\n function render_footnote_block_open(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n return generateFootnoteSectionStartHtml(renderInfo);\n }\n\n function render_footnote_block_close(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n return generateFootnoteSectionEndHtml(renderInfo);\n }\n\n function render_footnote_reference_open(tokens, idx, options, env, self) {\n return '';\n }\n\n function render_footnote_reference_close() {\n return '';\n }\n\n function render_footnote_mark_end_of_block() {\n return '';\n }\n\n function render_footnote_open(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n const id = render_footnote_anchor_name(renderInfo);\n const caption = render_footnote_caption(renderInfo);\n\n // allow both a JavaScript --> CSS approach via `data-footnote-caption`\n // and a classic CSS approach while a display:inline-block SUP presenting\n // the LI 'button' instead:\n return generateFootnoteStartHtml(id, caption, renderInfo);\n }\n\n function render_footnote_close(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n return generateFootnoteEndHtml(renderInfo);\n }\n\n function render_footnote_anchor_backref(tokens, idx, options, env, self) {\n const renderInfo: RenderInfoParameters = {\n tokens,\n idx,\n options,\n env,\n plugin_options,\n self\n };\n\n const tok = tokens[idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n const id = render_footnote_anchor_name(renderInfo);\n let refId = render_footnote_n(tokens, idx, false);\n refId = plugin_options.anchorFn(refId, false, renderInfo);\n\n return generateFootnoteBackRefHtml(id, refId, renderInfo);\n }\n\n\n\n md.renderer.rules.footnote_ref = render_footnote_ref;\n md.renderer.rules.footnote_block_open = render_footnote_block_open;\n md.renderer.rules.footnote_block_close = render_footnote_block_close;\n md.renderer.rules.footnote_reference_open = render_footnote_reference_open;\n md.renderer.rules.footnote_reference_close = render_footnote_reference_close;\n md.renderer.rules.footnote_mark_end_of_block = render_footnote_mark_end_of_block;\n md.renderer.rules.footnote_open = render_footnote_open;\n md.renderer.rules.footnote_close = render_footnote_close;\n md.renderer.rules.footnote_anchor = render_footnote_anchor_backref;\n\n\n\n function obtain_footnote_info_slot(env, label: string|null, at_definition: boolean) {\n // inline blocks have their own *child* environment in markdown-it v10+.\n // As the footnotes must live beyond the lifetime of the inline block env,\n // we must patch them into the `parentState.env` for the footnote_tail\n // handler to be able to access them afterwards!\n while (env.parentState) {\n env = env.parentState.env;\n assert.ok(env != null);\n }\n\n if (!env.footnotes) {\n env.footnotes = {\n // map label tto ID:\n refs: {},\n // store footnote info indexed by ID\n list: [],\n // remap ID to re-ordered ID (determines placement order for section notes and endnotes)\n idMap: [ 0 ],\n idMapCounter: 0,\n\n // and a counter for the generated sections (including asides); see the demo/test which\n // uses the generated `#fnsection-DDD` identifiers to hack/fix the styling, for example.\n sectionCounter: 0\n };\n }\n\n // When label is NULL, this is a request from in INLINE NOTE.\n\n // NOTE: IDs are index numbers, BUT they start at 1 instead of 0 to make life easier in check code:\n let footnoteId;\n let infoRec: footnoteMetaInfo;\n // label as index: prepend ':' to avoid conflict with Object.prototype members\n if (label == null || !env.footnotes.refs[':' + label]) {\n footnoteId = Math.max(1, env.footnotes.list.length);\n infoRec = {\n id: footnoteId,\n label,\n labelOverride: null,\n mode: null,\n content: null,\n tokens: null,\n count: 0\n };\n env.footnotes.list[footnoteId] = infoRec;\n if (label != null) {\n env.footnotes.refs[':' + label] = footnoteId;\n }\n } else {\n footnoteId = env.footnotes.refs[':' + label];\n infoRec = env.footnotes.list[footnoteId];\n assert.ok(!!infoRec, 'expects non-NULL footnote info record');\n }\n\n const idMap = env.footnotes.idMap;\n\n // now check if the idMap[] has been set up already as well. This depends on\n // when WE are invoked (`at_definition`) and the configured `options.sortOrder`:\n switch (plugin_options.sortOrder) {\n // 0: first *appearance* in the text\n default:\n case 0:\n // basically, this means: order as-is\n if (!idMap[footnoteId]) {\n idMap[footnoteId] = ++env.footnotes.idMapCounter;\n }\n break;\n\n // 1: first *reference* in the text\n case 1:\n if (!at_definition && !idMap[footnoteId]) {\n // first reference is now!\n idMap[footnoteId] = ++env.footnotes.idMapCounter;\n }\n break;\n\n // 2: *definition* in the text\n case 2:\n if (at_definition && !idMap[footnoteId]) {\n // definition is now!\n idMap[footnoteId] = ++env.footnotes.idMapCounter;\n }\n break;\n\n // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)\n case 3:\n case 4:\n // just note the footnoteId now; this must be re-ordered later when we have collected all footnotes.\n //\n // set it up when we get there...\n break;\n }\n\n return infoRec;\n }\n\n function find_end_of_block_marker(state, startIndex) {\n let idx, len;\n const tokens = state.tokens;\n for (idx = startIndex, len = tokens.length; idx < len; idx++) {\n if (tokens[idx].type === 'footnote_mark_end_of_block') { return idx; }\n }\n\n // Punch a slot into the token stream (at the very end)\n // for consistency with footnote_mark_end_of_block():\n const token = new state.Token('footnote_mark_end_of_block', '', 0);\n token.hidden = true;\n tokens.push(token);\n return tokens.length - 1;\n }\n\n function update_end_of_block_marker(state, footnoteId) {\n // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:\n // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the\n // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:\n const parentState = state.env.parentState;\n const parentIndex = state.env.parentTokenIndex;\n const markerTokenIndex = find_end_of_block_marker(parentState, parentIndex + 1);\n const token = parentState.tokens[markerTokenIndex];\n if (!token.meta) {\n token.meta = {\n footnote_list: []\n };\n }\n token.meta.footnote_list.push(footnoteId);\n }\n\n // Mark end of paragraph/heading/whatever BLOCK (or rather: START of the next block!)\n function footnote_mark_end_of_block(state, startLine, endLine, silent) {\n if (!silent && state.tokens.length > 0) {\n const token = state.push('footnote_mark_end_of_block', '', 0);\n token.hidden = true;\n }\n return false;\n }\n\n\n\n // Process footnote block definition\n function footnote_def(state, startLine, endLine, silent) {\n let oldBMark, oldTShift, oldSCount, oldParentType, pos, token,\n initial, offset, ch, posAfterColon,\n start = state.bMarks[startLine] + state.tShift[startLine],\n max = state.eMarks[startLine];\n\n // line should be at least 6 chars - \"[^x]: \" or \"[^x]:> \"\n if (start + 5 > max) { return false; }\n\n if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }\n\n for (pos = start + 2; pos < max; pos++) {\n if (state.src.charCodeAt(pos) === 0x0A /* LF */) { return false; }\n if (state.src.charCodeAt(pos) === 0x5D /* ] */) {\n break;\n }\n }\n const labelEnd = pos;\n\n if (pos === start + 2) { return false; } // no empty footnote labels\n if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x3A /* : */) { return false; }\n\n const mode_rec = determine_mode(state.src[pos + 1], '='); // default mode is section_note mode.\n if (mode_rec.fromInput) { pos++; }\n const mode = mode_rec.mode;\n\n if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x20 /* space */) { return false; }\n if (silent) { return true; }\n pos++;\n\n const labelInfo = decode_label(state.src.slice(start + 2, labelEnd), true);\n if (!labelInfo) { return false; }\n assert.ok(!labelInfo.extraText);\n\n // Now see if we already have a footnote ID for this footnote label:\n // fetch it if we have one and otherwise produce a new one so everyone\n // can use this from now on.\n //\n // This scenario is possible when the footnote *definition* comes BEFORE\n // the first actual footnote *use* (*reference*). This is UNUSUAL when people\n // write texts, but it is *not impossible*, particularly now that we have\n // specified-by-design that endnotes can be marked as such (`[^label]:: note text`)\n // and freely mixed with sidenotes (`[^label]:> note text`) and section\n // notes (`[^label]:= note text` (explicit mode) or `[^label]: note text`\n // (implicit mode)), where *section notes* will placed at the spot in the text\n // flow where they were *defined*. Again, highly irregular, BUT someone MAY\n // feel the need to place some section note *definitions* ABOVE their first\n // use point.\n //\n const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, true);\n if (labelInfo.labelOverride) {\n infoRec.labelOverride = labelInfo.labelOverride;\n }\n infoRec.mode = mode;\n infoRec.content = state.src.slice(pos, max);\n\n token = state.push('footnote_reference_open', '', 1);\n token.meta = {\n id: infoRec.id\n };\n token.hidden = true;\n\n oldBMark = state.bMarks[startLine];\n oldTShift = state.tShift[startLine];\n oldSCount = state.sCount[startLine];\n oldParentType = state.parentType;\n\n posAfterColon = pos;\n initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);\n\n while (pos < max) {\n ch = state.src.charCodeAt(pos);\n\n if (isSpace(ch)) {\n if (ch === 0x09) {\n offset += 4 - offset % 4;\n } else {\n offset++;\n }\n } else {\n break;\n }\n\n pos++;\n }\n\n state.tShift[startLine] = pos - posAfterColon;\n state.sCount[startLine] = offset - initial;\n\n state.bMarks[startLine] = posAfterColon;\n state.blkIndent += 4;\n state.parentType = 'footnote';\n\n if (state.sCount[startLine] < state.blkIndent) {\n state.sCount[startLine] += state.blkIndent;\n }\n\n state.md.block.tokenize(state, startLine, endLine, true);\n\n state.parentType = oldParentType;\n state.blkIndent -= 4;\n state.tShift[startLine] = oldTShift;\n state.sCount[startLine] = oldSCount;\n state.bMarks[startLine] = oldBMark;\n\n token = state.push('footnote_reference_close', '', -1);\n token.meta = {\n id: infoRec.id\n };\n\n return true;\n }\n\n\n\n // Process inline footnotes (^[...] or ^[>...])\n function footnote_inline(state, silent) {\n let labelStart,\n labelEnd,\n token,\n tokens,\n max = state.posMax,\n start = state.pos;\n\n if (start + 2 >= max) { return false; }\n if (state.src.charCodeAt(start) !== 0x5E/* ^ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5B/* [ */) { return false; }\n\n labelStart = start + 2;\n\n // NOTE: inline notes are automatically considered to be ASIDE notes,\n // UNLESS otherwise specified!\n //\n // Recognized 'modes':\n // '>': aside note (default for inline notes)\n // ':': end node\n // '=': section note (default for regular referenced notes)\n //\n // (Also note https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html:\n // our notes look like this: `[^ref]:` while Academic MarkDown references look\n // like this: `[@Belawog2012]` i.e. no '^' in there. Hence these can safely co-exist.)\n //\n const mode_rec = determine_mode(state.src[start + 2], '>'); // default mode is aside ~ sidenote mode.\n if (mode_rec.fromInput) {\n labelStart++;\n }\n const mode = mode_rec.mode;\n\n labelEnd = parseLinkLabel(state, start + 1);\n\n // parser failed to find ']', so it's not a valid note\n if (labelEnd < 0) { return false; }\n\n // We found the end of the link, and know for a fact it's a valid link;\n // so all that's left to do is to call tokenizer.\n //\n if (!silent) {\n // WARNING: claim our footnote slot for there MAY be nested footnotes\n // discovered in the next inline.parse() call below!\n const infoRec = obtain_footnote_info_slot(state.env, null, true);\n infoRec.mode = mode;\n infoRec.count++;\n\n token = state.push('footnote_ref', '', 0);\n token.meta = {\n id: infoRec.id\n };\n\n state.md.inline.parse(\n state.src.slice(labelStart, labelEnd),\n state.md,\n state.env,\n tokens = []\n );\n\n // Now fill our previously claimed slot:\n infoRec.content = state.src.slice(labelStart, labelEnd);\n infoRec.tokens = tokens;\n\n // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:\n // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the\n // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:\n update_end_of_block_marker(state, infoRec.id);\n\n //md.block.ruler.enable('footnote_mark_end_of_block');\n }\n\n state.pos = labelEnd + 1;\n state.posMax = max;\n return true;\n }\n\n\n\n // Check if this is a valid ffootnote reference label.\n //\n // Also see if there's a label OVERRIDE text or marker ('@') provided.\n //\n // Return the parsed label record.\n function decode_label(label: string, extra_text_is_labelOverride: boolean) {\n if (!label) {\n return null;\n }\n const m = label.match(/^(@?)(\\S+)(?:\\s+(.+))?$/); // label with OPTIONAL override text...\n if (!m) {\n return null;\n }\n assert.ok(m[2].length > 0);\n let extraText = m[3]?.trim();\n // label [output] override?\n let override = null;\n if (m[1]) {\n override = m[2];\n }\n if (extra_text_is_labelOverride && extraText) {\n override = extraText;\n extraText = null;\n }\n\n return {\n label: m[2],\n labelOverride: override,\n extraText\n };\n }\n\n\n\n // Process footnote references with text ([^label ...])\n function footnote_ref_with_text(state, silent) {\n let pos,\n footnoteSubId,\n token,\n max = state.posMax,\n start = state.pos;\n\n // should be at least 6 chars - \"[^l x]\"\n if (start + 5 > max) { return false; }\n\n if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }\n\n for (pos = start + 2; pos < max; pos++) {\n if (state.src.charCodeAt(pos) === 0x0A /* linefeed */) { return false; }\n if (state.src.charCodeAt(pos) === 0x5D /* ] */) {\n break;\n }\n }\n\n if (pos === start + 2) { return false; } // no empty footnote labels\n if (pos >= max) { return false; }\n pos++;\n\n const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), false);\n if (!labelInfo || !labelInfo.extraText) { return false; }\n assert.ok(labelInfo.extraText.length > 0);\n\n const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);\n if (labelInfo.labelOverride) {\n infoRec.labelOverride = labelInfo.labelOverride;\n }\n\n if (!silent) {\n footnoteSubId = infoRec.count;\n\n infoRec.count++;\n\n token = state.push('footnote_ref', '', 0);\n token.meta = {\n id: infoRec.id,\n subId: footnoteSubId,\n text: labelInfo.extraText\n };\n\n update_end_of_block_marker(state, infoRec.id);\n\n //md.block.ruler.enable('footnote_mark_end_of_block');\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n }\n\n\n\n // Process footnote references ([^...])\n function footnote_ref(state, silent) {\n let pos,\n footnoteSubId,\n token,\n max = state.posMax,\n start = state.pos;\n\n // should be at least 4 chars - \"[^x]\"\n if (start + 3 > max) { return false; }\n\n if (state.src.charCodeAt(start) !== 0x5B/* [ */) { return false; }\n if (state.src.charCodeAt(start + 1) !== 0x5E/* ^ */) { return false; }\n\n for (pos = start + 2; pos < max; pos++) {\n //if (state.src.charCodeAt(pos) === 0x20) { return false; }\n if (state.src.charCodeAt(pos) === 0x0A) { return false; }\n if (state.src.charCodeAt(pos) === 0x5D /* ] */) {\n break;\n }\n }\n\n if (pos === start + 2) { return false; } // no empty footnote labels\n if (pos >= max) { return false; }\n pos++;\n\n const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), true);\n if (!labelInfo) { return false; }\n assert.ok(!labelInfo.extraText);\n\n const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);\n if (labelInfo.labelOverride) {\n infoRec.labelOverride = labelInfo.labelOverride;\n }\n\n if (!silent) {\n footnoteSubId = infoRec.count;\n\n infoRec.count++;\n\n token = state.push('footnote_ref', '', 0);\n token.meta = {\n id: infoRec.id,\n subId: footnoteSubId\n };\n\n update_end_of_block_marker(state, infoRec.id);\n\n //md.block.ruler.enable('footnote_mark_end_of_block');\n }\n\n state.pos = pos;\n state.posMax = max;\n return true;\n }\n\n\n\n function place_footnote_definitions_at(state, token_idx: number, footnote_id_list, category: string, baseInfo: GenericInfoParameters) {\n if (footnote_id_list.length === 0) {\n return; // nothing to inject...\n }\n\n let inject_tokens = [];\n assert.ok(baseInfo.env.footnotes.list != null);\n const footnote_spec_list = baseInfo.env.footnotes.list;\n\n let token = new state.Token('footnote_block_open', '', 1);\n token.markup = plugin_options.headerFn(category, baseInfo.env, plugin_options);\n token.meta = {\n sectionId: ++baseInfo.env.footnotes.sectionCounter,\n category\n };\n inject_tokens.push(token);\n\n for (const id of footnote_id_list) {\n const fn = footnote_spec_list[id];\n const inject_start_index = inject_tokens.length;\n\n token = new state.Token('footnote_open', '', 1);\n token.meta = {\n id,\n category\n };\n inject_tokens.push(token);\n\n if (fn.label == null) {\n // process an inline footnote text:\n token = new state.Token('paragraph_open', 'p', 1);\n token.block = true;\n inject_tokens.push(token);\n\n token = new state.Token('inline', '', 0);\n token.children = fn.tokens;\n token.content = fn.content;\n inject_tokens.push(token);\n\n token = new state.Token('paragraph_close', 'p', -1);\n token.block = true;\n inject_tokens.push(token);\n } else {\n // process a labeled footnote:\n inject_tokens = inject_tokens.concat(fn.tokens || []);\n }\n\n //let lastParagraph;\n //if (inject_tokens[inject_tokens.length - 1].type === 'paragraph_close') {\n // lastParagraph = inject_tokens.pop();\n //} else {\n // lastParagraph = null;\n //}\n\n const cnt = fn.count;\n assert.ok(cnt >= 0);\n for (let j = 0; j < cnt; j++) {\n token = new state.Token('footnote_anchor', '', 0);\n token.meta = {\n id,\n subId: j,\n backrefCount: cnt,\n category\n };\n inject_tokens.push(token);\n }\n\n //if (lastParagraph) {\n // inject_tokens.push(lastParagraph);\n //}\n\n token = new state.Token('footnote_close', '', -1);\n token.meta = {\n id,\n category\n };\n inject_tokens.push(token);\n }\n\n token = new state.Token('footnote_block_close', '', -1);\n token.meta = {\n category\n };\n inject_tokens.push(token);\n\n state.tokens.splice(token_idx, 0, ...inject_tokens);\n }\n\n function more_footnote_reference_blocks_follow_immediately(tokens, idx) {\n let tok = tokens[idx];\n while (tok && (tok.type === 'footnote_mark_end_of_block' || tok.type === 'footnote_reference_close')) {\n idx++;\n tok = tokens[idx];\n }\n return tok && (tok.type === 'footnote_reference_open');\n }\n\n // Glue footnote tokens into appropriate slots of token stream.\n function footnote_tail(state, startLine, endLine, silent) {\n let i, l, j, t, token, current, currentRefToken,\n insideRef = false,\n refTokens = {};\n\n if (!state.env.footnotes) {\n // no footnotes at all? --> filter out all 'footnote_mark_end_of_block' chunks:\n state.tokens = state.tokens.filter(function (tok, idx) {\n return (tok.type !== 'footnote_mark_end_of_block');\n });\n return;\n }\n\n const idMap = state.env.footnotes.idMap;\n\n const baseInfo: GenericInfoParameters = {\n options: state.md.options,\n env: state.env,\n plugin_options,\n self: this\n };\n\n function footnote_print_comparer(idA, idB) {\n return idMap[idA] - idMap[idB];\n }\n\n\n // Rewrite the tokenstream to place the aside-footnotes and section footnotes where they need to be:\n const footnote_spec_list = state.env.footnotes.list;\n\n // extract the tokens constituting the footnote/sidenote *content* and\n // store that bunch in `refTokens[:]` instead, to be injected back into\n // the tokenstream at the appropriate spots.\n state.tokens = state.tokens.filter(function (tok, idx) {\n switch (tok.type) {\n // filter out 'footnote_mark_end_of_block' tokens which follow BLOCKS that do not contain any\n // footnote/sidenote/endnote references:\n case 'footnote_mark_end_of_block':\n if (!tok.meta) return false;\n if (!tok.meta.footnote_list) return false;\n break;\n\n case 'footnote_reference_open':\n insideRef = true;\n current = [];\n currentRefToken = tok;\n return true;\n\n case 'footnote_reference_close':\n insideRef = false;\n\n const infoRec = footnote_spec_list[tok.meta.id];\n infoRec.tokens = current;\n\n return true;\n }\n if (insideRef) {\n current.push(tok);\n }\n return !insideRef;\n });\n\n\n // execute configured sorting/mapping (`idMap`):\n switch (plugin_options.sortOrder) {\n // 0: first *appearance* in the text\n default:\n case 0:\n // 1: first *reference* in the text\n case 1:\n // 2: *definition* in the text\n case 2:\n // order is specified in the `idMap` already.\n break;\n\n // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)\n case 3:\n case 4:\n // the `idMap[]` array has not been set up and must be produced\n // to turn this into an alphanumerically-by-label sort order, where\n // a `footnoteId` based index will produce the order of appearance.\n const reIdMap = [];\n for (let i = 1; i < footnote_spec_list.length; i++) {\n reIdMap[i - 1] = i;\n }\n reIdMap.sort((idA, idB) => {\n const infoA = footnote_spec_list[idA];\n const infoB = footnote_spec_list[idB];\n assert.ok(infoA);\n assert.ok(infoB);\n\n // is any of these an inline footnote, i.e. without any label yet? Produce a fake label for sorting then!\n //\n // As stated elsewhere: inline section_notes and end_notes will end up among everyone else in this sort order mode.\n assert.ok(infoA.id === idA);\n assert.ok(infoB.id === idB);\n\n // Split a \"sort label\" up into its numerical part and the tail. Note that we don't call\n // it 'tail' but 'label', because we will need to compare the ENTIRE LABEL using string comparison\n // when the numeric leaders are identical, so as to ensure that 'labels' such as `00000` will sort\n // as 'higher' than `000`, both of which will be rated as numerically identical!\n function to_atoms(label) {\n // now extract number or numerical leader part.\n //\n // Only accept OBVIOUS, SIMPLE NUMERIC LEADERS! This is about *legibility*\n // of those numrical leaders, not a pedantic \"what is possibly legally numeric\"\n // challenge. Hence we DO NOT accept leading +/- and only a decimal dot when\n // there's a decimal number BEFORE it, such as in `5.1hack` --> `5.1`, but NOT\n // `.42oz`!\n //\n // Do not use `nmr = +lbl` as that would treat labels such as `0xf4` as hexadecimal numbers,\n // which we DO NOT want to happen.\n const m = label.match(/^\\d+(?:\\.\\d+)?/) || [ 'x' ];\n const nmr = +m[0] || Infinity; // non-numeric labels are rated NUMEICALLY HIGHER than any numerical leader.\n return {\n label,\n number: nmr\n };\n }\n\n const labelA = (plugin_options.sortOrder === 3 ?\n infoA.labelOverride || infoA.label || ('' + infoA.id) :\n plugin_options.mkLabel(infoA.id, infoA, baseInfo)\n );\n const labelB = (plugin_options.sortOrder === 3 ?\n infoB.labelOverride || infoB.label || ('' + infoB.id) :\n plugin_options.mkLabel(infoB.id, infoB, baseInfo)\n );\n const atomA = to_atoms(labelA);\n const atomB = to_atoms(labelB);\n const diff = atomA.number - atomB.number;\n return diff || atomA.label.localeCompare(atomB.label);\n // ^^^^^^^ shorthand for:\n //\n // if (isNaN(diff) || diff === 0) then stringcompare else numeric-difference\n });\n\n // Now turn this into a sort order map:\n for (let prio = 0; prio < reIdMap.length; prio++) {\n const id = reIdMap[prio];\n idMap[id] = prio;\n }\n break;\n }\n\n\n const inject_tokens = [];\n\n // Now go through the token stream and place the sidenotes, section_notes and endnotes where they belong:\n let aside_list;\n let section_list = new Set();\n const section_done_list = new Set(); // once a section_note has been printed, it should never appear again!\n const end_list = new Set();\n const used_list = new Set();\n\n let tokens = state.tokens;\n\n for (i = 0; i < tokens.length; i++) {\n const tok = tokens[i];\n switch (tok.type) {\n case 'footnote_mark_end_of_block':\n // check the gathered list of footnotes referenced in this block:\n // - dump the ones which are sidenotes\n // - mark the ones which are section- or end-notes.\n //\n // Note: make sure we don't produce duplicates in the collect sets.\n {\n aside_list = new Set();\n\n const refd_notes_list = (tok.meta?.footnote_list || []);\n for (const id of refd_notes_list) {\n const footnote = footnote_spec_list[id];\n\n switch (footnote.mode) {\n case '>':\n aside_list.add(id);\n used_list.add(id);\n break;\n\n case '=':\n if (!section_done_list.has(id)) {\n section_list.add(id);\n section_done_list.add(id);\n used_list.add(id);\n }\n break;\n\n default:\n case ':':\n end_list.add(id);\n used_list.add(id);\n break;\n }\n }\n\n const aside_ids = [];\n for (const id of aside_list.values()) {\n aside_ids.push(id);\n }\n aside_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, i + 1, aside_ids, 'aside', baseInfo);\n tokens = state.tokens;\n }\n break;\n\n case 'footnote_reference_close':\n // anywhere a footnote *definition* appeared in the original text is\n // also a place to dump the section_notes gathered to date, so to speak.\n //\n // However, DO detect clusters of footnote definitions and MERGE them\n // together:\n if (more_footnote_reference_blocks_follow_immediately(tokens, i + 1)) {\n continue;\n } else {\n const section_ids = [];\n for (const id of section_list.values()) {\n section_ids.push(id);\n }\n section_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, i + 1, section_ids, 'section', baseInfo);\n tokens = state.tokens;\n\n // and reset the tracking set:\n section_list = new Set();\n }\n break;\n }\n }\n\n // Now process the endnotes:\n {\n const end_ids = [];\n for (const id of end_list.values()) {\n end_ids.push(id);\n }\n end_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, tokens.length, end_ids, 'end', baseInfo);\n tokens = state.tokens;\n }\n\n // Now process the unused footnotes and dump them for diagnostic purposes:\n {\n const unused_ids = [];\n\n for (let i = 1; i < footnote_spec_list.length; i++) {\n const fn = footnote_spec_list[i];\n const id = fn.id;\n if (!used_list.has(id)) {\n console.error(`ERROR: footnote ID ${id} is defined but never used. Footnote will be added as an ERRONEOUS ENDNOTE to the output, so the situation is easy to diagnose!`, Object.assign({}, fn, { tokens: '......' }));\n unused_ids.push(id);\n }\n }\n unused_ids.sort(footnote_print_comparer);\n\n place_footnote_definitions_at(state, tokens.length, unused_ids, 'Error::Unused', baseInfo);\n //tokens = state.tokens;\n }\n\n // Update state_block too as we have rewritten & REPLACED the token array earlier in this call:\n // the reference `state.env.state_block.tokens` is still pointing to the OLD token array!\n state.env.state_block.tokens = state.tokens;\n }\n\n\n\n\n // attach ourselves to the start of block handling too\n md.block.ruler.before('table', 'footnote_mark_end_of_block', footnote_mark_end_of_block);\n\n md.block.ruler.before('reference', 'footnote_def', footnote_def, { alt: [ 'paragraph', 'reference' ] });\n md.inline.ruler.after('image', 'footnote_inline', footnote_inline);\n md.inline.ruler.after('footnote_inline', 'footnote_ref_with_text', footnote_ref_with_text);\n md.inline.ruler.after('footnote_ref_with_text', 'footnote_ref', footnote_ref);\n md.core.ruler.after('inline', 'footnote_tail', footnote_tail);\n}\n"],"names":["anchorFnDefault","n","excludeSubId","baseInfo","env","assert","ok","prefix","docId","length","captionFnDefault","headerFnDefault","category","determine_footnote_symbol","idx","info","plugin_options","label","labelOverride","numberSequence","len","slot","Number","isFinite","delta","dupli","remainder","core","str","i","bunched_mode_classes","generateFootnoteRefHtml","id","caption","refId","bunched_footnote_ref_mode","renderInfo","localOverride","tokens","meta","text","refCombiner","generateFootnoteSectionStartHtml","tok","header","markup","replace","sectionId","options","xhtmlOut","generateFootnoteSectionEndHtml","generateFootnoteStartHtml","generateFootnoteEndHtml","generateFootnoteBackRefHtml","subId","backrefCount","default_plugin_options","anchorFn","captionFn","headerFn","mkLabel","modeOverride","sortOrder","footnote_plugin","md","parseLinkLabel","helpers","isSpace","utils","Object","assign","determine_mode","mode","default_mode","override","includes","fromInput","render_footnote_n","mark","render_footnote_mark","token","footnotes","list","render_footnote_anchor_name","render_footnote_anchor_nameRef","render_footnote_caption","render_footnote_ref","self","next_token","next_token_meta","type","render_footnote_block_open","render_footnote_block_close","render_footnote_reference_open","render_footnote_reference_close","render_footnote_mark_end_of_block","render_footnote_open","render_footnote_close","render_footnote_anchor_backref","renderer","rules","footnote_ref","footnote_block_open","footnote_block_close","footnote_reference_open","footnote_reference_close","footnote_mark_end_of_block","footnote_open","footnote_close","footnote_anchor","obtain_footnote_info_slot","at_definition","parentState","refs","idMap","idMapCounter","sectionCounter","footnoteId","infoRec","Math","max","content","count","find_end_of_block_marker","state","startIndex","Token","hidden","push","update_end_of_block_marker","parentIndex","parentTokenIndex","markerTokenIndex","footnote_list","startLine","endLine","silent","footnote_def","oldBMark","oldTShift","oldSCount","oldParentType","pos","initial","offset","ch","posAfterColon","start","bMarks","tShift","eMarks","src","charCodeAt","labelEnd","mode_rec","labelInfo","decode_label","slice","extraText","sCount","parentType","blkIndent","block","tokenize","footnote_inline","labelStart","posMax","inline","parse","extra_text_is_labelOverride","m","match","trim","footnote_ref_with_text","footnoteSubId","place_footnote_definitions_at","token_idx","footnote_id_list","inject_tokens","footnote_spec_list","fn","children","concat","cnt","j","splice","more_footnote_reference_blocks_follow_immediately","footnote_tail","current","insideRef","filter","footnote_print_comparer","idA","idB","reIdMap","sort","infoA","infoB","to_atoms","nmr","Infinity","number","labelA","labelB","atomA","atomB","diff","localeCompare","prio","aside_list","section_list","Set","section_done_list","end_list","used_list","refd_notes_list","footnote","add","has","aside_ids","values","section_ids","end_ids","unused_ids","console","error","state_block","ruler","before","alt","after"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/markdownItFootnote.js b/dist/markdownItFootnote.modern.js
similarity index 100%
rename from dist/markdownItFootnote.js
rename to dist/markdownItFootnote.modern.js
diff --git a/dist/markdownItFootnote.js.map b/dist/markdownItFootnote.modern.js.map
similarity index 100%
rename from dist/markdownItFootnote.js.map
rename to dist/markdownItFootnote.modern.js.map
diff --git a/dist/markdownItFootnote.umd.js b/dist/markdownItFootnote.umd.js
new file mode 100644
index 0000000..e8ce0a7
--- /dev/null
+++ b/dist/markdownItFootnote.umd.js
@@ -0,0 +1,1304 @@
+/*! markdown-it-footnote 3.0.3-10 https://github.com//GerHobbelt/markdown-it-footnote @license MIT */
+
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('assert')) :
+ typeof define === 'function' && define.amd ? define(['assert'], factory) :
+ (global = global || self, global.markdownitFootnote = factory(global.assert));
+}(this, (function (assert) { 'use strict';
+
+ // Process footnotes
+
+ function anchorFnDefault(n, excludeSubId, baseInfo) {
+ const env = baseInfo.env;
+ assert.strict.ok(env != null);
+ let prefix = '';
+
+ if (typeof env.docId === 'string' && env.docId.length > 0) {
+ prefix = '-' + env.docId + '-';
+ }
+
+ return prefix + n;
+ }
+
+ function captionFnDefault(n, baseInfo) {
+ //return '[' + n + ']';
+ return '' + n;
+ }
+
+ function headerFnDefault(category, baseInfo) {
+ switch (category) {
+ case 'aside':
+ return 'Side Notes';
+
+ case 'section':
+ return 'Section Notes';
+
+ case 'end':
+ return 'Endnotes';
+
+ default:
+ // used for error category, e.g. 'Error::Unused'
+ return category;
+ }
+ }
+
+ function determine_footnote_symbol(idx, info, baseInfo) {
+ const plugin_options = baseInfo.plugin_options;
+ assert.strict.ok(plugin_options != null); // rule to construct the printed label:
+ //
+ // mark = labelOverride /* || info.label */ || idx;
+
+ const label = info.labelOverride;
+
+ if (label) {
+ return label;
+ }
+
+ if (plugin_options.numberSequence == null || plugin_options.numberSequence.length === 0) {
+ return '' + idx;
+ }
+
+ const len = plugin_options.numberSequence.length;
+
+ if (idx >= len) {
+ // is last slot numeric or alphanumerically?
+ const slot = plugin_options.numberSequence[len - 1];
+
+ if (Number.isFinite(slot)) {
+ const delta = idx - len + 1;
+ return '' + (slot + delta);
+ } // non-numerical last slot --> duplicate, triplicate, etc.
+
+
+ const dupli = idx / len | 0; // = int(x mod N)
+
+ const remainder = idx % len;
+ const core = plugin_options.numberSequence[remainder];
+ let str = '' + core;
+
+ for (let i = 1; i < dupli; i++) {
+ str += core;
+ }
+
+ return str;
+ }
+
+ return '' + plugin_options.numberSequence[idx];
+ }
+
+ const bunched_mode_classes = ['', 'footnote-bunched-ref-ref', 'footnote-bunched-ref-text'];
+
+ function generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo) {
+ let localOverride = renderInfo.tokens[renderInfo.idx].meta.text;
+
+ if (localOverride) {
+ localOverride = `${localOverride}`;
+ }
+
+ return `${localOverride || ''}${caption}` + (bunched_footnote_ref_mode !== 0 ? `${renderInfo.plugin_options.refCombiner || ''}` : '');
+ }
+
+ function generateFootnoteSectionStartHtml(renderInfo) {
+ const tok = renderInfo.tokens[renderInfo.idx];
+ assert.strict.ok(tok != null);
+ assert.strict.ok(tok.meta != null);
+ const header = tok.markup ? `
${tok.markup}
` : '';
+ let category = tok.meta.category;
+ assert.strict.ok(category.length > 0); // `category` can contain CSS class illegal characters, e.g. when category = 'Error::Unused':
+
+ category = category.replace(/[^a-zA-Z0-9_-]+/g, '_');
+ return `\n';
+ }
+
+ function generateFootnoteStartHtml(id, caption, renderInfo) {
+ // allow both a JavaWScript --> CSS approach via `data-footnote-caption`
+ // and a classic CSS approach while a display:inline-block SUP presenting
+ // the LI 'button' instead:
+ return `
\n';
+ }
+
+ function generateFootnoteBackRefHtml(id, refId, renderInfo) {
+ const tok = renderInfo.tokens[renderInfo.idx];
+ assert.strict.ok(tok != null);
+ assert.strict.ok(tok.meta != null);
+ /* ↩ with escape code to prevent display as Apple Emoji on iOS */
+
+ return ` \u21a9\uFE0E`;
+ }
+
+ const default_plugin_options = {
+ // atDocumentEnd: false, -- obsoleted option of the original plugin
+ anchorFn: anchorFnDefault,
+ captionFn: captionFnDefault,
+ headerFn: headerFnDefault,
+ mkLabel: determine_footnote_symbol,
+ // see also https://www.editage.com/insights/footnotes-in-tables-part-1-choice-of-footnote-markers-and-their-sequence
+ // why asterisk/star is not part of the default footnote marker sequence.
+ //
+ // For similar reasons, we DO NOT include the section § symbol in this list.
+ //
+ // when numberSequnce is NULL/empty, a regular numerical numbering is assumed.
+ // Otherwise, the array is indexed; when there are more footnotes than entries in
+ // the numberSequence array, the entries are re-used, but doubled/trippled, etc.
+ //
+ // When the indexing in this array hits a NUMERIC value (as last entry), any higher
+ // footnotes are NUMBERED starting at that number.
+ //
+ // NOTE: as we can reference the same footnote from multiple spots, we do not depend
+ // on CSS counter() approaches by default, but providee this mechanism in the plugin
+ // code itself.
+ numberSequence: ['†', '‡', '††', '‡‡', '¶', 1],
+ // Overrides the footnode mode when set to one of the following:
+ //
+ // Recognized 'modes':
+ // '>': aside note (default for inline notes)
+ // ':': end node
+ // '=': section note (default for regular referenced notes)
+ //
+ // Also accepts these keywords: 'aside', 'section', 'end'
+ //
+ modeOverride: null,
+ // list section notes and endnotes in order of:
+ //
+ // 0: first *appearance* in the text
+ // 1: first *reference* in the text
+ // 2: *definition* in the text
+ // 3: sorted alphanumerically by *coded* label,
+ // i.e. *numeric* labels are sorted in numeric order (so `10` comes AFTER `7`!),
+ // while all others are sorted using `String.localeCompare()`. When labels have
+ // a *numeric leading*, e.g. `71geo` --> `71`, that part is sorted numerically first.
+ //
+ // Here 'coded label' means the label constructed from the reference ids and label overrides
+ // as used in the markdown source, using the expression
+ // labelOverride || reference || id
+ // which gives for these examples (assuming them to be the only definitions in your input):
+ // [^refA]: ... --> null || 'refA' || 1
+ // [^refB LBL]: ... --> 'LBL' || 'refB' || 2
+ // 4: sorted alphanumerically by *printed* label
+ // which is like mode 3, but now for the label as will be seen in the *output*!
+ sortOrder: 4,
+ // what to print between bunched-together footnote references, i.e. the '+' in `blabla¹⁺²`
+ refCombiner: ','
+ };
+ function footnote_plugin(md, plugin_options) {
+ const parseLinkLabel = md.helpers.parseLinkLabel,
+ isSpace = md.utils.isSpace;
+ plugin_options = Object.assign({}, default_plugin_options, plugin_options);
+
+ function determine_mode(mode, default_mode) {
+ let override = null;
+
+ if (plugin_options.modeOverride) {
+
+ if ('>:='.includes(plugin_options.modeOverride)) {
+ override = plugin_options.modeOverride;
+ }
+ }
+
+ if ('>:='.includes(mode)) {
+ return {
+ mode: override || mode,
+ fromInput: true
+ };
+ }
+
+ return {
+ mode: override || default_mode,
+ fromInput: false
+ };
+ }
+
+ function render_footnote_n(tokens, idx, excludeSubId) {
+ const mark = tokens[idx].meta.id;
+ assert.strict.ok(Number.isFinite(mark));
+ assert.strict.ok(mark > 0);
+ let n = '' + mark; // = mark.toString();
+
+ assert.strict.ok(n.length > 0);
+
+ if (!excludeSubId && tokens[idx].meta.subId > 0) {
+ n += '-' + tokens[idx].meta.subId;
+ }
+
+ return n;
+ }
+
+ function render_footnote_mark(renderInfo) {
+ const token = renderInfo.tokens[renderInfo.idx];
+ assert.strict.ok(token != null);
+ assert.strict.ok(renderInfo.env.footnotes != null);
+ assert.strict.ok(renderInfo.env.footnotes.list != null);
+ const info = renderInfo.env.footnotes.list[token.meta.id];
+ assert.strict.ok(info != null);
+ const mark = plugin_options.mkLabel(token.meta.id, info, renderInfo);
+ assert.strict.ok(mark.length > 0);
+ return mark;
+ }
+
+ function render_footnote_anchor_name(renderInfo) {
+ const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, true);
+ return plugin_options.anchorFn(n, true, renderInfo);
+ }
+
+ function render_footnote_anchor_nameRef(renderInfo) {
+ const n = render_footnote_n(renderInfo.tokens, renderInfo.idx, false);
+ return plugin_options.anchorFn(n, false, renderInfo);
+ }
+
+ function render_footnote_caption(renderInfo) {
+ const n = render_footnote_mark(renderInfo);
+ return plugin_options.captionFn(n, renderInfo);
+ }
+
+ function render_footnote_ref(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const id = render_footnote_anchor_name(renderInfo);
+ const caption = render_footnote_caption(renderInfo);
+ const refId = render_footnote_anchor_nameRef(renderInfo); // check if multiple footnote references are bunched together:
+ // IFF they are, we should separate them with commas.
+ //
+ // Exception: when next token has an extra text (`meta.text`) the
+ // bunching together is not a problem as them the output will render
+ // like this: `bla1text2`, ergo a look
+ // like this: `bla¹text²` instead of bunched footnotes references ¹ and ²
+ // that would (without the extra comma injection) look like `bla¹²` instead
+ // of `x¹⁺²` (here '+' instead of ',' comma, but you get the idea -- there's no
+ // Unicode superscript-comma so that's why I used unicode superscript-plus
+ // in this 'ascii art' example).
+ //
+
+ const next_token = tokens[idx + 1] || {};
+ const next_token_meta = next_token.meta || {};
+ const bunched_footnote_ref_mode = next_token.type === 'footnote_ref' ? !next_token_meta.text ? 1 : 2 : 0;
+ return generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo);
+ }
+
+ function render_footnote_block_open(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ return generateFootnoteSectionStartHtml(renderInfo);
+ }
+
+ function render_footnote_block_close(tokens, idx, options, env, self) {
+ return generateFootnoteSectionEndHtml();
+ }
+
+ function render_footnote_reference_open(tokens, idx, options, env, self) {
+ return '';
+ }
+
+ function render_footnote_reference_close() {
+ return '';
+ }
+
+ function render_footnote_mark_end_of_block() {
+ return '';
+ }
+
+ function render_footnote_open(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const id = render_footnote_anchor_name(renderInfo);
+ const caption = render_footnote_caption(renderInfo); // allow both a JavaScript --> CSS approach via `data-footnote-caption`
+ // and a classic CSS approach while a display:inline-block SUP presenting
+ // the LI 'button' instead:
+
+ return generateFootnoteStartHtml(id, caption);
+ }
+
+ function render_footnote_close(tokens, idx, options, env, self) {
+ return generateFootnoteEndHtml();
+ }
+
+ function render_footnote_anchor_backref(tokens, idx, options, env, self) {
+ const renderInfo = {
+ tokens,
+ idx,
+ options,
+ env,
+ plugin_options,
+ self
+ };
+ const tok = tokens[idx];
+ assert.strict.ok(tok != null);
+ assert.strict.ok(tok.meta != null);
+ const id = render_footnote_anchor_name(renderInfo);
+ let refId = render_footnote_n(tokens, idx, false);
+ refId = plugin_options.anchorFn(refId, false, renderInfo);
+ return generateFootnoteBackRefHtml(id, refId, renderInfo);
+ }
+
+ md.renderer.rules.footnote_ref = render_footnote_ref;
+ md.renderer.rules.footnote_block_open = render_footnote_block_open;
+ md.renderer.rules.footnote_block_close = render_footnote_block_close;
+ md.renderer.rules.footnote_reference_open = render_footnote_reference_open;
+ md.renderer.rules.footnote_reference_close = render_footnote_reference_close;
+ md.renderer.rules.footnote_mark_end_of_block = render_footnote_mark_end_of_block;
+ md.renderer.rules.footnote_open = render_footnote_open;
+ md.renderer.rules.footnote_close = render_footnote_close;
+ md.renderer.rules.footnote_anchor = render_footnote_anchor_backref;
+
+ function obtain_footnote_info_slot(env, label, at_definition) {
+ // inline blocks have their own *child* environment in markdown-it v10+.
+ // As the footnotes must live beyond the lifetime of the inline block env,
+ // we must patch them into the `parentState.env` for the footnote_tail
+ // handler to be able to access them afterwards!
+ while (env.parentState) {
+ env = env.parentState.env;
+ assert.strict.ok(env != null);
+ }
+
+ if (!env.footnotes) {
+ env.footnotes = {
+ // map label tto ID:
+ refs: {},
+ // store footnote info indexed by ID
+ list: [],
+ // remap ID to re-ordered ID (determines placement order for section notes and endnotes)
+ idMap: [0],
+ idMapCounter: 0,
+ // and a counter for the generated sections (including asides); see the demo/test which
+ // uses the generated `#fnsection-DDD` identifiers to hack/fix the styling, for example.
+ sectionCounter: 0
+ };
+ } // When label is NULL, this is a request from in INLINE NOTE.
+ // NOTE: IDs are index numbers, BUT they start at 1 instead of 0 to make life easier in check code:
+
+
+ let footnoteId;
+ let infoRec; // label as index: prepend ':' to avoid conflict with Object.prototype members
+
+ if (label == null || !env.footnotes.refs[':' + label]) {
+ footnoteId = Math.max(1, env.footnotes.list.length);
+ infoRec = {
+ id: footnoteId,
+ label,
+ labelOverride: null,
+ mode: null,
+ content: null,
+ tokens: null,
+ count: 0
+ };
+ env.footnotes.list[footnoteId] = infoRec;
+
+ if (label != null) {
+ env.footnotes.refs[':' + label] = footnoteId;
+ }
+ } else {
+ footnoteId = env.footnotes.refs[':' + label];
+ infoRec = env.footnotes.list[footnoteId];
+ assert.strict.ok(!!infoRec, 'expects non-NULL footnote info record');
+ }
+
+ const idMap = env.footnotes.idMap; // now check if the idMap[] has been set up already as well. This depends on
+ // when WE are invoked (`at_definition`) and the configured `options.sortOrder`:
+
+ switch (plugin_options.sortOrder) {
+ // 0: first *appearance* in the text
+ default:
+ case 0:
+ // basically, this means: order as-is
+ if (!idMap[footnoteId]) {
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 1: first *reference* in the text
+
+ case 1:
+ if (!at_definition && !idMap[footnoteId]) {
+ // first reference is now!
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 2: *definition* in the text
+
+ case 2:
+ if (at_definition && !idMap[footnoteId]) {
+ // definition is now!
+ idMap[footnoteId] = ++env.footnotes.idMapCounter;
+ }
+
+ break;
+ // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)
+
+ case 3:
+ case 4:
+ // just note the footnoteId now; this must be re-ordered later when we have collected all footnotes.
+ //
+ // set it up when we get there...
+ break;
+ }
+
+ return infoRec;
+ }
+
+ function find_end_of_block_marker(state, startIndex) {
+ let idx, len;
+ const tokens = state.tokens;
+
+ for (idx = startIndex, len = tokens.length; idx < len; idx++) {
+ if (tokens[idx].type === 'footnote_mark_end_of_block') {
+ return idx;
+ }
+ } // Punch a slot into the token stream (at the very end)
+ // for consistency with footnote_mark_end_of_block():
+
+
+ const token = new state.Token('footnote_mark_end_of_block', '', 0);
+ token.hidden = true;
+ tokens.push(token);
+ return tokens.length - 1;
+ }
+
+ function update_end_of_block_marker(state, footnoteId) {
+ // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:
+ // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the
+ // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:
+ const parentState = state.env.parentState;
+ const parentIndex = state.env.parentTokenIndex;
+ const markerTokenIndex = find_end_of_block_marker(parentState, parentIndex + 1);
+ const token = parentState.tokens[markerTokenIndex];
+
+ if (!token.meta) {
+ token.meta = {
+ footnote_list: []
+ };
+ }
+
+ token.meta.footnote_list.push(footnoteId);
+ } // Mark end of paragraph/heading/whatever BLOCK (or rather: START of the next block!)
+
+
+ function footnote_mark_end_of_block(state, startLine, endLine, silent) {
+ if (!silent && state.tokens.length > 0) {
+ const token = state.push('footnote_mark_end_of_block', '', 0);
+ token.hidden = true;
+ }
+
+ return false;
+ } // Process footnote block definition
+
+
+ function footnote_def(state, startLine, endLine, silent) {
+ let oldBMark,
+ oldTShift,
+ oldSCount,
+ oldParentType,
+ pos,
+ token,
+ initial,
+ offset,
+ ch,
+ posAfterColon,
+ start = state.bMarks[startLine] + state.tShift[startLine],
+ max = state.eMarks[startLine]; // line should be at least 6 chars - "[^x]: " or "[^x]:> "
+
+ if (start + 5 > 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) === 0x0A
+ /* LF */
+ ) {
+ return false;
+ }
+
+ if (state.src.charCodeAt(pos) === 0x5D
+ /* ] */
+ ) {
+ break;
+ }
+ }
+
+ const labelEnd = pos;
+
+ if (pos === start + 2) {
+ return false;
+ } // no empty footnote labels
+
+
+ if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x3A
+ /* : */
+ ) {
+ return false;
+ }
+
+ const mode_rec = determine_mode(state.src[pos + 1], '='); // default mode is section_note mode.
+
+ if (mode_rec.fromInput) {
+ pos++;
+ }
+
+ const mode = mode_rec.mode;
+
+ if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 0x20
+ /* space */
+ ) {
+ return false;
+ }
+
+ if (silent) {
+ return true;
+ }
+
+ pos++;
+ const labelInfo = decode_label(state.src.slice(start + 2, labelEnd), true);
+
+ if (!labelInfo) {
+ return false;
+ }
+
+ assert.strict.ok(!labelInfo.extraText); // Now see if we already have a footnote ID for this footnote label:
+ // fetch it if we have one and otherwise produce a new one so everyone
+ // can use this from now on.
+ //
+ // This scenario is possible when the footnote *definition* comes BEFORE
+ // the first actual footnote *use* (*reference*). This is UNUSUAL when people
+ // write texts, but it is *not impossible*, particularly now that we have
+ // specified-by-design that endnotes can be marked as such (`[^label]:: note text`)
+ // and freely mixed with sidenotes (`[^label]:> note text`) and section
+ // notes (`[^label]:= note text` (explicit mode) or `[^label]: note text`
+ // (implicit mode)), where *section notes* will placed at the spot in the text
+ // flow where they were *defined*. Again, highly irregular, BUT someone MAY
+ // feel the need to place some section note *definitions* ABOVE their first
+ // use point.
+ //
+
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, true);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ infoRec.mode = mode;
+ infoRec.content = state.src.slice(pos, max);
+ token = state.push('footnote_reference_open', '', 1);
+ token.meta = {
+ id: infoRec.id
+ };
+ token.hidden = true;
+ oldBMark = state.bMarks[startLine];
+ oldTShift = state.tShift[startLine];
+ oldSCount = state.sCount[startLine];
+ oldParentType = state.parentType;
+ posAfterColon = pos;
+ initial = offset = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);
+
+ while (pos < max) {
+ ch = state.src.charCodeAt(pos);
+
+ if (isSpace(ch)) {
+ if (ch === 0x09) {
+ offset += 4 - offset % 4;
+ } else {
+ offset++;
+ }
+ } else {
+ break;
+ }
+
+ pos++;
+ }
+
+ state.tShift[startLine] = pos - posAfterColon;
+ state.sCount[startLine] = offset - initial;
+ state.bMarks[startLine] = posAfterColon;
+ state.blkIndent += 4;
+ state.parentType = 'footnote';
+
+ if (state.sCount[startLine] < state.blkIndent) {
+ state.sCount[startLine] += state.blkIndent;
+ }
+
+ state.md.block.tokenize(state, startLine, endLine, true);
+ state.parentType = oldParentType;
+ state.blkIndent -= 4;
+ state.tShift[startLine] = oldTShift;
+ state.sCount[startLine] = oldSCount;
+ state.bMarks[startLine] = oldBMark;
+ token = state.push('footnote_reference_close', '', -1);
+ token.meta = {
+ id: infoRec.id
+ };
+ return true;
+ } // Process inline footnotes (^[...] or ^[>...])
+
+
+ function footnote_inline(state, silent) {
+ let labelStart,
+ labelEnd,
+ token,
+ tokens,
+ 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; // NOTE: inline notes are automatically considered to be ASIDE notes,
+ // UNLESS otherwise specified!
+ //
+ // Recognized 'modes':
+ // '>': aside note (default for inline notes)
+ // ':': end node
+ // '=': section note (default for regular referenced notes)
+ //
+ // (Also note https://v4.chriskrycho.com/2015/academic-markdown-and-citations.html:
+ // our notes look like this: `[^ref]:` while Academic MarkDown references look
+ // like this: `[@Belawog2012]` i.e. no '^' in there. Hence these can safely co-exist.)
+ //
+
+ const mode_rec = determine_mode(state.src[start + 2], '>'); // default mode is aside ~ sidenote mode.
+
+ if (mode_rec.fromInput) {
+ labelStart++;
+ }
+
+ const mode = mode_rec.mode;
+ 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) {
+ // WARNING: claim our footnote slot for there MAY be nested footnotes
+ // discovered in the next inline.parse() call below!
+ const infoRec = obtain_footnote_info_slot(state.env, null, true);
+ infoRec.mode = mode;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id
+ };
+ state.md.inline.parse(state.src.slice(labelStart, labelEnd), state.md, state.env, tokens = []); // Now fill our previously claimed slot:
+
+ infoRec.content = state.src.slice(labelStart, labelEnd);
+ infoRec.tokens = tokens; // inject marker into parent = block level token stream to announce the advent of an (inline) footnote:
+ // because the markdown_it code uses a for() loop to go through the parent nodes while parsing the
+ // 'inline' chunks, we CANNOT safely inject a marker BEFORE the chunk, only AFTERWARDS:
+
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = labelEnd + 1;
+ state.posMax = max;
+ return true;
+ } // Check if this is a valid ffootnote reference label.
+ //
+ // Also see if there's a label OVERRIDE text or marker ('@') provided.
+ //
+ // Return the parsed label record.
+
+
+ function decode_label(label, extra_text_is_labelOverride) {
+ var _m$;
+
+ if (!label) {
+ return null;
+ }
+
+ const m = label.match(/^(@?)(\S+)(?:\s+(.+))?$/); // label with OPTIONAL override text...
+
+ if (!m) {
+ return null;
+ }
+
+ assert.strict.ok(m[2].length > 0);
+ let extraText = (_m$ = m[3]) == null ? void 0 : _m$.trim(); // label [output] override?
+
+ let override = null;
+
+ if (m[1]) {
+ override = m[2];
+ }
+
+ if (extra_text_is_labelOverride && extraText) {
+ override = extraText;
+ extraText = null;
+ }
+
+ return {
+ label: m[2],
+ labelOverride: override,
+ extraText
+ };
+ } // Process footnote references with text ([^label ...])
+
+
+ function footnote_ref_with_text(state, silent) {
+ let pos,
+ footnoteSubId,
+ token,
+ max = state.posMax,
+ start = state.pos; // should be at least 6 chars - "[^l x]"
+
+ if (start + 5 > 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) === 0x0A
+ /* linefeed */
+ ) {
+ 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++;
+ const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), false);
+
+ if (!labelInfo || !labelInfo.extraText) {
+ return false;
+ }
+
+ assert.strict.ok(labelInfo.extraText.length > 0);
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ if (!silent) {
+ footnoteSubId = infoRec.count;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id,
+ subId: footnoteSubId,
+ text: labelInfo.extraText
+ };
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = pos;
+ state.posMax = max;
+ return true;
+ } // Process footnote references ([^...])
+
+
+ function footnote_ref(state, silent) {
+ let pos,
+ footnoteSubId,
+ token,
+ max = state.posMax,
+ start = state.pos; // should be at least 4 chars - "[^x]"
+
+ if (start + 3 > 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) === 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++;
+ const labelInfo = decode_label(state.src.slice(start + 2, pos - 1), true);
+
+ if (!labelInfo) {
+ return false;
+ }
+
+ assert.strict.ok(!labelInfo.extraText);
+ const infoRec = obtain_footnote_info_slot(state.env, labelInfo.label, false);
+
+ if (labelInfo.labelOverride) {
+ infoRec.labelOverride = labelInfo.labelOverride;
+ }
+
+ if (!silent) {
+ footnoteSubId = infoRec.count;
+ infoRec.count++;
+ token = state.push('footnote_ref', '', 0);
+ token.meta = {
+ id: infoRec.id,
+ subId: footnoteSubId
+ };
+ update_end_of_block_marker(state, infoRec.id); //md.block.ruler.enable('footnote_mark_end_of_block');
+ }
+
+ state.pos = pos;
+ state.posMax = max;
+ return true;
+ }
+
+ function place_footnote_definitions_at(state, token_idx, footnote_id_list, category, baseInfo) {
+ if (footnote_id_list.length === 0) {
+ return; // nothing to inject...
+ }
+
+ let inject_tokens = [];
+ assert.strict.ok(baseInfo.env.footnotes.list != null);
+ const footnote_spec_list = baseInfo.env.footnotes.list;
+ let token = new state.Token('footnote_block_open', '', 1);
+ token.markup = plugin_options.headerFn(category, baseInfo.env, plugin_options);
+ token.meta = {
+ sectionId: ++baseInfo.env.footnotes.sectionCounter,
+ category
+ };
+ inject_tokens.push(token);
+
+ for (const id of footnote_id_list) {
+ const fn = footnote_spec_list[id];
+ token = new state.Token('footnote_open', '', 1);
+ token.meta = {
+ id,
+ category
+ };
+ inject_tokens.push(token);
+
+ if (fn.label == null) {
+ // process an inline footnote text:
+ token = new state.Token('paragraph_open', 'p', 1);
+ token.block = true;
+ inject_tokens.push(token);
+ token = new state.Token('inline', '', 0);
+ token.children = fn.tokens;
+ token.content = fn.content;
+ inject_tokens.push(token);
+ token = new state.Token('paragraph_close', 'p', -1);
+ token.block = true;
+ inject_tokens.push(token);
+ } else {
+ // process a labeled footnote:
+ inject_tokens = inject_tokens.concat(fn.tokens || []);
+ } //let lastParagraph;
+ //if (inject_tokens[inject_tokens.length - 1].type === 'paragraph_close') {
+ // lastParagraph = inject_tokens.pop();
+ //} else {
+ // lastParagraph = null;
+ //}
+
+
+ const cnt = fn.count;
+ assert.strict.ok(cnt >= 0);
+
+ for (let j = 0; j < cnt; j++) {
+ token = new state.Token('footnote_anchor', '', 0);
+ token.meta = {
+ id,
+ subId: j,
+ backrefCount: cnt,
+ category
+ };
+ inject_tokens.push(token);
+ } //if (lastParagraph) {
+ // inject_tokens.push(lastParagraph);
+ //}
+
+
+ token = new state.Token('footnote_close', '', -1);
+ token.meta = {
+ id,
+ category
+ };
+ inject_tokens.push(token);
+ }
+
+ token = new state.Token('footnote_block_close', '', -1);
+ token.meta = {
+ category
+ };
+ inject_tokens.push(token);
+ state.tokens.splice(token_idx, 0, ...inject_tokens);
+ }
+
+ function more_footnote_reference_blocks_follow_immediately(tokens, idx) {
+ let tok = tokens[idx];
+
+ while (tok && (tok.type === 'footnote_mark_end_of_block' || tok.type === 'footnote_reference_close')) {
+ idx++;
+ tok = tokens[idx];
+ }
+
+ return tok && tok.type === 'footnote_reference_open';
+ } // Glue footnote tokens into appropriate slots of token stream.
+
+
+ function footnote_tail(state, startLine, endLine, silent) {
+ let i,
+ current,
+ insideRef = false;
+
+ if (!state.env.footnotes) {
+ // no footnotes at all? --> filter out all 'footnote_mark_end_of_block' chunks:
+ state.tokens = state.tokens.filter(function (tok, idx) {
+ return tok.type !== 'footnote_mark_end_of_block';
+ });
+ return;
+ }
+
+ const idMap = state.env.footnotes.idMap;
+ const baseInfo = {
+ options: state.md.options,
+ env: state.env,
+ plugin_options,
+ self: this
+ };
+
+ function footnote_print_comparer(idA, idB) {
+ return idMap[idA] - idMap[idB];
+ } // Rewrite the tokenstream to place the aside-footnotes and section footnotes where they need to be:
+
+
+ const footnote_spec_list = state.env.footnotes.list; // extract the tokens constituting the footnote/sidenote *content* and
+ // store that bunch in `refTokens[:]` instead, to be injected back into
+ // the tokenstream at the appropriate spots.
+
+ state.tokens = state.tokens.filter(function (tok, idx) {
+ switch (tok.type) {
+ // filter out 'footnote_mark_end_of_block' tokens which follow BLOCKS that do not contain any
+ // footnote/sidenote/endnote references:
+ case 'footnote_mark_end_of_block':
+ if (!tok.meta) return false;
+ if (!tok.meta.footnote_list) return false;
+ break;
+
+ case 'footnote_reference_open':
+ insideRef = true;
+ current = [];
+ return true;
+
+ case 'footnote_reference_close':
+ insideRef = false;
+ const infoRec = footnote_spec_list[tok.meta.id];
+ infoRec.tokens = current;
+ return true;
+ }
+
+ if (insideRef) {
+ current.push(tok);
+ }
+
+ return !insideRef;
+ }); // execute configured sorting/mapping (`idMap`):
+
+ switch (plugin_options.sortOrder) {
+ // 0: first *appearance* in the text
+ default:
+ case 0: // 1: first *reference* in the text
+
+ case 1: // 2: *definition* in the text
+
+ case 2:
+ // order is specified in the `idMap` already.
+ break;
+ // 3: sorted alphanumerically by label (inline footnotes will end up at the top, before all other notes)
+
+ case 3:
+ case 4:
+ // the `idMap[]` array has not been set up and must be produced
+ // to turn this into an alphanumerically-by-label sort order, where
+ // a `footnoteId` based index will produce the order of appearance.
+ const reIdMap = [];
+
+ for (let i = 1; i < footnote_spec_list.length; i++) {
+ reIdMap[i - 1] = i;
+ }
+
+ reIdMap.sort((idA, idB) => {
+ const infoA = footnote_spec_list[idA];
+ const infoB = footnote_spec_list[idB];
+ assert.strict.ok(infoA);
+ assert.strict.ok(infoB); // is any of these an inline footnote, i.e. without any label yet? Produce a fake label for sorting then!
+ //
+ // As stated elsewhere: inline section_notes and end_notes will end up among everyone else in this sort order mode.
+
+ assert.strict.ok(infoA.id === idA);
+ assert.strict.ok(infoB.id === idB); // Split a "sort label" up into its numerical part and the tail. Note that we don't call
+ // it 'tail' but 'label', because we will need to compare the ENTIRE LABEL using string comparison
+ // when the numeric leaders are identical, so as to ensure that 'labels' such as `00000` will sort
+ // as 'higher' than `000`, both of which will be rated as numerically identical!
+
+ function to_atoms(label) {
+ // now extract number or numerical leader part.
+ //
+ // Only accept OBVIOUS, SIMPLE NUMERIC LEADERS! This is about *legibility*
+ // of those numrical leaders, not a pedantic "what is possibly legally numeric"
+ // challenge. Hence we DO NOT accept leading +/- and only a decimal dot when
+ // there's a decimal number BEFORE it, such as in `5.1hack` --> `5.1`, but NOT
+ // `.42oz`!
+ //
+ // Do not use `nmr = +lbl` as that would treat labels such as `0xf4` as hexadecimal numbers,
+ // which we DO NOT want to happen.
+ const m = label.match(/^\d+(?:\.\d+)?/) || ['x'];
+ const nmr = +m[0] || Infinity; // non-numeric labels are rated NUMEICALLY HIGHER than any numerical leader.
+
+ return {
+ label,
+ number: nmr
+ };
+ }
+
+ const labelA = plugin_options.sortOrder === 3 ? infoA.labelOverride || infoA.label || '' + infoA.id : plugin_options.mkLabel(infoA.id, infoA, baseInfo);
+ const labelB = plugin_options.sortOrder === 3 ? infoB.labelOverride || infoB.label || '' + infoB.id : plugin_options.mkLabel(infoB.id, infoB, baseInfo);
+ const atomA = to_atoms(labelA);
+ const atomB = to_atoms(labelB);
+ const diff = atomA.number - atomB.number;
+ return diff || atomA.label.localeCompare(atomB.label); // ^^^^^^^ shorthand for:
+ //
+ // if (isNaN(diff) || diff === 0) then stringcompare else numeric-difference
+ }); // Now turn this into a sort order map:
+
+ for (let prio = 0; prio < reIdMap.length; prio++) {
+ const id = reIdMap[prio];
+ idMap[id] = prio;
+ }
+
+ break;
+ }
+
+ let aside_list;
+ let section_list = new Set();
+ const section_done_list = new Set(); // once a section_note has been printed, it should never appear again!
+
+ const end_list = new Set();
+ const used_list = new Set();
+ let tokens = state.tokens;
+
+ for (i = 0; i < tokens.length; i++) {
+ const tok = tokens[i];
+
+ switch (tok.type) {
+ case 'footnote_mark_end_of_block':
+ // check the gathered list of footnotes referenced in this block:
+ // - dump the ones which are sidenotes
+ // - mark the ones which are section- or end-notes.
+ //
+ // Note: make sure we don't produce duplicates in the collect sets.
+ {
+ var _tok$meta;
+
+ aside_list = new Set();
+ const refd_notes_list = ((_tok$meta = tok.meta) == null ? void 0 : _tok$meta.footnote_list) || [];
+
+ for (const id of refd_notes_list) {
+ const footnote = footnote_spec_list[id];
+
+ switch (footnote.mode) {
+ case '>':
+ aside_list.add(id);
+ used_list.add(id);
+ break;
+
+ case '=':
+ if (!section_done_list.has(id)) {
+ section_list.add(id);
+ section_done_list.add(id);
+ used_list.add(id);
+ }
+
+ break;
+
+ default:
+ case ':':
+ end_list.add(id);
+ used_list.add(id);
+ break;
+ }
+ }
+
+ const aside_ids = [];
+
+ for (const id of aside_list.values()) {
+ aside_ids.push(id);
+ }
+
+ aside_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, i + 1, aside_ids, 'aside', baseInfo);
+ tokens = state.tokens;
+ }
+ break;
+
+ case 'footnote_reference_close':
+ // anywhere a footnote *definition* appeared in the original text is
+ // also a place to dump the section_notes gathered to date, so to speak.
+ //
+ // However, DO detect clusters of footnote definitions and MERGE them
+ // together:
+ if (more_footnote_reference_blocks_follow_immediately(tokens, i + 1)) {
+ continue;
+ } else {
+ const section_ids = [];
+
+ for (const id of section_list.values()) {
+ section_ids.push(id);
+ }
+
+ section_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, i + 1, section_ids, 'section', baseInfo);
+ tokens = state.tokens; // and reset the tracking set:
+
+ section_list = new Set();
+ }
+
+ break;
+ }
+ } // Now process the endnotes:
+
+
+ {
+ const end_ids = [];
+
+ for (const id of end_list.values()) {
+ end_ids.push(id);
+ }
+
+ end_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, tokens.length, end_ids, 'end', baseInfo);
+ tokens = state.tokens;
+ } // Now process the unused footnotes and dump them for diagnostic purposes:
+
+ {
+ const unused_ids = [];
+
+ for (let i = 1; i < footnote_spec_list.length; i++) {
+ const fn = footnote_spec_list[i];
+ const id = fn.id;
+
+ if (!used_list.has(id)) {
+ console.error(`ERROR: footnote ID ${id} is defined but never used. Footnote will be added as an ERRONEOUS ENDNOTE to the output, so the situation is easy to diagnose!`, Object.assign({}, fn, {
+ tokens: '......'
+ }));
+ unused_ids.push(id);
+ }
+ }
+
+ unused_ids.sort(footnote_print_comparer);
+ place_footnote_definitions_at(state, tokens.length, unused_ids, 'Error::Unused', baseInfo); //tokens = state.tokens;
+ } // Update state_block too as we have rewritten & REPLACED the token array earlier in this call:
+ // the reference `state.env.state_block.tokens` is still pointing to the OLD token array!
+
+ state.env.state_block.tokens = state.tokens;
+ } // attach ourselves to the start of block handling too
+
+
+ md.block.ruler.before('table', 'footnote_mark_end_of_block', footnote_mark_end_of_block);
+ md.block.ruler.before('reference', 'footnote_def', footnote_def, {
+ alt: ['paragraph', 'reference']
+ });
+ md.inline.ruler.after('image', 'footnote_inline', footnote_inline);
+ md.inline.ruler.after('footnote_inline', 'footnote_ref_with_text', footnote_ref_with_text);
+ md.inline.ruler.after('footnote_ref_with_text', 'footnote_ref', footnote_ref);
+ md.core.ruler.after('inline', 'footnote_tail', footnote_tail);
+ }
+
+ return footnote_plugin;
+
+})));
+//# sourceMappingURL=markdownItFootnote.umd.js.map
diff --git a/dist/markdownItFootnote.umd.js.map b/dist/markdownItFootnote.umd.js.map
new file mode 100644
index 0000000..2db10dc
--- /dev/null
+++ b/dist/markdownItFootnote.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"markdownItFootnote.umd.js","sources":["../index.ts"],"sourcesContent":["// Process footnotes\n//\n\nimport { strict as assert } from 'assert';\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Renderer partials\n\n\n\ninterface FootnotePluginOptions {\n numberSequence?: Array;\n modeOverride?: string;\n sortOrder: number;\n refCombiner?: string;\n}\n\ninterface GenericInfoParameters {\n options: any; // markdown_it options object\n plugin_options: FootnotePluginOptions;\n env: any; // markdown_it environment object\n self: any; // reference to this plugin instance\n}\n\ninterface RenderInfoParameters extends GenericInfoParameters {\n tokens: Array; // array of tokens\n idx: number; // index of current token in token array\n}\n\ninterface footnoteMetaInfo {\n id: number;\n label?: string;\n labelOverride?: string;\n mode?: string;\n content?: string;\n tokens?: Array;\n count: number;\n}\n\n\n\nfunction anchorFnDefault(n: number, excludeSubId: number, baseInfo: RenderInfoParameters) {\n const env = baseInfo.env;\n assert.ok(env != null);\n let prefix = '';\n if (typeof env.docId === 'string' && env.docId.length > 0) {\n prefix = '-' + env.docId + '-';\n }\n return prefix + n;\n}\n\nfunction captionFnDefault(n, baseInfo: RenderInfoParameters) {\n //return '[' + n + ']';\n return '' + n;\n}\n\nfunction headerFnDefault(category, baseInfo: GenericInfoParameters) {\n switch (category) {\n case 'aside':\n return 'Side Notes';\n\n case 'section':\n return 'Section Notes';\n\n case 'end':\n return 'Endnotes';\n\n default: // used for error category, e.g. 'Error::Unused'\n return category;\n }\n}\n\nfunction determine_footnote_symbol(idx: number, info: footnoteMetaInfo, baseInfo: GenericInfoParameters): string {\n const plugin_options = baseInfo.plugin_options;\n assert.ok(plugin_options != null);\n\n // rule to construct the printed label:\n //\n // mark = labelOverride /* || info.label */ || idx;\n const label = info.labelOverride;\n if (label) {\n return label;\n }\n if (plugin_options.numberSequence == null || plugin_options.numberSequence.length === 0) {\n return '' + idx;\n }\n const len = plugin_options.numberSequence.length;\n if (idx >= len) {\n // is last slot numeric or alphanumerically?\n const slot = plugin_options.numberSequence[len - 1];\n if (Number.isFinite(slot)) {\n const delta = idx - len + 1;\n return '' + (slot + delta);\n }\n\n // non-numerical last slot --> duplicate, triplicate, etc.\n const dupli = (idx / len) | 0; // = int(x mod N)\n const remainder = idx % len;\n const core = plugin_options.numberSequence[remainder];\n let str = '' + core;\n for (let i = 1; i < dupli; i++) {\n str += core;\n }\n return str;\n }\n\n return '' + plugin_options.numberSequence[idx];\n}\n\n\nconst bunched_mode_classes = [ '', 'footnote-bunched-ref-ref', 'footnote-bunched-ref-text' ];\n\n\nfunction generateFootnoteRefHtml(id, caption, refId, bunched_footnote_ref_mode, renderInfo: RenderInfoParameters) {\n let localOverride = renderInfo.tokens[renderInfo.idx].meta.text;\n if (localOverride) {\n localOverride = `${ localOverride }`;\n }\n return `${ localOverride || '' }${ caption }` +\n (bunched_footnote_ref_mode !== 0 ? `${ renderInfo.plugin_options.refCombiner || '' }` : '');\n}\n\nfunction generateFootnoteSectionStartHtml(renderInfo: RenderInfoParameters) {\n const tok = renderInfo.tokens[renderInfo.idx];\n assert.ok(tok != null);\n assert.ok(tok.meta != null);\n const header = (tok.markup ? `
${ tok.markup }
` : '');\n let category = tok.meta.category;\n assert.ok(category.length > 0);\n // `category` can contain CSS class illegal characters, e.g. when category = 'Error::Unused':\n category = category.replace(/[^a-zA-Z0-9_-]+/g, '_');\n return `\\n';\n}\n\nfunction generateFootnoteStartHtml(id, caption, renderInfo: RenderInfoParameters) {\n // allow both a JavaWScript --> CSS approach via `data-footnote-caption`\n // and a classic CSS approach while a display:inline-block SUP presenting\n // the LI 'button' instead:\n return `