Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`</#id>` as the group number plus a letter ("Figure 2a"); a `#` in a panel
caption stays literal. An opener carrying a quoted title or `[label]` stays
a generic container, as does a nested bare `::: figure`; both lint. HTML
renders `carve-figure-group` / `carve-figure-panels` / `carve-figure-panel`,
renders `carve-figure-group` / `carve-figure-panel` figures nested directly,
and PART 11 §10g fixes the writer spelling and the non-HTML degradations.
This is an observable parsing change inside 0.1.x for documents that already
hold a bare `::: figure` fence: the container reclassifies from a generic
Expand Down
2 changes: 1 addition & 1 deletion docs/graceful-degradation.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The table reflects the reference engines' renderer behavior.
| Footnotes | jump links | print-native footnotes; `[^id]` preserved in Markdown | degrades natively |
| Links / autolinks | clickable | clickable in PDF; URL preserved in plain text | degrades natively |
| Cross-references / TOC | anchor links | internal PDF links; anchors preserved in Markdown | degrades natively |
| Composite figure (`::: figure`) | one `<figure>` with a panels `<div>` and a group `<figcaption>`; layout hints (`columns-2`) pass through as classes | Markdown: panels in order, panel captions as `*(...)*`, group caption last as `**...**`; plain/terminal: group caption first, then each panel's caption + host degradation | normative - PART 9 §4c + the writer/degradation clause in PART 11 |
| Composite figure (`::: figure`) | one `<figure>` holding the panel figures directly plus a group `<figcaption>`; layout hints (`columns-2`) pass through as classes | Markdown: panels in order, panel captions as `*(...)*`, group caption last as `**...**`; plain/terminal: group caption first, then each panel's caption + host degradation | normative - PART 9 §4c + the writer/degradation clause in PART 11 |

The composite figure's contract is the floor applied with no exceptions: every
panel, every panel caption, any stray content between the panels, and the group
Expand Down
2 changes: 1 addition & 1 deletion docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ the command-line and editor behavior stay aligned.
| `figure-group-nested` | a `::: figure` opener inside a composite figure's body; nesting is rejected (PART 9 §4c), so the inner fence stays a generic container |
| `figure-group-opener-metadata` | a `::: figure` opener carrying a quoted title or `[label]`; the figure production takes neither, so the fence stays a generic container with both preserved (PART 9 §4c) |
| `figure-group-panel-number` | a `#` placeholder in a PANEL caption; panels are not sequence units, so the placeholder stays a literal `#` (PART 9 §4c) - number the group caption instead |
| `figure-group-empty` | a `::: figure` group with no captionable panel; the panels wrapper renders around the preserved content only (PART 9 §4c) |
| `figure-group-empty` | a `::: figure` group with no captionable panel; the group figure holds only the preserved content (PART 9 §4c) |
| `figure-group-single-panel` | a `::: figure` group holding a single panel; a plain captioned figure renders the same content without the group wrapper (PART 9 §4c) |

### Declaring a target version
Expand Down
4 changes: 1 addition & 3 deletions docs/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ paragraph:
<p>^ Figure #: A pull quote</p>

