From 1cac63d7e5d7b7440554ccc1a089edd6eebe4abf Mon Sep 17 00:00:00 2001 From: Kirill Kolesnikov Date: Thu, 3 Sep 2026 22:37:24 +0700 Subject: [PATCH] Sharpen codeblock-ownership.md with what changed since August, decide nothing new docs/architecture/codeblock-ownership.md already decided this on 2026-08-13 and already told Razor consumers to render escaped source with an app-owned pre-highlighting option. What it didn't have was confirmation of its own reconsideration criterion 2 -- "highlighting ownership for browser, Node SSR, and PHP is explicit." Browser and Node SSR are answered now, and weren't obvious in August: VfCodeBlock already calls onServerPrefetch, and Shiki's engine/javascript avoids WASM entirely, so highlighting runs in Node today without a browser. PHP stays open on purpose. Checked rather than assumed: no native PHP engine reproduces Shiki's output. The one established integration, spatie/shiki-php, shells out to a real Node process per render rather than reimplementing the engine -- which is exactly the "two engines obliged to agree" risk the icon-line decision escaped by precomputing, except an arbitrary code string has nothing to precompute. The realistic PHP-side choice is between that Node dependency and progressive enhancement (escaped markup, a client controller adds color, a flash of unhighlighted text is the unavoidable cost since there is nothing to precompute). Progressive enhancement is named as the likely direction because it matches everything else this migration built; it is not adopted here as a decision, since no real Razor consumer has asked for it yet. Also removed the same stale check:frozen-showcase acknowledgement fixed on the still-unmerged playground-ownership branch -- this branch forked from main before that landed, and it blocks verify here too. --- docs/architecture/codeblock-ownership.md | 38 +++++++++++++++++++ .../codemonster-ui-maturity-backlog.json | 2 +- scripts/ci/frozen-showcase.mjs | 5 +-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/docs/architecture/codeblock-ownership.md b/docs/architecture/codeblock-ownership.md index c2a3ad4f..3f8f91b3 100644 --- a/docs/architecture/codeblock-ownership.md +++ b/docs/architecture/codeblock-ownership.md @@ -2,6 +2,7 @@ Status: Accepted Date: 2026-08-13 +Revisited: 2026-09-03 Roadmap item: `CMUI-147` ## Decision @@ -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 diff --git a/migration/codemonster-ui-maturity-backlog.json b/migration/codemonster-ui-maturity-backlog.json index 1c7154a4..0672bc32 100644 --- a/migration/codemonster-ui-maturity-backlog.json +++ b/migration/codemonster-ui-maturity-backlog.json @@ -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", diff --git a/scripts/ci/frozen-showcase.mjs b/scripts/ci/frozen-showcase.mjs index ae1ba539..110191f7 100644 --- a/scripts/ci/frozen-showcase.mjs +++ b/scripts/ci/frozen-showcase.mjs @@ -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) {