diff --git a/package.json b/package.json index 5fc8ad5..259522b 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "@codemirror/lang-python": "^6.2.1", "@codemirror/lang-rust": "^6.0.2", "@codemirror/lang-sql": "^6.10.0", + "@codemirror/lang-vue": "^0.1.3", "@codemirror/lang-xml": "^6.1.0", "@codemirror/lang-yaml": "^6.1.3", "@codemirror/language": "^6.12.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ed2a9e..a5848b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ importers: '@codemirror/lang-sql': specifier: ^6.10.0 version: 6.10.0 + '@codemirror/lang-vue': + specifier: ^0.1.3 + version: 0.1.3 '@codemirror/lang-xml': specifier: ^6.1.0 version: 6.1.0 @@ -265,6 +268,9 @@ packages: '@codemirror/lang-sql@6.10.0': resolution: {integrity: sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==} + '@codemirror/lang-vue@0.1.3': + resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} + '@codemirror/lang-xml@6.1.0': resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} @@ -3015,6 +3021,15 @@ snapshots: '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.10 + '@codemirror/lang-vue@0.1.3': + dependencies: + '@codemirror/lang-html': 6.4.12 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.4 + '@lezer/common': 1.5.2 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.10 + '@codemirror/lang-xml@6.1.0': dependencies: '@codemirror/autocomplete': 6.20.3 diff --git a/src/client/lang.ts b/src/client/lang.ts index 8e7dc40..af83e23 100644 --- a/src/client/lang.ts +++ b/src/client/lang.ts @@ -4,12 +4,12 @@ * the CodeMirror language packages (bundled into the client). */ import { Language, LanguageSupport, StreamLanguage } from '@codemirror/language' -import { javascript } from '@codemirror/lang-javascript' +import { javascript, jsxLanguage, typescriptLanguage, tsxLanguage } from '@codemirror/lang-javascript' import { json } from '@codemirror/lang-json' import { markdown } from '@codemirror/lang-markdown' import { python } from '@codemirror/lang-python' import { html } from '@codemirror/lang-html' -import { css } from '@codemirror/lang-css' +import { css, cssLanguage } from '@codemirror/lang-css' import { xml } from '@codemirror/lang-xml' import { yaml } from '@codemirror/lang-yaml' import { sql } from '@codemirror/lang-sql' @@ -18,13 +18,36 @@ import { cpp } from '@codemirror/lang-cpp' import { rust } from '@codemirror/lang-rust' import { go } from '@codemirror/lang-go' import { php } from '@codemirror/lang-php' +import { vue } from '@codemirror/lang-vue' import { shell } from '@codemirror/legacy-modes/mode/shell' import { toml } from '@codemirror/legacy-modes/mode/toml' import { nginx } from '@codemirror/legacy-modes/mode/nginx' import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile' import { properties } from '@codemirror/legacy-modes/mode/properties' -import { csharp, kotlin } from '@codemirror/legacy-modes/mode/clike' +import { csharp, kotlin, dart, scala, objectiveCpp } from '@codemirror/legacy-modes/mode/clike' import { swift } from '@codemirror/legacy-modes/mode/swift' +import { sCSS, less } from '@codemirror/legacy-modes/mode/css' +import { sass } from '@codemirror/legacy-modes/mode/sass' +import { stylus } from '@codemirror/legacy-modes/mode/stylus' +import { ruby } from '@codemirror/legacy-modes/mode/ruby' +import { lua } from '@codemirror/legacy-modes/mode/lua' +import { perl } from '@codemirror/legacy-modes/mode/perl' +import { r } from '@codemirror/legacy-modes/mode/r' +import { groovy } from '@codemirror/legacy-modes/mode/groovy' +import { powerShell } from '@codemirror/legacy-modes/mode/powershell' +import { diff } from '@codemirror/legacy-modes/mode/diff' +import { protobuf } from '@codemirror/legacy-modes/mode/protobuf' +import { cmake } from '@codemirror/legacy-modes/mode/cmake' +import { pug } from '@codemirror/legacy-modes/mode/pug' +import { tcl } from '@codemirror/legacy-modes/mode/tcl' +import { haskell } from '@codemirror/legacy-modes/mode/haskell' +import { clojure } from '@codemirror/legacy-modes/mode/clojure' +import { erlang } from '@codemirror/legacy-modes/mode/erlang' +import { julia } from '@codemirror/legacy-modes/mode/julia' +import { pascal } from '@codemirror/legacy-modes/mode/pascal' +import { vb } from '@codemirror/legacy-modes/mode/vb' +import { vhdl } from '@codemirror/legacy-modes/mode/vhdl' +import { stex } from '@codemirror/legacy-modes/mode/stex' /** The lowercased file extension of a path ('' when none). */ export function extOf(path: string): string { @@ -63,10 +86,47 @@ export function languageKeyForExt(ext: string): string | null { case 'nginx': case 'conf': return 'nginx' case 'dockerfile': case 'docker': return 'dockerfile' case 'properties': case 'env': return 'properties' + case 'vue': return 'vue' + case 'scss': return 'scss' + case 'sass': return 'sass' + case 'less': return 'less' + case 'styl': return 'stylus' + case 'rb': return 'ruby' + case 'lua': return 'lua' + case 'pl': case 'pm': return 'perl' + case 'r': return 'r' + case 'dart': return 'dart' + case 'scala': case 'sc': return 'scala' + case 'groovy': return 'groovy' + case 'ps1': case 'psm1': return 'powershell' + case 'diff': case 'patch': return 'diff' + case 'proto': return 'protobuf' + case 'cmake': return 'cmake' + case 'pug': return 'pug' + case 'tcl': return 'tcl' + case 'hs': return 'haskell' + case 'clj': case 'cljs': return 'clojure' + case 'erl': return 'erlang' + case 'jl': return 'julia' + case 'pas': return 'pascal' + case 'vb': return 'vb' + case 'vhd': return 'vhdl' + case 'tex': return 'stex' + case 'mm': return 'objectivecpp' + // '.v' (Verilog/Coq/V) 与 '.m' (Objective-C/MATLAB) 存在跨语言歧义, + // 故意不映射——错配高亮比纯文本更误导。 default: return null } } +/** Per-lang `', + ) + const names = new Set() + let hasError = false + tree.iterate({ enter: (node) => { if (node.type.isError) hasError = true; names.add(node.name) } }) + expect(hasError).toBe(false) + expect(names.has('Script')).toBe(true) + expect(names.has('StyleSheet')).toBe(true) + expect(names.has('Interpolation')).toBe(true) + expect(names.has('SingleExpression')).toBe(true) + }) + + // P1-2 修复守护:') + const names = new Set() + let hasError = false + tree.iterate({ enter: (node) => { if (node.type.isError) hasError = true; names.add(node.name) } }) + expect(hasError).toBe(false) + // 两条正向鉴别:无 StyleSheet = CSS parser 未接管;无 StyleText = + // 内容确有 parser 接管(删掉 scss 条目时内容会退化回纯文本 StyleText)。 + expect(names.has('StyleSheet')).toBe(false) + expect(names.has('StyleText')).toBe(false) + }) }) describe('pdf preview kind', () => {