docs: state the code-language comments as current contracts

The new JSDoc and test prose narrated the change instead of the shipped
behavior: "pre-unification", "the old read table", "used to persist ... it
now persists". A reader at HEAD cannot resolve those stages, and the
persisted-value rule they describe is a durability contract that stands on
its own.

Restate each as the present contract: a suffix whose value a recorded
session already holds keeps it byte-identical; every other suffix takes its
language's short name. Rename the test's transcribed expectation away from
the branch vantage and re-wrap the module comment the earlier edit left
over-long.
This commit is contained in:
mektpoy committed 2026-09-23 14:23:07 +08:00
1 parent 5774f385f4
commit 88b1ea3c0b
6 files changed
+58 -55

No files matched your search

@@ -11,10 +11,11 @@
* (`@deepseek-ai/dsh-util-code-language`: python, rust, yaml, markup, …) is
* imported lazily and registered the first time such a language is requested,
* so a session that never opens a code surface in one of those languages pays
* neither the grammar modules nor their synchronous init. The first render of a lazy language falls back to plain text while its
* grammar loads, then {@link onGrammarLoaded} notifies subscribers to re-render
* with highlighting. An unknown or absent language falls back to plain text (no
* highlighting, still monospace) — never an error.
* neither the grammar modules nor their synchronous init. The first render of a
* lazy language falls back to plain text while its grammar loads, then
* {@link onGrammarLoaded} notifies subscribers to re-render with highlighting.
* An unknown or absent language falls back to plain text (no highlighting, still
* monospace) — never an error.
*/
import { createHighlighterCoreSync, createCssVariablesTheme } from 'shiki/core'
@@ -233,7 +234,7 @@ const LANG_ALIASES = new Map<string, string>([
/**
* Resolve a language hint to the grammar id {@link LANG_ALIASES} selects.
* @param lang - Language hint from a code surface: a shared canonical id or a legacy read-card hint.
* @param lang - Language hint from a code surface: a canonical grammar id or the read card's persisted short id.
* @returns The resolved grammar id, or `undefined` when the table aliases no grammar.
*/
export function grammarForHint(lang: string | undefined): string | undefined {
@@ -51,12 +51,12 @@ describe('code highlighting', () => {
expect(languageForPath).toBe(sharedLanguageForPath)
})
it('reaches one grammar from the shared canonical id and the read card legacy hint', () => {
// The read card persists the old short ids while this surface reads the
// canonical table directly; both must select the same grammar, so a
// persisted hint can never render differently from this surface's own
// selection. This is the alias-normalized check the identity assertion
// cannot make now that the read projection intentionally differs.
it("reaches one grammar from the shared canonical id and the read card's persisted hint", () => {
// The read card persists short ids while this surface reads the canonical
// table directly; both must select the same grammar, so a persisted hint can
// never render differently from this surface's own selection. The identity
// assertion above cannot cover that, because the two projections
// intentionally differ.
for (const extension of CODE_HIGHLIGHT_EXTENSIONS) {
const path = `file.${extension}`
const readHint = readLangHintForPath(path)
+3 -4
View File
@@ -173,10 +173,9 @@ ${body}
* Derive the persisted `lang` hint from a read path's file extension. The shared
* table in `@deepseek-ai/dsh-util-code-language` owns the recognized suffixes and
* the path rules (both separators, a leading dot as the extension separator, and
* prototype-key safety); `readLangHintForPath` projects the read card's
* historical short ids over it, so a suffix the pre-unification read table
* recognized keeps its byte-identical old value while a newly added suffix uses
* its language's short name.
* prototype-key safety); `readLangHintForPath` projects the read card's short ids
* over it, so a suffix whose value a recorded session already holds keeps it
* byte-identical while every other suffix uses its language's short name.
* @param path - the model-facing path the read reported.
* @returns the persisted language hint, or `undefined` when the extension maps to none.
*/
+14 -12
View File
@@ -119,11 +119,12 @@ describe('buildWindow', () => {
})
/**
* The pre-unification read table's extension-to-hint mapping, transcribed
* verbatim. A read card persisted one of these strings, so changing any value
* changes replay-visible output for an already-recorded session.
* The short `lang` values a recorded read persisted, transcribed verbatim.
* Changing any value changes replay-visible output for an already-recorded
* session, so this table is the test's independent expectation rather than a
* second read of the implementation's own data.
*/
const MASTER_READ_LANG_BY_EXTENSION: Readonly<Record<string, string>> = {
const PERSISTED_READ_LANG_BY_EXTENSION: Readonly<Record<string, string>> = {
ts: 'ts', tsx: 'tsx', mts: 'ts', cts: 'ts',
js: 'js', jsx: 'jsx', mjs: 'js', cjs: 'js',
json: 'json', jsonc: 'json',
@@ -138,16 +139,16 @@ const MASTER_READ_LANG_BY_EXTENSION: Readonly<Record<string, string>> = {
}
describe('langFromPath', () => {
it('keeps every pre-unification suffix byte-identical to the old persisted hint', () => {
expect(Object.keys(MASTER_READ_LANG_BY_EXTENSION)).toHaveLength(43)
for (const [extension, hint] of Object.entries(MASTER_READ_LANG_BY_EXTENSION)) {
it('keeps every already-persisted suffix byte-identical', () => {
expect(Object.keys(PERSISTED_READ_LANG_BY_EXTENSION)).toHaveLength(43)
for (const [extension, hint] of Object.entries(PERSISTED_READ_LANG_BY_EXTENSION)) {
expect(langFromPath(`file.${extension}`), extension).toBe(hint)
}
})
it('gives a suffix added after the old read table the language short id', () => {
// A suffix the old read table did not know used to persist the canonical
// grammar id; it now persists the language's short name.
it('gives every other suffix the language short id', () => {
// A suffix with no persisted value has none to preserve, so the projection
// applies the language's short name instead of the canonical grammar id.
expect(langFromPath('build.ps1')).toBe('ps1')
expect(langFromPath('deploy.bat')).toBe('bat')
expect(langFromPath('.env')).toBe('env')
@@ -167,7 +168,7 @@ describe('langFromPath', () => {
expect(langFromPath('notebook.ipynb')).toBe('json')
})
it('maps a known extension to its old short hint, case-insensitively', () => {
it('maps a known extension to its persisted short hint, case-insensitively', () => {
expect(langFromPath('src/a.ts')).toBe('ts')
expect(langFromPath('src/a.TSX')).toBe('tsx')
expect(langFromPath('/abs/module.mjs')).toBe('js')
@@ -177,7 +178,8 @@ describe('langFromPath', () => {
it('keeps the canonical ids the Client code surfaces use out of the persisted hint', () => {
// The Client reads the shared table directly; only this projection owns the
// persisted value, so the two intentionally differ for the old suffixes.
// persisted value, so the two intentionally differ for the suffixes a
// recorded session already holds.
expect(languageForPath('src/a.ts')).toBe('typescript')
expect(languageForPath('README.md')).toBe('markdown')
expect(langFromPath('src/a.ts')).not.toBe(languageForPath('src/a.ts'))
+19 -19
View File
@@ -5,9 +5,9 @@
* highlighter's alias table resolves, so a language returned here reaches
* `highlightLines`/`highlightToHtml` unchanged; a filename outside the table, or
* one naming a language the highlighter does not register, renders as plain text.
* The read card predates the shared table, so {@link readLangHintForPath} projects
* short ids over this table: the suffixes the old read table already recognized
* keep their historical values byte-identical, and every later suffix persists the
* The read tool persists a short `lang` id, so {@link readLangHintForPath}
* projects short ids over this table: a suffix whose value a recorded session
* already holds keeps it byte-identical, and every other suffix persists the
* canonical language's short name rather than its grammar id.
* @module @deepseek-ai/dsh-util-code-language
*/
@@ -101,10 +101,10 @@ const LANGUAGES = new Map(Object.entries(LANGUAGE_EXTENSIONS)
export const CODE_HIGHLIGHT_EXTENSIONS: readonly string[] = [...LANGUAGES.keys()]
/**
* The read card's historical short language hints for the suffixes its
* pre-unification table recognized. Keys are shared-table extensions, so the
* recognized set still derives from {@link LANGUAGE_EXTENSIONS}; values preserve
* the old persisted `lang` strings byte for byte. An extension absent here but
* The short `lang` values recorded sessions already hold, keyed by the suffix
* that produced them. Keys are shared-table extensions, so the recognized set
* derives from {@link LANGUAGE_EXTENSIONS}; each value is the exact string a
* recorded session persists and must not change. An extension absent here but
* present in the shared table falls back to {@link SHORT_BY_LANGUAGE}, so every
* persisted hint is a short id.
*/
@@ -123,13 +123,13 @@ const READ_LANG_BY_EXTENSION = new Map<string, string>(Object.entries({
}))
/**
* The short `lang` id the read card persists for each canonical language the
* pre-unification read table did not recognize. Keys are exactly the languages
* in {@link LANGUAGE_EXTENSIONS}: the 27 languages the old read table covered
* repeat their historical short id, and the remaining 33 shorten the grammar id
* (`powershell` to `ps1`, `hcl` to `tf`, `system-verilog` to `sv`).
* Keys are canonical ids, not untrusted extensions, so an object lookup cannot
* reach an `Object.prototype` member the way the extension tables can.
* The short `lang` id the read card persists, keyed by canonical language id.
* Keys are exactly the languages in {@link LANGUAGE_EXTENSIONS}: where
* {@link READ_LANG_BY_EXTENSION} does not already fix a suffix's value, this
* table supplies the language's short name (`powershell` to `ps1`, `hcl` to
* `tf`, `system-verilog` to `sv`) rather than the grammar id. Keys are canonical
* ids, not untrusted extensions, so an object lookup cannot reach an
* `Object.prototype` member the way the extension tables can.
*/
const SHORT_BY_LANGUAGE: Readonly<Record<string, string>> = {
typescript: 'ts',
@@ -218,11 +218,11 @@ export function languageForPath(path: string): string | undefined {
/**
* Derive the Host read card's persisted `lang` hint from a read path's
* extension. The hint is always a short id: a suffix the pre-unification read
* table recognized keeps its old value (`ts`, `md`, `cpp`, …), while a suffix
* only the shared table knows (`.ps1`, `.env`, `.tf`, …) uses its language's
* short name (`ps1`, `env`, `tf`, …) rather than the canonical grammar id. An
* unrecognized suffix stays `undefined`, so the card renders as plain text.
* extension. The hint is always a short id: a suffix a recorded session already
* holds keeps its persisted value (`ts`, `md`, `cpp`, …), while a suffix with no
* recorded value (`.ps1`, `.env`, `.tf`, …) uses its language's short name
* (`ps1`, `env`, `tf`, …) rather than the canonical grammar id. An unrecognized
* suffix stays `undefined`, so the card renders as plain text.
* @param path - the model-facing path the read reported.
* @returns the persisted language hint, or `undefined` when the extension maps to none.
*/
@@ -32,7 +32,7 @@ describe('languageForPath', () => {
expect(languageForPath(path)).toBe(language)
})
it('keeps the extensions the two former tables already agreed on', () => {
it('resolves the extensions the preview and read tables already agreed on', () => {
expect(languageForPath('src/a.ts')).toBe('typescript')
expect(languageForPath('src/a.TSX')).toBe('typescript')
expect(languageForPath('/abs/module.mjs')).toBe('javascript')
@@ -41,7 +41,7 @@ describe('languageForPath', () => {
expect(languageForPath('C:\\src\\main.rs')).toBe('rust')
})
it('resolves every extension that only the preview table knew, including the new ones', () => {
it('resolves every suffix the preview registry declares beyond the persisted read hints', () => {
for (const extension of ['jsonl', 'ndjson', 'pyw', 'pyi', 'rake', 'gemspec', 'hh', 'hxx', 'kts', 'xhtml', 'xsd', 'xsl', 'xslt']) {
expect(languageForPath(`file.${extension}`), extension).toBeDefined()
}
@@ -91,7 +91,7 @@ describe('languageForPath', () => {
})
describe('readLangHintForPath', () => {
it('keeps the read card pre-unification short hints for the old suffixes', () => {
it('keeps the read card short hints recorded sessions already hold', () => {
expect(readLangHintForPath('src/a.ts')).toBe('ts')
expect(readLangHintForPath('src/a.tsx')).toBe('tsx')
expect(readLangHintForPath('src/a.mts')).toBe('ts')
@@ -110,7 +110,7 @@ describe('readLangHintForPath', () => {
expect(readLangHintForPath('page.htm')).toBe('html')
})
it('uses the language short id for a suffix added after the old read table', () => {
it('uses the language short id for a suffix with no persisted value', () => {
expect(readLangHintForPath('build.ps1')).toBe('ps1')
expect(readLangHintForPath('.env')).toBe('env')
expect(readLangHintForPath('infra.tf')).toBe('tf')
@@ -137,11 +137,12 @@ describe('readLangHintForPath', () => {
}
it('persists a short id for every suffix, never a canonical grammar id', () => {
// The persisted `lang` has one style: the historical short id for the
// suffixes the old read table knew, the language's short name otherwise. A
// result outside both sets is a canonical grammar id leaking back in
// (`powershell`, `dotenv`, `latex`, `hcl`). The old table's `tsx`/`jsx`
// hints are the only legacy values absent from the short-name table.
// The persisted `lang` has one style: a short id. Every suffix must resolve
// to one of these short names, except the persisted `tsx`/`jsx` values,
// which the language table cannot express because typescript and javascript
// already shorten to `ts` and `js`. A result outside both sets is a
// canonical grammar id leaking back in (`powershell`, `dotenv`, `latex`,
// `hcl`).
const allowed = new Set([...Object.values(SHORT_BY_LANGUAGE), 'tsx', 'jsx'])
for (const extension of CODE_HIGHLIGHT_EXTENSIONS) {
const hint = readLangHintForPath(`file.${extension}`)