docs(docs-app): wire up build-time .gjs.md docs, start .md migration - #743
docs(docs-app): wire up build-time .gjs.md docs, start .md migration#743patricklx wants to merge 5 commits into
Conversation
2d8fa61 to
17681b4
Compare
…atus `shadow-demo-element.ts` still claimed it imports the app's stylesheets into each shadow root "mirroring `<Shadowed includeStyles>`". It stopped doing that in 1d7bfa3 ("do not add host styles"), which left the `STYLESHEET_SELECTOR` constant dead and the comment wrong. Drop the constant and describe what actually supplies the CSS: demos render `<ThemeSupport />` themselves, so the Carbon stylesheets land inside the shadow root as an inline `<style>`, and `:root` theme tokens inherit across the boundary as custom properties. Also record why `rehype-shadow-demo.ts` stays hand-rolled. kolay merged a generic `wrapDemos` rehype plugin (universal-ember/kolay#361, unreleased as of kolay 5.4.0 - it ships in the pending 6.0.0), but it wraps the demo placeholder in a component invocation rather than renaming it. repl-sdk grafts each compiled demo in afterwards via `element.querySelector('#<placeholderId>')`, which does not cross a shadow boundary, so a shadow-DOM wrapper would hide the placeholder and trip repl-sdk's "Could not find placeholder / target element" assertion. Renaming the placeholder keeps it in the light DOM, which is why the current implementation works. Comments only - no behavior change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Patrick Pircher <patrick.pircher@ibm.com>
Start of moving docs-app component docs off runtime-compiled .md (kolay's in-browser REPL) to build-time-compiled .gjs.md, following up on this PR's own investigation into kolay's wrapDemos status. Two infra gaps had to close first, both scoped to build-time docs only: - rehypeShadowDemo renames each demo placeholder div to a custom element, which kolay's build-time compiler can't find (it string-replaces the placeholder's literal `</div>`, which no longer exists), silently producing empty demos. Give it an opt-in `forBuildTimeInjection` mode that keeps an inner `<div>` for the injector to target; the runtime call site is untouched and emits byte-identical output. - Demo fences import `carbon-components-ember/components` and `carbon-components-ember/helpers`, which only resolve at runtime via setupKolay's dynamic module map (the package's real exports are the `/index` forms). Alias them for the build-time path, plus a `docs-support` alias backing `ThemeSupport`/`didInsert` and a `scope` string so `<ThemeSwitcher />`/`<APIDocs>`/etc. resolve at the top level of a `.gjs.md` file, mirroring the runtime `topLevelScope`. Converts tags.md and list/item.md (one flat, one nested-folder page) as a verified spike - browser-checked (not just glint/build) against an unconverted control page, since an empty demo looks identical to a known docs-app live-preview flake otherwise. notifications.md is intentionally left as .md: its demo uses setOwner() on a plain class for @service injection, which has no build-time equivalent without rewriting it as a real Component. Remaining ~58 .md docs still need converting; recipe and gotchas recorded in .pjp-runner/todo.md for follow-up work. Signed-off-by: Patrick Pircher <patrick.pircher@ibm.com>
54523d9 to
c9f3c2c
Compare
📖 Docs Preview🔗 Preview URL: https://ibm.github.io/carbon-components-ember/pr-previews/pr-743/ Built from commit 17d51ac |
Applies the recipe from the Tag/List Item spike (previous commit) to the
remaining 32 flat top-level component docs, moving them off the
runtime-compiled REPL onto kolay's build-time .gjs.md compiler. Each file
browser-verified (Playwright, headless build of dist) to confirm its live
demos actually render component markup inside their shadow root, not just
that glint/build stay green - an empty demo looks identical to a known
docs-app live-preview flake otherwise.
pagination.md's "sizes" demo used `@onPageChanged={{() => {}}}`, an inline
arrow expression inside a mustache that kolay's runtime REPL tolerated but
the real ember-template-compiler used for build-time .gjs.md does not
(`Expecting 'OPEN_SEXPR', ... got 'CLOSE_SEXPR'`). Fixed to use the same
`const noop = () => null` + `{{noop}}` pattern already used by the other two
demos in that file.
Remaining nested-folder docs (form/, list/, select/, etc.) and
1-get-started/index.md are left for a follow-up batch; notifications.md
stays .md pending its Context class becoming a real Component (see
.pjp-runner/todo.md).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Patrick Pircher <patrick.pircher@ibm.com>
…js.md Continues the flat-file batch: converts the form/, indicator/, layout/, list/, select/, skeleton/, and text-input/ subfolders (22 files) to build-time .gjs.md, following the same recipe. Each browser-verified (Playwright against a built dist) to confirm live demos render real content in their shadow root. progress/bar.md is left as .md: invoking bare <ProgressBar /> in a built .gjs.md page throws "Cannot destructure property 'compilable' of 'component' as it is null" during template compilation, regardless of args. Bisected via scratch pages to confirm it's not markdown content, not IconMap/registerIcon state (nothing in the library ever calls registerIcon, so that registry is always empty and unrelated), and not the generic <Icon> component in isolation (a standalone <Icon @ICON='...' /> demo builds and renders fine). ProgressBar is the only component in the library that invokes the generic <Icon @ICON='...'> string-keyed component from within a conditional block, so the bug is scoped to how kolay's build-time per-page compiler resolves that specific nested-conditional-component pattern from a precompiled library template. Needs deeper investigation into kolay/embroider's component resolution for this case; noted in .pjp-runner/todo.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Patrick Pircher <patrick.pircher@ibm.com>
|
the code blocks in docs do not have syntax highlighting. it works on main |
patricklx reported code blocks lost syntax highlighting on pages converted to build-time .gjs.md (works on main's runtime-compiled .md). vite.config.mjs's kolay() plugin only wired up rehypeShadowDemo for the build-time compiler; routes/application.ts's runtime setupKolay() call separately registers rehypeShikiFromHighlighter, which the build-time path never got. Added the equivalent rehypeShiki plugin to kolay()'s rehypePlugins, using @shikijs/rehype's default export (self-contained highlighter creation) since vite.config.mjs runs in Node at build time and doesn't need the runtime path's manual getHighlighterCore/loadWasm dance. Verified via Playwright that a converted page (tags) and an unconverted control (notifications, still runtime .md) render visually identical multi-color token highlighting, and that every built .gjs chunk contains shiki output. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Patrick Pircher <patrick.pircher@ibm.com>
|
Fixed the syntax-highlighting regression (17d51acd). Root cause: Fix: added Verified:
🤖 Generated with Claude Code |
Summary
Follow-up to the "check whether kolay's new shadow-DOM support can replace our downstream implementation" investigation, now extended into starting the migration of
docs-app's component docs from runtime-compiled.md(kolay's in-browser REPL) to build-time-compiled.gjs.md.Why move to
.gjs.md.mddocs are compiled on-demand in the browser (via repl-sdk);.gjs.mddocs are compiled once at build time into real Ember components. Moving reduces runtime REPL/compile cost per page and gets these docs full type-checking via glint.What this PR adds
kolay's vite plugin (
kolay()) already forwardsscope/rehypePlugins/remarkPluginsto its build-time.gjs.mdcompiler (undocumented inkolay's publicOptionstype, but wired incombined.js), so no upstream change was needed. Two real gaps had to close first, both scoped to the build-time path only:rehypeShadowDemosilently produced empty demos. It renames each demo's placeholder<div id="repl_N">to<carbon-shadow-demo id="repl_N">. Runtime.mdgrafts the compiled demo into that element byiddirectly. Build-time.gjs.md(kolay'sgjs-md.js) instead finds the node byidand injects the invocation by string-replacing the node's literal</div>— which no longer exists once the div is renamed, so the replace silently no-ops and the demo renders styled but empty. Fixed by givingrehypeShadowDemoan opt-in{ forBuildTimeInjection: true }mode that keeps an inner<div>for the injector to target (CarbonShadowDemore-parents whatever ends up inside it regardless of tag, so the wrapper is otherwise inert). The runtime call site inroutes/application.tsis untouched and emits byte-identical output.carbon-components-ember/componentsandcarbon-components-ember/helpersonly work at runtime becausesetupKolay's dynamicmodulesmap intercepts them before real module resolution — the package's realexportsonly has the/indexforms. Aliased both (anchoredRegExps, so already-correct/index//iconspecifiers elsewhere aren't affected) invite.config.mjs. Also added adocs-supportalias (newdocs-app/app/docs-support/index.tsbarrel) backing theThemeSupport/didInsertimports demos use, and ascopestring so<ThemeSwitcher />/<APIDocs>/<ComponentSignature>/<ModifierSignature>/<Callout>resolve at the top level of a.gjs.mdfile, mirroring the runtimetopLevelScope.Converted so far
tags.mdandlist/item.md(one flat page, one nested-folder page, to exercise both URL shapes) — verified in a real browser (not just glint/a green build) that the demo's shadow root contains real rendered component markup, compared against an unconverted.mdcontrol page in the same session. An empty demo looks identical to a known docs-app live-preview flake otherwise, so build success alone isn't proof.notifications.mdis intentionally left as.md: its demo usessetOwner()on a plain (non-Component) class to get@serviceinjection working, which has no build-time-import equivalent without rewriting it as a realComponentsubclass first.~58
.mddocs remain. Recipe and gotchas recorded for follow-up work.The original comment fix
shadow-demo-element.tsstill claimed it imports the app's stylesheets into each shadow root "mirroring<Shadowed includeStyles>". It stopped doing that in 1d7bfa3 (do not add host styles), which leftSTYLESHEET_SELECTORdead and the comment wrong. Shadow demos are styled anyway because component docs render<ThemeSupport />inside the demo, emitting the Carbon stylesheets as an inline<style>within the shadow root;:roottheme tokens inherit across the boundary as custom properties.Test plan
glintindocs-app: 20 errors, identical to themainbaseline (all pre-existing, none in touched files)DOCS_URL=versions/main pnpm buildindocs-app: succeeds2-components/tagsand2-components/list/itemrender real component markup inside their demos' shadow roots, matching a.mdcontrol pagepnpm lint: no new errors/warnings🤖 Generated with Claude Code