Skip to content

Spec: block attribute lines — multi-line + merge + reach (P2 §15) - #25

Merged
dereuromark merged 1 commit into
mainfrom
spec/block-attribute-lines
May 21, 2026
Merged

Spec: block attribute lines — multi-line + merge + reach (P2 §15)#25
dereuromark merged 1 commit into
mainfrom
spec/block-attribute-lines

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Addresses the P2 attribute multi-line/merge gap from the audit. Wires the previously-orphan block_attributes production into the grammar and pins the standalone-attribute-line semantics that carve-php and djot already implement (verified identical: {#id}\n{key=val}\n{.foo .bar}\n{key=val2}\n{.baz}\n{#id2}\nOkay<p id="id2" key="val2" class="foo bar baz">Okay</p>).

Grammar

  • block_attributes is now a first-class block-level line (it was defined but never referenced — orphan). Renders nothing on its own; attaches to a following block.
  • Multi-line block: attributes separated by any mix of whitespace/newlines (continuation lines may be indented), with a mandatory separator (no glued {#id.foo}).

PART 9 §15 (normative, not-context-free semantics)

  • Reach: leading attribute blocks float to the next block across blank lines; a dangling run (no following block) is dropped.
  • Accumulation: id last-wins, key=value last-wins per key, classes accumulate in order, no dedup ({.a .b} then {.b .c}class="a b b c" — matches djot + carve-php).
  • Multi-line: the } need not be on the opening line.

syntax.md §4.10 documents it with the djot canonical worked example.

Cross-impl status

carve-php implements §15 in full (it's the reference here). carve-js does not yet parse leading block-attribute lines — impl + corpus fixtures follow as the established spec-leads sequence (sections #18#16#19, tier #20#19#21, inline-span #22#21#23). 90/90 corpus + normativity pass.

Follow-ups

  • carve-js: parse leading block-attribute lines (accumulator + multi-line + reach).
  • carve: re-vendor carve-lib + add corpus fixtures.
  • carve-php: bump corpus submodule (already conformant).

Wires the previously-orphan block_attributes production into the block
rule and pins the standalone-attribute-line semantics that carve-php
and djot already implement.

Grammar (PART 2):
- block_attributes is now a first-class block-level line (was defined
  but unreferenced). It renders nothing on its own and attaches to a
  following block.
- block_attributes accepts a multi-line block: attributes separated by
  any mix of whitespace and newlines (continuation lines may be
  indented), with a mandatory separator between attributes (no glued
  {#id.foo}).

PART 9 §15 (NORMATIVE) -- the precise, not-context-free semantics:
- REACH: leading attribute blocks float forward to the next block,
  across intervening blank lines; a dangling run with no following
  block is dropped.
- ACCUMULATION over consecutive blocks: id last-wins, key=value
  last-wins per key, classes accumulate in order with NO dedup
  ({.a .b} then {.b .c} -> class="a b b c"). Matches djot's canonical
  example and carve-php.
- MULTI-LINE: a single block may wrap; the } need not be on the
  opening line.
- The target block's own trailing attributes merge under the same rules.

syntax.md §4.10 documents reach/accumulation/multi-line with the djot
canonical worked example.

carve-php implements §15 in full; carve-js does not yet parse leading
block-attribute lines -- impl + corpus follow (spec-leads sequence, as
with sections/tier/inline-span). 90/90 corpus + normativity pass.
@dereuromark
dereuromark merged commit f23760a into main May 21, 2026
2 checks passed
@dereuromark
dereuromark deleted the spec/block-attribute-lines branch May 21, 2026 15:13
dereuromark added a commit that referenced this pull request May 21, 2026
Completes the block-attribute-line rollout on the carve side (PART 9
§15, spec #25; carve-js renderer carve-js#22; carve-php already
conformant).

- docs/.vitepress/carve-lib: re-vendored from carve-js main (block-attr
  parser + per-block-type attr rendering).
- docs/examples.md + corpus: three new Attributes fixtures --
  17-attributes-2 (single attr line -> paragraph), -3 (consecutive
  class accumulation), -4 (attrs on a list). All class-focused so they
  agree byte-for-byte across carve-js AND carve-php (verified); they
  avoid the separate multi-attribute render-ORDER divergence (carve-js
  class/id/key vs carve-php id/class/key), tracked separately.
- resources/grammar.ebnf: tightens block_attributes to match BOTH
  reference impls -- a continuation is a single line break (+indent),
  and a BLANK line inside the braces ends the block (not interior
  padding). The earlier ws_nl form over-claimed blank-line support that
  neither carve-js nor carve-php implements. Adds §15 notes on the
  blank-line and quoted-} -across-lines (pathological, unsupported)
  edges.

93/93 corpus + normativity tests pass.
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