Files
paseo/packages/highlight/src/parsers.ts
T
Lorenzo FioreandGitHub 1917fdd131 fix(highlight): highlight Svelte components (#3487)
* fix(highlight): highlight Svelte components

`.svelte` had no entry in the extension table, so `highlightCode` fell through
to one unstyled token per line. That is the same table the file pane, the diff
tokens, markdown fences and the web editor all resolve through, so a component
rendered as plain text everywhere in the app.

Register `@replit/codemirror-lang-svelte`. Its `svelteLanguage` already wires
the mixed parsing for the `<script>` and `<style>` blocks, so the script gets
JS/TS roles, the style block gets CSS roles, and the template gets tag,
directive and mustache roles. It comes from the same publisher as the
`@replit/codemirror-lang-csharp` entry already in this package, and only the
grammar itself is declared: its CodeMirror peers resolve the same way the C#
grammar's peers already do.

* test(server): cover Svelte diff highlighting

The review surface in the issue is the diff, and the daemon is what tokenizes
it (`diff-highlighter.ts` calls `highlightCode`), so the regression belongs
here too: script, template block and markup roles on a `.svelte` hunk.
2026-08-17 12:43:11 +00:00

103 lines
3.2 KiB
TypeScript

import { defineLanguageFacet, Language, StreamLanguage } from "@codemirror/language";
import { dart } from "@codemirror/legacy-modes/mode/clike";
import { swift } from "@codemirror/legacy-modes/mode/swift";
import { parser as jsParser } from "@lezer/javascript";
import { parser as jsonParser } from "@lezer/json";
import { parser as cssParser } from "@lezer/css";
import { parser as cppParser } from "@lezer/cpp";
import { parser as goParser } from "@lezer/go";
import { parser as htmlParser } from "@lezer/html";
import { parser as javaParser } from "@lezer/java";
import { parser as pythonParser } from "@lezer/python";
import { parser as markdownParser } from "@lezer/markdown";
import { parser as phpParser } from "@lezer/php";
import { parser as rustParser } from "@lezer/rust";
import { parser as xmlParser } from "@lezer/xml";
import { parser as yamlParser } from "@lezer/yaml";
import { csharpLanguage } from "@replit/codemirror-lang-csharp";
import { nixLanguage } from "@replit/codemirror-lang-nix";
import { svelteLanguage } from "@replit/codemirror-lang-svelte";
import { parser as elixirParser } from "lezer-elixir";
import type { Parser } from "@lezer/common";
function language(parser: Parser): Language {
return new Language(defineLanguageFacet(), parser);
}
const languagesByExtension: Record<string, Language> = {
// JavaScript/TypeScript
js: language(jsParser),
jsx: language(jsParser.configure({ dialect: "jsx" })),
ts: language(jsParser.configure({ dialect: "ts" })),
tsx: language(jsParser.configure({ dialect: "ts jsx" })),
mjs: language(jsParser),
cjs: language(jsParser),
// C / C++ / Objective-C
c: language(cppParser),
h: language(cppParser),
cc: language(cppParser),
cpp: language(cppParser),
cxx: language(cppParser),
hpp: language(cppParser),
hxx: language(cppParser),
m: language(cppParser),
mm: language(cppParser),
// JSON
json: language(jsonParser),
// CSS
css: language(cssParser),
scss: language(cssParser),
// HTML
html: language(htmlParser),
htm: language(htmlParser),
// Svelte
svelte: svelteLanguage,
// XML
xml: language(xmlParser),
// Java
java: language(javaParser),
// Python
py: language(pythonParser),
// Go
go: language(goParser),
// PHP
php: language(phpParser),
// YAML
yaml: language(yamlParser),
yml: language(yamlParser),
// Rust
rs: language(rustParser),
// Swift
swift: StreamLanguage.define(swift),
// Dart
dart: StreamLanguage.define(dart),
// C#
cs: csharpLanguage,
// Nix
nix: nixLanguage,
// Elixir
ex: language(elixirParser),
exs: language(elixirParser),
// Markdown
md: language(markdownParser),
mdx: language(markdownParser),
};
export function getLanguageForFile(filename: string): Language | null {
const ext = filename.split(".").pop()?.toLowerCase();
if (!ext) return null;
return languagesByExtension[ext] ?? null;
}
export function getParserForFile(filename: string): Parser | null {
return getLanguageForFile(filename)?.parser ?? null;
}
export function isLanguageSupported(filename: string): boolean {
return getParserForFile(filename) !== null;
}
export function getSupportedExtensions(): string[] {
return Object.keys(languagesByExtension);
}