mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 16:42:21 -05:00
Add reusable prettier wrapper CLI (denoland/deno_std#165)
This also fixes an issue with the path on azure-pipelines.
Original: e7837ff0f0
This commit is contained in:
parent
e6d1b5ed3e
commit
0eb1a49b38
19 changed files with 584 additions and 291 deletions
|
@ -26,6 +26,6 @@ jobs:
|
|||
vmImage: 'vs2017-win2016'
|
||||
steps:
|
||||
- powershell: iwr https://deno.land/x/install/install.ps1 -out install.ps1; .\install.ps1 $(DENO_VERSION)
|
||||
- script: echo '##vso[task.prependpath]C:\Users\VssAdministrator\.deno\bin\'
|
||||
- script: 'C:\Users\VssAdministrator\.deno\bin\deno.exe test.ts --allow-run --allow-net --allow-write'
|
||||
- script: 'C:\Users\VssAdministrator\.deno\bin\deno.exe format.ts --allow-run --allow-write --check'
|
||||
- bash: echo "##vso[task.prependpath]C:\Users\VssAdministrator\.deno\\bin"
|
||||
- bash: deno.exe test.ts --allow-run --allow-net --allow-write
|
||||
- bash: deno.exe format.ts --allow-run --allow-write --check
|
||||
|
|
165
format.ts
165
format.ts
|
@ -1,159 +1,26 @@
|
|||
#!/usr/bin/env deno --allow-run --allow-write
|
||||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
/**
|
||||
* This script formats the source files in the repository.
|
||||
*
|
||||
* Usage: deno format.ts [--check]
|
||||
*
|
||||
* Options:
|
||||
* --check Checks if the source files are formatted.
|
||||
*/
|
||||
import { args, platform, readAll, exit, run, readFile, writeFile } from "deno";
|
||||
import { exit, args } from "deno";
|
||||
import { parse } from "./flags/mod.ts";
|
||||
import { prettier, prettierPlugins } from "./prettier/prettier.ts";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
// Runs commands in cross-platform way
|
||||
function xrun(opts) {
|
||||
return run({
|
||||
...opts,
|
||||
args: platform.os === "win" ? ["cmd.exe", "/c", ...opts.args] : opts.args
|
||||
});
|
||||
}
|
||||
|
||||
// Gets the source files in the repository
|
||||
async function getSourceFiles() {
|
||||
return decoder
|
||||
.decode(
|
||||
await readAll(
|
||||
xrun({
|
||||
args: ["git", "ls-files"],
|
||||
stdout: "piped"
|
||||
}).stdout
|
||||
)
|
||||
)
|
||||
.trim()
|
||||
.split(/\r?\n/);
|
||||
}
|
||||
|
||||
async function readFileIfExists(filename: string): Promise<string | null> {
|
||||
let data;
|
||||
try {
|
||||
data = await readFile(filename);
|
||||
} catch (e) {
|
||||
// The file is deleted. Returns null.
|
||||
return null;
|
||||
}
|
||||
|
||||
return decoder.decode(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the file has been formatted with prettier.
|
||||
*/
|
||||
async function checkFile(
|
||||
filename: string,
|
||||
parser: "typescript" | "markdown"
|
||||
): Promise<boolean> {
|
||||
const text = await readFileIfExists(filename);
|
||||
|
||||
if (!text) {
|
||||
// The file is deleted. Skip.
|
||||
return;
|
||||
}
|
||||
|
||||
const formatted = prettier.check(text, {
|
||||
parser,
|
||||
plugins: prettierPlugins
|
||||
});
|
||||
|
||||
if (!formatted) {
|
||||
// TODO: print some diff info here to show why this failed
|
||||
console.error(`${filename} ... Not formatted`);
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given file.
|
||||
*/
|
||||
async function formatFile(
|
||||
filename: string,
|
||||
parser: "typescript" | "markdown"
|
||||
): Promise<void> {
|
||||
const text = await readFileIfExists(filename);
|
||||
|
||||
if (!text) {
|
||||
// The file is deleted. Skip.
|
||||
return;
|
||||
}
|
||||
|
||||
const formatted = prettier.format(text, {
|
||||
parser,
|
||||
plugins: prettierPlugins
|
||||
});
|
||||
|
||||
if (text !== formatted) {
|
||||
console.log(`Formatting ${filename}`);
|
||||
await writeFile(filename, encoder.encode(formatted));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the all files have been formatted with prettier.
|
||||
*/
|
||||
async function checkSourceFiles() {
|
||||
const checks = [];
|
||||
|
||||
(await getSourceFiles()).forEach(file => {
|
||||
if (/\.ts$/.test(file)) {
|
||||
checks.push(checkFile(file, "typescript"));
|
||||
} else if (/\.md$/.test(file)) {
|
||||
checks.push(checkFile(file, "markdown"));
|
||||
}
|
||||
});
|
||||
|
||||
const results = await Promise.all(checks);
|
||||
|
||||
if (results.every(result => result)) {
|
||||
exit(0);
|
||||
} else {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the all files with prettier.
|
||||
*/
|
||||
async function formatSourceFiles() {
|
||||
const formats = [];
|
||||
|
||||
(await getSourceFiles()).forEach(file => {
|
||||
if (/\.ts$/.test(file)) {
|
||||
formats.push(formatFile(file, "typescript"));
|
||||
} else if (/\.md$/.test(file)) {
|
||||
formats.push(formatFile(file, "markdown"));
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(formats);
|
||||
exit(0);
|
||||
}
|
||||
import { xrun, executableSuffix } from "./prettier/util.ts";
|
||||
|
||||
async function main(opts) {
|
||||
try {
|
||||
const args = [
|
||||
`deno${executableSuffix}`,
|
||||
"--allow-write",
|
||||
"--allow-run",
|
||||
"prettier/main.ts",
|
||||
"--ignore",
|
||||
"testdata",
|
||||
"--ignore",
|
||||
"vendor"
|
||||
];
|
||||
|
||||
if (opts.check) {
|
||||
await checkSourceFiles();
|
||||
} else {
|
||||
await formatSourceFiles();
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
exit(1);
|
||||
args.push("--check");
|
||||
}
|
||||
|
||||
exit((await xrun({ args }).status()).code);
|
||||
}
|
||||
|
||||
main(parse(args));
|
||||
|
|
|
@ -901,7 +901,30 @@
|
|||
"application/octet-stream": {
|
||||
"source": "iana",
|
||||
"compressible": false,
|
||||
"extensions": ["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"]
|
||||
"extensions": [
|
||||
"bin",
|
||||
"dms",
|
||||
"lrf",
|
||||
"mar",
|
||||
"so",
|
||||
"dist",
|
||||
"distz",
|
||||
"pkg",
|
||||
"bpk",
|
||||
"dump",
|
||||
"elc",
|
||||
"deploy",
|
||||
"exe",
|
||||
"dll",
|
||||
"deb",
|
||||
"dmg",
|
||||
"iso",
|
||||
"img",
|
||||
"msi",
|
||||
"msp",
|
||||
"msm",
|
||||
"buffer"
|
||||
]
|
||||
},
|
||||
"application/oda": {
|
||||
"source": "iana",
|
||||
|
@ -5154,7 +5177,17 @@
|
|||
},
|
||||
"application/x-director": {
|
||||
"source": "apache",
|
||||
"extensions": ["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"]
|
||||
"extensions": [
|
||||
"dir",
|
||||
"dcr",
|
||||
"dxr",
|
||||
"cst",
|
||||
"cct",
|
||||
"cxt",
|
||||
"w3d",
|
||||
"fgd",
|
||||
"swa"
|
||||
]
|
||||
},
|
||||
"application/x-doom": {
|
||||
"source": "apache",
|
||||
|
@ -6704,9 +6737,7 @@
|
|||
},
|
||||
"message/disposition-notification": {
|
||||
"source": "iana",
|
||||
"extensions": [
|
||||
"disposition-notification"
|
||||
]
|
||||
"extensions": ["disposition-notification"]
|
||||
},
|
||||
"message/external-body": {
|
||||
"source": "iana"
|
||||
|
|
39
prettier/README.md
Normal file
39
prettier/README.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
# prettier
|
||||
|
||||
Prettier APIs and tools for deno
|
||||
|
||||
## Use as a CLI
|
||||
|
||||
To formats the source files, run:
|
||||
|
||||
```console
|
||||
deno --allow-run --allow-write https://deno.land/x/std/prettier/main.ts
|
||||
```
|
||||
|
||||
You can format only specific files by passing the arguments.
|
||||
|
||||
```console
|
||||
deno --allow-run --allow-write https://deno.land/x/std/prettier/main.ts path/to/script.ts
|
||||
```
|
||||
|
||||
You can format files on specific directory by passing the directory's path.
|
||||
|
||||
```console
|
||||
deno --allow-run --allow-write https://deno.land/x/std/prettier/main.ts path/to/script.ts
|
||||
```
|
||||
|
||||
## Use API
|
||||
|
||||
You can use APIs of prettier as the following:
|
||||
|
||||
```ts
|
||||
import {
|
||||
prettier,
|
||||
prettierPlugins
|
||||
} from "https://deno.land/x/std/prettier/prettier.ts";
|
||||
|
||||
prettier.format("const x = 1", {
|
||||
parser: "babel",
|
||||
plugins: prettierPlugins
|
||||
}); // => "const x = 1;"
|
||||
```
|
248
prettier/main.ts
Executable file
248
prettier/main.ts
Executable file
|
@ -0,0 +1,248 @@
|
|||
#!/usr/bin/env deno --allow-run --allow-write
|
||||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
// This script formats the given source files. If the files are omitted, it
|
||||
// formats the all files in the repository.
|
||||
import {
|
||||
args,
|
||||
platform,
|
||||
readAll,
|
||||
lstat,
|
||||
exit,
|
||||
run,
|
||||
readFile,
|
||||
writeFile
|
||||
} from "deno";
|
||||
import { xrun } from "./util.ts";
|
||||
import { parse } from "../flags/mod.ts";
|
||||
import { prettier, prettierPlugins } from "./prettier.ts";
|
||||
|
||||
const HELP_MESSAGE = `
|
||||
Formats the given files. If no arg is passed, then formats the all files.
|
||||
|
||||
Usage: deno prettier/main.ts [options] [files...]
|
||||
|
||||
Options:
|
||||
-H, --help Show this help message and exit.
|
||||
--check Check if the source files are formatted.
|
||||
--ignore <path> Ignore the given path(s).
|
||||
|
||||
Example:
|
||||
deno prettier/main.ts script1.ts script2.js
|
||||
Formats the files
|
||||
|
||||
deno prettier/main.ts --check script1.ts script2.js
|
||||
Checks if the files are formatted
|
||||
|
||||
deno prettier/main.ts
|
||||
Formats the all files in the repository
|
||||
`;
|
||||
|
||||
// Available parsers
|
||||
type ParserLabel = "typescript" | "babel" | "markdown" | "json";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
// Lists files in the given directory.
|
||||
// TODO: Replace git usage with deno's API calls
|
||||
async function listFiles(dir: string = "."): Promise<string[]> {
|
||||
return decoder
|
||||
.decode(
|
||||
await readAll(
|
||||
xrun({
|
||||
args: ["git", "ls-files", dir],
|
||||
stdout: "piped"
|
||||
}).stdout
|
||||
)
|
||||
)
|
||||
.trim()
|
||||
.split(/\r?\n/);
|
||||
}
|
||||
|
||||
async function getSourceFiles(args: string[]): Promise<string[]> {
|
||||
if (args.length === 0) {
|
||||
return listFiles();
|
||||
}
|
||||
|
||||
const results = args.map(async path => {
|
||||
if ((await lstat(path)).isDirectory()) {
|
||||
return listFiles(path);
|
||||
}
|
||||
|
||||
return path;
|
||||
});
|
||||
|
||||
return [].concat(...(await Promise.all(results)));
|
||||
}
|
||||
|
||||
// Filters out the files which contains any pattern in the given ignoreList.
|
||||
function filterIgnoreList(files: string[], ignoreList: string[]) {
|
||||
return files.filter(path =>
|
||||
ignoreList.every(pattern => !path.includes(pattern))
|
||||
);
|
||||
}
|
||||
|
||||
async function readFileIfExists(filename: string): Promise<string | null> {
|
||||
let data;
|
||||
try {
|
||||
data = await readFile(filename);
|
||||
} catch (e) {
|
||||
// The file is deleted. Returns null.
|
||||
return null;
|
||||
}
|
||||
|
||||
return decoder.decode(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the file has been formatted with prettier.
|
||||
*/
|
||||
async function checkFile(
|
||||
filename: string,
|
||||
parser: ParserLabel
|
||||
): Promise<boolean> {
|
||||
const text = await readFileIfExists(filename);
|
||||
|
||||
if (!text) {
|
||||
// The file is deleted. Skip.
|
||||
return;
|
||||
}
|
||||
|
||||
const formatted = prettier.check(text, {
|
||||
parser,
|
||||
plugins: prettierPlugins
|
||||
});
|
||||
|
||||
if (!formatted) {
|
||||
// TODO: print some diff info here to show why this failed
|
||||
console.error(`${filename} ... Not formatted`);
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the given file.
|
||||
*/
|
||||
async function formatFile(
|
||||
filename: string,
|
||||
parser: ParserLabel
|
||||
): Promise<void> {
|
||||
const text = await readFileIfExists(filename);
|
||||
|
||||
if (!text) {
|
||||
// The file is deleted. Skip.
|
||||
return;
|
||||
}
|
||||
|
||||
const formatted = prettier.format(text, {
|
||||
parser,
|
||||
plugins: prettierPlugins
|
||||
});
|
||||
|
||||
if (text !== formatted) {
|
||||
console.log(`Formatting ${filename}`);
|
||||
await writeFile(filename, encoder.encode(formatted));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the right prettier parser for the given path.
|
||||
*/
|
||||
function selectParser(path: string): ParserLabel | null {
|
||||
if (/\.ts$/.test(path)) {
|
||||
return "typescript";
|
||||
} else if (/\.js$/.test(path)) {
|
||||
return "babel";
|
||||
} else if (/\.json$/.test(path)) {
|
||||
return "json";
|
||||
} else if (/\.md$/.test(path)) {
|
||||
return "markdown";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the files of the given paths have been formatted with prettier.
|
||||
* If paths are empty, then checks all the files.
|
||||
*/
|
||||
async function checkSourceFiles(
|
||||
args: string[],
|
||||
ignoreList: string[]
|
||||
): Promise<void> {
|
||||
const checks = [];
|
||||
|
||||
filterIgnoreList(await getSourceFiles(args), ignoreList).forEach(file => {
|
||||
const parser = selectParser(file);
|
||||
if (parser) {
|
||||
checks.push(checkFile(file, parser));
|
||||
}
|
||||
});
|
||||
|
||||
const results = await Promise.all(checks);
|
||||
|
||||
if (results.every(result => result)) {
|
||||
console.log("Every file is formatted");
|
||||
exit(0);
|
||||
} else {
|
||||
console.log("Some files are not formatted");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the files of the given paths with prettier.
|
||||
* If paths are empty, then formats all the files.
|
||||
*/
|
||||
async function formatSourceFiles(
|
||||
args: string[],
|
||||
ignoreList: string[]
|
||||
): Promise<void> {
|
||||
const formats = [];
|
||||
|
||||
filterIgnoreList(await getSourceFiles(args), ignoreList).forEach(file => {
|
||||
const parser = selectParser(file);
|
||||
if (parser) {
|
||||
formats.push(formatFile(file, parser));
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(formats);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
async function main(opts) {
|
||||
const { help, ignore, check, _: args } = opts;
|
||||
|
||||
if (help) {
|
||||
console.log(HELP_MESSAGE);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
const ignoreList: string[] = Array.isArray(ignore) ? ignore : [ignore];
|
||||
|
||||
try {
|
||||
if (check) {
|
||||
await checkSourceFiles(args, ignoreList);
|
||||
} else {
|
||||
await formatSourceFiles(args, ignoreList);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main(
|
||||
parse(args.slice(1), {
|
||||
string: ["ignore"],
|
||||
boolean: ["check", "help"],
|
||||
default: {
|
||||
ignore: []
|
||||
},
|
||||
alias: {
|
||||
H: "help"
|
||||
}
|
||||
})
|
||||
);
|
87
prettier/main_test.ts
Normal file
87
prettier/main_test.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { test, assertEqual } from "../testing/mod.ts";
|
||||
import { xrun, executableSuffix } from "./util.ts";
|
||||
import { readAll } from "deno";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
async function run(args: string[]) {
|
||||
const p = xrun({ args, stdout: "piped" });
|
||||
|
||||
const stdout = decoder.decode(await readAll(p.stdout));
|
||||
const { code } = await p.status();
|
||||
|
||||
return { stdout, code };
|
||||
}
|
||||
|
||||
const cmd = [
|
||||
`deno${executableSuffix}`,
|
||||
"--allow-run",
|
||||
"--allow-write",
|
||||
"prettier/main.ts"
|
||||
];
|
||||
const testdata = "prettier/testdata";
|
||||
|
||||
function normalizeOutput(output: string): string {
|
||||
return output
|
||||
.replace(/\r/g, "")
|
||||
.replace(/\\/g, "/")
|
||||
.trim()
|
||||
.split("\n")
|
||||
.sort()
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
async function clearTestdataChanges() {
|
||||
await xrun({ args: ["git", "checkout", testdata] }).status();
|
||||
}
|
||||
|
||||
test(async function testPrettierCheckAndFormatFiles() {
|
||||
await clearTestdataChanges();
|
||||
|
||||
const files = [`${testdata}/0.ts`, `${testdata}/1.js`];
|
||||
|
||||
var { code, stdout } = await run([...cmd, "--check", ...files]);
|
||||
assertEqual(code, 1);
|
||||
assertEqual(normalizeOutput(stdout), "Some files are not formatted");
|
||||
|
||||
var { code, stdout } = await run([...cmd, ...files]);
|
||||
assertEqual(code, 0);
|
||||
assertEqual(
|
||||
normalizeOutput(stdout),
|
||||
`Formatting prettier/testdata/0.ts
|
||||
Formatting prettier/testdata/1.js`
|
||||
);
|
||||
|
||||
var { code, stdout } = await run([...cmd, "--check", ...files]);
|
||||
assertEqual(code, 0);
|
||||
assertEqual(normalizeOutput(stdout), "Every file is formatted");
|
||||
|
||||
await clearTestdataChanges();
|
||||
});
|
||||
|
||||
test(async function testPrettierCheckAndFormatDirs() {
|
||||
await clearTestdataChanges();
|
||||
|
||||
const dirs = [`${testdata}/foo`, `${testdata}/bar`];
|
||||
|
||||
var { code, stdout } = await run([...cmd, "--check", ...dirs]);
|
||||
assertEqual(code, 1);
|
||||
assertEqual(normalizeOutput(stdout), "Some files are not formatted");
|
||||
|
||||
var { code, stdout } = await run([...cmd, ...dirs]);
|
||||
assertEqual(code, 0);
|
||||
assertEqual(
|
||||
normalizeOutput(stdout),
|
||||
`Formatting prettier/testdata/bar/0.ts
|
||||
Formatting prettier/testdata/bar/1.js
|
||||
Formatting prettier/testdata/foo/0.ts
|
||||
Formatting prettier/testdata/foo/1.js`
|
||||
);
|
||||
|
||||
var { code, stdout } = await run([...cmd, "--check", ...dirs]);
|
||||
assertEqual(code, 0);
|
||||
assertEqual(normalizeOutput(stdout), "Every file is formatted");
|
||||
|
||||
await clearTestdataChanges();
|
||||
});
|
|
@ -1,7 +1,8 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import "./standalone.js";
|
||||
import "./parser_typescript.js";
|
||||
import "./parser_markdown.js";
|
||||
import "./vendor/standalone.js";
|
||||
import "./vendor/parser_typescript.js";
|
||||
import "./vendor/parser_babylon.js";
|
||||
import "./vendor/parser_markdown.js";
|
||||
|
||||
// TODO: provide decent type declarions for these
|
||||
const { prettier, prettierPlugins } = window as any;
|
||||
|
|
1
prettier/testdata/0.ts
vendored
Normal file
1
prettier/testdata/0.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log (0)
|
1
prettier/testdata/1.js
vendored
Normal file
1
prettier/testdata/1.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log (1)
|
1
prettier/testdata/bar/0.ts
vendored
Normal file
1
prettier/testdata/bar/0.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log (0)
|
1
prettier/testdata/bar/1.js
vendored
Normal file
1
prettier/testdata/bar/1.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log (1)
|
1
prettier/testdata/foo/0.ts
vendored
Normal file
1
prettier/testdata/foo/0.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log (0)
|
1
prettier/testdata/foo/1.js
vendored
Normal file
1
prettier/testdata/foo/1.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
console.log (1)
|
12
prettier/util.ts
Normal file
12
prettier/util.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { platform, run } from "deno";
|
||||
|
||||
// Runs a command in cross-platform way
|
||||
export function xrun(opts) {
|
||||
return run({
|
||||
...opts,
|
||||
args: platform.os === "win" ? ["cmd.exe", "/c", ...opts.args] : opts.args
|
||||
});
|
||||
}
|
||||
|
||||
export const executableSuffix = platform.os === "win" ? ".exe" : "";
|
1
prettier/vendor/parser_babylon.js
vendored
Normal file
1
prettier/vendor/parser_babylon.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
test.ts
1
test.ts
|
@ -21,6 +21,7 @@ import "log/test.ts";
|
|||
import "log/handlers_test.ts";
|
||||
import "log/logger_test.ts";
|
||||
import "media_types/test.ts";
|
||||
import "prettier/main_test.ts";
|
||||
import "testing/test.ts";
|
||||
import "textproto/test.ts";
|
||||
import "ws/sha1_test.ts";
|
||||
|
|
Loading…
Reference in a new issue