Files
deepseek-harness/packages/util/code-language
mektpoy 6945da14cb feat(web): unify the code-highlight language table and extend it
The document Code preview and the Host read card each owned an
extension-to-language table that had drifted: the preview table had 13
extensions the read card lacked, and the two returned different language
ids for the same suffix. Both now resolve through the new zero-dependency
@deepseek-ai/dsh-util-code-language, which also adds common Windows,
config, markup, and language extensions. Every added grammar stays in the
lazy set; the boot grammars are unchanged.

Fixes #4822
2026-09-21 17:42:11 +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 filename or path to a canonical grammar id case-insensitively, recognizing both path separators and treating a leading dot as the extension separator (.env resolves to dotenv). CODE_HIGHLIGHT_EXTENSIONS lists every recognized suffix for a preview registry. The package is browser-safe, has no Cordis service or runtime state, and leaves the actual 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. 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.