/*! markdown-it-footnote 4.0.0 https://github.com/markdown-it/markdown-it-footnote @license MIT */
(function(global, factory) {
  typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, 
  global.markdownitFootnote = factory());
})(this, (function() {
  "use strict";
  // Process footnotes
  
  /// /////////////////////////////////////////////////////////////////////////////
  // Renderer partials
    function render_footnote_anchor_name(tokens, idx, options, env /*, slf */) {
    const n = Number(tokens[idx].meta.id + 1).toString();
    let prefix = "";
    if (typeof env.docId === "string") prefix = `-${env.docId}-`;
    return prefix + n;
  }
  function render_footnote_caption(tokens, idx /*, options, env, slf */) {
    let n = Number(tokens[idx].meta.id + 1).toString();
    if (tokens[idx].meta.subId > 0) n += `:${tokens[idx].meta.subId}`;
    return `[${n}]`;
  }
  function render_footnote_ref(tokens, idx, options, env, slf) {
    const id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf);
    const caption = slf.rules.footnote_caption(tokens, idx, options, env, slf);
    let refid = id;
    if (tokens[idx].meta.subId > 0) refid += `:${tokens[idx].meta.subId}`;
    return `<sup class="footnote-ref"><a href="#fn${id}" id="fnref${refid}">${caption}</a></sup>`;
  }
  function render_footnote_block_open(tokens, idx, options) {
    return (options.xhtmlOut ? '<hr class="footnotes-sep" />\n' : '<hr class="footnotes-sep">\n') + '<section class="footnotes">\n' + '<ol class="footnotes-list">\n';
  }
  function render_footnote_block_close() {
    return "</ol>\n</section>\n";
  }
  function render_footnote_open(tokens, idx, options, env, slf) {
    let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf);
    if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`;
    return `<li id="fn${id}" class="footnote-item">`;
  }
  function render_footnote_close() {
    return "</li>\n";
  }
  function render_footnote_anchor(tokens, idx, options, env, slf) {
    let id = slf.rules.footnote_anchor_name(tokens, idx, options, env, slf);
    if (tokens[idx].meta.subId > 0) id += `:${tokens[idx].meta.subId}`
    /* ↩ with escape code to prevent display as Apple Emoji on iOS */;
    return ` <a href="#fnref${id}" class="footnote-backref">\u21a9\ufe0e</a>`;
  }
  function footnote_plugin(md) {
    const parseLinkLabel = md.helpers.parseLinkLabel;
    const isSpace = md.utils.isSpace;
    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_open = render_footnote_open;
    md.renderer.rules.footnote_close = render_footnote_close;
    md.renderer.rules.footnote_anchor = render_footnote_anchor;
    // helpers (only used in other rules, no tokens are attached to those)
        md.renderer.rules.footnote_caption = render_footnote_caption;
    md.renderer.rules.footnote_anchor_name = render_footnote_anchor_name;
    // Process footnote block definition
        function footnote_def(state, startLine, endLine, silent) {
      const start = state.bMarks[startLine] + state.tShift[startLine];
      const max = state.eMarks[startLine];
      // line should be at least 5 chars - "[^x]:"
            if (start + 4 > max) return false;
      if (state.src.charCodeAt(start) !== 91 /* [ */) return false;
      if (state.src.charCodeAt(start + 1) !== 94 /* ^ */) return false;
      let pos;
      for (pos = start + 2; pos < max; pos++) {
        if (state.src.charCodeAt(pos) === 32) return false;
        if (state.src.charCodeAt(pos) === 93 /* ] */) {
          break;
        }
      }
      if (pos === start + 2) return false;
 // no empty footnote labels
            if (pos + 1 >= max || state.src.charCodeAt(++pos) !== 58 /* : */) return false;
      if (silent) return true;
      pos++;
      if (!state.env.footnotes) state.env.footnotes = {};
      if (!state.env.footnotes.refs) state.env.footnotes.refs = {};
      const label = state.src.slice(start + 2, pos - 2);
      state.env.footnotes.refs[`:${label}`] = -1;
      const token_fref_o = new state.Token("footnote_reference_open", "", 1);
      token_fref_o.meta = {
        label: label
      };
      token_fref_o.level = state.level++;
      state.tokens.push(token_fref_o);
      const oldBMark = state.bMarks[startLine];
      const oldTShift = state.tShift[startLine];
      const oldSCount = state.sCount[startLine];
      const oldParentType = state.parentType;
      const posAfterColon = pos;
      const initial = state.sCount[startLine] + pos - (state.bMarks[startLine] + state.tShift[startLine]);
      let offset = initial;
      while (pos < max) {
        const ch = state.src.charCodeAt(pos);
        if (isSpace(ch)) {
          if (ch === 9) {
            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;
      const token_fref_c = new state.Token("footnote_reference_close", "", -1);
      token_fref_c.level = --state.level;
      state.tokens.push(token_fref_c);
      return true;
    }
    // Process inline footnotes (^[...])
        function footnote_inline(state, silent) {
      const max = state.posMax;
      const start = state.pos;
      if (start + 2 >= max) return false;
      if (state.src.charCodeAt(start) !== 94 /* ^ */) return false;
      if (state.src.charCodeAt(start + 1) !== 91 /* [ */) return false;
      const labelStart = start + 2;
      const labelEnd = parseLinkLabel(state, start + 1);
      // parser failed to find ']', so it's not a valid note
            if (labelEnd < 0) return false;
      // We found the end of the link, and know for a fact it's a valid link;
      // so all that's left to do is to call tokenizer.
      
            if (!silent) {
        if (!state.env.footnotes) state.env.footnotes = {};
        if (!state.env.footnotes.list) state.env.footnotes.list = [];
        const footnoteId = state.env.footnotes.list.length;
        const tokens = [];
        state.md.inline.parse(state.src.slice(labelStart, labelEnd), state.md, state.env, tokens);
        const token = state.push("footnote_ref", "", 0);
        token.meta = {
          id: footnoteId
        };
        state.env.footnotes.list[footnoteId] = {
          content: state.src.slice(labelStart, labelEnd),
          tokens: tokens
        };
      }
      state.pos = labelEnd + 1;
      state.posMax = max;
      return true;
    }
    // Process footnote references ([^...])
        function footnote_ref(state, silent) {
      const max = state.posMax;
      const start = state.pos;
      // should be at least 4 chars - "[^x]"
            if (start + 3 > max) return false;
      if (!state.env.footnotes || !state.env.footnotes.refs) return false;
      if (state.src.charCodeAt(start) !== 91 /* [ */) return false;
      if (state.src.charCodeAt(start + 1) !== 94 /* ^ */) return false;
      let pos;
      for (pos = start + 2; pos < max; pos++) {
        if (state.src.charCodeAt(pos) === 32) return false;
        if (state.src.charCodeAt(pos) === 10) return false;
        if (state.src.charCodeAt(pos) === 93 /* ] */) {
          break;
        }
      }
      if (pos === start + 2) return false;
 // no empty footnote labels
            if (pos >= max) return false;
      pos++;
      const label = state.src.slice(start + 2, pos - 1);
      if (typeof state.env.footnotes.refs[`:${label}`] === "undefined") return false;
      if (!silent) {
        if (!state.env.footnotes.list) state.env.footnotes.list = [];
        let footnoteId;
        if (state.env.footnotes.refs[`:${label}`] < 0) {
          footnoteId = state.env.footnotes.list.length;
          state.env.footnotes.list[footnoteId] = {
            label: label,
            count: 0
          };
          state.env.footnotes.refs[`:${label}`] = footnoteId;
        } else {
          footnoteId = state.env.footnotes.refs[`:${label}`];
        }
        const footnoteSubId = state.env.footnotes.list[footnoteId].count;
        state.env.footnotes.list[footnoteId].count++;
        const token = state.push("footnote_ref", "", 0);
        token.meta = {
          id: footnoteId,
          subId: footnoteSubId,
          label: label
        };
      }
      state.pos = pos;
      state.posMax = max;
      return true;
    }
    // Glue footnote tokens to end of token stream
        function footnote_tail(state) {
      let tokens;
      let current;
      let currentLabel;
      let insideRef = false;
      const refTokens = {};
      if (!state.env.footnotes) {
        return;
      }
      state.tokens = state.tokens.filter((function(tok) {
        if (tok.type === "footnote_reference_open") {
          insideRef = true;
          current = [];
          currentLabel = tok.meta.label;
          return false;
        }
        if (tok.type === "footnote_reference_close") {
          insideRef = false;
          // prepend ':' to avoid conflict with Object.prototype members
                    refTokens[":" + currentLabel] = current;
          return false;
        }
        if (insideRef) {
          current.push(tok);
        }
        return !insideRef;
      }));
      if (!state.env.footnotes.list) {
        return;
      }
      const list = state.env.footnotes.list;
      state.tokens.push(new state.Token("footnote_block_open", "", 1));
      for (let i = 0, l = list.length; i < l; i++) {
        const token_fo = new state.Token("footnote_open", "", 1);
        token_fo.meta = {
          id: i,
          label: list[i].label
        };
        state.tokens.push(token_fo);
        if (list[i].tokens) {
          tokens = [];
          const token_po = new state.Token("paragraph_open", "p", 1);
          token_po.block = true;
          tokens.push(token_po);
          const token_i = new state.Token("inline", "", 0);
          token_i.children = list[i].tokens;
          token_i.content = list[i].content;
          tokens.push(token_i);
          const token_pc = new state.Token("paragraph_close", "p", -1);
          token_pc.block = true;
          tokens.push(token_pc);
        } else if (list[i].label) {
          tokens = refTokens[`:${list[i].label}`];
        }
        if (tokens) state.tokens = state.tokens.concat(tokens);
        let lastParagraph;
        if (state.tokens[state.tokens.length - 1].type === "paragraph_close") {
          lastParagraph = state.tokens.pop();
        } else {
          lastParagraph = null;
        }
        const t = list[i].count > 0 ? list[i].count : 1;
        for (let j = 0; j < t; j++) {
          const token_a = new state.Token("footnote_anchor", "", 0);
          token_a.meta = {
            id: i,
            subId: j,
            label: list[i].label
          };
          state.tokens.push(token_a);
        }
        if (lastParagraph) {
          state.tokens.push(lastParagraph);
        }
        state.tokens.push(new state.Token("footnote_close", "", -1));
      }
      state.tokens.push(new state.Token("footnote_block_close", "", -1));
    }
    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", footnote_ref);
    md.core.ruler.after("inline", "footnote_tail", footnote_tail);
  }
  return footnote_plugin;
}));
