hey look a thing
This commit is contained in:
commit
dac0a80d47
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
*.vsix
|
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// A launch configuration that launches the extension inside a new window
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Extension",
|
||||||
|
"type": "extensionHost",
|
||||||
|
"request": "launch",
|
||||||
|
"args": [
|
||||||
|
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# embedded-string-highlighting
|
||||||
|
|
||||||
|
> textmate grammars can't be *that* bad right??
|
22
base.package.json
Normal file
22
base.package.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "embedded-string-highlighting",
|
||||||
|
"displayName": "fuck fuck fuck",
|
||||||
|
"description": "yeet",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.98.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Programming Languages"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "node build.mjs",
|
||||||
|
"build:watch": "nodemon -e js,mjs,cjs --exec npm run build"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"dprint": "^0.49.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"nodemon": "^3.1.9",
|
||||||
|
"vscode-textmate": "^9.2.0"
|
||||||
|
}
|
||||||
|
}
|
14
build.mts
Executable file
14
build.mts
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import {glob, writeFile} from 'node:fs/promises';
|
||||||
|
|
||||||
|
for await (const input of glob('./**/*.json.{js,mjs,ts,mts}')) {
|
||||||
|
(async () => {
|
||||||
|
const m = await import(`./${input}`);
|
||||||
|
await writeFile(
|
||||||
|
input.replace(/\.json\..*$/, '.json'),
|
||||||
|
JSON.stringify(m.default, null, '\t'),
|
||||||
|
{encoding: 'utf-8'},
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
}
|
39
dprint.json
Normal file
39
dprint.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"typescript": {
|
||||||
|
"lineWidth": 80,
|
||||||
|
"indentWidth": 4,
|
||||||
|
"useTabs": true,
|
||||||
|
"quoteStyle": "alwaysSingle",
|
||||||
|
"quoteProps": "consistent",
|
||||||
|
"useBraces": "always",
|
||||||
|
"arrowFunction.useParentheses": "preferNone",
|
||||||
|
"enumDeclaration.memberSpacing": "newLine",
|
||||||
|
"spaceSurroundingProperties": false,
|
||||||
|
"exportDeclaration.spaceSurroundingNamedExports": false,
|
||||||
|
"importDeclaration.spaceSurroundingNamedImports": false,
|
||||||
|
"constructor.spaceBeforeParentheses": true,
|
||||||
|
"functionDeclaration.spaceBeforeParentheses": true,
|
||||||
|
"functionExpression.spaceBeforeParentheses": true,
|
||||||
|
"getAccessor.spaceBeforeParentheses": true,
|
||||||
|
"setAccessor.spaceBeforeParentheses": true,
|
||||||
|
"method.spaceBeforeParentheses": true
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"indentWidth": 4,
|
||||||
|
"useTabs": true
|
||||||
|
},
|
||||||
|
"markdown": {
|
||||||
|
"emphasisKind": "asterisks",
|
||||||
|
"strongKind": "asterisks"
|
||||||
|
},
|
||||||
|
"excludes": [
|
||||||
|
"**/node_modules",
|
||||||
|
"**/*-lock.json",
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"https://plugins.dprint.dev/typescript-0.93.3.wasm",
|
||||||
|
"https://plugins.dprint.dev/json-0.19.4.wasm",
|
||||||
|
"https://plugins.dprint.dev/markdown-0.17.8.wasm"
|
||||||
|
]
|
||||||
|
}
|
34
embeddedLanguages.mts
Normal file
34
embeddedLanguages.mts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import packageJSON from './base.package.json';
|
||||||
|
|
||||||
|
const languages: {
|
||||||
|
id: string;
|
||||||
|
sourceScope: string;
|
||||||
|
aliases?: string[];
|
||||||
|
}[] = [
|
||||||
|
{id: 'javascript', sourceScope: 'source.js'},
|
||||||
|
{id: 'typescript', sourceScope: 'source.ts'},
|
||||||
|
{id: 'javascriptreact', sourceScope: 'source.js.jsx'},
|
||||||
|
{id: 'typescriptreact', sourceScope: 'source.tsx'},
|
||||||
|
{id: 'json', sourceScope: 'source.json'},
|
||||||
|
{id: 'jsonc', sourceScope: 'source.json.comments'},
|
||||||
|
{id: 'jsonl', sourceScope: 'source.json.lines'},
|
||||||
|
{id: 'shellscript', sourceScope: 'source.shell'},
|
||||||
|
{id: 'rust', sourceScope: 'source.rust'},
|
||||||
|
{id: 'css', sourceScope: 'source.css'},
|
||||||
|
{id: 'scss', sourceScope: 'source.css.scss'},
|
||||||
|
{id: 'less', sourceScope: 'source.css.less'},
|
||||||
|
{id: 'html', sourceScope: 'text.html.derivative'},
|
||||||
|
{id: 'sql', sourceScope: 'source.sql'},
|
||||||
|
{id: 'markdown', sourceScope: 'text.html.markdown'},
|
||||||
|
{id: 'xml', sourceScope: 'text.xml'},
|
||||||
|
{id: 'yaml', sourceScope: 'source.yaml'},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default languages.map(language => ({
|
||||||
|
id: language.id,
|
||||||
|
tags: [language.id, ...(language.aliases ?? [])],
|
||||||
|
sourceScope: language.sourceScope,
|
||||||
|
embedScopeInline: `meta.embedded.inline.${language.id}`,
|
||||||
|
embedScopeBlock: `meta.embedded.block.${language.id}`,
|
||||||
|
injectionScope: `${packageJSON.name}.injection.${language.id}`,
|
||||||
|
}));
|
40
grammar.mts
Normal file
40
grammar.mts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import {IRawGrammar} from 'vscode-textmate';
|
||||||
|
|
||||||
|
// vscode-textmate doesn't expose anything else so fine we'll do it ourselves
|
||||||
|
|
||||||
|
type AllOptionalWritable<T> = { -readonly [K in keyof T]?: T[K] };
|
||||||
|
export type Overwrite<T, U> = {
|
||||||
|
[K in keyof (T & U)]: K extends keyof U ? U[K]
|
||||||
|
: K extends keyof T ? T[K]
|
||||||
|
: never;
|
||||||
|
};
|
||||||
|
type RemoveLocation<T> = Omit<T, '$vscodeTextmateLocation'>;
|
||||||
|
|
||||||
|
type Cleanup<T, Overrides = unknown> = AllOptionalWritable<
|
||||||
|
RemoveLocation<Overwrite<T, Overrides>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
type IRawRepository = IRawGrammar['repository'];
|
||||||
|
type IRawRule = IRawRepository[string];
|
||||||
|
type IRawCaptures = NonNullable<IRawRule['captures']>;
|
||||||
|
|
||||||
|
export type Captures = Cleanup<IRawCaptures>;
|
||||||
|
export type Rule = Cleanup<IRawRule, {
|
||||||
|
captures: Captures;
|
||||||
|
beginCaptures: Captures;
|
||||||
|
endCaptures: Captures;
|
||||||
|
whileCaptures: Captures;
|
||||||
|
repository: Repository;
|
||||||
|
}>;
|
||||||
|
export type Repository = Cleanup<IRawRepository, {
|
||||||
|
[name: string]: Rule;
|
||||||
|
$self: Rule;
|
||||||
|
$base: Rule;
|
||||||
|
}>;
|
||||||
|
export type Grammar = Cleanup<IRawGrammar, {
|
||||||
|
repository: Repository;
|
||||||
|
patterns: Rule[];
|
||||||
|
injections: {
|
||||||
|
[expression: string]: Rule;
|
||||||
|
};
|
||||||
|
}>;
|
569
package-lock.json
generated
Normal file
569
package-lock.json
generated
Normal file
|
@ -0,0 +1,569 @@
|
||||||
|
{
|
||||||
|
"name": "embedded-string-highlighting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "embedded-string-highlighting",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"devDependencies": {
|
||||||
|
"dprint": "^0.49.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"nodemon": "^3.1.9",
|
||||||
|
"vscode-textmate": "^9.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.98.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/darwin-arm64": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-b8fwjdfYrX5H+QyeWiB27gPc1GMVdd2LorCtsZWC+MDQO6NOgpuxJePqccbQlFUumy2rfmQuLQprnldvQZhceg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/darwin-x64": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-cA/DIPlHClkufLufuIfcXHtZdlyP9U05RuJLvvAfHwJAxyeEC/chKYVc5BVz86RxMIq6czFGpJHoFtTjrfM3YA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/linux-arm64-glibc": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-UBo3lDJhotT+qza2S48DOPI64MirkJMoFDidh/TJBjokio2TcGd+QUzuB9O7J1+R3AlbwyObcTECjJryCNohHQ==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/linux-arm64-musl": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-XWAPL6Hp+zqk9bi57450wuy4yz4fvT72L3Zji3X7ChL5KD/apMUzQnZhmTpln2sxwIgJ3nCbzEzlF7jhhp/7KA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/linux-riscv64-glibc": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/linux-riscv64-glibc/-/linux-riscv64-glibc-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-6GlGcauMeMbCCJ15OmAMkarouCifij9hb12Vz5UUZPevnutVoWRTQBPQLfllmd+9Znsp23fHnmzmykibdwj4Gw==",
|
||||||
|
"cpu": [
|
||||||
|
"riscv64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/linux-x64-glibc": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-PJUM1G8L2xwF9R1s4/J6kf29S2sJ/sZGy3ah7g5Uj+oYkZq6SlMOrx3xqCXEkKSa0T6Xuc1bUBcJyrjEf36xiw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/linux-x64-musl": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-+WIInBwbCXYmWZcYYmnD8HdcZj6q8ewy6mPpHH6SDMtWr6nrxzyIVLFr72XeiBoHnVsQFUhN+wv5Bm5NnpJtRw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/win32-arm64": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/win32-arm64/-/win32-arm64-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-AteygrhmT7OXIgE/72REUfTPs/+qU0I1vhU379AYXgcWzOKy6Eeyi8lAt17oF7OmGT4IuyrKEDjpdTxhOWLsQw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/@dprint/win32-x64": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-8bE6P9T/32Gd+zMAkcwvUHzOLEMnbHEMgsgiKypYsdFTskpDz+y1GLJvMaxIFd2DB2tMx9TdBYuBQrJroTsMeQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/anymatch": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Python-2.0"
|
||||||
|
},
|
||||||
|
"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==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/binary-extensions": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dprint": {
|
||||||
|
"version": "0.49.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dprint/-/dprint-0.49.0.tgz",
|
||||||
|
"integrity": "sha512-xtBPZbPKWOOJH5al4h6rgzsGHuXpyK7TFJCQ5/TW8Z4zkcB9dfmPAh14/Yp5YZcB798D0liztXw+Nd7suzdzBQ==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"dprint": "bin.js"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@dprint/darwin-arm64": "0.49.0",
|
||||||
|
"@dprint/darwin-x64": "0.49.0",
|
||||||
|
"@dprint/linux-arm64-glibc": "0.49.0",
|
||||||
|
"@dprint/linux-arm64-musl": "0.49.0",
|
||||||
|
"@dprint/linux-riscv64-glibc": "0.49.0",
|
||||||
|
"@dprint/linux-x64-glibc": "0.49.0",
|
||||||
|
"@dprint/linux-x64-musl": "0.49.0",
|
||||||
|
"@dprint/win32-arm64": "0.49.0",
|
||||||
|
"@dprint/win32-x64": "0.49.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ignore-by-default": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/js-yaml": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"js-yaml": "bin/js-yaml.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/nodemon": {
|
||||||
|
"version": "3.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz",
|
||||||
|
"integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^3.5.2",
|
||||||
|
"debug": "^4",
|
||||||
|
"ignore-by-default": "^1.0.1",
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
"pstree.remy": "^1.1.8",
|
||||||
|
"semver": "^7.5.3",
|
||||||
|
"simple-update-notifier": "^2.0.0",
|
||||||
|
"supports-color": "^5.5.0",
|
||||||
|
"touch": "^3.1.0",
|
||||||
|
"undefsafe": "^2.0.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nodemon": "bin/nodemon.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/nodemon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pstree.remy": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
|
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||||
|
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/simple-update-notifier": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/touch": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"nodetouch": "bin/nodetouch.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undefsafe": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/vscode-textmate": {
|
||||||
|
"version": "9.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-9.2.0.tgz",
|
||||||
|
"integrity": "sha512-rkvG4SraZQaPSN/5XjwKswdU0OP9MF28QjrYzUBbhb8QyG3ljB1Ky996m++jiI7KdiAP2CkBiQZd9pqEDTClqA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
package.json.mts
Normal file
35
package.json.mts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import packageJSON from './base.package.json';
|
||||||
|
import languages from './embeddedLanguages.mts';
|
||||||
|
import {merge} from './util.mts';
|
||||||
|
|
||||||
|
// All host languages embed the same set of embedded languages
|
||||||
|
const embeddedLanguages = merge(
|
||||||
|
languages.map(embeddedLanguage => ({
|
||||||
|
[embeddedLanguage.embedScopeInline]: embeddedLanguage.id,
|
||||||
|
[embeddedLanguage.embedScopeBlock]: embeddedLanguage.id,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...packageJSON,
|
||||||
|
name: 'embedded-string-highlighting',
|
||||||
|
displayName: 'fuck fuck fuck',
|
||||||
|
description: 'yeet',
|
||||||
|
version: '0.0.1',
|
||||||
|
engines: {
|
||||||
|
vscode: '^1.98.0',
|
||||||
|
},
|
||||||
|
categories: [
|
||||||
|
'Programming Languages',
|
||||||
|
],
|
||||||
|
contributes: {
|
||||||
|
grammars: [
|
||||||
|
{
|
||||||
|
path: './syntaxes/javascript.injection.json',
|
||||||
|
scopeName: 'embedded-string-highlighting.injection',
|
||||||
|
injectTo: ['source.js'],
|
||||||
|
embeddedLanguages,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
40
syntaxes/javascript.injection.json.mts
Normal file
40
syntaxes/javascript.injection.json.mts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import embeddedLanguages from '../embeddedLanguages.mjs';
|
||||||
|
import {merge} from '../util.mjs';
|
||||||
|
|
||||||
|
const elements = merge(embeddedLanguages.map(embeddedLanguage => ({
|
||||||
|
[`tagged-template-literal-block-${embeddedLanguage.id}`]: {
|
||||||
|
begin: `(${embeddedLanguage.id})(\`)`,
|
||||||
|
end: '`',
|
||||||
|
beginCaptures: {
|
||||||
|
1: {
|
||||||
|
name:
|
||||||
|
'entity.name.function.tagged-template.js entity.name.embedded-language',
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
name:
|
||||||
|
'string.template.js punctuation.definition.string.template.begin.js punctuation.definition.embedded-source.begin',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
endCaptures: {
|
||||||
|
0: {
|
||||||
|
name:
|
||||||
|
'string.template.js punctuation.definition.string.template.end.js punctuation.definition.embedded-source.end',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
contentName: embeddedLanguage.embedScopeBlock,
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
include: embeddedLanguage.sourceScope,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})));
|
||||||
|
|
||||||
|
export default {
|
||||||
|
scopeName: 'embedded-string-highlighting.injection',
|
||||||
|
injectionSelector: 'L:source.js -string -comment',
|
||||||
|
repository: elements,
|
||||||
|
patterns: Object.keys(elements).map(ruleKey => ({
|
||||||
|
include: `#${ruleKey}`,
|
||||||
|
})),
|
||||||
|
};
|
10
util.mts
Normal file
10
util.mts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {Overwrite} from './grammar.mts';
|
||||||
|
|
||||||
|
type AllMerged<Objects extends any[]> = Objects extends
|
||||||
|
[infer T, infer U, ...infer Rest] ? AllMerged<[Overwrite<T, U>, ...Rest]>
|
||||||
|
: Objects extends [infer T, ...infer Rest] ? T
|
||||||
|
: Objects extends (infer Rest)[] ? Rest
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export const merge = <T extends any[]>(objects: T): AllMerged<T> =>
|
||||||
|
Object.assign(Object.create(null), ...objects);
|
Loading…
Reference in a new issue