def footnote_ref(state: StateInline, silent: bool): """Process footnote references ([^...])""" maximum = state.posMax start = state.pos # should be at least 4 chars - "[^x]" if start + 3 > maximum: return False if "footnotes" not in state.env or "refs" not in state.env["footnotes"]: return False if state.srcCharCode[start] != 0x5B: # /* [ */ return False if state.srcCharCode[start + 1] != 0x5E: # /* ^ */ return False pos = start + 2 while pos < maximum: if state.srcCharCode[pos] == 0x20: return False if state.srcCharCode[pos] == 0x0A: return False if state.srcCharCode[pos] == 0x5D: # /* ] */ break pos += 1 if pos == start + 2: # no empty footnote labels return False if pos >= maximum: return False pos += 1 label = state.src[start + 2:pos - 1] if (":" + label) not in state.env["footnotes"]["refs"]: return False if not silent: if "list" not in state.env["footnotes"]: state.env["footnotes"]["list"] = {} if state.env["footnotes"]["refs"][":" + label] < 0: footnoteId = len(state.env["footnotes"]["list"]) state.env["footnotes"]["list"][footnoteId] = { "label": label, "count": 0 } state.env["footnotes"]["refs"][":" + label] = footnoteId else: footnoteId = state.env["footnotes"]["refs"][":" + label] footnoteSubId = state.env["footnotes"]["list"][footnoteId]["count"] state.env["footnotes"]["list"][footnoteId]["count"] += 1 token = state.push("footnote_ref", "", 0) token.meta = {"id": footnoteId, "subId": footnoteSubId, "label": label} state.pos = pos state.posMax = maximum return True
def footnote_inline(state: StateInline, silent: bool): """Process inline footnotes (^[...])""" maximum = state.posMax start = state.pos if start + 2 >= maximum: return False if state.srcCharCode[start] != 0x5E: # /* ^ */ return False if state.srcCharCode[start + 1] != 0x5B: # /* [ */ return False labelStart = start + 2 labelEnd = parseLinkLabel(state, start + 1) # parser failed to find ']', so it's not a valid note if labelEnd < 0: return False # We found the end of the link, and know for a fact it's a valid link # so all that's left to do is to call tokenizer. # if not silent: refs = state.env.setdefault("footnotes", {}).setdefault("list", {}) footnoteId = len(refs) tokens = [] state.md.inline.parse(state.src[labelStart:labelEnd], state.md, state.env, tokens) token = state.push("footnote_ref", "", 0) token.meta = {"id": footnoteId} refs[footnoteId] = { "content": state.src[labelStart:labelEnd], "tokens": tokens } state.pos = labelEnd + 1 state.posMax = maximum return True