scaffold: VSCode/VSCodium extension wrapping testium lsp
A thin LSP client that spawns `testium lsp` and forwards messages to
VSCode. All language intelligence lives in the testium repo, so this
extension only needs republishing for editor-side UX changes.
- package.json: declares the .tum language, registers the LSP client,
exposes testium.serverPath and testium.trace.server settings.
- src/extension.ts: vscode-languageclient setup over stdio, surfaces a
user-visible error if `testium lsp` can't start.
- syntaxes/tum.tmLanguage.json: TextMate grammar embedding source.yaml
plus tum-specific tokens for $(name), <| python |>, {% jinja %},
{{ jinja }}.
- language-configuration.json: comment char, bracket pairs, auto-close
for $(/), <|/|>, {%/%}, {{/}}.
- README.md: install (incl. testium[lsp] extra), settings, packaging
via vsce, publish to both VS Marketplace and Open VSX (the latter
is what VSCodium / Cursor / Gitpod use — same .vsix artifact).
Works identically on VSCode and VSCodium — no Microsoft-proprietary
API surface used.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
out/
|
||||
*.vsix
|
||||
.vscode-test/
|
||||
*.tsbuildinfo
|
||||
12
.vscodeignore
Normal file
12
.vscodeignore
Normal file
@@ -0,0 +1,12 @@
|
||||
.vscode/**
|
||||
.vscode-test/**
|
||||
src/**
|
||||
.gitignore
|
||||
.git
|
||||
tsconfig.json
|
||||
node_modules/.cache/**
|
||||
**/*.map
|
||||
**/*.ts
|
||||
!out/**/*.js
|
||||
.github/**
|
||||
.editorconfig
|
||||
95
README.md
95
README.md
@@ -0,0 +1,95 @@
|
||||
# Testium Assist
|
||||
|
||||
Language support for [testium](https://git.beafrancois.fr/v-and-v/testium) `.tum`
|
||||
test scripts: syntax highlighting, completion, hover, and (later)
|
||||
diagnostics.
|
||||
|
||||
Works the same on **VSCode** and **VSCodium** — the extension uses
|
||||
only the standard VSCode API and `vscode-languageclient`, no
|
||||
Microsoft-proprietary surface.
|
||||
|
||||
## How it works
|
||||
|
||||
The extension is a thin LSP client that spawns the language server
|
||||
shipped with testium itself (`testium lsp`). All the language
|
||||
intelligence (item types, parameter completion, schema awareness)
|
||||
lives in the testium repo — every new item type or parameter you add
|
||||
upstream becomes available in the editor on the next testium upgrade,
|
||||
without re-publishing this extension.
|
||||
|
||||
Two static parts live here, because they need to run *before* the LSP
|
||||
has a chance to start:
|
||||
|
||||
- **Syntax highlighting** — a TextMate grammar under `syntaxes/`
|
||||
delegates to the base YAML grammar and adds tokens for testium's
|
||||
`$(name)`, `<| python expr |>`, and Jinja `{% … %}` / `{{ … }}`
|
||||
constructs.
|
||||
- **Editor configuration** — comment character, bracket pairs,
|
||||
auto-close pairs for `$( )`, `<| |>`, `{% %}`, `{{ }}`.
|
||||
|
||||
## Requirements
|
||||
|
||||
- VSCode ≥ 1.80 (or any recent VSCodium build).
|
||||
- A working `testium` installation with the `lsp` extra:
|
||||
```sh
|
||||
pip install 'testium[lsp]'
|
||||
```
|
||||
Or, when developing testium from source:
|
||||
```sh
|
||||
pip install -e /path/to/testium/src[lsp]
|
||||
```
|
||||
|
||||
## Settings
|
||||
|
||||
| Setting | Default | Description |
|
||||
|---|---|---|
|
||||
| `testium.serverPath` | `testium` | Path to the `testium` executable. Set this to your venv's `bin/testium` if `testium` isn't on `$PATH`. |
|
||||
| `testium.trace.server` | `off` | LSP trace level surfaced in the **Testium LSP** output channel. |
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npm run compile # one-shot build
|
||||
npm run watch # rebuild on save
|
||||
```
|
||||
|
||||
Press **F5** in VSCode to launch a development host with the extension
|
||||
loaded. Open any `.tum` file; the **Testium LSP** output channel shows
|
||||
the language-server traffic when `testium.trace.server` is set to
|
||||
`messages` or `verbose`.
|
||||
|
||||
## Packaging
|
||||
|
||||
```sh
|
||||
npx vsce package # produces testium-assist-<v>.vsix
|
||||
```
|
||||
|
||||
To install locally without publishing:
|
||||
- **Code/Codium UI** — `Extensions: Install from VSIX…` from the
|
||||
command palette, pick the `.vsix`.
|
||||
- **CLI** — `code --install-extension testium-assist-<v>.vsix` (or
|
||||
`codium --install-extension …`).
|
||||
|
||||
## Publishing
|
||||
|
||||
The extension targets two registries:
|
||||
|
||||
- **VS Marketplace** (used by VSCode) — `npx vsce publish`. Requires a
|
||||
Microsoft publisher account.
|
||||
- **Open VSX** (used by VSCodium, Cursor, Gitpod, Theia, Eclipse Che) —
|
||||
`npx ovsx publish`. Free and open.
|
||||
|
||||
Both consume the same `.vsix` artifact. A GitHub Actions workflow that
|
||||
runs both on tag push is the typical setup.
|
||||
|
||||
## Status
|
||||
|
||||
This is the MVP: completion of test item type names at the start of a
|
||||
new step. Hover, parameter completion, outline and diagnostics will
|
||||
follow as the testium LSP server gains those features — no extension
|
||||
re-publish needed.
|
||||
|
||||
## License
|
||||
|
||||
EUPL-1.2 — same as testium.
|
||||
|
||||
38
language-configuration.json
Normal file
38
language-configuration.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "#"
|
||||
},
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
],
|
||||
"autoClosingPairs": [
|
||||
{ "open": "{", "close": "}" },
|
||||
{ "open": "[", "close": "]" },
|
||||
{ "open": "(", "close": ")" },
|
||||
{ "open": "\"", "close": "\"", "notIn": ["string"] },
|
||||
{ "open": "'", "close": "'", "notIn": ["string"] },
|
||||
{ "open": "$(", "close": ")" },
|
||||
{ "open": "<|", "close": "|>" },
|
||||
{ "open": "{%", "close": "%}" },
|
||||
{ "open": "{{", "close": "}}" }
|
||||
],
|
||||
"surroundingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
],
|
||||
"indentationRules": {
|
||||
"increaseIndentPattern": "^.*:\\s*$",
|
||||
"decreaseIndentPattern": "^\\s+[}\\]].*$"
|
||||
},
|
||||
"onEnterRules": [
|
||||
{
|
||||
"beforeText": "^\\s*-\\s+[^:]*:\\s*$",
|
||||
"action": { "indent": "indent" }
|
||||
}
|
||||
]
|
||||
}
|
||||
128
package-lock.json
generated
Normal file
128
package-lock.json
generated
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"name": "testium-assist",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "testium-assist",
|
||||
"version": "0.1.0",
|
||||
"license": "EUPL-1.2",
|
||||
"dependencies": {
|
||||
"vscode-languageclient": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/vscode": "^1.80.0",
|
||||
"typescript": "^5.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.80.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.19.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.41.tgz",
|
||||
"integrity": "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/vscode": {
|
||||
"version": "1.120.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.120.0.tgz",
|
||||
"integrity": "sha512-feaT4Rst+FkTch5zz/ZbNCxoIvo55YU80Be2kiL7OJcod4+CUYf2lUBPdIJzozNnSEMq1VRTGrWEcCGFB3fBmA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
|
||||
"integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "5.1.9",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
|
||||
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz",
|
||||
"integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vscode-jsonrpc": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
|
||||
"integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageclient": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz",
|
||||
"integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==",
|
||||
"dependencies": {
|
||||
"minimatch": "^5.1.0",
|
||||
"semver": "^7.3.7",
|
||||
"vscode-languageserver-protocol": "3.17.5"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.82.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver-protocol": {
|
||||
"version": "3.17.5",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
|
||||
"integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
|
||||
"dependencies": {
|
||||
"vscode-jsonrpc": "8.2.0",
|
||||
"vscode-languageserver-types": "3.17.5"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-languageserver-types": {
|
||||
"version": "3.17.5",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
|
||||
"integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
69
package.json
Normal file
69
package.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "testium-assist",
|
||||
"displayName": "Testium Assist",
|
||||
"description": "Language support for testium .tum test scripts. Completion, hover and diagnostics powered by the testium LSP server (`testium lsp`).",
|
||||
"version": "0.1.0",
|
||||
"publisher": "testium",
|
||||
"license": "EUPL-1.2",
|
||||
"engines": {
|
||||
"vscode": "^1.80.0"
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"main": "./out/extension.js",
|
||||
"activationEvents": [
|
||||
"onLanguage:tum"
|
||||
],
|
||||
"contributes": {
|
||||
"languages": [
|
||||
{
|
||||
"id": "tum",
|
||||
"aliases": [
|
||||
"Testium TUM",
|
||||
"tum"
|
||||
],
|
||||
"extensions": [
|
||||
".tum"
|
||||
],
|
||||
"configuration": "./language-configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "tum",
|
||||
"scopeName": "source.tum",
|
||||
"path": "./syntaxes/tum.tmLanguage.json"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"title": "Testium Assist",
|
||||
"properties": {
|
||||
"testium.serverPath": {
|
||||
"type": "string",
|
||||
"default": "testium",
|
||||
"description": "Path to the testium executable used to start the language server (`<path> lsp`). Defaults to looking up `testium` on $PATH."
|
||||
},
|
||||
"testium.trace.server": {
|
||||
"type": "string",
|
||||
"enum": ["off", "messages", "verbose"],
|
||||
"default": "off",
|
||||
"description": "Trace the LSP communication between VSCode and the testium server in the Output panel."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "tsc -p .",
|
||||
"watch": "tsc -p . --watch",
|
||||
"vscode:prepublish": "npm run compile"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageclient": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/vscode": "^1.80.0",
|
||||
"typescript": "^5.4.0"
|
||||
}
|
||||
}
|
||||
71
src/extension.ts
Normal file
71
src/extension.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Testium Assist — VSCode language client for .tum files.
|
||||
*
|
||||
* This extension is a thin LSP client: it spawns `testium lsp` and forwards
|
||||
* LSP messages between VSCode and the server. All the language intelligence
|
||||
* (completion, hover, diagnostics, …) lives in the testium repository itself
|
||||
* (`src/testium/lsp/`), which keeps this extension shippable independently
|
||||
* of testium's feature evolution.
|
||||
*
|
||||
* The user can override the testium executable through the
|
||||
* `testium.serverPath` setting (useful when working with a virtualenv or a
|
||||
* source checkout).
|
||||
*/
|
||||
import * as vscode from "vscode";
|
||||
import {
|
||||
LanguageClient,
|
||||
LanguageClientOptions,
|
||||
ServerOptions,
|
||||
TransportKind,
|
||||
} from "vscode-languageclient/node";
|
||||
|
||||
let client: LanguageClient | undefined;
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
||||
const config = vscode.workspace.getConfiguration("testium");
|
||||
const serverPath = config.get<string>("serverPath", "testium");
|
||||
|
||||
const serverOptions: ServerOptions = {
|
||||
run: { command: serverPath, args: ["lsp"], transport: TransportKind.stdio },
|
||||
debug: {
|
||||
command: serverPath,
|
||||
args: ["lsp"],
|
||||
transport: TransportKind.stdio,
|
||||
},
|
||||
};
|
||||
|
||||
const clientOptions: LanguageClientOptions = {
|
||||
documentSelector: [
|
||||
{ scheme: "file", language: "tum" },
|
||||
],
|
||||
// Echo the user-visible setting into the client so the LSP trace shows up
|
||||
// in the Output panel under "Testium LSP".
|
||||
traceOutputChannel: vscode.window.createOutputChannel("Testium LSP"),
|
||||
};
|
||||
|
||||
client = new LanguageClient(
|
||||
"testiumLsp",
|
||||
"Testium LSP",
|
||||
serverOptions,
|
||||
clientOptions,
|
||||
);
|
||||
|
||||
// start() throws if the executable can't be found; we surface that as a
|
||||
// user-visible message instead of a silent failure in the dev console.
|
||||
try {
|
||||
await client.start();
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
vscode.window.showErrorMessage(
|
||||
`Testium Assist: failed to start the language server (${serverPath} lsp). ${msg}`,
|
||||
);
|
||||
client = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deactivate(): Promise<void> {
|
||||
if (client) {
|
||||
await client.stop();
|
||||
client = undefined;
|
||||
}
|
||||
}
|
||||
81
syntaxes/tum.tmLanguage.json
Normal file
81
syntaxes/tum.tmLanguage.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||
"name": "Testium TUM",
|
||||
"scopeName": "source.tum",
|
||||
"patterns": [
|
||||
{ "include": "#tum-tokens" },
|
||||
{ "include": "source.yaml" }
|
||||
],
|
||||
"repository": {
|
||||
"tum-tokens": {
|
||||
"patterns": [
|
||||
{ "include": "#globaldict-reference" },
|
||||
{ "include": "#eval-expression" },
|
||||
{ "include": "#jinja-statement" },
|
||||
{ "include": "#jinja-expression" }
|
||||
]
|
||||
},
|
||||
"globaldict-reference": {
|
||||
"name": "variable.other.tum.globaldict",
|
||||
"begin": "\\$\\(",
|
||||
"end": "\\)",
|
||||
"beginCaptures": {
|
||||
"0": { "name": "punctuation.definition.variable.begin.tum" }
|
||||
},
|
||||
"endCaptures": {
|
||||
"0": { "name": "punctuation.definition.variable.end.tum" }
|
||||
},
|
||||
"patterns": [
|
||||
{ "name": "entity.name.variable.tum", "match": "[A-Za-z_][A-Za-z0-9_]*" }
|
||||
]
|
||||
},
|
||||
"eval-expression": {
|
||||
"name": "meta.embedded.expression.tum",
|
||||
"begin": "<\\|",
|
||||
"end": "\\|>",
|
||||
"beginCaptures": {
|
||||
"0": { "name": "punctuation.definition.expression.begin.tum" }
|
||||
},
|
||||
"endCaptures": {
|
||||
"0": { "name": "punctuation.definition.expression.end.tum" }
|
||||
},
|
||||
"patterns": [
|
||||
{ "include": "source.python" }
|
||||
]
|
||||
},
|
||||
"jinja-statement": {
|
||||
"name": "meta.embedded.block.jinja.tum",
|
||||
"begin": "\\{%-?",
|
||||
"end": "-?%\\}",
|
||||
"beginCaptures": {
|
||||
"0": { "name": "punctuation.definition.template-statement.begin.tum" }
|
||||
},
|
||||
"endCaptures": {
|
||||
"0": { "name": "punctuation.definition.template-statement.end.tum" }
|
||||
},
|
||||
"patterns": [
|
||||
{ "name": "keyword.control.jinja.tum",
|
||||
"match": "\\b(for|endfor|if|elif|else|endif|set|include|extends|block|endblock|macro|endmacro|in|and|or|not|is|with|without|context)\\b" },
|
||||
{ "name": "string.quoted.double.jinja.tum", "match": "\"(?:[^\"\\\\]|\\\\.)*\"" },
|
||||
{ "name": "string.quoted.single.jinja.tum", "match": "'(?:[^'\\\\]|\\\\.)*'" },
|
||||
{ "name": "constant.numeric.jinja.tum", "match": "\\b[0-9]+(?:\\.[0-9]+)?\\b" }
|
||||
]
|
||||
},
|
||||
"jinja-expression": {
|
||||
"name": "meta.embedded.expression.jinja.tum",
|
||||
"begin": "\\{\\{-?",
|
||||
"end": "-?\\}\\}",
|
||||
"beginCaptures": {
|
||||
"0": { "name": "punctuation.definition.template-expression.begin.tum" }
|
||||
},
|
||||
"endCaptures": {
|
||||
"0": { "name": "punctuation.definition.template-expression.end.tum" }
|
||||
},
|
||||
"patterns": [
|
||||
{ "name": "string.quoted.double.jinja.tum", "match": "\"(?:[^\"\\\\]|\\\\.)*\"" },
|
||||
{ "name": "string.quoted.single.jinja.tum", "match": "'(?:[^'\\\\]|\\\\.)*'" },
|
||||
{ "name": "variable.other.jinja.tum", "match": "[A-Za-z_][A-Za-z0-9_]*" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
15
tsconfig.json
Normal file
15
tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022"],
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", ".vscode-test"]
|
||||
}
|
||||
Reference in New Issue
Block a user