Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions docs/architecture/codeblock-ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Status: Accepted
Date: 2026-08-13
Revisited: 2026-09-03
Roadmap item: `CMUI-147`

## Decision
Expand Down Expand Up @@ -47,6 +48,43 @@ It stays local to CodeBlock until a second concrete consumer needs the same exec
- Rebranding selectors and tokens without a Razor consumer would be an in-place rename, contrary to
the migration policy.

## What changed since, and what did not

By 2026-09-03 icon geometry had crossed into CodeMonster UI as precomputed data, and Playground had
been re-checked against the same question and confirmed to have no server equivalent. That made
reconsideration criterion 2 above -- "highlighting ownership for browser, Node SSR, and PHP is
explicit" -- worth answering as far as it currently can be, rather than leaving it as an open
checkbox nobody had looked at since 2026-08-13.

**Browser and Node SSR are already answered**, and were not obvious in August: `VfCodeBlock` calls
`onServerPrefetch`, and the code comment at its mount hook says so directly -- "SSR can already
contain Shiki output." Shiki's `engine/javascript` avoids the WASM Oniguruma engine entirely, so
highlighting already runs outside a browser today, during Vue SSR in Node. That rules out one
possible reason to keep deferring: this was never blocked on Shiki needing a browser.

**PHP is not answered, and the two ways to answer it carry genuinely different costs** -- which is
why this stays a reconsideration criterion rather than a decision made here:

- _Progressive enhancement_: Razor renders escaped, working `pre`/`code` -- exactly what "Consumer
guidance" above already prescribes -- and a controller loads Shiki's browser bundle
(`shiki/bundle/web`, a real published export) to color it client-side. This is the same shape as
every other adapter in this line: no PHP runtime dependency, a flash of unhighlighted text is the
cost, and it cannot be removed the way the theme flash was, because `code` is arbitrary per-request
content rather than a small enumerable set a build step could precompute.
- _A PHP-side highlighter matching Shiki's output_: checked rather than assumed, and the answer is
that none exists as a native PHP engine. The one established PHP integration, `spatie/shiki-php`,
is not an independent engine -- it shells out to a real Node process per render. Adopting that
model would make CodeBlock the only place in the entire Razor adapter with a hard Node.js runtime
dependency at request time, unlike every other component and layout, all of which are pure PHP.
Writing a from-scratch PHP tokenizer for the same TextMate grammars Shiki consumes would reintroduce
exactly the "two engines obliged to agree" risk the icon-line decision avoided by precomputing --
except here the input is unbounded, so there is nothing to precompute once and ship.

Progressive enhancement is the one consistent with everything else this migration has built and
already what "Consumer guidance" recommends for Razor; it is written here as the likely direction,
not as an adopted decision -- criterion 2 stays open until a real Razor consumer forces the choice,
and criteria 1, 3, 4, and 5 remain entirely unaddressed.

## Consumer guidance

Vue consumers that need the complete highlighted and copyable experience should keep the dedicated
Expand Down
2 changes: 1 addition & 1 deletion migration/codemonster-ui-maturity-backlog.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
"retainedProducts": [
{
"package": "@codemonster-ru/vueforge-codeblock",
"reason": "Highlighting and trusted generated markup do not have a current shared Vue and Razor contract."
"reason": "Highlighting works server-side in Node (confirmed: Shiki's JS engine, no WASM) but has no PHP equivalent without either a client-side flash of unhighlighted text or a hard Node runtime dependency in Razor -- the one established PHP integration shells out to Node rather than reimplementing the engine. See docs/architecture/codeblock-ownership.md."
},
{
"package": "@codemonster-ru/vueforge-playground",
Expand Down
5 changes: 1 addition & 4 deletions scripts/ci/frozen-showcase.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ export function findFrozenShowcaseChanges(changedPaths) {
* describes and rot into a list nobody reads. The visual gate remains the authority on whether
* pixels actually moved; this only records that someone looked.
*/
export const acknowledgedChanges = {
'examples/vue/src/sections/icons/IconsShowcase.vue':
'Import path only: the VueForge icons package moved to packages/vueforge-icons so the CodeMonster line could take the packages/icons name. The imported file is unchanged, so nothing renders differently.',
};
export const acknowledgedChanges = {};

/** Reports acknowledged paths that no longer differ, so the list cannot outlive its reasons. */
export function findStaleAcknowledgements(changedPaths, acknowledged = acknowledgedChanges) {
Expand Down
Loading