Skip to content

Parse footnote definitions where they occur - #311

Merged
dereuromark merged 1 commit into
masterfrom
fix/nested-footnote-bodies
Oct 16, 2026
Merged

dereuromark merged 1 commit into
masterfrom
fix/nested-footnote-bodies

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Footnote bodies were parsed in a pre-pass that only saw unindented definitions at the top level. Anywhere else the note was registered with no content.

Input:

> [^p]: n

[^p]

djot.js 9790d4d, note 1:

<li id="fn1">
<p>n<a href="#fnref1" role="doc-backlink">↩︎</a></p>
</li>

djot-php before: the same note with an empty <p>. The same for [^p]: n, - [^p]: n, 1. [^p]: n and a definition indented inside another note.

The syntax description: "The contents of the note are parsed as block-level content." It sets no column for the marker.

The pre-pass also read lines that are not definitions. With

text [^p]
[^p]: n

the second line is paragraph text ("Paragraphs can never be interrupted by other block-level elements"), but djot-php also put n into the note. A marker line inside a code block filled the note the same way.

Change

The pre-pass (BlockParser::extractFootnotes(), protected) is removed. The block parser parses each definition where it appears, with the same line collection as before. A later definition of a label replaces an earlier one, as djot.js does. The note body is parsed without the pending block attributes around it.

References can now come before their definition in parse order, so the "Undefined footnote" warning is dropped at the end when the label was defined after all.

Measured against djot.js

On the 4853 generated block-family inputs, djot-php differed from djot.js 9790d4d on 1686 before (after #310) and 1282 after. 404 cases moved to matching, none the other way.

Not in this PR:

  • - [^p]: n followed by an unindented lazy line. djot.js continues the note, djot-php ends the list. Fixing it in the list tracker alone breaks other cases that depend on how a block-start line after a container paragraph is handled, so it goes with that change.
  • text [^p] then [^p]: n still differs from djot.js in the second reference's id (fnref1-2 here, none in djot.js). That is the repeated-reference rendering, which the syntax description does not settle.

Footnote bodies were parsed in a pre-pass that only saw unindented
definitions at the top level. A definition inside a quote, list item or
another note, or with leading spaces, registered an empty note. The same
pass also took marker lines that were paragraph continuation or code block
content, so `text [^p]` followed by `[^p]: n` showed the line as text and
also filled the note.

The pre-pass (BlockParser::extractFootnotes()) is gone: each definition is
parsed by the block parser where it appears, and a later definition of a
label replaces an earlier one, as in djot.js. The body is parsed without the
pending block attributes around it.

A reference can now precede its definition in parse order, so an "Undefined
footnote" warning is dropped at the end when the label turned out to be
defined.
@dereuromark dereuromark added the bug Something isn't working label Oct 16, 2026
@codecov

codecov Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.93939% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.07%. Comparing base (a1caef9) to head (8c8f03f).

Files with missing lines Patch % Lines
src/Parser/BlockParser.php 93.93% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master     #311   +/-   ##
=========================================
  Coverage     93.06%   93.07%           
- Complexity     4718     4721    +3     
=========================================
  Files           118      118           
  Lines         12623    12631    +8     
=========================================
+ Hits          11748    11756    +8     
  Misses          875      875           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dereuromark
dereuromark merged commit c3e8319 into master Oct 16, 2026
6 checks passed
@dereuromark
dereuromark deleted the fix/nested-footnote-bodies branch October 16, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant