Skip to content

spec: rule the two-caption collision the wrapper clause left open - #1236

Merged
dereuromark merged 1 commit into
mainfrom
spec/two-caption-collision
Aug 16, 2026
Merged

spec: rule the two-caption collision the wrapper clause left open#1236
dereuromark merged 1 commit into
mainfrom
spec/two-caption-collision

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Split out of markup-carve/carve#1211 so the descriptive part of that PR can land without carrying a normative decision with it.

#1211 documents that a figure may wrap a table and that no Carve source spells it. This is the case that clause left open, and it is normative rather than descriptive, which is why it is separated.

The collision

A table carries an optional caption, so figure{ target: table{ caption }, caption } is a schema-valid tree with TWO captions and one ^ slot to write them into. The wrapper clause says the writer emits "the target and its caption" without saying whose, which is unambiguous only while the table has none.

What happens today, measured on carve-js

With the slot free, the figure's caption fills it and the output reparses as a table. With the slot taken, the writer emits a second ^ line - and that line is not a caption. A ^ line following a caption line is an ordinary paragraph, so the outer caption lands in the output as literal body prose:

<p>^ Outer</p>

That is worse than losing the wrapper. Losing the wrapper is observable through the diagnostic the clause already requires; spelling the caption as prose hides the loss inside the rendered output, where nothing reports it and a reader sees a stray line of text.

Why this follows rather than decides

The rule is that the figure's caption is lost with the wrapper, and a writer must not emit a second ^ line. That is what the clause already says applied one step further: the wrapper is lost, the figure's caption is part of the wrapper, so it goes with it.

The one thing worth your explicit nod

It is still a normative sentence, and carve-js currently violates it - that is how the behavior above was measured. Merging this creates a conformance gap that carve-js has to close. If you would rather state it as a note than as a MUST, say so and it becomes one; the argument for the behavior does not change either way.

Nothing else in the spec is touched: one 12-line addition to resources/grammar.ebnf, in the clause #1211 adds.

Base automatically changed from spec/figure-table-interchange to main August 16, 2026 09:24
@dereuromark
dereuromark deleted the branch main August 16, 2026 09:24
@dereuromark dereuromark reopened this Aug 16, 2026
A `table` carries an optional `caption`, so a `figure` targeting a captioned
table is a schema-valid tree with two captions and one `^ ` slot. The clause
said the writer emits "the target and its caption" without saying whose, which
is only unambiguous when the table has none.

Measured on carve-js. With the slot free the figure's caption fills it and the
output reparses as a `table`. With the slot taken the writer emits a second
`^ ` line, and that line is not a caption: a `^ ` line after a caption line is
an ordinary paragraph, so the output carries "Outer" as literal body prose and
renders it inside a `<p>`.

That is a worse outcome than losing the wrapper, and it is the outcome this
clause exists to keep a writer from discovering on its own. The rule follows
from what the clause already says rather than adding a new decision: the
wrapper is lost, and the figure's caption is part of the wrapper, so it goes
with it and the writer emits no second line. Losing it cleanly keeps the loss
observable through the diagnostic; spelling it as prose hides it in the output.
@dereuromark
dereuromark force-pushed the spec/two-caption-collision branch from f969118 to e7787d4 Compare August 16, 2026 09:25
@dereuromark
dereuromark merged commit 95fe6e8 into main Aug 16, 2026
4 checks passed
@dereuromark
dereuromark deleted the spec/two-caption-collision branch August 16, 2026 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant