Skip to content

feat: a bare figure fence is one figure of ordered panels - #986

Merged
dereuromark merged 2 commits into
mainfrom
feat/1122-composite-figures
Aug 15, 2026
Merged

feat: a bare figure fence is one figure of ordered panels#986
dereuromark merged 2 commits into
mainfrom
feat/1122-composite-figures

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Part of markup-carve/carve#1122; spec: markup-carve/carve#1215.

What

A bare ::: figure container is a composite figure (PART 9 §4c): one figure_group node whose direct captionable children - the figure nodes the unchanged inner caption rules build, and table nodes - are its PANELS, in source order, with stray content preserved in place between them. The ^ caption after the CLOSING fence is the caption of the whole group: caption placement's sixth host, this container kind only, with the usual one-optional-blank-line allowance.

  • Numbering: the group is ONE numbering unit. ^ Figure #: draws one number; panels draw nothing; a panel with an id resolves </#id> as the group number plus a letter by panel order ("Figure 2a", a..z then aa, ab, ...). Panel ids register only when the group itself drew a number. The ingest path renumbers through the same pass the parse runs, so the two cannot disagree.
  • HTML: the corpus-pinned shape - class-first carve-figure-group on the group and carve-figure-panel on each panel, an unconditional carve-figure-panels div, the group <figcaption> last. A wrapped table panel keeps its own <caption>.
  • Openers that are not this production: a quoted title or a [label] on the opener stays a generic container, as does a bare opener nested inside an open group at ANY depth (groups do not nest). Both parse exactly as before and lint.
  • Lint: figure-group-opener-metadata, figure-group-nested, figure-group-panel-number. The two STRICT-PROFILE findings §4c names (figure-group-empty, figure-group-single-panel) are deliberately not shipped: this lint surface has no severity or profile axis yet, and reporting them unconditionally would flag documents the clause calls valid.
  • Writer: the authored form back - attribute line, bare opener, closer at the opener's width, the group caption as an unescaped ^ line on the closer, and the \^ escape kept where a blank pair detached the caption into a paragraph (corpus 318-composite-figures-6).
  • Degradation (PART 11 §10g): Markdown emits panels in order with each panel caption as an emphasized *...* paragraph and the group caption last in bold; plain text and the terminal put the group caption first, then each panel's caption line over its host's degradation.
  • Wire: additive figure_group node (PART 12 §16) - children, optional caption, attrs, pos, no target/title/label/shortCaption; ingest closed per §11. src/wire_fields.rs regenerated from the moved schema.
  • HTML import: the engine's own carve-figure-group output comes back as the node it left as; a <figure> without the own-output class stays an unsupported element.

One deliberate behavior alignment outside the group itself: an UNRESOLVED caption_number now renders as the literal # in HTML, which is what the Markdown, plain-text and terminal renderers already emitted. From a parse this state is reachable only in panel captions; on the ingest path a caption_number without n shows the visible # instead of disappearing.

Sequenced after the quote-attribution withdrawal

This work was built on #984 and rebased onto main the moment that PR merged, so the branch is one commit off current main. The dependency was structural, not stylistic: the spec pin this feature needs sits past upstream's quote-attribution withdrawal (markup-carve/carve#1213), and without 984 that pin is red on arrival - the regenerated wire-field map refuses the attribution property the engine still published, and the corpus round-trip sweeps (corpus_round_trip, adjacent_text_runs, the ingest-budget sweep) have no per-slug allowlist to carry the mismatch. With 984 on main, no carve#1213 exclusions were needed: every corpus category stays in IMPLEMENTED and the ten new 318-composite-figures documents render byte-exact.

Temporary spec pin

The spec submodule points at the spec draft branch commit 078c32d (markup-carve/carve#1215, spec/1122-composite-figures) so the ten 318-composite-figures corpus documents and the figure_group schema entry are present. The pin is temporary and moves to the merged main commit before this PR leaves draft.

Rollout order

Engine PRs (carve-js, carve-php, carve-rs) merge first; the spec corpus pin moves after; satellites (pandoc-carve, carve-lsp, carve-hexapdf, carve-sile, wysiwyg) are follow-ups, filed not implemented.

@dereuromark dereuromark added the enhancement New feature or request label Aug 15, 2026
dereuromark added a commit to markup-carve/carve-py that referenced this pull request Aug 15, 2026
…drawal (#40)

* chore: bump the engine past the table scope rule and the caption withdrawal

`main` has been red at `test_corpus_renders_byte_identically` since 2026-08-13.
The pin sat at carve-rs 9130a7c ("bump spec corpus submodule to carve b1e5f5d"),
39 commits behind that repo's `main`, and the spec corpus this binding is checked
against moved underneath it.

Measured against the corpus at carve 3154f1a, each pin built and installed as a
wheel:

    pin 9130a7c   1017 pairs, 77 mismatches
    pin 9ff0878   1017 pairs,  9 mismatches

68 documents move from mismatching to byte-identical, none move the other way,
and the 9 that remain are the same 9 in both runs.

The compiled extension really moved rather than only the manifest. The embedded
cargo checkout path in `carve.abi3.so` reads
`checkouts/carve-rs-7867d825a4352386/9130a7c` before and
`checkouts/carve-rs-7867d825a4352386/9ff0878` after, and the file's sha256 goes
from 46d72f51 to c4f412e5.

Of the 68, 44 gain `scope` on every `th`: PART 10 SST9, implemented in carve-rs
7660a02. They are not all named for tables, because a table inside a footnote
body or under a caption carries the rule too (`203`, `225`, `281`, `282`, `285`,
`47-numbered-cross-references-4`, `89-block-attribute-lines-4`).

The other 24 come from the rest of the range:

- `293`, `299`: the semantic-name rules and the tier split.
- `300`: an attribute needs a separator before the next one.
- `301`: a derived title yields to an authored one.
- `302`: a math span's base class keeps the class slot in place.
- `305`: an abbreviation expands inside an inline container.
- `313`, `314`, `315`, `45-inline-extensions*`, `71-attribute-edge-cases-11`:
  the reference, footnote and inline-note resolution fixes.

Every one is catch-up: the binding now agrees with a spec fixture it previously
disagreed with. No corpus fixture was touched.

`tests/test_carve.py::test_table` asserted `<th>a</th>`, which was the output of
an engine predating SST9 rather than anything the spec asks for. 44 corpus
fixtures spell `scope="col"`, so the hand-written expectation was the stale side.
That is the failure mode the corpus gate exists to catch, and the reason it sits
beside these unit tests.

The remaining 9 are `318-composite-figures*`, and they are not pin drift. The
spec added them at carve 9cd27d8 today, and carve-rs implements the rule only on
the open draft `markup-carve/carve-rs#986`, so no merged carve-rs revision
renders them. Pinning that branch would revert everything merged after it, so
this stays on the engine's `main` tip and those 9 stay red here until that PR
lands.

* style: join the carve-rs use block rustfmt wants on one line

`cargo fmt --check` has been failing on `src/lib.rs:14` since the import list
last shrank: six names fit inside the width, so rustfmt joins them and the
committed vertical form is a diff.

CI here does not run `cargo fmt`, so nothing reported it. Kept separate from
the engine bump because it shares no reasoning with it.
@dereuromark
dereuromark marked this pull request as ready for review August 15, 2026 11:47
@dereuromark
dereuromark force-pushed the feat/1122-composite-figures branch from 629e547 to c83d649 Compare August 15, 2026 12:54
PART 9 section 4c: `::: figure` with nothing else on the opener is a
composite figure - a `figure_group` node whose direct captionable
children (the figures the unchanged inner caption rules build, and
tables) are its panels, in source order, with stray content preserved
in place between them. The `^ ` caption after the CLOSING fence is
the caption of the whole group: caption placement's sixth host, this
container kind only, one optional blank line, two detach.

The group is one numbering unit. Its caption draws one number from
the shared per-label sequence; panels draw nothing, and a panel with
an id resolves a crossref as the group number plus a letter by panel
order, a..z then aa, ab. Panel ids register only when the group drew.
A `#` placeholder in a panel caption has nothing to resolve against
and stays the literal `#` - which the HTML renderer now prints for
any unresolved caption number, the way the Markdown, plain and
terminal targets always did.

An opener carrying a quoted title or a label stays a generic
container, and so does a bare opener nested anywhere inside an open
group's body: groups do not nest, and both spellings lint alongside
the panel placeholder under the section's rule ids. The two
strict-profile findings the section names wait for a lint severity
axis rather than shipping unconditionally.

The canonical writer emits the authored form back, the caret on the
closer unescaped because that position is the caption slot, and
escaped where a blank pair detached the caption into a paragraph.
The non-HTML targets degrade per PART 11 section 10g: Markdown puts
each panel caption after its host as an emphasized paragraph and the
group caption last in bold; plain text and the terminal lead with the
group caption, the only line on those targets that says what the
following blocks are one of. AST JSON gains the additive
figure_group node, closed on ingest like every other, renumbered on
ingest through the same pass the parse runs; the HTML importer reads
the engine's own group shape back. The spec submodule moves onto the
branch that pins the ten corpus documents, and the wire-field map
regenerates from its schema.
The bridge landed while this branch was out, and its outbound match is
exhaustive over BlockNode, so the new node had to get a decision rather than
a default.

The vendored carve-grammars schema map has no name for `figure_group` - the
editor schema predates PART 9 section 4c - and adding one here would fork the
map this bridge exists to read rather than repeat. So the group degrades to
the generic container the map does have, the same one an admonition rides on:
every panel and the group caption survive, and the fact that they were one
figure is reported as degraded. The reason lives in the map's `unmapped`
section, where the bridge's own guard test requires a decision for every wire
type, with a provenance note to keep it across the next refresh until
carve-grammars carries one of its own.

The corpus ratchet moves from 791/215 to 793/224. That is the eleven
composite-figure documents arriving with the spec pin and nothing else: the
corpus went from 1006 pairs to 1017, the eleven added pairs are all
`318-composite-figures*`, and no existing pair changed content. Two hold no
node the editor schema lacks and round-trip strictly; nine carry a group.
@dereuromark dereuromark reopened this Aug 15, 2026
@dereuromark
dereuromark merged commit 49c513d into main Aug 15, 2026
2 checks passed
@dereuromark
dereuromark deleted the feat/1122-composite-figures branch August 15, 2026 13:25
dereuromark added a commit to markup-carve/carve-go that referenced this pull request Aug 15, 2026
…ibutes

The previous rebuild in this branch left thirteen corpus documents diverging,
all of them naming two constructs the engine did not yet have. Both have since
landed in carve-rs: markup-carve/carve-rs#986 (PART 9 section 4c, composite
figures) and markup-carve/carve-rs#996 (a cell's attributes bind after its kind
and alignment markers). Rebuilt via this repository's own build-wasm.sh, which
writes REV and the digest in the same step as the bytes.

REV moves from c83d64922bcb080d5a85aecd2f53adf506fbe8c6 to
98de7874ad2e81f69e57764562c83f4918522ac2 (carve-rs main).

Measured against carve 1436f39a, 1025 corpus pairs:

  before this commit  13 diverging
  after               0 diverging

The thirteen that closed are the nine `318-composite-figures*` documents that
were failing and the four `319-cell-attributes-*` documents that were failing.
All eleven `318-composite-figures` documents and all six `319-cell-attributes`
documents now match the spec.

The control is no longer vacuous. `318-composite-figures-8` asserts that an
opener carrying a title or a `[label]` stays a generic container. Before this
rebuild it passed for the wrong reason: the engine had no rule separating a
bare opener from a decorated one, so stripping the title and the label changed
nothing but two metadata lines. It now discriminates structurally. The document
as written renders:

    <div class="figure">
      <p class="admonition-title">A titled figure div</p>
      <figure>
        <img src="a.png" alt="one">
        <figcaption>(a) One</figcaption>
      </figure>
    </div>
    <p>^ Not a group caption</p>

and the same document with the title and the label removed, so both openers are
bare, renders a different production entirely:

    <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>
      <figcaption>Not a group caption</figcaption>
    </figure>

No allowlist and no drift file exists in this repository, and none is added.
dereuromark added a commit to markup-carve/carve-go that referenced this pull request Aug 15, 2026
…gures (#39)

* fix: the corpus population guard reads the pages where the spec keeps them

The guard that decides whether a corpus run compared a whole corpus reads the
spec's example pages and counts their `::: compare` blocks, because a count
derived from the directory under test would move with the directory and could
not detect truncation. It read them from docs/examples/.

markup-carve/carve#1194 made those pages generated sources and filed them under
resources/examples/, beside the other generator inputs. The read is fatal when
it misses, by design, so the corpus job stopped at the first page instead of
comparing anything:

    no corpus source page at .../docs/examples/core.md: no such file or
    directory. tests/corpus is generated from these pages; if the spec moved
    them, this helper has to move with them

That is the failure the guard is supposed to produce, and it is also why every
real divergence behind it went unreported: the job has been red since
2026-08-14 with a wiring error on top of a stale artifact, and only the wiring
error was visible. The helper now takes the route corpus_ast_test.go already
takes to resources/ast-schema.json.

Measured against carve main: the job goes from fatal-before-first-comparison to
1023 pairs compared, 81 of them diverging.

* chore: rebuild the embedded wasm, and name what the engine still cannot render

This module has no parser. It embeds a wasm32-wasip1 build of carve-rs and
renders by driving it over WASI stdio, so its conformance is the embedded
artifact's conformance and "implementing" a construct here means rebuilding
against a carve-rs that implements it.

Rebuilt from carve-rs c83d64922bcb080d5a85aecd2f53adf506fbe8c6 (main). Measured
against carve main, with the population guard fixed so the comparison runs at
all: 81 of 1023 corpus documents diverged before, 13 after. The 68 that this
closes are the ordinary staleness the corpus job exists to catch - tables,
captions, attribute parsing, footnote and reference resolution.

The 13 that remain are not staleness. They are two constructs carve-rs itself
does not implement, so no rebuild reaches them:

  - 318-composite-figures{,-2,-3,-4,-5,-6,-9,-10,-11}: PART 9 §4c, composite
    figures. carve-rs#986 was the port and was closed unmerged.
  - 319-cell-attributes-bind-after-the-kind-and-alignment-markers{,-2,-3,-6}:
    an attribute block after a cell's `=` marker is still rendered as cell text.

Two of the eleven composite-figure documents pass, and they are worth naming
because of WHY they pass: -7 (a `^ ` line after a `::: note` closer is an
ordinary paragraph) and -8 (an opener carrying a title or a label stays a
generic container) both assert the PRE-§4c behavior, which this engine has
always had. -8 in particular is the control for the whole clause, and today it
passes vacuously: making its openers bare changes nothing in the output but the
title and label lines, because the engine has no rule that tells a bare opener
from a decorated one. It will only start meaning something once §4c lands
upstream.

The corpus job stays strict. Nothing here suppresses those 13; the job is red
for them, which is the accurate report.

TestToHTML_Table asserted a bare <th>. The header cell carries scope="col" now,
pinned by the corpus documents this rebuild brings into line, so the hand-written
expectation moves with it - the failure mode corpus_test.go's comment predicts
for the hand-written half of this suite.

THE NATIVE COMPARISON NOW REQUIRES CARVE_BIN. TestToHTML_ByteIdenticalToNative
and the static byte check assert "the wasm renders what the native engine
renders", which is a statement about ONE revision - the native side has to be
the carve-rs internal/wasm/REV names. The helper picked its own reference off
the filesystem instead: two hardcoded target/ paths, then `carve` on PATH, none
of which is that revision by construction. It failed exactly that way here, with
a stale local build predating scope="col" reporting a byte mismatch on tables
against a wasm the corpus proves correct. A check that chooses its own reference
cannot tell "the wasm is wrong" from "the thing I found is old", and it reported
the first. It now skips until a caller vouches for a binary, which is what CI
already did on every run.

* chore: rebuild the embedded wasm past composite figures and cell attributes

The previous rebuild in this branch left thirteen corpus documents diverging,
all of them naming two constructs the engine did not yet have. Both have since
landed in carve-rs: markup-carve/carve-rs#986 (PART 9 section 4c, composite
figures) and markup-carve/carve-rs#996 (a cell's attributes bind after its kind
and alignment markers). Rebuilt via this repository's own build-wasm.sh, which
writes REV and the digest in the same step as the bytes.

REV moves from c83d64922bcb080d5a85aecd2f53adf506fbe8c6 to
98de7874ad2e81f69e57764562c83f4918522ac2 (carve-rs main).

Measured against carve 1436f39a, 1025 corpus pairs:

  before this commit  13 diverging
  after               0 diverging

The thirteen that closed are the nine `318-composite-figures*` documents that
were failing and the four `319-cell-attributes-*` documents that were failing.
All eleven `318-composite-figures` documents and all six `319-cell-attributes`
documents now match the spec.

The control is no longer vacuous. `318-composite-figures-8` asserts that an
opener carrying a title or a `[label]` stays a generic container. Before this
rebuild it passed for the wrong reason: the engine had no rule separating a
bare opener from a decorated one, so stripping the title and the label changed
nothing but two metadata lines. It now discriminates structurally. The document
as written renders:

    <div class="figure">
      <p class="admonition-title">A titled figure div</p>
      <figure>
        <img src="a.png" alt="one">
        <figcaption>(a) One</figcaption>
      </figure>
    </div>
    <p>^ Not a group caption</p>

and the same document with the title and the label removed, so both openers are
bare, renders a different production entirely:

    <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>
      <figcaption>Not a group caption</figcaption>
    </figure>

No allowlist and no drift file exists in this repository, and none is added.
dereuromark added a commit to markup-carve/carve-py that referenced this pull request Aug 15, 2026
…#41)

This binding has no parser. It calls carve-rs through PyO3, so a construct the
engine gains is a construct this package gains the moment the pin moves, and
until then thirteen corpus documents diverged here for reasons no Python change
could reach.

Both constructs have now landed upstream: markup-carve/carve-rs#986 (PART 9
section 4c, composite figures) and markup-carve/carve-rs#996 (a cell's
attributes bind after its kind and alignment markers).

The pin moves from 9ff087845ebbc31e650fed4faea01f4eea895b82 to
98de7874ad2e81f69e57764562c83f4918522ac2 (carve-rs main), in Cargo.toml and in
Cargo.lock together.

Measured against carve 1436f39a, 1025 corpus pairs, wheel rebuilt each time:

  at 9ff08784   13 diverging
  at 98de7874    0 diverging

The thirteen were the nine `318-composite-figures*` documents and the four
`319-cell-attributes-*` documents that were failing; all eleven of the former
and all six of the latter now match the spec.

The control for the clause, `318-composite-figures-8`, asserts that an opener
carrying a title or a `[label]` stays a generic container. It passed at the old
pin as well, but only because the engine had no rule separating a bare opener
from a decorated one - both spellings rendered `<div class="figure">`, so the
document could not have failed. At the new pin the same mutation, stripping the
title and the `[label]` so both openers are bare, changes the production:

    <div class="figure">
      <p class="admonition-title">A titled figure div</p>
      ...
    </div>
    <p>^ Not a group caption</p>

becomes

    <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>
      <figcaption>Not a group caption</figcaption>
    </figure>

Nothing is allowlisted or skipped; the corpus test compares every pair.

The CHANGELOG entry lands under the existing 0.1.1 heading rather than a new
one. v0.1.1 is a draft, not a release, so the last released tag is v0.1.0 and a
consumer upgrading from it sees a single engine move.
dereuromark added a commit to markup-carve/carve-wasm that referenced this pull request Aug 15, 2026
…#34)

This crate wraps carve-rs and exposes it through wasm-bindgen; it has no parser
of its own. The pin had not moved since 6f1d9bfb, and the corpus measured the
cost: 94 of 1025 documents rendered something other than what the spec pins.

The pin moves to 98de7874ad2e81f69e57764562c83f4918522ac2 (carve-rs main), in
Cargo.toml and Cargo.lock together. Cargo.lock also gains pulldown-cmark and
unicase, which the engine now depends on.

