Skip to content

Heading ids: adopt jgm/djot # 393 (case + non-ASCII preserved) - #72

Merged
dereuromark merged 1 commit into
mainfrom
feat/heading-ids-393-spec
Jun 6, 2026
Merged

Heading ids: adopt jgm/djot # 393 (case + non-ASCII preserved)#72
dereuromark merged 1 commit into
mainfrom
feat/heading-ids-393-spec

Conversation

@dereuromark

@dereuromark dereuromark commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Adopts the settled jgm/djot # 393 rule for
auto-generated heading ids in the carve spec, mirroring the same change already made
in djot-php (php-collective/djot#224).

Change

Auto heading ids now preserve letter case and all non-ASCII characters: replace
each maximal run of non-alphanumeric ASCII with a single -, trim, and prefix s-
for a leading digit. Previously they were lowercased, ASCII-transliterated, and used
a section- prefix.

Heading before after (#393)
# Getting Started getting-started Getting-Started
# Über uns uber-uns Über-uns
# 2024 Recap section-2024-recap s-2024-Recap
# 日本語 日本語 日本語

What's in this PR

  • carve-lib re-vendored from the docs: carve-rs reads the stamp now, so the table moves #393 carve-js build.
  • docs/examples.md heading examples regenerated → corpus tests/corpus + tests/spec updated (12 heading pairs).
  • resources/grammar.ebnf: new NORMATIVE heading-identifier rule.
  • Docs: case-study/syntax.md "Automatic Identifiers" rewritten; feature-analysis note updated.

ASCII folding becomes an opt-in implementation mode (carve-js asciiHeadingIds
parse option; carve-php AsciiHeadingIdsExtension) — never the default.

Resolves the spec side of #71

This is step 1 of 3 for #71. The
matching impl PRs (carve-js feat/heading-ids-393; carve-php pending) land after this,
then #71 closes. Conformance suite green (196 pass, 2 pre-existing skips).

Re-vendor carve-lib from the #393 carve-js build and regenerate the heading-id
corpus examples. Auto ids now preserve letter case and all non-ASCII characters,
replace each maximal run of non-alphanumeric ASCII with a single '-', and use an
's-' prefix for a leading digit (previously lowercase + ASCII-fold + 'section-').

Add a NORMATIVE heading-identifier rule to resources/grammar.ebnf and update the
case-study and feature docs. ASCII folding becomes an opt-in implementation mode
(carve-js 'asciiHeadingIds' parse option; carve-php 'AsciiHeadingIdsExtension').

Part of the heading-id slug resolution (#71).
@dereuromark
dereuromark merged commit 5ade343 into main Jun 6, 2026
2 checks passed
@dereuromark
dereuromark deleted the feat/heading-ids-393-spec branch June 6, 2026 20:36
dereuromark added a commit that referenced this pull request Jun 6, 2026
#73)

#72 adopted jgm/djot#393's case-preserving ids, but case preservation broke
</#id> cross-references: a lowercase ref no longer matched a case-preserved id
(e.g. `# Getting Started` -> `Getting-Started`, so `</#getting-started>` failed).

Switch carve to LOWERCASE (Unicode-aware; non-ASCII characters preserved, only
their case folded) - the GitHub/SSG convention authors expect for anchors, which
makes ids and the common cross-reference case-insensitive with no special lookup.

Re-vendor the lowercase carve-lib, regenerate the heading-id corpus examples,
and update the normative grammar rule + case-study/feature docs. carve now
deliberately diverges from djot-php (case-preserving per #393); both keep the
opt-in ASCII fold (carve-js asciiHeadingIds; carve-php AsciiHeadingIdsExtension).

Refs #71.
@dereuromark dereuromark changed the title Heading ids: adopt jgm/djot#393 (case + non-ASCII preserved) Heading ids: adopt jgm/djot # 393 (case + non-ASCII preserved) Jun 7, 2026
dereuromark added a commit that referenced this pull request Jun 7, 2026
Re-vendor carve-lib from the #393 carve-js build and regenerate the heading-id
corpus examples. Auto ids now preserve letter case and all non-ASCII characters,
replace each maximal run of non-alphanumeric ASCII with a single '-', and use an
's-' prefix for a leading digit (previously lowercase + ASCII-fold + 'section-').

Add a NORMATIVE heading-identifier rule to resources/grammar.ebnf and update the
case-study and feature docs. ASCII folding becomes an opt-in implementation mode
(carve-js 'asciiHeadingIds' parse option; carve-php 'AsciiHeadingIdsExtension').

Part of the heading-id slug resolution (#71).
dereuromark added a commit that referenced this pull request Jun 7, 2026
#73)

#72 adopted jgm/djot # 393's case-preserving ids, but case preservation broke
</#id> cross-references: a lowercase ref no longer matched a case-preserved id
(e.g. `# Getting Started` -> `Getting-Started`, so `</#getting-started>` failed).

Switch carve to LOWERCASE (Unicode-aware; non-ASCII characters preserved, only
their case folded) - the GitHub/SSG convention authors expect for anchors, which
makes ids and the common cross-reference case-insensitive with no special lookup.

Re-vendor the lowercase carve-lib, regenerate the heading-id corpus examples,
and update the normative grammar rule + case-study/feature docs. carve now
deliberately diverges from djot-php (case-preserving per #393); both keep the
opt-in ASCII fold (carve-js asciiHeadingIds; carve-php AsciiHeadingIdsExtension).

Refs #71.
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