Skip to content

docs(guide): state the html tier's tag spelling on react-pages, scope the react tier's - #7939

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-7006-react-pages-html-tier-tag-spelling
Sep 6, 2026
Merged

docs(guide): state the html tier's tag spelling on react-pages, scope the react tier's#7939
baozhoutao merged 1 commit into
mainfrom
claude/issue-7006-react-pages-html-tier-tag-spelling

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #7006

content/docs/guide/react-pages.md is the home for both source-authoring tiers, but the only tag-naming rule it stated was the react tier's PascalCase one. A kind:'html' author who followed the stated rule was rejected at save time, with nothing on the page naming the rule they broke — while the page's own html examples already demonstrated the correct spelling.

Prose only. No parser, manifest or authorable-surface change: the rule already is what this page now says, the page was simply silent about it. Modelled on the same fix upstream (objectstack-ai/objectstack#13734), which repairs this defect on content/docs/ui/react-pages.mdx.

(Tag names below are written without their angle brackets — the platform's body sanitizer eats short angle-bracket fragments.)

The rule, re-measured (not taken from the card)

Re-read on the objectstack checkout at a4816a7:

  • packages/sdui-parser/src/index.ts:41const allowedTags = new Set(Object.keys(manifest.components));
  • packages/sdui-parser/src/parse.ts:95if (this.opts.allowedTags && !this.opts.allowedTags.has(tag)) {, error is not an allowed component

An exact Set.has against the manifest's own keys. grep -nE 'toLowerCase|toUpperCase|localeCompare' over packages/sdui-parser/src/ hits only codegen.ts (which derives the react tier's PascalCase names) — nothing on the whitelist path. The card's premise holds.

Registry figures re-measured independently in this repo, from packages/core/src/registry/public-blocks.ts: 57 entries, 28 carrying a namespace prefix, 4 snake_case after the colon (record:related_list, record:line_items, record:quick_actions, record:reference_rail) — matching the card's numbers exactly.

Edit 1 — the kind:'html' section now states the spelling

Unchanged sentence above it: "Only tags in the public block manifest are allowed, props are validated against each block's declared inputs, and unknown tags are a hard error at save time."

Added after it:

Those tags are the registered type names, written verbatim — whatever the registry spells, character for character, including a record: / page: / element: / action: namespace prefix and any underscore inside the name: list-view, object-form, record:related_list, record:quick_actions. The whitelist is an exact string comparison, so nothing is normalised for you: the PascalCase tags this page shows for kind:'react' are the other tier's convention and are not registered names (ListView is rejected with ListView is not an allowed component), and neither is a name re-spelled to look uniform — record:related-list is not registered, only record:related_list is.

The wording deliberately says "the registered type name, verbatim" and never "kebab-case". "kebab-case" would send an author to record:related-list, which is not registered either — so the paragraph names that wrong spelling explicitly and rules it out. The upstream model PR does use the phrase "lowercase and kebab-case"; that half of its wording is not copied here.

Edit 2 — the react-tier naming passages are scoped

Before (scope table row):

| The public data blocks | Every public non-container block, as a PascalCase tag — but what resolves and what you author against are two different sets, below. |

After:

| The public data blocks | Every public non-container block, as a PascalCase tag on this tier — but what resolves and what you author against are two different sets, below. |

Before (tag derivation):

Tags are derived by splitting the registry type on -, _ and : and PascalCasing each part: object-grid → ObjectGrid, record:details → RecordDetails.

After:

On this tier tags are derived by splitting the registry type on -, _ and : and PascalCasing each part: object-grid → ObjectGrid, record:details → RecordDetails. A kind:'html' page writes the registry type itself instead — object-grid, record:details.

The section names kind:'html' at seven places; only the section itself gained the rule.

Reverse verification — anchor counts (grep -c, on the page)

Phrase Count Expected
registered type names, written verbatim 1 1 (new anchor)
On this tier 1 1 (new anchor)
on this tier (case-insensitive, both edits) 2 2
record:related-list (the wrong spelling, named as wrong) 1 1
kebab-casecontrol, the trap wording 0 0
PascalCase 2 was 1; +1 in the html section, where it is named as the other tier's convention

Gates (redirect-then-capture; each gate's own verdict line)

Run at 7686d3c80, worktree base b8e3f8379.

Gate Exit Verdict line
node scripts/check-doc-fence-languages.mjs 0 check:doc-fences — every TypeScript block in 227 document(s) is fenced ts/tsx/typescript…
node scripts/check-doc-component-types.mjs 0 Every documented component type is registered.
node scripts/check-doc-snippet-types.mjs 0 Semantic phase: 467 of 467 block(s) judged, 0 failed. / Every covered documentation snippet compiles against the built types.
node scripts/check-doc-links.mjs 0 Links are valid across 17 scan roots.
node scripts/check-control-bytes.mjs 0 check-control-bytes: OK (scanned 6407 tracked text file(s); skipped 85 binary).
node scripts/check-changeset-presence.mjs 0 No source or published contract of a released package changed in this range, so no changeset is owed.
node scripts/check-governed-queue-guard.mjs --test content/docs/guide/react-pages.md 0 NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched.

check:doc-snippets was run for real, not narrowed: its --build-filter closure (34 tasks) was built first under the shared verify lock, so its exit 0 is a verdict about documents rather than an exit 2 "could not run".

Extra control-byte sweep beyond the gate: grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over the edited file — no hits.

Files changed

content/docs/guide/react-pages.md — 1 file, +18 / −5. No changeset (the gate above says none is owed: a docs page under content/docs releases nothing).


Generated by Claude Code

…ier's

`content/docs/guide/react-pages.md` covers both source-authoring tiers but
stated only the react tier's PascalCase rule, so a `kind:'html'` author copied a
spelling the parser rejects at save time with nothing on the page naming the
rule they broke.

Two prose edits, modelled on the same fix upstream:

- the `kind:'html'` section now says how whitelist entries are spelled — the
  registered type names written verbatim, namespace prefix and underscores
  included, with a prefixed and a snake_case example, and an explicit note that
  neither a PascalCase borrow nor a re-spelled `record:related-list` is
  registered;
- the react-tier naming passages (the scope table row and the tag-derivation
  paragraph) are now scoped with "on this tier", and the derivation points at
  what an html page writes instead.

The whitelist is `new Set(Object.keys(manifest.components))` compared by exact
`Set.has` with no case folding, so this documents the rule as it already is; no
parser, manifest or authorable-surface change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013uAaxiwgYDybsTNV9xwa1M
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.

docs: react-pages.md states only the react tier's PascalCase tag rule, so html-tier authors copy a spelling the parser rejects

2 participants