initial commit
This commit is contained in:
commit
ac1872501c
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"root": true,
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"@typescript-eslint"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/naming-convention": "warn",
|
||||||
|
"@typescript-eslint/semi": "warn",
|
||||||
|
"curly": "warn",
|
||||||
|
"eqeqeq": "warn",
|
||||||
|
"no-throw-literal": "warn",
|
||||||
|
"semi": "off"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
.vscode/
|
||||||
|
node_modules
|
||||||
|
out
|
||||||
|
.vscode-test/
|
||||||
|
*.vsix
|
|
@ -0,0 +1,11 @@
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
dist: bionic
|
||||||
|
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- node
|
||||||
|
- lts/*
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm run vscode:prepublish
|
|
@ -0,0 +1,10 @@
|
||||||
|
.vscode/**
|
||||||
|
.vscode-test/**
|
||||||
|
out/test/**
|
||||||
|
src/**
|
||||||
|
.gitignore
|
||||||
|
.yarnrc
|
||||||
|
**/tsconfig.json
|
||||||
|
**/.eslintrc.json
|
||||||
|
**/*.map
|
||||||
|
**/*.ts
|
|
@ -0,0 +1 @@
|
||||||
|
# Change Log
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 CismonX <admin@cismon.net>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,15 @@
|
||||||
|
# vscode-texinfo
|
||||||
|
|
||||||
|
Texinfo language support for Visual Studio Code.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
**Warning**: This extension is in the early stage of development. **DO NOT USE**.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
To enable the preview feature, the `makeinfo` command-line tool, which is a part of [GNU Texinfo](https://www.gnu.org/software/texinfo/), should be present on your system.
|
||||||
|
|
||||||
|
## Extension Settings
|
||||||
|
|
||||||
|
See VSCode settings for details.
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"lineComment": "@c"
|
||||||
|
},
|
||||||
|
"brackets": [
|
||||||
|
["{", "}"]
|
||||||
|
],
|
||||||
|
"autoClosingPairs": [
|
||||||
|
["{", "}"]
|
||||||
|
],
|
||||||
|
"surroundingPairs": [
|
||||||
|
["{", "}"]
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,129 @@
|
||||||
|
{
|
||||||
|
"name": "texinfo",
|
||||||
|
"displayName": "Texinfo Language Support",
|
||||||
|
"description": "Syntax highlighting, autocompletion and preview support for Texinfo.",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "CismonX",
|
||||||
|
"email": "admin@cismon.net",
|
||||||
|
"url": "https://cismon.net"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/CismonX/vscode-texinfo"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.49.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Linters",
|
||||||
|
"Other",
|
||||||
|
"Programming Languages",
|
||||||
|
"Snippets"
|
||||||
|
],
|
||||||
|
"main": "./out/extension.js",
|
||||||
|
"activationEvents": [
|
||||||
|
"onLanguage:texinfo"
|
||||||
|
],
|
||||||
|
"contributes": {
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "texinfo.showPreview",
|
||||||
|
"title": "Show preview (Texinfo)",
|
||||||
|
"icon": "$(open-preview)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"menus": {
|
||||||
|
"editor/title": [
|
||||||
|
{
|
||||||
|
"command": "texinfo.showPreview",
|
||||||
|
"when": "editorLangId == texinfo",
|
||||||
|
"group": "navigation"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"configuration": {
|
||||||
|
"title": "Texinfo",
|
||||||
|
"properties": {
|
||||||
|
"texinfo.makeinfo": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "makeinfo",
|
||||||
|
"markdownDescription": "Path to the `makeinfo` command."
|
||||||
|
},
|
||||||
|
"texinfo.preview.noHeaders": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"markdownDescription": "Suppress node separators in preview. See `makeinfo --help` for details."
|
||||||
|
},
|
||||||
|
"texinfo.preview.maxSize": {
|
||||||
|
"type": "integer",
|
||||||
|
"default": "2",
|
||||||
|
"markdownDescription": "Max allowed size (in MiB) for the preview document."
|
||||||
|
},
|
||||||
|
"texinfo.preview.errorLimit": {
|
||||||
|
"type": "integer",
|
||||||
|
"default": 100,
|
||||||
|
"markdownDescription": "Max tolerated number of errors when trying to display preview."
|
||||||
|
},
|
||||||
|
"texinfo.preview.force": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"markdownDescription": "Preserve preview even if errors."
|
||||||
|
},
|
||||||
|
"texinfo.preview.noValidate": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"markdownDescription": "Supress node cross-reference validation."
|
||||||
|
},
|
||||||
|
"texinfo.preview.noWarn": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"markdownDescription": "Suppress warnings."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"languages": [
|
||||||
|
{
|
||||||
|
"id": "texinfo",
|
||||||
|
"aliases": [
|
||||||
|
"Texinfo"
|
||||||
|
],
|
||||||
|
"extensions": [
|
||||||
|
".texi",
|
||||||
|
".texinfo",
|
||||||
|
".txi"
|
||||||
|
],
|
||||||
|
"configuration": "./language-configuration.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grammars": [
|
||||||
|
{
|
||||||
|
"language": "texinfo",
|
||||||
|
"scopeName": "text.texinfo",
|
||||||
|
"path": "./out/texinfo.tmGrammar.json",
|
||||||
|
"configuration": "./language-configuration.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"vscode:prepublish": "npm run lint && npm run build",
|
||||||
|
"compile": "tsc -p ./",
|
||||||
|
"prepare": "sh ./scripts/prepare.sh",
|
||||||
|
"build": "npm run prepare && npm run compile",
|
||||||
|
"lint": "eslint src --ext ts",
|
||||||
|
"watch": "tsc -watch -p ./"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^14.11.2",
|
||||||
|
"@types/vscode": "^1.49.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^3.8.0",
|
||||||
|
"@typescript-eslint/parser": "^3.8.0",
|
||||||
|
"eslint": "^7.10.0",
|
||||||
|
"typescript": "^4.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cson": "^7.20.0",
|
||||||
|
"language-texinfo": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Convert TextMate grammar from CSON to JSON (VSCode cannot recognize CSON ones).
|
||||||
|
TMGRAMMAR_CSON=./node_modules/language-texinfo/grammars/texinfo.cson
|
||||||
|
TMGRAMMAR_JSON=./out/texinfo.tmGrammar.json
|
||||||
|
cson2json $TMGRAMMAR_CSON > $TMGRAMMAR_JSON
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* converter.ts
|
||||||
|
*
|
||||||
|
* @author CismonX <admin@cismon.net>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Options } from './options';
|
||||||
|
import { exec } from './utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Texinfo to HTML converter.
|
||||||
|
*/
|
||||||
|
export class Converter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a texinfo document to HTML.
|
||||||
|
*
|
||||||
|
* @param path Path to the Texinfo document to be converted.
|
||||||
|
*/
|
||||||
|
static async convert(path: string) {
|
||||||
|
const converter = new Converter(path);
|
||||||
|
return await converter.convert();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The options to be passed to the `makeinfo` command.
|
||||||
|
*/
|
||||||
|
private readonly options = ['-o', '-', '--no-split', '--html'];
|
||||||
|
|
||||||
|
private constructor(path: string) {
|
||||||
|
if (Options.noHeaders) {
|
||||||
|
this.options.push('--no-headers');
|
||||||
|
}
|
||||||
|
if (Options.force) {
|
||||||
|
this.options.push('--force');
|
||||||
|
}
|
||||||
|
if (Options.noValidate) {
|
||||||
|
this.options.push('--no-validate');
|
||||||
|
}
|
||||||
|
if (Options.noWarn) {
|
||||||
|
this.options.push('--no-warn');
|
||||||
|
}
|
||||||
|
this.options.push(`--error-limit=${Options.errorLimit}`);
|
||||||
|
this.options.push(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async convert() {
|
||||||
|
const makeinfo = Options.makeinfo;
|
||||||
|
const maxBuffer = Options.maxSize * 1024 * 1024;
|
||||||
|
return await exec(makeinfo, this.options, maxBuffer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* extension.ts - Texinfo extension entry
|
||||||
|
*
|
||||||
|
* @author CismonX <admin@cismon.net>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { Preview } from './preview';
|
||||||
|
import { Options } from './options';
|
||||||
|
|
||||||
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.workspace.onDidSaveTextDocument(Preview.update),
|
||||||
|
vscode.workspace.onDidCloseTextDocument(Preview.close),
|
||||||
|
vscode.commands.registerTextEditorCommand('texinfo.showPreview', Preview.show));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deactivate() {
|
||||||
|
Preview.destroyAll();
|
||||||
|
Options.clear();
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/**
|
||||||
|
* options.ts
|
||||||
|
*
|
||||||
|
* @author CismonX <admin@cismon.net>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
|
let options: Options | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get extension options.
|
||||||
|
*
|
||||||
|
* See `contributes.configuration` of package.json for details.
|
||||||
|
*/
|
||||||
|
export class Options {
|
||||||
|
|
||||||
|
private static get instance() {
|
||||||
|
if (options === undefined) {
|
||||||
|
options = new Options('texinfo');
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clear() {
|
||||||
|
options = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get makeinfo() {
|
||||||
|
return Options.instance.getString('makeinfo');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get noHeaders() {
|
||||||
|
return Options.instance.getBoolean('preview.noHeaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get maxSize() {
|
||||||
|
return Options.instance.getNumber('preview.maxSize');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get errorLimit() {
|
||||||
|
return Options.instance.getNumber('preview.errorLimit');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get force() {
|
||||||
|
return Options.instance.getBoolean('preview.force');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get noValidate() {
|
||||||
|
return Options.instance.getBoolean('preview.noValidate');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get noWarn() {
|
||||||
|
return Options.instance.getBoolean('preview.noWarn');
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly configuration: vscode.WorkspaceConfiguration;
|
||||||
|
|
||||||
|
private constructor(section: string) {
|
||||||
|
this.configuration = vscode.workspace.getConfiguration(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getString(section: string) {
|
||||||
|
return this.configuration.get<string>(section) ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private getBoolean(section: string) {
|
||||||
|
return this.configuration.get<boolean>(section) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getNumber(section: string) {
|
||||||
|
return this.configuration.get<number>(section) ?? 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
* preview.ts
|
||||||
|
*
|
||||||
|
* @author CismonX <admin@cismon.net>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { Converter } from './converter';
|
||||||
|
import { prompt } from './utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Texinfo document preview.
|
||||||
|
*/
|
||||||
|
export class Preview {
|
||||||
|
|
||||||
|
private static readonly map = new Map<vscode.TextDocument, Preview>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create (if not yet created) and show preview for a Texinfo document.
|
||||||
|
*
|
||||||
|
* @param editor The editor where the document is being held.
|
||||||
|
*/
|
||||||
|
static async show(editor: vscode.TextEditor) {
|
||||||
|
const document = editor.document;
|
||||||
|
if (document.isUntitled) {
|
||||||
|
if (!await prompt('Save this document to display preview.', 'Save')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!await document.save()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Preview.map.get(document) ?? new Preview(document)).panel.reveal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the document has a corresponding Texinfo preview, update the preview.
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
*/
|
||||||
|
static update(document: vscode.TextDocument) {
|
||||||
|
Preview.getByDocument(document)?.updateWebview();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the document has a corresponding Texinfo preview, close the preview.
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
*/
|
||||||
|
static close(document: vscode.TextDocument) {
|
||||||
|
Preview.getByDocument(document)?.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
static destroyAll() {
|
||||||
|
Preview.map.forEach((preview) => preview.destroy());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get associated preview instance of the given document.
|
||||||
|
*
|
||||||
|
* @param document
|
||||||
|
*/
|
||||||
|
private static getByDocument(document: vscode.TextDocument) {
|
||||||
|
return document.languageId !== 'texinfo' ? undefined : Preview.map.get(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly panel: vscode.WebviewPanel;
|
||||||
|
|
||||||
|
private readonly disposables = new Array<vscode.Disposable>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the preview is updating.
|
||||||
|
*/
|
||||||
|
private updating = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a preview update request is pending.
|
||||||
|
*/
|
||||||
|
private pendingUpdate = false;
|
||||||
|
|
||||||
|
private constructor(private readonly document: vscode.TextDocument) {
|
||||||
|
this.panel = vscode.window.createWebviewPanel('texinfo.preview', '', vscode.ViewColumn.Beside);
|
||||||
|
this.disposables.push(this.panel.onDidDispose(() => this.destroy()));
|
||||||
|
Preview.map.set(this.document, this);
|
||||||
|
this.updateWebview();
|
||||||
|
}
|
||||||
|
|
||||||
|
private get title() {
|
||||||
|
const updating = this.updating ? '(Updating) ' : '';
|
||||||
|
const fileName = path.basename(this.document.fileName);
|
||||||
|
return `${updating}Preview ${fileName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private destroy() {
|
||||||
|
this.disposables.forEach((event) => event.dispose());
|
||||||
|
this.panel.dispose();
|
||||||
|
Preview.map.delete(this.document);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async updateWebview() {
|
||||||
|
if (this.updating) {
|
||||||
|
this.pendingUpdate = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.updating = true;
|
||||||
|
this.pendingUpdate = false;
|
||||||
|
this.panel.title = this.title;
|
||||||
|
const htmlCode = await Converter.convert(this.document.fileName);
|
||||||
|
if (htmlCode === undefined) {
|
||||||
|
vscode.window.showErrorMessage(`Failed to show preview for file ${this.document.fileName}.`);
|
||||||
|
} else {
|
||||||
|
this.panel.webview.html = htmlCode;
|
||||||
|
}
|
||||||
|
this.updating = false;
|
||||||
|
this.panel.title = this.title;
|
||||||
|
if (this.pendingUpdate) {
|
||||||
|
this.updateWebview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* utils.ts - Helper functions
|
||||||
|
*
|
||||||
|
* @author CismonX <admin@cismon.net>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as child_process from 'child_process';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a prompt with two buttons, "Confirm" and "Cancel", and wait for user action.
|
||||||
|
*
|
||||||
|
* @param message The message to be displayed on the prompt.
|
||||||
|
* @param confirm Text to be displayed on the "Confirm" button.
|
||||||
|
* @yields Whether the user clicked the "Confirm" button.
|
||||||
|
*/
|
||||||
|
export async function prompt(message: string, confirm: string) {
|
||||||
|
return confirm === await vscode.window.showInformationMessage(message, confirm, 'Cancel');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute command and get output.
|
||||||
|
*
|
||||||
|
* @param path Path to the executable file.
|
||||||
|
* @param args Arguments to be passed to the command.
|
||||||
|
* @param maxBuffer Max output buffer size.
|
||||||
|
* @yields The output data, or `undefined` if execution fails.
|
||||||
|
*/
|
||||||
|
export function exec(path: string, args: string[], maxBuffer: number) {
|
||||||
|
return new Promise<string | undefined>((resolve) => {
|
||||||
|
child_process.execFile(path, args, { maxBuffer: maxBuffer }, (error, stdout, stderr) => {
|
||||||
|
if (stderr) {
|
||||||
|
console.log(stderr);
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
resolve(undefined);
|
||||||
|
} else {
|
||||||
|
resolve(stdout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es6",
|
||||||
|
"outDir": "out",
|
||||||
|
"lib": [
|
||||||
|
"es6"
|
||||||
|
],
|
||||||
|
"sourceMap": true,
|
||||||
|
"rootDir": "src",
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitReturns": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
".vscode-test"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue