| 1 | // Pure language resolution — no highlight.js dependency. Non-lazy consumers (e.g. |
| 2 | // ToolCard) guess a language from a path without pulling the highlighter into the |
| 3 | // main bundle; highlight.js stays behind the lazy editor seam. highlight.ts |
| 4 | // imports ALIASES from here and adds the hljs-backed validation. |
| 5 | |
| 6 | export const ALIASES: Record<string, string> = { |
| 7 | // JavaScript ecosystem |
| 8 | ts: "typescript", |
| 9 | tsx: "typescript", |
| 10 | js: "javascript", |
| 11 | jsx: "javascript", |
| 12 | mjs: "javascript", |
| 13 | cjs: "javascript", |
| 14 | coffee: "coffeescript", |
| 15 | // Shell |
| 16 | sh: "bash", |
| 17 | shell: "bash", |
| 18 | zsh: "bash", |
| 19 | // Python |
| 20 | py: "python", |
| 21 | // Rust |
| 22 | rs: "rust", |
| 23 | // YAML |
| 24 | yml: "yaml", |
| 25 | // XML / markup dialects — no native hljs lexer for XAML, so map to XML |
| 26 | html: "xml", |
| 27 | xaml: "xml", |
| 28 | // Markdown |
| 29 | md: "markdown", |
| 30 | // C family |
| 31 | cs: "csharp", |
| 32 | "c#": "csharp", |
| 33 | cxx: "cpp", |
| 34 | cc: "cpp", |
| 35 | h: "c", |
| 36 | hpp: "cpp", |
| 37 | // Ruby |
| 38 | rb: "ruby", |
| 39 | // Kotlin |
| 40 | kt: "kotlin", |
| 41 | kts: "kotlin", |
| 42 | // PowerShell |
| 43 | ps1: "powershell", |
| 44 | psd1: "powershell", |
| 45 | psm1: "powershell", |
| 46 | // Config / data |
| 47 | toml: "ini", |
| 48 | // Docker / build |
| 49 | dockerfile: "dockerfile", |
| 50 | makefile: "makefile", |
| 51 | // Objective-C |
| 52 | objc: "objectivec", |
| 53 | // F# |
| 54 | "f#": "fsharp", |
| 55 | // Perl |
| 56 | pm: "perl", |
| 57 | // Haskell |
| 58 | lhs: "haskell", |
| 59 | // Erlang |
| 60 | hrl: "erlang", |
| 61 | // Clojure |
| 62 | cljc: "clojure", |
| 63 | cljs: "clojure", |
| 64 | // Julia |
| 65 | jl: "julia", |
| 66 | // R |
| 67 | r: "r", |
| 68 | // LaTeX |
| 69 | tex: "latex", |
| 70 | ltx: "latex", |
| 71 | // SCSS |
| 72 | scss: "scss", |
| 73 | // Less |
| 74 | less: "less", |
| 75 | // Vim |
| 76 | vim: "vim", |
| 77 | // Nginx |
| 78 | nginx: "nginx", |
| 79 | // Apache |
| 80 | apache: "apache", |
| 81 | // Protobuf |
| 82 | proto: "protobuf", |
| 83 | // GraphQL |
| 84 | graphql: "graphql", |
| 85 | gql: "graphql", |
| 86 | // CMake |
| 87 | cmake: "cmake", |
| 88 | // Gradle |
| 89 | gradle: "gradle", |
| 90 | // Properties |
| 91 | properties: "properties", |
| 92 | // Groovy |
| 93 | groovy: "groovy", |
| 94 | gvy: "groovy", |
| 95 | // Lua |
| 96 | lua: "lua", |
| 97 | // Dart |
| 98 | dart: "dart", |
| 99 | // MATLAB |
| 100 | matlab: "matlab", |
| 101 | }; |
| 102 | |
| 103 | // Keep these values as semantic fence tags rather than highlight.js lexer names. |
| 104 | // UI consumers pass them through resolveLang(), while plain-text consumers (such |
| 105 | // as plan revisions) preserve useful distinctions like TSX vs TypeScript and |
| 106 | // XAML vs XML for the model. |
| 107 | export const FILE_LANGUAGE_BY_EXTENSION: Readonly<Record<string, string>> = { |
| 108 | // JavaScript |
| 109 | go: "go", |
| 110 | ts: "typescript", |
| 111 | tsx: "tsx", |
| 112 | js: "javascript", |
| 113 | jsx: "jsx", |
| 114 | mjs: "javascript", |
| 115 | cjs: "javascript", |
| 116 | coffee: "coffeescript", |
| 117 | // Data |
| 118 | json: "json", |
| 119 | yaml: "yaml", |
| 120 | yml: "yaml", |
| 121 | xml: "xml", |
| 122 | xaml: "xaml", |
| 123 | html: "html", |
| 124 | // Shell |
| 125 | sh: "bash", |
| 126 | bash: "bash", |
| 127 | zsh: "bash", |
| 128 | // Python |
| 129 | py: "python", |
| 130 | // Rust |
| 131 | rs: "rust", |
| 132 | // CSS |
| 133 | css: "css", |
| 134 | scss: "scss", |
| 135 | less: "less", |
| 136 | // Markdown |
| 137 | md: "markdown", |
| 138 | // C family |
| 139 | cs: "csharp", |
| 140 | c: "c", |
| 141 | cpp: "cpp", |
| 142 | cc: "cpp", |
| 143 | cxx: "cpp", |
| 144 | h: "c", |
| 145 | hpp: "cpp", |
| 146 | // Java / JVM |
| 147 | java: "java", |
| 148 | kt: "kotlin", |
| 149 | kts: "kotlin", |
| 150 | scala: "scala", |
| 151 | groovy: "groovy", |
| 152 | gvy: "groovy", |
| 153 | gradle: "gradle", |
| 154 | // .NET |
| 155 | fs: "fsharp", |
| 156 | fsx: "fsharp", |
| 157 | vb: "vbnet", |
| 158 | // Database |
| 159 | sql: "sql", |
| 160 | // Scripting |
| 161 | rb: "ruby", |
| 162 | php: "php", |
| 163 | lua: "lua", |
| 164 | dart: "dart", |
| 165 | perl: "perl", |
| 166 | pl: "perl", |
| 167 | pm: "perl", |
| 168 | r: "r", |
| 169 | // Apple |
| 170 | swift: "swift", |
| 171 | m: "objectivec", |
| 172 | mm: "objectivec", |
| 173 | // Functional |
| 174 | haskell: "haskell", |
| 175 | hs: "haskell", |
| 176 | lhs: "haskell", |
| 177 | elixir: "elixir", |
| 178 | ex: "elixir", |
| 179 | exs: "elixir", |
| 180 | clojure: "clojure", |
| 181 | clj: "clojure", |
| 182 | cljs: "clojure", |
| 183 | cljc: "clojure", |
| 184 | erlang: "erlang", |
| 185 | erl: "erlang", |
| 186 | hrl: "erlang", |
| 187 | fsharp: "fsharp", |
| 188 | // Scientific |
| 189 | julia: "julia", |
| 190 | jl: "julia", |
| 191 | matlab: "matlab", |
| 192 | // Shell / config |
| 193 | ps1: "powershell", |
| 194 | psd1: "powershell", |
| 195 | psm1: "powershell", |
| 196 | dockerfile: "dockerfile", |
| 197 | nginx: "nginx", |
| 198 | properties: "properties", |
| 199 | protobuf: "protobuf", |
| 200 | proto: "protobuf", |
| 201 | graphql: "graphql", |
| 202 | gql: "graphql", |
| 203 | toml: "toml", |
| 204 | makefile: "makefile", |
| 205 | cmake: "cmake", |
| 206 | // Document |
| 207 | latex: "latex", |
| 208 | tex: "latex", |
| 209 | ltx: "latex", |
| 210 | // Editor |
| 211 | vim: "vim", |
| 212 | }; |
| 213 | |
| 214 | export const FILE_LANGUAGE_BY_NAME: Readonly<Record<string, string>> = { |
| 215 | ".htaccess": "apache", |
| 216 | "cmakelists.txt": "cmake", |
| 217 | containerfile: "dockerfile", |
| 218 | dockerfile: "dockerfile", |
| 219 | "httpd.conf": "apache", |
| 220 | gnumakefile: "makefile", |
| 221 | makefile: "makefile", |
| 222 | "nginx.conf": "nginx", |
| 223 | }; |
| 224 | |
| 225 | // pathToLang infers a semantic language tag from either a special basename or |
| 226 | // a file extension. Matching both slash styles keeps desktop previews and tool |
| 227 | // diffs consistent when a Windows path reaches the frontend. |
| 228 | export function pathToLang(path: string): string { |
| 229 | const name = path.split(/[\\/]/).filter(Boolean).pop()?.toLowerCase() ?? ""; |
| 230 | if (!name) return ""; |
| 231 | |
| 232 | const exact = FILE_LANGUAGE_BY_NAME[name]; |
| 233 | if (exact) return exact; |
| 234 | if (/^(?:dockerfile|containerfile)\./.test(name)) return "dockerfile"; |
| 235 | if (/^(?:gnu)?makefile\./.test(name)) return "makefile"; |
| 236 | |
| 237 | const dot = name.lastIndexOf("."); |
| 238 | if (dot < 0) return ""; |
| 239 | return FILE_LANGUAGE_BY_EXTENSION[name.slice(dot + 1)] ?? ""; |
| 240 | } |
| 241 | |
| 242 | // Backward-compatible name for the existing tool-diff callers. |
| 243 | export const extToLang = pathToLang; |
| 244 |