Skip to content

Keep attributes in their container, fix final newline and reference URL continuation - #314

Merged
dereuromark merged 4 commits into
masterfrom
fix/small-block-divergences
Oct 16, 2026
Merged

dereuromark merged 4 commits into
masterfrom
fix/small-block-divergences

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Three smaller differences from djot.js 9790d4d, one commit each.

Block attributes leaked out of their container

::: d
{#x}
:::
tail

djot.js: <p>tail</p>. djot-php: <p id="x">tail</p>. Also - a, blank, {#x}, blank, tail: the list took the blank line, so the reset a blank line does never ran. The syntax description: "put the attributes on the line immediately before the block".

Pending attributes are now dropped when a div closes and when a block's parse ends on a blank line. > {#x} followed by tail still puts the id on tail, as djot.js does.

Unclosed code fence at the end got an extra newline

A fence line alone rendered as <pre><code>\n</code></pre>, and a fence line followed by x as x\n\n. djot.js gives <pre><code></code></pre> and x\n. The cause was the input split: the newline that ends the last line left an empty string behind, which block parsing read as one more line. The line list now stops at the last terminated line.

Reference URL continuation

[r]: /u
  a b

[r][]

djot.js: <p>a b</p> and a link to /u. djot-php linked to /ua b, and > tail gave /u> tail. The syntax description: "None of the chunks of the URL may contain internal whitespace." A continuation line now holds a single chunk.

It also has to be indented past the definition's own [: [r]: /u followed by tail makes tail a paragraph. The description shows only a continuation under a column-0 definition and does not say what the indentation is measured from, so this follows djot.js. A chunk with trailing spaces still continues the URL; djot.js makes it a paragraph, which the description does not support either way.

Measured against djot.js

On the 4853 generated block-family inputs, djot-php differed from djot.js on 1077 before (after #312) and 1041 after: 1046, 1046 and 1041 after each commit. 36 cases moved to matching and none the other way. The fence commit moves no case on its own, because every generated input it touches also differs in another way; the differential's fence family drops from 38 minimized cases to none.

@dereuromark dereuromark added the bug Something isn't working label Oct 16, 2026
An attribute line at the end of a div applied to the block after the div:

    ::: d
    {#x}
    :::
    tail

gave `<p id="x">tail</p>`. The same happened for an attribute line at the
end of a list item followed by a blank line (`- a`, blank, `  {#x}`, blank,
`tail`): the list took the blank line, so the reset a blank line normally
does never ran. djot.js keeps `tail` without the id in both. The syntax
description: "put the attributes on the line immediately before the block".

Pending attributes are now dropped when a div closes and when a block's
parse ends on a blank line. An attribute line directly before a lazy line
that ends a block quote (`> {#x}`, `tail`) still reaches `tail`, as in
djot.js.
Splitting the input on newlines left an empty string after a final newline,
and block parsing saw it as one more line. That only showed where a block
keeps blank lines verbatim: an unclosed code fence at the end of the
document got an extra newline. A fence line alone rendered as
`<pre><code>\n</code></pre>`, and a fence line followed by `x` as `x\n\n`.
djot.js gives `<pre><code></code></pre>` and `x\n`.

The line list now ends with the last line the newline terminates.
Any indented line after a reference definition was appended to its URL:
`[r]: /u` followed by `  a b` linked to `/ua b`, and `  > tail` to
`/u> tail`. The syntax description: "None of the chunks of the URL may
contain internal whitespace." djot.js ends the definition there and parses
the line as a block.

A continuation line also has to be indented past the definition's own `[`:
`  [r]: /u` followed by `  tail` makes `tail` a paragraph. The description
only shows a continuation indented under a column-0 definition and does not
say what the indentation is measured from; this follows djot.js.
@dereuromark
dereuromark force-pushed the fix/small-block-divergences branch from 6a008b3 to 828c033 Compare October 16, 2026 14:02
@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.08%. Comparing base (b038fb5) to head (58a4359).

Additional details and impacted files
@@            Coverage Diff            @@
##             master     #314   +/-   ##
=========================================
  Coverage     93.07%   93.08%           
- Complexity     4732     4737    +5     
=========================================
  Files           118      118           
  Lines         12636    12645    +9     
=========================================
+ Hits          11761    11770    +9     
  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.

Dropping the empty string after the final newline left three loop exits
that only that phantom line reached in the suite: the attribute look-ahead
of a list item, the roman/alphabetic list disambiguation and the row span
pre-scan of a table. These inputs reach them with a real blank line.
@dereuromark
dereuromark merged commit 43bfbcc into master Oct 16, 2026
6 checks passed
@dereuromark
dereuromark deleted the fix/small-block-divergences branch October 16, 2026 14:11
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