private BlockState TryOpen(BlockProcessor processor, bool isContinue) { // We expect footnote to appear only at document level and not indented more than a code indent block var currentContainer = processor.GetCurrentContainerOpened(); if (processor.IsCodeIndent || (!isContinue && currentContainer.GetType() != typeof(MarkdownDocument)) || (isContinue && !(currentContainer is FootnoteGroup))) { return(BlockState.None); } var saved = processor.Column; string label; int start = processor.Start; SourceSpan labelSpan; if (!LinkHelper.TryParseLabel(ref processor.Line, false, out label, out labelSpan) || !label.StartsWith("^") || processor.CurrentChar != ':') { processor.GoToColumn(saved); return(BlockState.None); } // Advance the column int deltaColumn = processor.Start - start; processor.Column = processor.Column + deltaColumn; processor.NextChar(); // Skip ':' var footnote = new Footnote(this) { Label = label, LabelSpan = labelSpan, }; // Maintain a list of all footnotes at document level var footnotes = processor.Document.GetData(DocumentKey) as FootnoteGroup; if (footnotes == null) { footnotes = new FootnoteGroup(this); processor.Document.Add(footnotes); processor.Document.SetData(DocumentKey, footnotes); processor.Document.ProcessInlinesEnd += Document_ProcessInlinesEnd; } footnotes.Add(footnote); var linkRef = new FootnoteLinkReferenceDefinition() { Footnote = footnote, CreateLinkInline = CreateLinkToFootnote, Line = processor.LineIndex, Span = new SourceSpan(start, processor.Start - 2), // account for ]: LabelSpan = labelSpan, Label = label }; processor.Document.SetLinkReferenceDefinition(footnote.Label, linkRef); processor.NewBlocks.Push(footnote); return(BlockState.Continue); }