<figure class="carve-figure-group" id="ep"> <!-- after -->
<div class="carve-figure-panels">
<blockquote><p>To be</p></blockquote>
</div>
<blockquote><p>To be</p></blockquote>
<figcaption>Figure 1: A pull quote</figcaption>
</figure>
```
Expand Down
14 changes: 14 additions & 0 deletions resources/engine-pin-drift.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,17 @@
# Emptying this file is the normal end state after `npm run bump-carve-pin`.
#
# Format: <slug><space><space><reason>

# PART 9 §4c wrapper removal (carve#1122): panels nest directly in the group
# figure; the pinned carve-js still wraps them in the withdrawn
# `<div class="carve-figure-panels">`. Clears with the engine updates and a
# pin bump.
318-composite-figures §4c wrapper removal; the pin still emits the panels div
318-composite-figures-2 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-3 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-4 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-5 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-6 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-9 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-10 §4c wrapper removal; the pin still emits the panels div
318-composite-figures-11 §4c wrapper removal; the pin still emits the panels div
170 changes: 77 additions & 93 deletions resources/examples/edge-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -17696,8 +17696,10 @@ A bare `::: figure` container is ONE figure holding ordered panels (PART 9
`figure` and `table` nodes the unchanged inner caption rules build - are the
panels, and the `^ ` line after the closing fence is the caption of the whole
group. That closer is caption placement's sixth host (PART 9 §4), and the only
`:::` kind that takes one. The group renders class-first, the panels wrapped in
an unconditional `carve-figure-panels` div.
`:::` kind that takes one. The group renders class-first, the panels nested
directly in the group `figure` - HTML's figure content model admits flow
content beside a first-or-last `figcaption`, so no wrapper element sits
between them.

:::: compare

Expand All @@ -17717,16 +17719,14 @@ an unconditional `carve-figure-panels` div.

```html
<figure class="carve-figure-group columns-2" id="fig-x">
<div class="carve-figure-panels">
<figure class="carve-figure-panel" id="fig-x-a">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel" id="fig-x-b">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
</div>
<figure class="carve-figure-panel" id="fig-x-a">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel" id="fig-x-b">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
<figcaption>Figure 1: Group caption</figcaption>
</figure>
```
Expand Down Expand Up @@ -17766,16 +17766,14 @@ See </#fig-x> and </#fig-x-a>.
<figcaption>Figure 1: First</figcaption>
</figure>
<figure class="carve-figure-group" id="fig-x">
<div class="carve-figure-panels">
<figure class="carve-figure-panel" id="fig-x-a">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel" id="fig-x-b">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
</div>
<figure class="carve-figure-panel" id="fig-x-a">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel" id="fig-x-b">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
<figcaption>Figure 2: Second</figcaption>
</figure>
<p>See <a href="#fig-x">Figure 2</a> and <a href="#fig-x-a">Figure 2a</a>.</p>
Expand All @@ -17800,16 +17798,14 @@ A group without a caption is a valid, unnumbered group - no trailing

```html
<figure class="carve-figure-group">
<div class="carve-figure-panels">
<figure class="carve-figure-panel">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
</div>
<figure class="carve-figure-panel">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
</figure>
```

Expand All @@ -17830,12 +17826,10 @@ strict profiles as `figure-group-single-panel`).

```html
<figure class="carve-figure-group">
<div class="carve-figure-panels">
<figure class="carve-figure-panel">
<img src="l.png" alt="lone">
<figcaption>The only panel</figcaption>
</figure>
</div>
<figure class="carve-figure-panel">
<img src="l.png" alt="lone">
<figcaption>The only panel</figcaption>
</figure>
<figcaption>Figure 1: One panel is valid</figcaption>
</figure>
```
Expand Down Expand Up @@ -17865,17 +17859,15 @@ Both panels were shot on the same day.

```html
<figure class="carve-figure-group">
<div class="carve-figure-panels">
<p>Both panels were shot on the same day.</p>
<figure class="carve-figure-panel" id="fig-s-a">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel" id="fig-s-b">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
</div>
<p>Both panels were shot on the same day.</p>
<figure class="carve-figure-panel" id="fig-s-a">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
<figure class="carve-figure-panel" id="fig-s-b">
<img src="b.png" alt="two">
<figcaption>(b) Two</figcaption>
</figure>
<figcaption>Figure 1: With a note between the panels</figcaption>
</figure>
```
Expand All @@ -17900,12 +17892,10 @@ line an ordinary paragraph.

```html
<figure class="carve-figure-group">
<div class="carve-figure-panels">
<figure class="carve-figure-panel">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
</div>
<figure class="carve-figure-panel">
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
</figure>
<p>^ Figure #: Detached</p>
```
Expand Down Expand Up @@ -17988,13 +17978,11 @@ outer group numbers.

```html
<figure class="carve-figure-group">
<div class="carve-figure-panels">
<div class="figure">
<figure>
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
</div>
<div class="figure">
<figure>
<img src="a.png" alt="one">
<figcaption>(a) One</figcaption>
</figure>
</div>
<figcaption>Figure 1: Outer only</figcaption>
</figure>
Expand Down Expand Up @@ -18036,30 +18024,28 @@ $$`E = mc^2`

````html
<figure class="carve-figure-group" id="fig-m">
<div class="carve-figure-panels">
<figure class="carve-figure-panel">
<table>
<thead><tr><th scope="col">Kind</th><th scope="col">N</th></tr></thead>
<tbody>
<tr><td>a</td><td>1</td></tr>
</tbody>
</table>
</figure>
<figure class="carve-figure-panel">
<pre><code class="language-js">const x = 1
<figure class="carve-figure-panel">
<table>
<thead><tr><th scope="col">Kind</th><th scope="col">N</th></tr></thead>
<tbody>
<tr><td>a</td><td>1</td></tr>
</tbody>
</table>
</figure>
<figure class="carve-figure-panel">
<pre><code class="language-js">const x = 1
</code></pre>
<figcaption>A listing panel</figcaption>
</figure>
<figure class="carve-figure-panel">
<p><span class="math display">\[E = mc^2\]</span></p>
<figcaption>An equation panel</figcaption>
</figure>
<blockquote><p>Measured twice.</p></blockquote>
<figure class="carve-figure-panel">
<blockquote><p>Brevity.</p></blockquote>
<figcaption>A quoted panel</figcaption>
</figure>
</div>
<figcaption>A listing panel</figcaption>
</figure>
<figure class="carve-figure-panel">
<p><span class="math display">\[E = mc^2\]</span></p>
<figcaption>An equation panel</figcaption>
</figure>
<blockquote><p>Measured twice.</p></blockquote>
<figure class="carve-figure-panel">
<blockquote><p>Brevity.</p></blockquote>
<figcaption>A quoted panel</figcaption>
</figure>
<figcaption>Figure 1: Mixed panels</figcaption>
</figure>
````
Expand Down Expand Up @@ -18087,14 +18073,12 @@ source.

```html
<figure class="carve-figure-group">
<div class="carve-figure-panels">
<aside class="admonition note">
<figure>
<img src="x.png" alt="x">
<figcaption>Figure 2: inner</figcaption>
</figure>
</aside>
</div>
<aside class="admonition note">
<figure>
<img src="x.png" alt="x">
<figcaption>Figure 2: inner</figcaption>
</figure>
</aside>
<figcaption>Figure 1: group</figcaption>
</figure>
```
Expand Down
35 changes: 21 additions & 14 deletions resources/grammar.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -3404,9 +3404,7 @@ EOF = (* end of file *) ;
^ Figure #: A pull quote

<figure class="carve-figure-group">
<div class="carve-figure-panels">
<blockquote><p>To be</p></blockquote>
</div>
<blockquote><p>To be</p></blockquote>
<figcaption>Figure 1: A pull quote</figcaption>
</figure>

Expand Down Expand Up @@ -3481,27 +3479,36 @@ EOF = (* end of file *) ;
318-composite-figures):

<figure class="carve-figure-group [hints]" id="...">
<div class="carve-figure-panels">
<figure class="carve-figure-panel" id="...">
...panel host...
<figcaption>...</figcaption>
</figure>
...
</div>
<figure class="carve-figure-panel" id="...">
...panel host...
<figcaption>...</figcaption>
</figure>
...
<figcaption>Label N: group caption</figcaption>
</figure>

PANELS NEST DIRECTLY, WITH NO WRAPPER ELEMENT BETWEEN. HTML's `figure`
content model is a `figcaption` first or last plus FLOW CONTENT, and
`figure` is itself flow content, so nested panel figures are exactly
what the element admits -- no intermediate `div` is needed to make the
shape valid, and none is emitted. This is also the shape Pandoc's
writers produce for its native subfigures, which keeps HTML
import/export symmetric with the Pandoc bridge. The initial draft of
this clause wrapped the panels in a `<div class="carve-figure-panels">`;
that form was revised to the flat one before any release, so no
shipped document ever carried the wrapper.

The class is FIRST on the group and on each panel, exactly the typed-
container convention (`admonition note`): `carve-figure-group` leads,
classes from the preceding attribute line -- layout hints such as
`columns-2` pass through as classes, profile-sanitized like any class
-- merge after it, then the id and remaining attributes in source
order. A panel renders as the `<figure>` its host already produces,
with `carve-figure-panel` leading its classes the same way. No group
caption -> no trailing `<figcaption>`. Zero panels -> the
`carve-figure-panels` div still wraps whatever content was preserved;
the panels div is unconditional so a consumer styling the shape never
branches on child count.
caption -> no trailing `<figcaption>`. Zero panels -> the group
`<figure>` holds the preserved content directly; a consumer selects
panels by the `carve-figure-panel` class, never by position, so the
shape needs no branch on child count.

5. TABLE MODEL -- OPERATIONAL SEMANTICS (cell split, row validity,
header cells, span walk, continuation rows, delimiter row, row
Expand Down
Loading