Add tasks for building typescript-code
This commit is contained in:
parent
bdb2e4e02f
commit
f1906b03cd
|
@ -2,5 +2,8 @@
|
||||||
"name": "SilverStripe Environment",
|
"name": "SilverStripe Environment",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"service": "silverstripe",
|
"service": "silverstripe",
|
||||||
"workspaceFolder": "/vscode/src/mantra"
|
"workspaceFolder": "/vscode/src/mantra",
|
||||||
|
"extensions": [
|
||||||
|
"ms-vscode.vscode-typescript-tslint-plugin"
|
||||||
|
]
|
||||||
}
|
}
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -51,6 +51,9 @@ typings/
|
||||||
# Output of 'npm pack'
|
# Output of 'npm pack'
|
||||||
*.tgz
|
*.tgz
|
||||||
|
|
||||||
|
# Output of 'composer archive'
|
||||||
|
*.tar
|
||||||
|
|
||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
|
@ -77,3 +80,6 @@ vendor/
|
||||||
|
|
||||||
# MySQL cache
|
# MySQL cache
|
||||||
.devcontainer/mysql-data
|
.devcontainer/mysql-data
|
||||||
|
|
||||||
|
# Build files
|
||||||
|
/javascript/
|
||||||
|
|
126
.gulp/Settings.ts
Normal file
126
.gulp/Settings.ts
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
import Path = require("upath");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides settings for building the project.
|
||||||
|
*/
|
||||||
|
export class Settings
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A value indicating whether the project should be built in watched mode.
|
||||||
|
*/
|
||||||
|
public Watch = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target of the project-build.
|
||||||
|
*/
|
||||||
|
public Target: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the source-code root.
|
||||||
|
*/
|
||||||
|
private sourceRoot = "src";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the root of the typescript-project.
|
||||||
|
*/
|
||||||
|
private typeScriptProjectRoot = "App";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the root of the typescript-source.
|
||||||
|
*/
|
||||||
|
private typeScriptSourceRoot = "src";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to save the javascript-code to.
|
||||||
|
*/
|
||||||
|
private libraryPath = "javascript";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of the `Settings` class.
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* The target of the project-build.
|
||||||
|
*/
|
||||||
|
public constructor(target: string)
|
||||||
|
{
|
||||||
|
this.Target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value indicating whether the debug-mode is enabled.
|
||||||
|
*/
|
||||||
|
public get Debug()
|
||||||
|
{
|
||||||
|
return this.Target === "Debug";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the solution.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public RootPath(...path: string[])
|
||||||
|
{
|
||||||
|
return Path.join(Path.dirname(__dirname), ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the source-code.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public SourceRoot(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.sourceRoot, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the typescript-project.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TypeScriptProjectRoot(...path: string[])
|
||||||
|
{
|
||||||
|
return this.SourceRoot(this.typeScriptProjectRoot, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the typescript-source.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TypeScriptSourceRoot(...path: string[])
|
||||||
|
{
|
||||||
|
return this.TypeScriptProjectRoot(this.typeScriptSourceRoot, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the directory to save the javascript-code to.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public LibraryPath(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.libraryPath, ...path);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ import { TaskFunction } from "gulp";
|
||||||
*/
|
*/
|
||||||
declare global
|
declare global
|
||||||
{
|
{
|
||||||
|
// tslint:disable-next-line: completed-docs
|
||||||
interface Function extends TaskFunction
|
interface Function extends TaskFunction
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
14
.vscode/extensions.json
vendored
Normal file
14
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
|
||||||
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
|
"recommendations": [
|
||||||
|
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||||
|
"ms-vscode-remote.remote-containers"
|
||||||
|
],
|
||||||
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
|
||||||
|
"javascript.format.placeOpenBraceOnNewLineForControlBlocks": true,
|
||||||
|
"javascript.format.placeOpenBraceOnNewLineForFunctions": true,
|
||||||
|
"typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
|
||||||
|
"typescript.format.placeOpenBraceOnNewLineForControlBlocks": true,
|
||||||
|
"typescript.format.placeOpenBraceOnNewLineForFunctions": true
|
||||||
|
}
|
|
@ -36,12 +36,18 @@
|
||||||
"archive": {
|
"archive": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"/*.tar",
|
"/*.tar",
|
||||||
|
".devcontainer",
|
||||||
|
".gulp",
|
||||||
".gitignore",
|
".gitignore",
|
||||||
|
".vscode/",
|
||||||
"gulpfile.ts",
|
"gulpfile.ts",
|
||||||
"node_modules/",
|
"node_modules/",
|
||||||
"package-lock.json",
|
"package-lock.json",
|
||||||
"package.json",
|
"package.json",
|
||||||
"test/"
|
"src/",
|
||||||
|
"test/",
|
||||||
|
"tsconfig.json",
|
||||||
|
"tslint.json"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
|
|
278
gulpfile.ts
278
gulpfile.ts
|
@ -1,5 +1,80 @@
|
||||||
|
import browserify = require("browserify");
|
||||||
|
import log = require("fancy-log");
|
||||||
|
import gulp = require("gulp");
|
||||||
|
import { TaskFunction } from "gulp";
|
||||||
|
import gulpIf = require("gulp-if");
|
||||||
|
import terser = require("gulp-terser");
|
||||||
|
import merge = require("merge-stream");
|
||||||
|
import minimist = require("minimist");
|
||||||
|
import { Server, Socket } from "net";
|
||||||
|
import PromiseQueue = require("promise-queue");
|
||||||
|
import { parseArgsStringToArgv } from "string-argv";
|
||||||
|
import Path = require("upath");
|
||||||
|
import buffer = require("vinyl-buffer");
|
||||||
|
import vinylSourceStream = require("vinyl-source-stream");
|
||||||
|
import Watchify = require("watchify");
|
||||||
|
import { Settings } from "./.gulp/Settings";
|
||||||
import "./.gulp/TaskFunction";
|
import "./.gulp/TaskFunction";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port to listen for stop-requests.
|
||||||
|
*/
|
||||||
|
const watchConnectorPort = 50958;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message that is printed when starting the compilation in watch mode.
|
||||||
|
*/
|
||||||
|
const watchStartMessage = "Starting compilation in watch mode...";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message that is printed when starting an incremental compilation.
|
||||||
|
*/
|
||||||
|
const incrementalMessage = "File change detected. Starting incremental compilation...";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the message that is printed after finishing a compilation in watch mode.
|
||||||
|
*
|
||||||
|
* @param errorCount
|
||||||
|
* The number of errors which occurred.
|
||||||
|
*/
|
||||||
|
const watchFinishMessage = (errorCount: number) =>
|
||||||
|
{
|
||||||
|
return `Found ${errorCount} errors. Watching for file changes.`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments passed by the user.
|
||||||
|
*/
|
||||||
|
let options = ParseArgs(process.argv.slice(2));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the specified arguments.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* The arguments to parse.
|
||||||
|
*/
|
||||||
|
function ParseArgs(args: string[])
|
||||||
|
{
|
||||||
|
return minimist(
|
||||||
|
args,
|
||||||
|
{
|
||||||
|
string: [
|
||||||
|
"target"
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
target: "t"
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
target: "Debug"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings for building the project.
|
||||||
|
*/
|
||||||
|
let settings = new Settings(options["target"]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the project.
|
* Initializes the project.
|
||||||
*/
|
*/
|
||||||
|
@ -9,3 +84,206 @@ export function Initialize(done: () => void)
|
||||||
}
|
}
|
||||||
|
|
||||||
Initialize.description = "Initializes the project.";
|
Initialize.description = "Initializes the project.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the project in watched mode.
|
||||||
|
*/
|
||||||
|
export let Watch: TaskFunction = (done) =>
|
||||||
|
{
|
||||||
|
settings.Watch = true;
|
||||||
|
Build();
|
||||||
|
|
||||||
|
let server = new Server(
|
||||||
|
(socket) =>
|
||||||
|
{
|
||||||
|
socket.on(
|
||||||
|
"data",
|
||||||
|
(data) =>
|
||||||
|
{
|
||||||
|
let args = parseArgsStringToArgv(data.toString());
|
||||||
|
socket.destroy();
|
||||||
|
|
||||||
|
if (args[0] === "stop")
|
||||||
|
{
|
||||||
|
let options = ParseArgs(args.slice(1));
|
||||||
|
|
||||||
|
if (options["target"] === settings.Target)
|
||||||
|
{
|
||||||
|
server.close();
|
||||||
|
done();
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(watchConnectorPort);
|
||||||
|
};
|
||||||
|
|
||||||
|
Watch.description = "Builds the project in watched mode.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the project.
|
||||||
|
*/
|
||||||
|
export async function Build()
|
||||||
|
{
|
||||||
|
if (settings.Watch)
|
||||||
|
{
|
||||||
|
log.info(watchStartMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
Library();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the TypeScript- and JavaScript-library.
|
||||||
|
*/
|
||||||
|
export async function Library()
|
||||||
|
{
|
||||||
|
let streams: Array<Promise<NodeJS.ReadWriteStream>> = [];
|
||||||
|
let queue = new PromiseQueue();
|
||||||
|
let tsConfigFile = settings.TypeScriptProjectRoot("tsconfig.json");
|
||||||
|
let tsConfig = require(tsConfigFile);
|
||||||
|
|
||||||
|
let optionBase: browserify.Options = {
|
||||||
|
...Watchify.args,
|
||||||
|
node: true,
|
||||||
|
ignoreMissing: true,
|
||||||
|
debug: settings.Debug
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let errorMessages: string[] = [];
|
||||||
|
let files = (tsConfig.files as string[]).map(
|
||||||
|
(file) => Path.relative(settings.TypeScriptSourceRoot(), settings.TypeScriptProjectRoot(file)));
|
||||||
|
|
||||||
|
for (let file of files)
|
||||||
|
{
|
||||||
|
let bundler = browserify(
|
||||||
|
{
|
||||||
|
...optionBase,
|
||||||
|
basedir: settings.LibraryPath(Path.dirname(file)),
|
||||||
|
entries: [
|
||||||
|
settings.TypeScriptSourceRoot(file)
|
||||||
|
],
|
||||||
|
standalone: Path.join(Path.dirname(file), Path.parse(file).name)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (settings.Watch)
|
||||||
|
{
|
||||||
|
bundler = Watchify(bundler);
|
||||||
|
}
|
||||||
|
|
||||||
|
bundler.plugin(
|
||||||
|
require("tsify"),
|
||||||
|
{
|
||||||
|
project: tsConfigFile
|
||||||
|
});
|
||||||
|
|
||||||
|
let bundle = async () =>
|
||||||
|
{
|
||||||
|
return new Promise<NodeJS.ReadWriteStream>(
|
||||||
|
(resolve) =>
|
||||||
|
{
|
||||||
|
let stream = bundler.bundle().on(
|
||||||
|
"error",
|
||||||
|
(error) =>
|
||||||
|
{
|
||||||
|
let message: string = error.message;
|
||||||
|
|
||||||
|
if (!errorMessages.includes(message))
|
||||||
|
{
|
||||||
|
errorMessages.push(message);
|
||||||
|
log.error(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).pipe(
|
||||||
|
vinylSourceStream(Path.changeExt(file, "js"))
|
||||||
|
).pipe(
|
||||||
|
buffer()
|
||||||
|
).pipe(
|
||||||
|
gulpIf(
|
||||||
|
settings.Debug,
|
||||||
|
terser()
|
||||||
|
)
|
||||||
|
).pipe(
|
||||||
|
gulp.dest(settings.LibraryPath())
|
||||||
|
);
|
||||||
|
|
||||||
|
stream.on(
|
||||||
|
"end",
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (settings.Watch && ((queue.getQueueLength() + queue.getPendingLength()) === 1))
|
||||||
|
{
|
||||||
|
log.info(watchFinishMessage(errorMessages.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMessages.splice(0, errorMessages.length);
|
||||||
|
resolve(stream);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (settings.Watch)
|
||||||
|
{
|
||||||
|
bundler.on(
|
||||||
|
"update",
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if ((queue.getQueueLength() + queue.getPendingLength()) === 0)
|
||||||
|
{
|
||||||
|
log.info(incrementalMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.add(
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
return bundle();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let build = () => queue.add(bundle);
|
||||||
|
build.displayName = Build.displayName;
|
||||||
|
build.description = Build.description;
|
||||||
|
streams.push(build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return merge(await Promise.all(streams)) as NodeJS.ReadWriteStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
Library.description = "Builds the TypeScript- and JavaScript-library.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops a watch-task.
|
||||||
|
*/
|
||||||
|
export async function Stop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await new Promise(
|
||||||
|
(resolve, reject) =>
|
||||||
|
{
|
||||||
|
let client = new Socket();
|
||||||
|
|
||||||
|
client.connect(
|
||||||
|
watchConnectorPort,
|
||||||
|
"localhost",
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
client.write(`stop -t ${settings.Target}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on("close", resolve);
|
||||||
|
client.on("error", reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
log.info("The specified task is not running.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop.description = "Stops a watch-task";
|
1660
package-lock.json
generated
1660
package-lock.json
generated
File diff suppressed because it is too large
Load diff
35
package.json
35
package.json
|
@ -5,9 +5,42 @@
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@manuth/tsconfig": "^1.2.2",
|
||||||
|
"@manuth/tslint-presets": "^1.0.4",
|
||||||
|
"@types/bootstrap": "^4.3.1",
|
||||||
|
"@types/browserify": "^12.0.36",
|
||||||
|
"@types/fancy-log": "^1.3.1",
|
||||||
"@types/gulp": "^4.0.6",
|
"@types/gulp": "^4.0.6",
|
||||||
|
"@types/gulp-if": "0.0.33",
|
||||||
|
"@types/gulp-terser": "^1.2.0",
|
||||||
|
"@types/jquery": "^3.3.31",
|
||||||
|
"@types/merge-stream": "^1.1.2",
|
||||||
|
"@types/minimist": "^1.2.0",
|
||||||
|
"@types/node": "^12.7.11",
|
||||||
|
"@types/promise-queue": "^2.2.0",
|
||||||
|
"@types/vinyl-buffer": "^1.0.0",
|
||||||
|
"@types/vinyl-source-stream": "0.0.30",
|
||||||
|
"@types/watchify": "^3.7.4",
|
||||||
|
"bootstrap": "^4.3.1",
|
||||||
|
"browserify": "^16.5.0",
|
||||||
|
"fancy-log": "^1.3.3",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-if": "^3.0.0",
|
||||||
|
"gulp-terser": "^1.2.0",
|
||||||
|
"jquery": "^3.4.1",
|
||||||
|
"merge-stream": "^2.0.0",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"popper.js": "^1.15.0",
|
||||||
|
"promise-queue": "^2.2.5",
|
||||||
|
"string-argv": "^0.3.1",
|
||||||
"ts-node": "^8.4.1",
|
"ts-node": "^8.4.1",
|
||||||
"typescript": "^3.6.3"
|
"tsify": "^4.0.1",
|
||||||
|
"tslint": "^5.20.0",
|
||||||
|
"typescript": "^3.6.3",
|
||||||
|
"typescript-tslint-plugin": "^0.5.4",
|
||||||
|
"upath": "^1.2.0",
|
||||||
|
"vinyl-buffer": "^1.0.1",
|
||||||
|
"vinyl-source-stream": "^2.0.0",
|
||||||
|
"watchify": "^3.11.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
src/App/src/main.ts
Normal file
3
src/App/src/main.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import "bootstrap";
|
||||||
|
import "jquery";
|
||||||
|
import "popper.js";
|
13
src/App/tsconfig.json
Normal file
13
src/App/tsconfig.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/main.ts"
|
||||||
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "src",
|
||||||
|
"lib": [
|
||||||
|
"es7",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"target": "es5"
|
||||||
|
}
|
||||||
|
}
|
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"extends": "@manuth/tsconfig/recommended",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": [
|
||||||
|
"es7"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "typescript-tslint-plugin"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"target": "es5"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"./gulpfile.ts"
|
||||||
|
]
|
||||||
|
}
|
6
tslint.json
Normal file
6
tslint.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"extends": "@manuth/tslint-presets/recommended",
|
||||||
|
"rules": {
|
||||||
|
"interface-name": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue