Skip to content

Commit a23d1c1

Browse files
committed
Reset Markdown note state between parses
Inline notes inside reference labels can run during the reference-gathering pass. Reset note state for each parse and reject inline notes before note ordering starts so reused parser instances do not accept stale footnote data.
1 parent b7b12c2 commit a23d1c1

3 files changed

Lines changed: 24 additions & 4 deletions

File tree

lib/rdoc/markdown.kpeg

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@
439439
def parse markdown
440440
@references = {}
441441
@unlinked_references = {}
442+
@footnotes = nil
443+
@note_order = nil
442444

443445
markdown += "\n\n"
444446

@@ -1236,7 +1238,9 @@ InlineNote = &{ notes? }
12361238
@StartList:a
12371239
( !"]" Inline:l { a << l } )+
12381240
"]"
1239-
{ ref = [:inline, @note_order.length]
1241+
{ raise ParseError, 'invalid inline note' unless @note_order
1242+
1243+
ref = [:inline, @note_order.length]
12401244
@footnotes[ref] = paragraph a
12411245

12421246
note_for ref

lib/rdoc/markdown.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,8 @@ def paragraph parts
824824
def parse markdown
825825
@references = {}
826826
@unlinked_references = {}
827+
@footnotes = nil
828+
@note_order = nil
827829

828830
markdown += "\n\n"
829831

@@ -15478,7 +15480,7 @@ def _Note
1547815480
return _tmp
1547915481
end
1548015482

15481-
# InlineNote = &{ notes? } "^[" @StartList:a (!"]" Inline:l { a << l })+ "]" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }
15483+
# InlineNote = &{ notes? } "^[" @StartList:a (!"]" Inline:l { a << l })+ "]" { raise ParseError, 'invalid inline note' unless @note_order ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }
1548215484
def _InlineNote
1548315485

1548415486
_save = self.pos
@@ -15569,7 +15571,9 @@ def _InlineNote
1556915571
self.pos = _save
1557015572
break
1557115573
end
15572-
@result = begin; ref = [:inline, @note_order.length]
15574+
@result = begin; raise ParseError, 'invalid inline note' unless @note_order
15575+
15576+
ref = [:inline, @note_order.length]
1557315577
@footnotes[ref] = paragraph a
1557415578

1557515579
note_for ref
@@ -16843,7 +16847,7 @@ def _DefinitionListDefinition
1684316847
Rules[:_NoteReference] = rule_info("NoteReference", "&{ notes? } RawNoteReference:ref { note_for ref }")
1684416848
Rules[:_RawNoteReference] = rule_info("RawNoteReference", "\"[^\" < (!@Newline !\"]\" .)+ > \"]\" { text }")
1684516849
Rules[:_Note] = rule_info("Note", "&{ notes? } @NonindentSpace RawNoteReference:ref \":\" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }")
16846-
Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" @StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }")
16850+
Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" @StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { raise ParseError, 'invalid inline note' unless @note_order ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }")
1684716851
Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*")
1684816852
Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine !RawNoteReference OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }")
1684916853
Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (@Sp StrChunk:format)? @Sp @Newline? < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format.instance_of?(String) verbatim }")

test/rdoc/rdoc_markdown_test.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,18 @@ def test_parse_note_reference_in_reference_label
10251025
assert_equal expected, doc
10261026
end
10271027

1028+
def test_parse_note_inline_in_reference_label_after_reuse
1029+
@parser.notes = true
1030+
1031+
parse "Some text. ^[With a footnote]"
1032+
1033+
error = assert_raise RDoc::Markdown::ParseError do
1034+
parse "[foo ^[note]]: /url\n"
1035+
end
1036+
1037+
assert_equal 'invalid inline note', error.message
1038+
end
1039+
10281040
def test_parse_note_no_notes
10291041
@parser.notes = false
10301042

0 commit comments

Comments
 (0)