Files
deepseek-harness/packages/util/code-language
mektpoy b0ad792e6b fix(web): keep dedicated previews and the read-card lang domain
The shared code-language table must not claim a suffix a dedicated viewer
declares, and the Host read card must keep the `lang` values it already
persisted.

- Drop `csv` from the shared table: Code registers before Spreadsheet, so
  the earlier body would take `.csv` and the browser snapshot gate fails.
- Add `readLangHintForPath`, the read card's legacy projection over the
  shared table: the 43 pre-unification suffixes keep their old short ids
  byte for byte, new suffixes use the canonical id.
- Add an ownership regression test over the full preview registry that
  turns red when `csv` returns, plus byte-level and alias-normalized tests
  for the read projection.
2026-09-21 19:14:08 +08:00
..

description, kind
description kind
Single file-extension to syntax-highlighting language table shared by the Client code surfaces and the Host read card. package-library

dsh-util-code-language

English | 中文

Summary

The repository's one file-extension to syntax-highlighting language table, shared by the Client's document Code preview and diff review and by the Host read tool's persisted lang hint. languageForPath maps a path to a canonical grammar id case-insensitively, recognizing both path separators and treating a leading dot as the separator (.env is dotenv); CODE_HIGHLIGHT_EXTENSIONS lists every suffix for a preview registry. readLangHintForPath projects the read card's older short ids over the table so previously persisted values stay byte-identical. The package is browser-safe, stateless, and leaves tokenization to the Client highlighter.

Table of Contents


Language selection

The table lives in src/index.ts. Each key is a canonical language id — the grammar id the Client highlighter resolves — and each value is the lowercase extensions without the dot that select it. languageForPath(path) takes the text after the last dot of the final path segment, lowercases it, and looks it up in a Map; a Map keeps a filename such as foo.constructor from resolving an Object.prototype member. An unlisted dotfile (.gitignore), an absent extension, a trailing dot, and an unknown suffix all return undefined, which every consumer renders as plain text; a leading dot is still the separator, so .env resolves to dotenv. Both / and \ separate path segments, so a Windows path resolves like a POSIX one.

The set is curated for common source, config, script, data, and markup extensions rather than mirroring a full language registry. Extensions with no matching grammar map to the nearest one (properties to ini, whose registration carries the properties alias); certificate and lock extensions (pem, crt, key, cer, lock) stay unlisted, and csv stays unlisted because the Spreadsheet preview declares the suffix and must keep it, so the earlier Code registration cannot claim it. readLangHintForPath is a projection over this table: a suffix the pre-unification read table recognized returns its old short id, a suffix present only here returns its canonical id, and an unrecognized suffix returns undefined. A consumer that needs the Client highlighter to actually tokenize a language still depends on that grammar being registered there — an id without a loaded grammar renders as plain text rather than failing.


Known Limitations and Deferred Work

  • Extension-only matching — languageForPath reads a suffix, so names recognized without one (Dockerfile, Makefile, .gitignore, .editorconfig) stay unlisted. Filename rules are deferred.
  • No content sniffing — a file with an absent or unknown extension stays plain text even when its bytes are unambiguous; the table never inspects content.
  • Curated, not exhaustive — the table is smaller than Shiki's grammar catalog and GitHub linguist; adding a language means adding both the extension entry and the Client grammar registration.

Dev Note

Working context for maintainers — click to expand

None.

Runtime invariant: No companion is published. This utility owns no mutable runtime relationship.