Render a composite figure as one numbered unit - #5
Merged
Conversation
PART 9 section 4c gives a bare ::: figure fence its own exchange node, figure_group: one figure of ordered panels, where the panels are the figure and table children in source order, any other child is stray group content kept in place, and the caption after the closing fence belongs to the whole group. The pinned engine predated the node, so the renderer, whose unknown node types are hard errors, would stop on the first composite figure the day the pin moved. The pin moves here, and the handler arrives with it. The group maps to one markdown:internal:captioned-figure. Resilient numbers every captioned figure and table it typesets and files each into a list, so unmarked panels would take a number and a list entry each: a two-panel group would consume three figure-sequence draws and file three entries. The panels therefore carry unnumbered and notoc, the two classes Resilient's captioned commands already read. The group takes the only number, the list of figures gains exactly one entry per group, each panel keeps its own caption, and a group without a caption numbers nothing, matching the engine. Only DIRECT children are panels: a captioned figure nested inside stray group content keeps its own number, which is the engine's rule as well. Resilient's captioned elements are not floats, and no layer below acts on a columns-N class, so the group typesets as the paged-output contract's degradation floor: a vertical stack of panels with their captions in source order, group caption last. The class survives on the emitted options, so a future Resilient float or column mechanism finds it; a hint decides arrangement, never content. The renderer test grows a group fixture in the broad document plus four checks: the group as the one numbered element with caption last and number resolved, the uncaptioned group emitting no caption command, the direct-children depth (marking every captioned descendant instead leaves the other checks green), and a standalone captioned figure staying numbered so the classes cannot be fixed at the wrong layer. The smoke test now also asserts that the installed engine emits figure_group at all, because on an older engine the construct arrives as an admonition and every composite check would pass while testing nothing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2.
What this is
The direct-AST renderer gains the
figure_grouphandler that #2 and the README's gate list named as the step this repository owns. A bare::: figurefence (Carve PART 9 section 4c) now typesets as ONE numbered figure of ordered panels instead of stopping the pipeline withUnsupported Carve AST node type 'figure_group'the moment the engine pin moved past the node.The engine gate is cleared the same way the rest of this pipeline is built: the
Dockerfilepin moves from carve-js8815874tobde69f85(current carve-js main), the first pin that emits the node. The newest npm release (0.1.3) still predates it, and the README's requirements section now says so.What renders how
markdown:internal:captioned-figurecarrying the group's attributes. Its caption - already resolved by the engine,caption_numberincluded - closes the figure, and the list of figures gains exactly one entry per group.figureandtablechildren) keep their own captions but carryunnumberedandnotoc, the two classes Resilient's captioned commands already read. Left unmarked, a two-panel group would consume three figure numbers and file three list entries (Resilient numbers every captioned element it typesets).::: notein the group keeps its own number, which is the engine's rule too.For
examples/composite-figure.crv(table panel + listing panel under^ Figure #: Two panels, one figure) that comes out as: table with its(a)caption, listing with its(b)caption, group captionFigure 1: Two panels, one figurelast, one list-of-figures entry.Where this sits against the paged-output contract
The contract in #2 mirrors markup-carve/carve-hexapdf#18, whose merged implementation (markup-carve/carve-hexapdf#19) owns its whole layout stack and could deliver the float, the split rule and
columns-N. This adapter deliberately does not own a layout engine, and Resilient's captioned elements are not floats (its book class says so of itself), so:columns-Nhonored when width suffices: NOT expressible below this adapter today. The group typesets as the contract's degradation floor - a vertical stack of panels with captions in source order, group caption last - and thecolumns-Nclass survives on the emitted options for the day Resilient grows a float or column mechanism.The README states all of this, including the one caveat shared with every captioned element here rather than specific to groups: Resilient prefixes its own
Figure N.label from its own counter next to the label Carve resolved into the caption text.Relation to #4
Draft #4 solved the numbering half of this ticket for the pandoc-carve pipeline, and #1 replaced that pipeline with the direct-AST renderer after #4 was drafted, which is why that branch is CONFLICTING. This PR delivers the same semantics (panels
unnumbered+notoc, direct-children rule, titled-opener control living engine-side now) natively incarve/renderer.lua. If this merges, #4 can close as superseded.Tests
test/renderer.luagrows a group fixture in the broad invariant document plus four checks: the group as the one numbered element with its caption last and the engine's number resolved; an uncaptioned group emitting no caption command; the direct-children depth, pinned by a nested::: notefigure (marking every captioned DESCENDANT leaves the other checks green, so this is the discriminating one); and a standalone captioned figure staying numbered, so the panel classes cannot be fixed at the figure or table handler layer.test/smoke.shnow also asserts the installed engine emitsfigure_groupat all - on a pre-4c engine the construct arrives as an admonition and every composite check would pass while testing nothing - and typesets the new example to PDF.