Measured against carve 1436f39a, artifact rebuilt with `wasm-pack build
--target nodejs` for each row and driven through the JS API, which is what
tests/corpus.mjs does:

  at 6f1d9bfb   94 diverging
  at 98de7874    0 diverging

The 94 are dominated by tables (a header cell carries `scope`, cell attributes,
alignment, spans, continuation rows), attribute parsing, footnote and reference
resolution, semantic spans, and the language attribute. Thirteen of them are the
two constructs this bump was taken for: nine `318-composite-figures*` documents
and four `319-cell-attributes-*`. All eleven `318-composite-figures` documents
and all six `319-cell-attributes` documents now match.

Composite figures are PART 9 section 4c, landed upstream as
markup-carve/carve-rs#986; the cell-attribute order is
markup-carve/carve-rs#996.

The clause's control, `318-composite-figures-8`, asserts that an opener carrying
a title or a `[label]` stays a generic container. At the old pin it could not
have failed: the engine had no rule separating a bare opener from a decorated
one, which the corpus shows directly - `-8` passed while every bare-opener
document diverged by rendering the same `<div class="figure">`. At the new pin
the distinction is real. Stripping the title and the `[label]` from `-8`, so
both openers are bare, changes the production:

    <div class="figure">
      <p class="admonition-title">A titled figure div</p>
      <figure>
        <img src="a.png" alt="one">
        <figcaption>(a) One</figcaption>
      </figure>
    </div>
    <p>^ Not a group caption</p>

becomes

    <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>
      <figcaption>Not a group caption</figcaption>
    </figure>

Nothing is allowlisted; this repository has no allowlist and does not gain one.
smoke.mjs and the AST schema check pass unchanged.
dereuromark added a commit to markup-carve/carve-rb that referenced this pull request Aug 15, 2026
…#66)

This gem has no parser. ext/carve is a magnus binding over carve-rs, pinned to
an exact revision, so a construct the engine gains arrives here when the pin
moves and not before. Thirteen corpus documents diverged for that reason alone.

Both constructs have landed upstream: markup-carve/carve-rs#986 (PART 9 section
4c, composite figures) and markup-carve/carve-rs#996 (a cell's attributes bind
after its kind and alignment markers).

The pin moves from 8dada737f608da124e06a1f7e43f962f98a3e68a to
98de7874ad2e81f69e57764562c83f4918522ac2, in ext/carve/Cargo.toml and
ext/carve/Cargo.lock together.

Measured against carve 1436f39a, extension recompiled each time, 1025 corpus
pairs:

  at 8dada737   13 diverging
  at 98de7874    0 diverging

The thirteen were the nine `318-composite-figures*` documents and the four
`319-cell-attributes-*` documents that were failing; all eleven of the former
and all six of the latter now match the spec.

EXPECTED in test/corpus_ast_types_test.rb gains `figure_group`. That list is a
one-directional check: a recorded type going missing fails, a new one only
warns, and this run warned. Recording it is what makes the type load-bearing -
if a later pin drops the group node, the suite says which type went rather than
leaving thirteen documents to explain it. It is a tightening, not a widening:
the old pin produced no unrecorded type at all, so this line would have failed
the suite before the bump.

The control for the clause, `318-composite-figures-8`, asserts that an opener
carrying a title or a `[label]` stays a generic container. At the old pin it
could not have failed - the engine had no rule separating a bare opener from a
decorated one, so both spellings rendered `<div class="figure">`, which is what
every diverging bare-opener document showed. At the new pin the mutation that
should break it does. Stripping the title and the `[label]` so both openers are
bare turns

    <div class="figure">
      <p class="admonition-title">A titled figure div</p>
      <figure>
        <img src="a.png" alt="one">
        <figcaption>(a) One</figcaption>
      </figure>
    </div>
    <p>^ Not a group caption</p>

into

    <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>
      <figcaption>Not a group caption</figcaption>
    </figure>

Nothing is allowlisted or skipped. The CHANGELOG entries go under the existing
Unreleased heading, which already argues from v0.1.0, the only released tag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant