Moves @types/prettier to this repository (#14212)
* Rename `types` to `thirs-party-types` * Copy `index.d.ts` from `@types/prettier` * Make public APIs async * Add missing `formatAST` * Fix `CustomParser` * Fix `Parser.parse` signature * Add comment * Add `standalonw.d.ts` * first implement * Fix path * Add missing parser `.d.ts` * Fix * Fix path * Introduce valid tests * Add unit tests for dts files * Add unit tests * Simplify unit testing * Tweaks structures * Revert needless change * Fix types path * Introduce `ts-expect` * Fix doc utils api * Add AstPath API * Fix API * Fix tests * Fix changelog * Move dts * Update module specifiers * Remove generate dts config file * Update build scripts * Fix type errors * Refactor with namespace imports * Update comments * Fix build script * Improve build script * `typing` -> `types` * Clean up * Minor tweak * Minor tweak * Modify `exports` field * Fix paths in builder * Refactor * Refactor * Address review * Update changelog * Address reviews * Remove `since` from tests * Improve utils type def * Mark deprecated methods * Address review * Move docs types * Address review * Update c8 config * Minor tweak --------- Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
1 parent
164eab2f86
commit
813df18df6
33 files changed
+1899
-60
No files matched your search
@@ -271,6 +271,7 @@ module.exports = {
|
||||
"tests/format/**/jsfmt.spec.js",
|
||||
"tests/integration/**/*.js",
|
||||
"tests/unit/**/*.js",
|
||||
"tests/dts/unit/**/*.js",
|
||||
"scripts/release/__tests__/**/*.spec.js",
|
||||
],
|
||||
env: {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#### Add `.d.ts` files (#14212 by @sosukesuzuki, @fisker)
|
||||
|
||||
Add type definition files required to use Prettier's JavaScript API from TypeScript. This eliminates the need for users to install `@types/prettier`.
|
||||
@@ -61,6 +61,7 @@ const config = {
|
||||
"<rootDir>/tests/format/**/jsfmt.spec.js",
|
||||
"<rootDir>/tests/integration/__tests__/**/*.js",
|
||||
"<rootDir>/tests/unit/**/*.js",
|
||||
"<rootDir>/tests/dts/unit/**/*.js",
|
||||
],
|
||||
testPathIgnorePatterns,
|
||||
// collectCoverage: ENABLE_CODE_COVERAGE,
|
||||
|
||||
+5
-2
@@ -15,6 +15,7 @@
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./src/index.cjs",
|
||||
"types": "./src/index.d.ts",
|
||||
"default": "./src/index.js"
|
||||
},
|
||||
"./*": "./*"
|
||||
@@ -147,7 +148,8 @@
|
||||
"semver": "7.3.8",
|
||||
"serialize-javascript": "6.0.1",
|
||||
"snapshot-diff": "0.10.0",
|
||||
"tempy": "3.0.0"
|
||||
"tempy": "3.0.0",
|
||||
"ts-expect": "1.3.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"trim": "1.0.1"
|
||||
@@ -192,7 +194,8 @@
|
||||
"src/index.cjs",
|
||||
"src/document/debug.js",
|
||||
"src/utils/unexpected-node-error.js",
|
||||
"src/language-js/types/estree.d.ts"
|
||||
"src/language-js/types/estree.d.ts",
|
||||
"src/**/**/*.d.ts"
|
||||
]
|
||||
},
|
||||
"browserslist": [
|
||||
|
||||
@@ -128,7 +128,7 @@ async function buildLicense({ file, files, shouldCollectLicenses }) {
|
||||
return;
|
||||
}
|
||||
|
||||
const javascriptFiles = files.filter((file) => !file.isMetaFile);
|
||||
const javascriptFiles = files.filter((file) => file.kind === "javascript");
|
||||
if (javascriptFiles.some((file) => !Array.isArray(file.dependencies))) {
|
||||
return { skipped: true };
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
writeJson,
|
||||
} from "../utils/index.mjs";
|
||||
|
||||
async function buildPackageJson({ files }) {
|
||||
const packageJson = await readJson(path.join(PROJECT_ROOT, "package.json"));
|
||||
async function buildPackageJson({ file, files }) {
|
||||
const packageJson = await readJson(path.join(PROJECT_ROOT, file.input));
|
||||
|
||||
const bin = files.find(
|
||||
(file) =>
|
||||
@@ -20,6 +20,7 @@ async function buildPackageJson({ files }) {
|
||||
packageJson.exports = {
|
||||
".": {
|
||||
require: "./index.cjs",
|
||||
types: "./index.d.ts",
|
||||
default: "./index.mjs",
|
||||
},
|
||||
"./*": "./*",
|
||||
@@ -32,6 +33,7 @@ async function buildPackageJson({ files }) {
|
||||
file.isPlugin ? `./plugins/${basename}` : `./${basename}`,
|
||||
{
|
||||
require: `./${file.output.file}`,
|
||||
types: `./${file.output.file.replace(/\.js$/, ".d.ts")}`,
|
||||
default: `./${file.output.file.replace(/\.js$/, ".mjs")}`,
|
||||
},
|
||||
];
|
||||
@@ -74,7 +76,7 @@ async function buildPackageJson({ files }) {
|
||||
};
|
||||
packageJson.files = files.map(({ output: { file } }) => file).sort();
|
||||
|
||||
await writeJson(path.join(DIST_DIR, "package.json"), packageJson);
|
||||
await writeJson(path.join(DIST_DIR, file.output.file), packageJson);
|
||||
}
|
||||
|
||||
export default buildPackageJson;
|
||||
@@ -48,7 +48,8 @@ async function buildFile({ file, files, shouldCollectLicenses, cliOptions }) {
|
||||
let displayName = file.output.file;
|
||||
if (
|
||||
(file.platform === "universal" && file.output.format !== "esm") ||
|
||||
(file.output.file.startsWith("index.") && file.output.format !== "esm")
|
||||
(file.output.file.startsWith("index.") && file.output.format !== "esm") ||
|
||||
file.kind === "types"
|
||||
) {
|
||||
displayName = ` ${displayName}`;
|
||||
}
|
||||
|
||||
+107
-53
@@ -1,8 +1,14 @@
|
||||
import path from "node:path";
|
||||
import url from "node:url";
|
||||
import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import { PROJECT_ROOT, DIST_DIR, copyFile } from "../utils/index.mjs";
|
||||
import {
|
||||
PROJECT_ROOT,
|
||||
DIST_DIR,
|
||||
copyFile,
|
||||
writeFile,
|
||||
} from "../utils/index.mjs";
|
||||
import buildJavascriptModule from "./build-javascript-module.js";
|
||||
import buildPackageJson from "./build-package-json.js";
|
||||
import buildLicense from "./build-license.js";
|
||||
@@ -16,6 +22,58 @@ const {
|
||||
} = createEsmUtils(import.meta);
|
||||
const resolveEsmModulePath = async (specifier) =>
|
||||
url.fileURLToPath(await importMetaResolve(specifier));
|
||||
const copyFileBuilder = ({ file }) =>
|
||||
copyFile(
|
||||
path.join(PROJECT_ROOT, file.input),
|
||||
path.join(DIST_DIR, file.output.file)
|
||||
);
|
||||
|
||||
async function typesFileBuilder({ file }) {
|
||||
/**
|
||||
* @typedef {{ from: string, to: string }} ImportPathReplacement
|
||||
* @typedef {{ [input: string]: Array<ImportPathReplacement> }} ReplacementMap
|
||||
*/
|
||||
|
||||
/** @type {Array<ImportPathReplacement>} */
|
||||
const jsParsersImportReplacement = [
|
||||
{ from: "../../index.js", to: "../index.js" },
|
||||
];
|
||||
/** @type {ReplacementMap} */
|
||||
const pathReplacementMap = {
|
||||
"src/index.d.ts": [{ from: "./document/index.js", to: "./doc.js" }],
|
||||
"src/language-js/parse/acorn-and-espree.d.ts": jsParsersImportReplacement,
|
||||
"src/language-js/parse/angular.d.ts": jsParsersImportReplacement,
|
||||
"src/language-js/parse/babel.d.ts": jsParsersImportReplacement,
|
||||
"src/language-js/parse/flow.d.ts": jsParsersImportReplacement,
|
||||
"src/language-js/parse/meriyah.d.ts": jsParsersImportReplacement,
|
||||
"src/language-js/parse/typescript.d.ts": jsParsersImportReplacement,
|
||||
};
|
||||
const replacements = pathReplacementMap[file.input] ?? [];
|
||||
let data = await fs.promises.readFile(file.input, "utf8");
|
||||
for (const { from, to } of replacements) {
|
||||
data = data.replaceAll(
|
||||
new RegExp(` from "${from}";`, "g"),
|
||||
` from "${to}";`
|
||||
);
|
||||
}
|
||||
await writeFile(path.join(DIST_DIR, file.output.file), data);
|
||||
}
|
||||
|
||||
function getTypesFileConfig({ input: jsFileInput, outputBaseName }) {
|
||||
const input = jsFileInput.replace(/\.[cm]?js$/, ".d.ts");
|
||||
if (!fs.existsSync(path.join(PROJECT_ROOT, input))) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
input,
|
||||
output: {
|
||||
file: outputBaseName + ".d.ts",
|
||||
},
|
||||
kind: "types",
|
||||
build: typesFileBuilder,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} BuildOptions
|
||||
@@ -25,18 +83,18 @@ const resolveEsmModulePath = async (specifier) =>
|
||||
* @property {boolean?} minify - disable code minification
|
||||
*
|
||||
* @typedef {Object} Output
|
||||
* @property {'esm' | 'umd' | 'cjs' | 'text' | 'json'} format - File format
|
||||
* @property {"esm" | "umd" | "cjs" | "text" | "json"} format - File format
|
||||
* @property {string} file - path of the output file in the `dist/` folder
|
||||
* @property {string?} umdVariableName - name for the UMD file (for plugins, it'll be `prettierPlugins.${name}`)
|
||||
*
|
||||
* @typedef {Object} File
|
||||
* @property {string?} input - input of the file
|
||||
* @property {string} input - input of the file
|
||||
* @property {Output} output - output of the file
|
||||
* @property {"javascript" | "types" | "meta"} kind - file kind
|
||||
* @property {function} build - file generate function
|
||||
* @property {'node' | 'universal'} platform - ESBuild platform
|
||||
* @property {"node" | "universal"} platform - ESBuild platform
|
||||
* @property {BuildOptions} buildOptions - ESBuild options
|
||||
* @property {boolean?} isPlugin - file is a plugin
|
||||
* @property {boolean?} isMeta - file is a meta file (package.json, LICENSE README.md)
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -400,22 +458,27 @@ const universalFiles = [...nonPluginUniversalFiles, ...pluginFiles].flatMap(
|
||||
outputBaseName ??= path.basename(input);
|
||||
|
||||
return [
|
||||
{
|
||||
format: "esm",
|
||||
file: `${outputBaseName}${extensions.esm}`,
|
||||
},
|
||||
{
|
||||
format: "umd",
|
||||
file: `${outputBaseName}${extensions.umd}`,
|
||||
umdVariableName,
|
||||
},
|
||||
].map((output) => ({
|
||||
input,
|
||||
output,
|
||||
platform: "universal",
|
||||
buildOptions,
|
||||
isPlugin,
|
||||
}));
|
||||
...[
|
||||
{
|
||||
format: "esm",
|
||||
file: `${outputBaseName}${extensions.esm}`,
|
||||
},
|
||||
{
|
||||
format: "umd",
|
||||
file: `${outputBaseName}${extensions.umd}`,
|
||||
umdVariableName,
|
||||
},
|
||||
].map((output) => ({
|
||||
input,
|
||||
output,
|
||||
platform: "universal",
|
||||
buildOptions,
|
||||
isPlugin,
|
||||
build: buildJavascriptModule,
|
||||
kind: "javascript",
|
||||
})),
|
||||
getTypesFileConfig({ input, outputBaseName }),
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
@@ -481,21 +544,26 @@ const nodejsFiles = [
|
||||
},
|
||||
],
|
||||
},
|
||||
].map((file) => {
|
||||
].flatMap((file) => {
|
||||
let { input, output, outputBaseName, ...buildOptions } = file;
|
||||
|
||||
const format = input.endsWith(".cjs") ? "cjs" : "esm";
|
||||
outputBaseName ??= path.basename(input, path.extname(input));
|
||||
|
||||
return {
|
||||
input,
|
||||
output: {
|
||||
format,
|
||||
file: `${outputBaseName}${extensions[format]}`,
|
||||
return [
|
||||
{
|
||||
input,
|
||||
output: {
|
||||
format,
|
||||
file: `${outputBaseName}${extensions[format]}`,
|
||||
},
|
||||
platform: "node",
|
||||
buildOptions,
|
||||
build: buildJavascriptModule,
|
||||
kind: "javascript",
|
||||
},
|
||||
platform: "node",
|
||||
buildOptions,
|
||||
};
|
||||
getTypesFileConfig({ input, outputBaseName }),
|
||||
];
|
||||
});
|
||||
|
||||
const metaFiles = [
|
||||
@@ -503,37 +571,23 @@ const metaFiles = [
|
||||
input: "package.json",
|
||||
output: {
|
||||
format: "json",
|
||||
file: "package.json",
|
||||
},
|
||||
build: buildPackageJson,
|
||||
},
|
||||
{
|
||||
output: {
|
||||
format: "text",
|
||||
file: "README.md",
|
||||
},
|
||||
async build() {
|
||||
await copyFile(
|
||||
path.join(PROJECT_ROOT, "README.md"),
|
||||
path.join(DIST_DIR, "README.md")
|
||||
);
|
||||
},
|
||||
input: "README.md",
|
||||
build: copyFileBuilder,
|
||||
},
|
||||
{
|
||||
output: {
|
||||
format: "text",
|
||||
file: "LICENSE",
|
||||
},
|
||||
input: "LICENSE",
|
||||
build: buildLicense,
|
||||
},
|
||||
].map((file) => ({ ...file, isMetaFile: true }));
|
||||
].map((file) => ({
|
||||
...file,
|
||||
output: { file: file.input, ...file.output },
|
||||
kind: "meta",
|
||||
}));
|
||||
|
||||
/** @type {Files[]} */
|
||||
const files = [
|
||||
...[...nodejsFiles, ...universalFiles].map((file) => ({
|
||||
...file,
|
||||
build: buildJavascriptModule,
|
||||
})),
|
||||
...metaFiles,
|
||||
];
|
||||
const files = [...nodejsFiles, ...universalFiles, ...metaFiles].filter(Boolean);
|
||||
export default files;
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-expect-error
|
||||
import { __internal as sharedWithCli } from "../index.js";
|
||||
|
||||
export const {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import sdbm from "sdbm";
|
||||
// @ts-expect-error
|
||||
import { __internal as sharedWithCli } from "../index.js";
|
||||
|
||||
const { arrayify, isNonEmptyArray, partition } = sharedWithCli.utils;
|
||||
|
||||
Vendored
+248
@@ -0,0 +1,248 @@
|
||||
// https://github.com/prettier/prettier/blob/next/src/document/index.js
|
||||
export namespace builders {
|
||||
type DocCommand =
|
||||
| Align
|
||||
| BreakParent
|
||||
| Cursor
|
||||
| Fill
|
||||
| Group
|
||||
| IfBreak
|
||||
| Indent
|
||||
| IndentIfBreak
|
||||
| Label
|
||||
| Line
|
||||
| LineSuffix
|
||||
| LineSuffixBoundary
|
||||
| Trim;
|
||||
type Doc = string | Doc[] | DocCommand;
|
||||
|
||||
interface Align {
|
||||
type: "align";
|
||||
contents: Doc;
|
||||
n: number | string | { type: "root" };
|
||||
}
|
||||
|
||||
interface BreakParent {
|
||||
type: "break-parent";
|
||||
}
|
||||
|
||||
interface Cursor {
|
||||
type: "cursor";
|
||||
placeholder: symbol;
|
||||
}
|
||||
|
||||
interface Fill {
|
||||
type: "fill";
|
||||
parts: Doc[];
|
||||
}
|
||||
|
||||
interface Group {
|
||||
type: "group";
|
||||
contents: Doc;
|
||||
break: boolean;
|
||||
expandedStates: Doc[];
|
||||
}
|
||||
|
||||
interface HardlineWithoutBreakParent extends Line {
|
||||
hard: true;
|
||||
}
|
||||
|
||||
interface IfBreak {
|
||||
type: "if-break";
|
||||
breakContents: Doc;
|
||||
flatContents: Doc;
|
||||
}
|
||||
|
||||
interface Indent {
|
||||
type: "indent";
|
||||
contents: Doc;
|
||||
}
|
||||
|
||||
interface IndentIfBreak {
|
||||
type: "indent-if-break";
|
||||
}
|
||||
|
||||
interface Label {
|
||||
type: "label";
|
||||
}
|
||||
|
||||
interface Line {
|
||||
type: "line";
|
||||
soft?: boolean | undefined;
|
||||
hard?: boolean | undefined;
|
||||
literal?: boolean | undefined;
|
||||
}
|
||||
|
||||
interface LineSuffix {
|
||||
type: "line-suffix";
|
||||
contents: Doc;
|
||||
}
|
||||
|
||||
interface LineSuffixBoundary {
|
||||
type: "line-suffix-boundary";
|
||||
}
|
||||
|
||||
interface LiterallineWithoutBreakParent extends Line {
|
||||
hard: true;
|
||||
literal: true;
|
||||
}
|
||||
|
||||
type LiteralLine = [LiterallineWithoutBreakParent, BreakParent];
|
||||
|
||||
interface Softline extends Line {
|
||||
soft: true;
|
||||
}
|
||||
|
||||
type Hardline = [HardlineWithoutBreakParent, BreakParent];
|
||||
|
||||
interface Trim {
|
||||
type: "trim";
|
||||
}
|
||||
|
||||
interface GroupOptions {
|
||||
shouldBreak?: boolean | undefined;
|
||||
id?: symbol | undefined;
|
||||
}
|
||||
|
||||
function addAlignmentToDoc(doc: Doc, size: number, tabWidth: number): Doc;
|
||||
|
||||
/** @see [align](https://github.com/prettier/prettier/blob/main/commands.md#align) */
|
||||
function align(widthOrString: Align["n"], doc: Doc): Align;
|
||||
|
||||
/** @see [breakParent](https://github.com/prettier/prettier/blob/main/commands.md#breakparent) */
|
||||
const breakParent: BreakParent;
|
||||
|
||||
/** @see [conditionalGroup](https://github.com/prettier/prettier/blob/main/commands.md#conditionalgroup) */
|
||||
function conditionalGroup(alternatives: Doc[], options?: GroupOptions): Group;
|
||||
|
||||
/** @see [dedent](https://github.com/prettier/prettier/blob/main/commands.md#dedent) */
|
||||
function dedent(doc: Doc): Align;
|
||||
|
||||
/** @see [dedentToRoot](https://github.com/prettier/prettier/blob/main/commands.md#dedenttoroot) */
|
||||
function dedentToRoot(doc: Doc): Align;
|
||||
|
||||
/** @see [fill](https://github.com/prettier/prettier/blob/main/commands.md#fill) */
|
||||
function fill(docs: Doc[]): Fill;
|
||||
|
||||
/** @see [group](https://github.com/prettier/prettier/blob/main/commands.md#group) */
|
||||
function group(doc: Doc, opts?: GroupOptions): Group;
|
||||
|
||||
/** @see [hardline](https://github.com/prettier/prettier/blob/main/commands.md#hardline) */
|
||||
const hardline: Hardline;
|
||||
|
||||
/** @see [hardlineWithoutBreakParent](https://github.com/prettier/prettier/blob/main/commands.md#hardlinewithoutbreakparent-and-literallinewithoutbreakparent) */
|
||||
const hardlineWithoutBreakParent: HardlineWithoutBreakParent;
|
||||
|
||||
/** @see [ifBreak](https://github.com/prettier/prettier/blob/main/commands.md#ifbreak) */
|
||||
function ifBreak(
|
||||
ifBreak: Doc,
|
||||
noBreak?: Doc,
|
||||
options?: { groupId?: symbol | undefined }
|
||||
): IfBreak;
|
||||
|
||||
/** @see [indent](https://github.com/prettier/prettier/blob/main/commands.md#indent) */
|
||||
function indent(doc: Doc): Indent;
|
||||
|
||||
/** @see [indentIfBreak](https://github.com/prettier/prettier/blob/main/commands.md#indentifbreak) */
|
||||
function indentIfBreak(
|
||||
doc: Doc,
|
||||
opts: { groupId: symbol; negate?: boolean | undefined }
|
||||
): IndentIfBreak;
|
||||
|
||||
/** @see [join](https://github.com/prettier/prettier/blob/main/commands.md#join) */
|
||||
function join(sep: Doc, docs: Doc[]): Doc[];
|
||||
|
||||
/** @see [label](https://github.com/prettier/prettier/blob/main/commands.md#label) */
|
||||
function label(label: any | undefined, contents: Doc): Doc;
|
||||
|
||||
/** @see [line](https://github.com/prettier/prettier/blob/main/commands.md#line) */
|
||||
const line: Line;
|
||||
|
||||
/** @see [lineSuffix](https://github.com/prettier/prettier/blob/main/commands.md#linesuffix) */
|
||||
function lineSuffix(suffix: Doc): LineSuffix;
|
||||
|
||||
/** @see [lineSuffixBoundary](https://github.com/prettier/prettier/blob/main/commands.md#linesuffixboundary) */
|
||||
const lineSuffixBoundary: LineSuffixBoundary;
|
||||
|
||||
/** @see [literalline](https://github.com/prettier/prettier/blob/main/commands.md#literalline) */
|
||||
const literalline: LiteralLine;
|
||||
|
||||
/** @see [literallineWithoutBreakParent](https://github.com/prettier/prettier/blob/main/commands.md#hardlinewithoutbreakparent-and-literallinewithoutbreakparent) */
|
||||
const literallineWithoutBreakParent: LiterallineWithoutBreakParent;
|
||||
|
||||
/** @see [markAsRoot](https://github.com/prettier/prettier/blob/main/commands.md#markasroot) */
|
||||
function markAsRoot(doc: Doc): Align;
|
||||
|
||||
/** @see [softline](https://github.com/prettier/prettier/blob/main/commands.md#softline) */
|
||||
const softline: Softline;
|
||||
|
||||
/** @see [trim](https://github.com/prettier/prettier/blob/main/commands.md#trim) */
|
||||
const trim: Trim;
|
||||
|
||||
/** @see [cursor](https://github.com/prettier/prettier/blob/main/commands.md#cursor) */
|
||||
const cursor: Cursor;
|
||||
}
|
||||
|
||||
export namespace debug {
|
||||
function printDocToDebug(doc: builders.Doc): string;
|
||||
}
|
||||
|
||||
export namespace printer {
|
||||
function printDocToString(
|
||||
doc: builders.Doc,
|
||||
options: Options
|
||||
): {
|
||||
formatted: string;
|
||||
cursorNodeStart?: number | undefined;
|
||||
cursorNodeText?: string | undefined;
|
||||
};
|
||||
interface Options {
|
||||
/**
|
||||
* Specify the line length that the printer will wrap on.
|
||||
* @default 80
|
||||
*/
|
||||
printWidth: number;
|
||||
/**
|
||||
* Specify the number of spaces per indentation-level.
|
||||
* @default 2
|
||||
*/
|
||||
tabWidth: number;
|
||||
/**
|
||||
* Indent lines with tabs instead of spaces
|
||||
* @default false
|
||||
*/
|
||||
useTabs: boolean;
|
||||
parentParser?: string | undefined;
|
||||
__embeddedInHtml?: boolean | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace utils {
|
||||
function getDocParts(doc: builders.Doc): builders.Doc;
|
||||
function willBreak(doc: builders.Doc): boolean;
|
||||
function traverseDoc(
|
||||
doc: builders.Doc,
|
||||
onEnter?: (doc: builders.Doc) => void | boolean,
|
||||
onExit?: (doc: builders.Doc) => void,
|
||||
shouldTraverseConditionalGroups?: boolean
|
||||
): void;
|
||||
function findInDoc<T = builders.Doc>(
|
||||
doc: builders.Doc,
|
||||
callback: (doc: builders.Doc) => T,
|
||||
defaultValue: T
|
||||
): T;
|
||||
function mapDoc<T = builders.Doc>(
|
||||
doc: builders.Doc,
|
||||
callback: (doc: builders.Doc) => T
|
||||
): T;
|
||||
function propagateBreaks(doc: builders.Doc): void;
|
||||
function removeLines(doc: builders.Doc): builders.Doc;
|
||||
function stripTrailingHardline(doc: builders.Doc): builders.Doc;
|
||||
function cleanDoc(doc: builders.Doc): builders.Doc;
|
||||
function replaceEndOfLine(
|
||||
doc: builders.Doc,
|
||||
replacement?: builders.Doc
|
||||
): builders.Doc;
|
||||
function canBreak(doc: builders.Doc): boolean;
|
||||
function getDocType(doc: builders.Doc): string;
|
||||
}
|
||||
Vendored
+903
@@ -0,0 +1,903 @@
|
||||
// Copied from `@types/prettier`
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5bb07fc4b087cb7ee91084afa6fe750551a7bbb1/types/prettier/index.d.ts
|
||||
|
||||
// Minimum TypeScript Version: 4.2
|
||||
|
||||
// Add `export {}` here to shut off automatic exporting from index.d.ts. There
|
||||
// are quite a few utility types here that don't need to be shipped with the
|
||||
// exported module.
|
||||
export {};
|
||||
|
||||
import { builders, debug, printer, utils } from "./document/index.js";
|
||||
|
||||
export namespace doc {
|
||||
export { builders, debug, printer, utils };
|
||||
}
|
||||
|
||||
// This utility is here to handle the case where you have an explicit union
|
||||
// between string literals and the generic string type. It would normally
|
||||
// resolve out to just the string type, but this generic LiteralUnion maintains
|
||||
// the intellisense of the original union.
|
||||
//
|
||||
// It comes from this issue: microsoft/TypeScript#29729:
|
||||
// https://github.com/microsoft/TypeScript/issues/29729#issuecomment-700527227
|
||||
export type LiteralUnion<T extends U, U = string> =
|
||||
| T
|
||||
| (Pick<U, never> & { _?: never | undefined });
|
||||
|
||||
export type AST = any;
|
||||
export type Doc = doc.builders.Doc;
|
||||
|
||||
// The type of elements that make up the given array T.
|
||||
type ArrayElement<T> = T extends Array<infer E> ? E : never;
|
||||
|
||||
// A union of the properties of the given object that are arrays.
|
||||
type ArrayProperties<T> = {
|
||||
[K in keyof T]: NonNullable<T[K]> extends any[] ? K : never;
|
||||
}[keyof T];
|
||||
|
||||
// A union of the properties of the given array T that can be used to index it.
|
||||
// If the array is a tuple, then that's going to be the explicit indices of the
|
||||
// array, otherwise it's going to just be number.
|
||||
type IndexProperties<T extends { length: number }> = IsTuple<T> extends true
|
||||
? Exclude<Partial<T>["length"], T["length"]>
|
||||
: number;
|
||||
|
||||
// Effectively performing T[P], except that it's telling TypeScript that it's
|
||||
// safe to do this for tuples, arrays, or objects.
|
||||
type IndexValue<T, P> = T extends any[]
|
||||
? P extends number
|
||||
? T[P]
|
||||
: never
|
||||
: P extends keyof T
|
||||
? T[P]
|
||||
: never;
|
||||
|
||||
// Determines if an object T is an array like string[] (in which case this
|
||||
// evaluates to false) or a tuple like [string] (in which case this evaluates to
|
||||
// true).
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type IsTuple<T> = T extends []
|
||||
? true
|
||||
: T extends [infer First, ...infer Remain]
|
||||
? IsTuple<Remain>
|
||||
: false;
|
||||
|
||||
type CallProperties<T> = T extends any[] ? IndexProperties<T> : keyof T;
|
||||
type IterProperties<T> = T extends any[]
|
||||
? IndexProperties<T>
|
||||
: ArrayProperties<T>;
|
||||
|
||||
type CallCallback<T, U> = (path: AstPath<T>, index: number, value: any) => U;
|
||||
type EachCallback<T> = (
|
||||
path: AstPath<ArrayElement<T>>,
|
||||
index: number,
|
||||
value: any
|
||||
) => void;
|
||||
type MapCallback<T, U> = (
|
||||
path: AstPath<ArrayElement<T>>,
|
||||
index: number,
|
||||
value: any
|
||||
) => U;
|
||||
|
||||
// https://github.com/prettier/prettier/blob/next/src/common/ast-path.js
|
||||
export class AstPath<T = any> {
|
||||
constructor(value: T);
|
||||
|
||||
get key(): string | null;
|
||||
get index(): number | null;
|
||||
get node(): T;
|
||||
get parent(): T | null;
|
||||
get grandparent(): T | null;
|
||||
get isInArray(): boolean;
|
||||
get siblings(): T[] | null;
|
||||
get next(): T | null;
|
||||
get previous(): T | null;
|
||||
get isFirst(): boolean;
|
||||
get isLast(): boolean;
|
||||
get isRoot(): boolean;
|
||||
get root(): T;
|
||||
get ancestors(): T[];
|
||||
|
||||
stack: T[];
|
||||
|
||||
callParent<U>(callback: (path: this) => U, count?: number): U;
|
||||
|
||||
/**
|
||||
* @deprecated Please use `AstPath#key` or `AstPath#index`
|
||||
*/
|
||||
getName(): PropertyKey | null;
|
||||
|
||||
/**
|
||||
* @deprecated Please use `AstPath#node` or `AstPath#siblings`
|
||||
*/
|
||||
getValue(): T;
|
||||
|
||||
getNode(count?: number): T | null;
|
||||
|
||||
getParentNode(count?: number): T | null;
|
||||
|
||||
match(
|
||||
...predicates: Array<
|
||||
(node: any, name: string | null, number: number | null) => boolean
|
||||
>
|
||||
): boolean;
|
||||
|
||||
// For each of the tree walk functions (call, each, and map) this provides 5
|
||||
// strict type signatures, along with a fallback at the end if you end up
|
||||
// calling more than 5 properties deep. This helps a lot with typing because
|
||||
// for the majority of cases you're calling fewer than 5 properties, so the
|
||||
// tree walk functions have a clearer understanding of what you're doing.
|
||||
//
|
||||
// Note that resolving these types is somewhat complicated, and it wasn't
|
||||
// even supported until TypeScript 4.2 (before it would just say that the
|
||||
// type instantiation was excessively deep and possibly infinite).
|
||||
|
||||
call<U>(callback: CallCallback<T, U>): U;
|
||||
call<U, P1 extends CallProperties<T>>(
|
||||
callback: CallCallback<IndexValue<T, P1>, U>,
|
||||
prop1: P1
|
||||
): U;
|
||||
call<U, P1 extends keyof T, P2 extends CallProperties<T[P1]>>(
|
||||
callback: CallCallback<IndexValue<IndexValue<T, P1>, P2>, U>,
|
||||
prop1: P1,
|
||||
prop2: P2
|
||||
): U;
|
||||
call<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends CallProperties<T[P1]>,
|
||||
P3 extends CallProperties<IndexValue<T[P1], P2>>
|
||||
>(
|
||||
callback: CallCallback<
|
||||
IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>,
|
||||
U
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3
|
||||
): U;
|
||||
call<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends CallProperties<T[P1]>,
|
||||
P3 extends CallProperties<IndexValue<T[P1], P2>>,
|
||||
P4 extends CallProperties<IndexValue<IndexValue<T[P1], P2>, P3>>
|
||||
>(
|
||||
callback: CallCallback<
|
||||
IndexValue<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, P4>,
|
||||
U
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
prop4: P4
|
||||
): U;
|
||||
call<U, P extends PropertyKey>(
|
||||
callback: CallCallback<any, U>,
|
||||
prop1: P,
|
||||
prop2: P,
|
||||
prop3: P,
|
||||
prop4: P,
|
||||
...props: P[]
|
||||
): U;
|
||||
|
||||
each(callback: EachCallback<T>): void;
|
||||
each<P1 extends IterProperties<T>>(
|
||||
callback: EachCallback<IndexValue<T, P1>>,
|
||||
prop1: P1
|
||||
): void;
|
||||
each<P1 extends keyof T, P2 extends IterProperties<T[P1]>>(
|
||||
callback: EachCallback<IndexValue<IndexValue<T, P1>, P2>>,
|
||||
prop1: P1,
|
||||
prop2: P2
|
||||
): void;
|
||||
each<
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>
|
||||
>(
|
||||
callback: EachCallback<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3
|
||||
): void;
|
||||
each<
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>,
|
||||
P4 extends IterProperties<IndexValue<IndexValue<T[P1], P2>, P3>>
|
||||
>(
|
||||
callback: EachCallback<
|
||||
IndexValue<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, P4>
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
prop4: P4
|
||||
): void;
|
||||
each(
|
||||
callback: EachCallback<any[]>,
|
||||
prop1: PropertyKey,
|
||||
prop2: PropertyKey,
|
||||
prop3: PropertyKey,
|
||||
prop4: PropertyKey,
|
||||
...props: PropertyKey[]
|
||||
): void;
|
||||
|
||||
map<U>(callback: MapCallback<T, U>): U[];
|
||||
map<U, P1 extends IterProperties<T>>(
|
||||
callback: MapCallback<IndexValue<T, P1>, U>,
|
||||
prop1: P1
|
||||
): U[];
|
||||
map<U, P1 extends keyof T, P2 extends IterProperties<T[P1]>>(
|
||||
callback: MapCallback<IndexValue<IndexValue<T, P1>, P2>, U>,
|
||||
prop1: P1,
|
||||
prop2: P2
|
||||
): U[];
|
||||
map<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>
|
||||
>(
|
||||
callback: MapCallback<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, U>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3
|
||||
): U[];
|
||||
map<
|
||||
U,
|
||||
P1 extends keyof T,
|
||||
P2 extends IterProperties<T[P1]>,
|
||||
P3 extends IterProperties<IndexValue<T[P1], P2>>,
|
||||
P4 extends IterProperties<IndexValue<IndexValue<T[P1], P2>, P3>>
|
||||
>(
|
||||
callback: MapCallback<
|
||||
IndexValue<IndexValue<IndexValue<IndexValue<T, P1>, P2>, P3>, P4>,
|
||||
U
|
||||
>,
|
||||
prop1: P1,
|
||||
prop2: P2,
|
||||
prop3: P3,
|
||||
prop4: P4
|
||||
): U[];
|
||||
map<U>(
|
||||
callback: MapCallback<any[], U>,
|
||||
prop1: PropertyKey,
|
||||
prop2: PropertyKey,
|
||||
prop3: PropertyKey,
|
||||
prop4: PropertyKey,
|
||||
...props: PropertyKey[]
|
||||
): U[];
|
||||
}
|
||||
|
||||
/** @deprecated `FastPath` was renamed to `AstPath` */
|
||||
export type FastPath<T = any> = AstPath<T>;
|
||||
|
||||
export type BuiltInParser = (text: string, options?: any) => AST;
|
||||
export type BuiltInParserName =
|
||||
| "acorn"
|
||||
| "angular"
|
||||
| "babel-flow"
|
||||
| "babel-ts"
|
||||
| "babel"
|
||||
| "css"
|
||||
| "espree"
|
||||
| "flow"
|
||||
| "glimmer"
|
||||
| "graphql"
|
||||
| "html"
|
||||
| "json-stringify"
|
||||
| "json"
|
||||
| "json5"
|
||||
| "less"
|
||||
| "lwc"
|
||||
| "markdown"
|
||||
| "mdx"
|
||||
| "meriyah"
|
||||
| "scss"
|
||||
| "typescript"
|
||||
| "vue"
|
||||
| "yaml";
|
||||
export type BuiltInParsers = Record<BuiltInParserName, BuiltInParser>;
|
||||
|
||||
export type CustomParser = (
|
||||
text: string,
|
||||
options: Options
|
||||
) => AST | Promise<AST>;
|
||||
|
||||
/**
|
||||
* For use in `.prettierrc.js`, `.prettierrc.cjs`, `prettierrc.mjs`, `prettier.config.js`, `prettier.config.cjs`, `prettier.config.mjs`
|
||||
*/
|
||||
export interface Config extends Options {
|
||||
overrides?: Array<{
|
||||
files: string | string[];
|
||||
excludeFiles?: string | string[];
|
||||
options?: Options;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface Options extends Partial<RequiredOptions> {}
|
||||
|
||||
export interface RequiredOptions extends doc.printer.Options {
|
||||
/**
|
||||
* Print semicolons at the ends of statements.
|
||||
* @default true
|
||||
*/
|
||||
semi: boolean;
|
||||
/**
|
||||
* Use single quotes instead of double quotes.
|
||||
* @default false
|
||||
*/
|
||||
singleQuote: boolean;
|
||||
/**
|
||||
* Use single quotes in JSX.
|
||||
* @default false
|
||||
*/
|
||||
jsxSingleQuote: boolean;
|
||||
/**
|
||||
* Print trailing commas wherever possible.
|
||||
* @default "all"
|
||||
*/
|
||||
trailingComma: "none" | "es5" | "all";
|
||||
/**
|
||||
* Print spaces between brackets in object literals.
|
||||
* @default true
|
||||
*/
|
||||
bracketSpacing: boolean;
|
||||
/**
|
||||
* Put the `>` of a multi-line HTML (HTML, JSX, Vue, Angular) element at the end of the last line instead of being
|
||||
* alone on the next line (does not apply to self closing elements).
|
||||
* @default false
|
||||
*/
|
||||
bracketSameLine: boolean;
|
||||
/**
|
||||
* Put the `>` of a multi-line JSX element at the end of the last line instead of being alone on the next line.
|
||||
* @default false
|
||||
* @deprecated use bracketSameLine instead
|
||||
*/
|
||||
jsxBracketSameLine: boolean;
|
||||
/**
|
||||
* Format only a segment of a file.
|
||||
* @default 0
|
||||
*/
|
||||
rangeStart: number;
|
||||
/**
|
||||
* Format only a segment of a file.
|
||||
* @default Number.POSITIVE_INFINITY
|
||||
*/
|
||||
rangeEnd: number;
|
||||
/**
|
||||
* Specify which parser to use.
|
||||
*/
|
||||
parser: LiteralUnion<BuiltInParserName> | CustomParser;
|
||||
/**
|
||||
* Specify the input filepath. This will be used to do parser inference.
|
||||
*/
|
||||
filepath: string;
|
||||
/**
|
||||
* Prettier can restrict itself to only format files that contain a special comment, called a pragma, at the top of the file.
|
||||
* This is very useful when gradually transitioning large, unformatted codebases to prettier.
|
||||
* @default false
|
||||
*/
|
||||
requirePragma: boolean;
|
||||
/**
|
||||
* Prettier can insert a special @format marker at the top of files specifying that
|
||||
* the file has been formatted with prettier. This works well when used in tandem with
|
||||
* the --require-pragma option. If there is already a docblock at the top of
|
||||
* the file then this option will add a newline to it with the @format marker.
|
||||
* @default false
|
||||
*/
|
||||
insertPragma: boolean;
|
||||
/**
|
||||
* By default, Prettier will wrap markdown text as-is since some services use a linebreak-sensitive renderer.
|
||||
* In some cases you may want to rely on editor/viewer soft wrapping instead, so this option allows you to opt out.
|
||||
* @default "preserve"
|
||||
*/
|
||||
proseWrap: "always" | "never" | "preserve";
|
||||
/**
|
||||
* Include parentheses around a sole arrow function parameter.
|
||||
* @default "always"
|
||||
*/
|
||||
arrowParens: "avoid" | "always";
|
||||
/**
|
||||
* Provide ability to support new languages to prettier.
|
||||
*/
|
||||
plugins: Array<string | Plugin>;
|
||||
/**
|
||||
* Specify plugin directory paths to search for plugins if not installed in the same `node_modules` where prettier is located.
|
||||
*/
|
||||
pluginSearchDirs: string[] | false;
|
||||
/**
|
||||
* How to handle whitespaces in HTML.
|
||||
* @default "css"
|
||||
*/
|
||||
htmlWhitespaceSensitivity: "css" | "strict" | "ignore";
|
||||
/**
|
||||
* Which end of line characters to apply.
|
||||
* @default "lf"
|
||||
*/
|
||||
endOfLine: "auto" | "lf" | "crlf" | "cr";
|
||||
/**
|
||||
* Change when properties in objects are quoted.
|
||||
* @default "as-needed"
|
||||
*/
|
||||
quoteProps: "as-needed" | "consistent" | "preserve";
|
||||
/**
|
||||
* Whether or not to indent the code inside <script> and <style> tags in Vue files.
|
||||
* @default false
|
||||
*/
|
||||
vueIndentScriptAndStyle: boolean;
|
||||
/**
|
||||
* Control whether Prettier formats quoted code embedded in the file.
|
||||
* @default "auto"
|
||||
*/
|
||||
embeddedLanguageFormatting: "auto" | "off";
|
||||
/**
|
||||
* Enforce single attribute per line in HTML, Vue and JSX.
|
||||
* @default false
|
||||
*/
|
||||
singleAttributePerLine: boolean;
|
||||
}
|
||||
|
||||
export interface ParserOptions<T = any> extends RequiredOptions {
|
||||
locStart: (node: T) => number;
|
||||
locEnd: (node: T) => number;
|
||||
originalText: string;
|
||||
}
|
||||
|
||||
export interface Plugin<T = any> {
|
||||
languages?: SupportLanguage[] | undefined;
|
||||
parsers?:
|
||||
| { [parserName: string]: Parser<T> | (() => Promise<Parser<T>>) }
|
||||
| undefined;
|
||||
printers?: { [astFormat: string]: Printer<T> } | undefined;
|
||||
options?: SupportOptions | undefined;
|
||||
defaultOptions?: Partial<RequiredOptions> | undefined;
|
||||
}
|
||||
|
||||
export interface Parser<T = any> {
|
||||
parse: (text: string, options: ParserOptions<T>) => T | Promise<T>;
|
||||
astFormat: string;
|
||||
hasPragma?: ((text: string) => boolean) | undefined;
|
||||
locStart: (node: T) => number;
|
||||
locEnd: (node: T) => number;
|
||||
preprocess?:
|
||||
| ((text: string, options: ParserOptions<T>) => string)
|
||||
| undefined;
|
||||
}
|
||||
|
||||
export interface Printer<T = any> {
|
||||
print(
|
||||
path: AstPath<T>,
|
||||
options: ParserOptions<T>,
|
||||
print: (path: AstPath<T>) => Doc,
|
||||
args?: unknown
|
||||
): Doc;
|
||||
embed?:
|
||||
| ((
|
||||
path: AstPath<T>,
|
||||
print: (path: AstPath<T>) => Doc,
|
||||
textToDoc: (text: string, options: Options) => Doc,
|
||||
options: ParserOptions<T>
|
||||
) => Doc | null)
|
||||
| undefined;
|
||||
insertPragma?: (text: string) => string;
|
||||
/**
|
||||
* @returns `null` if you want to remove this node
|
||||
* @returns `void` if you want to use modified newNode
|
||||
* @returns anything if you want to replace the node with it
|
||||
*/
|
||||
massageAstNode?: ((node: any, newNode: any, parent: any) => any) | undefined;
|
||||
hasPrettierIgnore?: ((path: AstPath<T>) => boolean) | undefined;
|
||||
canAttachComment?: ((node: T) => boolean) | undefined;
|
||||
isBlockComment?: ((node: T) => boolean) | undefined;
|
||||
willPrintOwnComments?: ((path: AstPath<T>) => boolean) | undefined;
|
||||
printComment?:
|
||||
| ((commentPath: AstPath<T>, options: ParserOptions<T>) => Doc)
|
||||
| undefined;
|
||||
handleComments?:
|
||||
| {
|
||||
ownLine?:
|
||||
| ((
|
||||
commentNode: any,
|
||||
text: string,
|
||||
options: ParserOptions<T>,
|
||||
ast: T,
|
||||
isLastComment: boolean
|
||||
) => boolean)
|
||||
| undefined;
|
||||
endOfLine?:
|
||||
| ((
|
||||
commentNode: any,
|
||||
text: string,
|
||||
options: ParserOptions<T>,
|
||||
ast: T,
|
||||
isLastComment: boolean
|
||||
) => boolean)
|
||||
| undefined;
|
||||
remaining?:
|
||||
| ((
|
||||
commentNode: any,
|
||||
text: string,
|
||||
options: ParserOptions<T>,
|
||||
ast: T,
|
||||
isLastComment: boolean
|
||||
) => boolean)
|
||||
| undefined;
|
||||
}
|
||||
| undefined;
|
||||
}
|
||||
|
||||
export interface CursorOptions extends Options {
|
||||
/**
|
||||
* Specify where the cursor is.
|
||||
*/
|
||||
cursorOffset: number;
|
||||
rangeStart?: never;
|
||||
rangeEnd?: never;
|
||||
}
|
||||
|
||||
export interface CursorResult {
|
||||
formatted: string;
|
||||
cursorOffset: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* `format` is used to format text using Prettier. [Options](https://prettier.io/docs/en/options.html) may be provided to override the defaults.
|
||||
*/
|
||||
export function format(source: string, options?: Options): Promise<string>;
|
||||
|
||||
/**
|
||||
* `check` checks to see if the file has been formatted with Prettier given those options and returns a `Boolean`.
|
||||
* This is similar to the `--list-different` parameter in the CLI and is useful for running Prettier in CI scenarios.
|
||||
*/
|
||||
export function check(source: string, options?: Options): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* `formatWithCursor` both formats the code, and translates a cursor position from unformatted code to formatted code.
|
||||
* This is useful for editor integrations, to prevent the cursor from moving when code is formatted.
|
||||
*
|
||||
* The `cursorOffset` option should be provided, to specify where the cursor is. This option cannot be used with `rangeStart` and `rangeEnd`.
|
||||
*/
|
||||
export function formatWithCursor(
|
||||
source: string,
|
||||
options: CursorOptions
|
||||
): Promise<CursorResult>;
|
||||
|
||||
export function formatAST(ast: any, options?: Options): Promise<string>;
|
||||
|
||||
export interface ResolveConfigOptions {
|
||||
/**
|
||||
* If set to `false`, all caching will be bypassed.
|
||||
*/
|
||||
useCache?: boolean | undefined;
|
||||
/**
|
||||
* Pass directly the path of the config file if you don't wish to search for it.
|
||||
*/
|
||||
config?: string | undefined;
|
||||
/**
|
||||
* If set to `true` and an `.editorconfig` file is in your project,
|
||||
* Prettier will parse it and convert its properties to the corresponding prettier configuration.
|
||||
* This configuration will be overridden by `.prettierrc`, etc. Currently,
|
||||
* the following EditorConfig properties are supported:
|
||||
* - indent_style
|
||||
* - indent_size/tab_width
|
||||
* - max_line_length
|
||||
*/
|
||||
editorconfig?: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* `resolveConfig` can be used to resolve configuration for a given source file,
|
||||
* passing its path as the first argument. The config search will start at the
|
||||
* file path and continue to search up the directory.
|
||||
* (You can use `process.cwd()` to start searching from the current directory).
|
||||
*
|
||||
* A promise is returned which will resolve to:
|
||||
*
|
||||
* - An options object, providing a [config file](https://prettier.io/docs/en/configuration.html) was found.
|
||||
* - `null`, if no file was found.
|
||||
*
|
||||
* The promise will be rejected if there was an error parsing the configuration file.
|
||||
*/
|
||||
export function resolveConfig(
|
||||
filePath: string,
|
||||
options?: ResolveConfigOptions
|
||||
): Promise<Options | null>;
|
||||
|
||||
/**
|
||||
* `resolveConfigFile` can be used to find the path of the Prettier configuration file,
|
||||
* that will be used when resolving the config (i.e. when calling `resolveConfig`).
|
||||
*
|
||||
* A promise is returned which will resolve to:
|
||||
*
|
||||
* - The path of the configuration file.
|
||||
* - `null`, if no file was found.
|
||||
*
|
||||
* The promise will be rejected if there was an error parsing the configuration file.
|
||||
*/
|
||||
export function resolveConfigFile(filePath?: string): Promise<string | null>;
|
||||
|
||||
/**
|
||||
* As you repeatedly call `resolveConfig`, the file system structure will be cached for performance. This function will clear the cache.
|
||||
* Generally this is only needed for editor integrations that know that the file system has changed since the last format took place.
|
||||
*/
|
||||
export function clearConfigCache(): Promise<void>;
|
||||
|
||||
export interface SupportLanguage {
|
||||
name: string;
|
||||
since?: string | undefined;
|
||||
parsers: BuiltInParserName[] | string[];
|
||||
group?: string | undefined;
|
||||
tmScope?: string | undefined;
|
||||
aceMode?: string | undefined;
|
||||
codemirrorMode?: string | undefined;
|
||||
codemirrorMimeType?: string | undefined;
|
||||
aliases?: string[] | undefined;
|
||||
extensions?: string[] | undefined;
|
||||
filenames?: string[] | undefined;
|
||||
linguistLanguageId?: number | undefined;
|
||||
vscodeLanguageIds?: string[] | undefined;
|
||||
interpreters?: string[] | undefined;
|
||||
}
|
||||
|
||||
export interface SupportOptionRange {
|
||||
start: number;
|
||||
end: number;
|
||||
step: number;
|
||||
}
|
||||
|
||||
export type SupportOptionType =
|
||||
| "int"
|
||||
| "string"
|
||||
| "boolean"
|
||||
| "choice"
|
||||
| "path";
|
||||
|
||||
export type CoreCategoryType =
|
||||
| "Config"
|
||||
| "Editor"
|
||||
| "Format"
|
||||
| "Other"
|
||||
| "Output"
|
||||
| "Global"
|
||||
| "Special";
|
||||
|
||||
export interface BaseSupportOption<Type extends SupportOptionType> {
|
||||
readonly name?: string | undefined;
|
||||
/**
|
||||
* Usually you can use {@link CoreCategoryType}
|
||||
*/
|
||||
category: string;
|
||||
/**
|
||||
* The type of the option.
|
||||
*
|
||||
* When passing a type other than the ones listed below, the option is
|
||||
* treated as taking any string as argument, and `--option <${type}>` will
|
||||
* be displayed in --help.
|
||||
*/
|
||||
type: Type;
|
||||
/**
|
||||
* Indicate that the option is deprecated.
|
||||
*
|
||||
* Use a string to add an extra message to --help for the option,
|
||||
* for example to suggest a replacement option.
|
||||
*/
|
||||
deprecated?: true | string | undefined;
|
||||
/**
|
||||
* Description to be displayed in --help. If omitted, the option won't be
|
||||
* shown at all in --help.
|
||||
*/
|
||||
description?: string | undefined;
|
||||
}
|
||||
|
||||
export interface IntSupportOption extends BaseSupportOption<"int"> {
|
||||
default?: number | undefined;
|
||||
array?: false | undefined;
|
||||
range?: SupportOptionRange | undefined;
|
||||
}
|
||||
|
||||
export interface IntArraySupportOption extends BaseSupportOption<"int"> {
|
||||
default?: Array<{ value: number[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export interface StringSupportOption extends BaseSupportOption<"string"> {
|
||||
default?: string | undefined;
|
||||
array?: false | undefined;
|
||||
}
|
||||
|
||||
export interface StringArraySupportOption extends BaseSupportOption<"string"> {
|
||||
default?: Array<{ value: string[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export interface BooleanSupportOption extends BaseSupportOption<"boolean"> {
|
||||
default?: boolean | undefined;
|
||||
array?: false | undefined;
|
||||
description: string;
|
||||
oppositeDescription?: string | undefined;
|
||||
}
|
||||
|
||||
export interface BooleanArraySupportOption
|
||||
extends BaseSupportOption<"boolean"> {
|
||||
default?: Array<{ value: boolean[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export interface ChoiceSupportOption<Value = any>
|
||||
extends BaseSupportOption<"choice"> {
|
||||
default?: Value | Array<{ value: Value }> | undefined;
|
||||
description: string;
|
||||
choices: Array<{
|
||||
since?: string | undefined;
|
||||
value: Value;
|
||||
description: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface PathSupportOption extends BaseSupportOption<"path"> {
|
||||
default?: string | undefined;
|
||||
array?: false | undefined;
|
||||
}
|
||||
|
||||
export interface PathArraySupportOption extends BaseSupportOption<"path"> {
|
||||
default?: Array<{ value: string[] }> | undefined;
|
||||
array: true;
|
||||
}
|
||||
|
||||
export type SupportOption =
|
||||
| IntSupportOption
|
||||
| IntArraySupportOption
|
||||
| StringSupportOption
|
||||
| StringArraySupportOption
|
||||
| BooleanSupportOption
|
||||
| BooleanArraySupportOption
|
||||
| ChoiceSupportOption
|
||||
| PathSupportOption
|
||||
| PathArraySupportOption;
|
||||
|
||||
export interface SupportOptions extends Record<string, SupportOption> {}
|
||||
|
||||
export interface SupportInfo {
|
||||
languages: SupportLanguage[];
|
||||
options: SupportOption[];
|
||||
}
|
||||
|
||||
export interface FileInfoOptions {
|
||||
ignorePath?: string | undefined;
|
||||
withNodeModules?: boolean | undefined;
|
||||
plugins?: string[] | undefined;
|
||||
resolveConfig?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface FileInfoResult {
|
||||
ignored: boolean;
|
||||
inferredParser: string | null;
|
||||
}
|
||||
|
||||
export function getFileInfo(
|
||||
filePath: string,
|
||||
options?: FileInfoOptions
|
||||
): Promise<FileInfoResult>;
|
||||
|
||||
/**
|
||||
* Returns an object representing the parsers, languages and file types Prettier supports for the current version.
|
||||
*/
|
||||
export function getSupportInfo(): Promise<SupportInfo>;
|
||||
|
||||
/**
|
||||
* `version` field in `package.json`
|
||||
*/
|
||||
export const version: string;
|
||||
|
||||
// https://github.com/prettier/prettier/blob/next/src/utils/public.js
|
||||
export namespace util {
|
||||
interface SkipOptions {
|
||||
backwards?: boolean | undefined;
|
||||
}
|
||||
|
||||
type Quote = "'" | '"';
|
||||
|
||||
function getMaxContinuousCount(text: string, searchString: string): number;
|
||||
|
||||
function getStringWidth(text: string): number;
|
||||
|
||||
function getAlignmentSize(
|
||||
text: string,
|
||||
tabWidth: number,
|
||||
startIndex?: number | undefined
|
||||
): number;
|
||||
|
||||
function getIndentSize(value: string, tabWidth: number): number;
|
||||
|
||||
function skipNewline(
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions | undefined
|
||||
): number | false;
|
||||
|
||||
function skipInlineComment(
|
||||
text: string,
|
||||
startIndex: number | false
|
||||
): number | false;
|
||||
|
||||
function skipTrailingComment(
|
||||
text: string,
|
||||
startIndex: number | false
|
||||
): number | false;
|
||||
|
||||
function skipTrailingComment(
|
||||
text: string,
|
||||
startIndex: number | false
|
||||
): number | false;
|
||||
|
||||
function hasNewline(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
options?: SkipOptions | undefined
|
||||
): boolean;
|
||||
|
||||
function hasNewlineInRange(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
endIndex: number
|
||||
): boolean;
|
||||
|
||||
function hasSpaces(
|
||||
text: string,
|
||||
startIndex: number,
|
||||
options?: SkipOptions | undefined
|
||||
): boolean;
|
||||
|
||||
function getNextNonSpaceNonCommentCharacter(
|
||||
text: string,
|
||||
startIndex: number
|
||||
): string;
|
||||
|
||||
function makeString(
|
||||
rawText: string,
|
||||
enclosingQuote: Quote,
|
||||
unescapeUnnecessaryEscapes?: boolean | undefined
|
||||
): string;
|
||||
|
||||
function skip(
|
||||
characters: string | RegExp
|
||||
): (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions
|
||||
) => number | false;
|
||||
|
||||
const skipWhitespace: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions
|
||||
) => number | false;
|
||||
|
||||
const skipSpaces: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions
|
||||
) => number | false;
|
||||
|
||||
const skipToLineEnd: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions
|
||||
) => number | false;
|
||||
|
||||
const skipEverythingButNewLine: (
|
||||
text: string,
|
||||
startIndex: number | false,
|
||||
options?: SkipOptions
|
||||
) => number | false;
|
||||
|
||||
function addLeadingComment(node: any, comment: any): void;
|
||||
|
||||
function addDanglingComment(node: any, comment: any, marker: any): void;
|
||||
|
||||
function addTrailingComment(node: any, comment: any): void;
|
||||
}
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
css: Parser;
|
||||
less: Parser;
|
||||
scss: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
graphql: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
glimmer: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
html: Parser;
|
||||
angular: Parser;
|
||||
vue: Parser;
|
||||
lwc: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import { Parser } from "../../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
acorn: Parser;
|
||||
espree: Parser;
|
||||
};
|
||||
};
|
||||
|
||||
export = parser;
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
import { Parser } from "../../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
__ng_action: Parser;
|
||||
__ng_binding: Parser;
|
||||
__ng_interpolation: Parser;
|
||||
__ng_directive: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
import { Parser } from "../../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
babel: Parser;
|
||||
"babel-flow": Parser;
|
||||
"babel-ts": Parser;
|
||||
json: Parser;
|
||||
json5: Parser;
|
||||
"json-stringify": Parser;
|
||||
__js_expression: Parser;
|
||||
__vue_expression: Parser;
|
||||
__vue_event_binding: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import { Parser } from "../../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
flow: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import { Parser } from "../../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
meriyah: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { Parser } from "../../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
typescript: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
remark: Parser;
|
||||
markdown: Parser;
|
||||
mdx: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
declare const parser: {
|
||||
parsers: {
|
||||
yaml: Parser;
|
||||
};
|
||||
};
|
||||
export = parser;
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
import { CursorOptions, CursorResult, Options, SupportInfo } from "./index.js";
|
||||
|
||||
/**
|
||||
* formatWithCursor both formats the code, and translates a cursor position from unformatted code to formatted code.
|
||||
* This is useful for editor integrations, to prevent the cursor from moving when code is formatted
|
||||
*
|
||||
* The cursorOffset option should be provided, to specify where the cursor is. This option cannot be used with rangeStart and rangeEnd.
|
||||
*
|
||||
* ```js
|
||||
* await prettier.formatWithCursor(" 1", { cursorOffset: 2, parser: "babel" });
|
||||
* ```
|
||||
* `-> { formatted: "1;\n", cursorOffset: 1 }`
|
||||
*/
|
||||
export function formatWithCursor(
|
||||
source: string,
|
||||
options: CursorOptions
|
||||
): Promise<CursorResult>;
|
||||
|
||||
/**
|
||||
* `format` is used to format text using Prettier. [Options](https://prettier.io/docs/en/options.html) may be provided to override the defaults.
|
||||
*/
|
||||
export function format(source: string, options?: Options): Promise<string>;
|
||||
|
||||
/**
|
||||
* `check` checks to see if the file has been formatted with Prettier given those options and returns a `Boolean`.
|
||||
* This is similar to the `--list-different` parameter in the CLI and is useful for running Prettier in CI scenarios.
|
||||
*/
|
||||
export function check(source: string, options?: Options): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Returns an object representing the parsers, languages and file types Prettier supports for the current version.
|
||||
*/
|
||||
export function getSupportInfo(): Promise<SupportInfo>;
|
||||
@@ -0,0 +1,5 @@
|
||||
import * as doc from "../../../../src/document";
|
||||
|
||||
doc.builders.dedent;
|
||||
doc.printer.printDocToString;
|
||||
doc.debug.printDocToDebug;
|
||||
@@ -0,0 +1,60 @@
|
||||
import * as prettier from "../../../../src/index";
|
||||
|
||||
prettier.format("foo ( );", { semi: false });
|
||||
prettier.check("foo ( );", { semi: false });
|
||||
prettier.formatWithCursor(" 1", { cursorOffset: 2 });
|
||||
prettier.resolveConfig("path/to/somewhere").then((options) => {
|
||||
if (options !== null) {
|
||||
prettier.format("hello world", options);
|
||||
}
|
||||
});
|
||||
prettier.getFileInfo("./tsconfig.json").then((result) => {
|
||||
if (result.inferredParser !== "json") {
|
||||
throw new Error("Bad parser");
|
||||
}
|
||||
});
|
||||
// @ts-expect-error
|
||||
prettier.resolveConfig();
|
||||
prettier.resolveConfigFile().then((filePath) => {
|
||||
if (filePath !== null) {
|
||||
prettier.resolveConfig(filePath);
|
||||
}
|
||||
});
|
||||
prettier.resolveConfigFile("/path").then((filePath) => {
|
||||
if (filePath !== null) {
|
||||
prettier.resolveConfig(filePath);
|
||||
}
|
||||
});
|
||||
prettier.clearConfigCache();
|
||||
prettier.getSupportInfo();
|
||||
|
||||
prettier.doc.builders.trim;
|
||||
prettier.doc.builders.trim.type;
|
||||
prettier.doc.builders.cursor;
|
||||
prettier.doc.builders.cursor.type;
|
||||
prettier.doc.builders.cursor.placeholder;
|
||||
|
||||
prettier.format("pluginSearchDir is empty", {
|
||||
pluginSearchDirs: [],
|
||||
});
|
||||
|
||||
prettier.format("pluginSearchDir is not empty", {
|
||||
pluginSearchDirs: ["/a", "/b"],
|
||||
});
|
||||
|
||||
prettier.format("pluginSearchDir is not empty and mixed with weird stuff", {
|
||||
pluginSearchDirs: ["c", "d", ""],
|
||||
});
|
||||
|
||||
prettier.format("pluginSearchDir is false", {
|
||||
pluginSearchDirs: false,
|
||||
});
|
||||
|
||||
prettier.format("pluginSearchDir can not be true", {
|
||||
// @ts-expect-error
|
||||
pluginSearchDirs: true,
|
||||
});
|
||||
|
||||
prettier.format("singleAttributePerLine is available", {
|
||||
singleAttributePerLine: true,
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import * as prettier from "../../../../src/index";
|
||||
|
||||
import acornEspreeParser from "../../../../src/language-js/parse/acorn-and-espree";
|
||||
import angularParser from "../../../../src/language-js/parse/angular";
|
||||
import babelParser from "../../../../src/language-js/parse/babel";
|
||||
import flowParser from "../../../../src/language-js/parse/flow";
|
||||
import glimmerParser from "../../../../src/language-handlebars/parser-glimmer";
|
||||
import graphqlParser from "../../../../src/language-graphql/parser-graphql";
|
||||
import htmlParser from "../../../../src/language-html/parser-html";
|
||||
import markdownParser from "../../../../src/language-markdown/parser-markdown";
|
||||
import meriyahParser from "../../../../src/language-js/parse/meriyah";
|
||||
import postcssParser from "../../../../src/language-css/parser-postcss";
|
||||
import typescriptParser from "../../../../src/language-js/parse/typescript";
|
||||
import yamlParser from "../../../../src/language-yaml/parser-yaml";
|
||||
|
||||
acornEspreeParser.parsers.acorn.parse;
|
||||
acornEspreeParser.parsers.espree.parse;
|
||||
angularParser.parsers.__ng_action.parse;
|
||||
babelParser.parsers.babel.parse;
|
||||
flowParser.parsers.flow.parse;
|
||||
glimmerParser.parsers.glimmer.parse;
|
||||
graphqlParser.parsers.graphql.parse;
|
||||
htmlParser.parsers.html.parse;
|
||||
htmlParser.parsers.vue.parse;
|
||||
htmlParser.parsers.lwc.parse;
|
||||
htmlParser.parsers.angular.parse;
|
||||
markdownParser.parsers.markdown.parse;
|
||||
markdownParser.parsers.mdx.parse;
|
||||
meriyahParser.parsers.meriyah.parse;
|
||||
postcssParser.parsers.css.parse;
|
||||
postcssParser.parsers.less.parse;
|
||||
postcssParser.parsers.scss.parse;
|
||||
typescriptParser.parsers.typescript.parse;
|
||||
yamlParser.parsers.yaml.parse;
|
||||
|
||||
prettier.format("hello world", {
|
||||
plugins: [
|
||||
acornEspreeParser,
|
||||
angularParser,
|
||||
babelParser,
|
||||
flowParser,
|
||||
glimmerParser,
|
||||
htmlParser,
|
||||
markdownParser,
|
||||
meriyahParser,
|
||||
postcssParser,
|
||||
typescriptParser,
|
||||
yamlParser,
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,143 @@
|
||||
import * as prettier from "../../../../src/index";
|
||||
import { expectType } from "ts-expect";
|
||||
|
||||
interface PluginAST {
|
||||
kind: "line";
|
||||
value: string;
|
||||
}
|
||||
|
||||
const plugin: prettier.Plugin<PluginAST> = {
|
||||
languages: [
|
||||
{
|
||||
name: "Shell",
|
||||
parsers: ["sh"],
|
||||
interpreters: ["bash", "zsh"],
|
||||
},
|
||||
],
|
||||
parsers: {
|
||||
lines: {
|
||||
parse(text, options) {
|
||||
return { kind: "line", value: "This is a line" };
|
||||
},
|
||||
astFormat: "lines",
|
||||
locStart: (node) => {
|
||||
expectType<PluginAST>(node);
|
||||
return 0;
|
||||
},
|
||||
locEnd: (node) => {
|
||||
expectType<PluginAST>(node);
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
},
|
||||
printers: {
|
||||
lines: {
|
||||
print(path, options, print) {
|
||||
expectType<prettier.AstPath<PluginAST>>(path);
|
||||
expectType<(path: prettier.AstPath<PluginAST>) => prettier.Doc>(print);
|
||||
|
||||
const node = path.getValue();
|
||||
expectType<PluginAST>(node);
|
||||
|
||||
return node.value;
|
||||
},
|
||||
printComment(commentPath, options) {
|
||||
const comment = commentPath.getValue();
|
||||
return comment.value;
|
||||
},
|
||||
},
|
||||
},
|
||||
options: {
|
||||
testBoolOption: {
|
||||
type: "boolean",
|
||||
category: "Test",
|
||||
default: true,
|
||||
description: "Move open brace for code blocks onto new line.",
|
||||
oppositeDescription:
|
||||
"Don't move open brace for code blocks onto new line.",
|
||||
},
|
||||
testBoolArrOption: {
|
||||
type: "boolean",
|
||||
array: true,
|
||||
category: "Test",
|
||||
default: [{ value: [true, false, true] }],
|
||||
deprecated: true,
|
||||
description: "Move open brace for code blocks onto new line.",
|
||||
},
|
||||
testIntOption: {
|
||||
type: "int",
|
||||
category: "Global",
|
||||
default: 15,
|
||||
range: {
|
||||
start: 5,
|
||||
end: 100,
|
||||
step: 5,
|
||||
},
|
||||
deprecated: "Deprecated can be a string describing deprecation status.",
|
||||
description: "This is a number.",
|
||||
},
|
||||
testIntArrOption: {
|
||||
type: "int",
|
||||
category: "Test",
|
||||
default: [{ value: [3, 8, 12] }],
|
||||
array: true,
|
||||
description: "This is a number.",
|
||||
},
|
||||
testStringOption: {
|
||||
type: "string",
|
||||
category: "Test",
|
||||
default: "default",
|
||||
description: "This is a string.",
|
||||
},
|
||||
testStringArrOption: {
|
||||
type: "string",
|
||||
category: "Test",
|
||||
default: [{ value: ["one", "two", "three"] }],
|
||||
array: true,
|
||||
description: "This is a string.",
|
||||
},
|
||||
testChoiceOption: {
|
||||
type: "choice",
|
||||
default: "one",
|
||||
choices: [
|
||||
{ value: "one", description: "The number one" },
|
||||
{ value: "two", description: "The number two" },
|
||||
{ value: "three", description: "The number three" },
|
||||
],
|
||||
category: "Test",
|
||||
description: "Choose one of three.",
|
||||
},
|
||||
testChoiceComplexOption: {
|
||||
type: "choice",
|
||||
default: [{ since: "1.0.7", value: "banana" }, { value: "apple" }],
|
||||
choices: [
|
||||
{ value: "apple", description: "A fruit." },
|
||||
{ value: "orange", since: "1.0.6", description: "A different fruit." },
|
||||
{
|
||||
value: "banana",
|
||||
since: "1.0.5",
|
||||
description: "Added in 1.0.5, made default in 1.0.7.",
|
||||
},
|
||||
],
|
||||
category: "Test",
|
||||
description: "Choose one of three.",
|
||||
},
|
||||
testPathOption: {
|
||||
type: "path",
|
||||
category: "Test",
|
||||
default: "./path.js",
|
||||
},
|
||||
testPathArrOption: {
|
||||
type: "path",
|
||||
category: "Test",
|
||||
array: true,
|
||||
default: [{ value: ["./pathA.js", "./pathB.js"] }],
|
||||
},
|
||||
testNoDefaultOption: {
|
||||
type: "path",
|
||||
category: "Test",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
prettier.format("a line!", { parser: "lines", plugins: [plugin] });
|
||||
@@ -0,0 +1,159 @@
|
||||
import * as prettier from "../../../../src/index";
|
||||
import { expectType } from "ts-expect";
|
||||
|
||||
type NestedAst = Nested1 | Nested2 | Nested3;
|
||||
interface Nested1 {
|
||||
kind: "1";
|
||||
item2: Nested2;
|
||||
list2: Nested2[];
|
||||
list4?: Nested2[];
|
||||
}
|
||||
interface Nested2 {
|
||||
kind: "2";
|
||||
item3: Nested3;
|
||||
list3: Nested3[];
|
||||
}
|
||||
interface Nested3 {
|
||||
kind: "3";
|
||||
item1: Nested1;
|
||||
list1: Nested1[];
|
||||
}
|
||||
|
||||
function print(
|
||||
// Using Nested1 because we're assuming you've already determined the kind
|
||||
// of node based on some discriminated union. If you're determining the kind
|
||||
// of node within the same place that you need access to the path, it's
|
||||
// easiest to do something the to effect of:
|
||||
//
|
||||
// if (node.kind === "1") {
|
||||
// const nodePath = path as AstPath<typeof node>;
|
||||
// }
|
||||
//
|
||||
// In the example above, nodePath will then be a type-narrowed version of
|
||||
// the path variable that you can then use to correctly type the tree-walk
|
||||
// functions.
|
||||
path: prettier.AstPath<Nested1>,
|
||||
options: prettier.ParserOptions<NestedAst>,
|
||||
print: (path: prettier.AstPath<NestedAst>) => prettier.doc.builders.Doc
|
||||
): prettier.doc.builders.Doc {
|
||||
path.call((child) => {
|
||||
expectType<prettier.AstPath<Nested1>>(child);
|
||||
});
|
||||
|
||||
path.call((child) => {
|
||||
expectType<prettier.AstPath<Nested2>>(child);
|
||||
}, "item2");
|
||||
|
||||
path.call(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<Nested3>>(child);
|
||||
},
|
||||
"item2",
|
||||
"item3"
|
||||
);
|
||||
|
||||
path.call(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<Nested1>>(child);
|
||||
},
|
||||
"item2",
|
||||
"item3",
|
||||
"item1"
|
||||
);
|
||||
|
||||
path.call(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<Nested2>>(child);
|
||||
},
|
||||
"item2",
|
||||
"item3",
|
||||
"item1",
|
||||
"item2"
|
||||
);
|
||||
|
||||
path.call(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<any>>(child);
|
||||
},
|
||||
"item2",
|
||||
"item3",
|
||||
"item1",
|
||||
"item2",
|
||||
"item3"
|
||||
);
|
||||
|
||||
path.each((child) => {
|
||||
expectType<prettier.AstPath<Nested2>>(child);
|
||||
}, "list2");
|
||||
|
||||
path.each((child) => {
|
||||
expectType<prettier.AstPath<Nested2>>(child);
|
||||
}, "list4");
|
||||
|
||||
path.each(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<Nested3>>(child);
|
||||
},
|
||||
"list2",
|
||||
0,
|
||||
"list3"
|
||||
);
|
||||
|
||||
path.each(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<any>>(child);
|
||||
},
|
||||
"list2",
|
||||
0,
|
||||
"list3",
|
||||
0,
|
||||
"list1"
|
||||
);
|
||||
|
||||
path.map((child) => {
|
||||
expectType<prettier.AstPath<Nested2>>(child);
|
||||
}, "list2");
|
||||
|
||||
path.map((child) => {
|
||||
expectType<prettier.AstPath<Nested2>>(child);
|
||||
}, "list4");
|
||||
|
||||
path.map(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<Nested3>>(child);
|
||||
},
|
||||
"list2",
|
||||
0,
|
||||
"list3"
|
||||
);
|
||||
|
||||
path.map(
|
||||
(child) => {
|
||||
expectType<prettier.AstPath<any>>(child);
|
||||
},
|
||||
"list2",
|
||||
0,
|
||||
"list3",
|
||||
0,
|
||||
"list1"
|
||||
);
|
||||
|
||||
// @ts-expect-error
|
||||
path.call(print, "list2");
|
||||
// @ts-expect-error
|
||||
path.call(print, "list4");
|
||||
// @ts-expect-error
|
||||
path.call(print, "item2", "list3");
|
||||
|
||||
// @ts-expect-error
|
||||
path.each(print, "item2");
|
||||
// @ts-expect-error
|
||||
path.each(print, "item2", "item3");
|
||||
|
||||
// @ts-expect-error
|
||||
path.map(print, "item2");
|
||||
// @ts-expect-error
|
||||
path.map(print, "item2", "item3");
|
||||
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import * as prettierStandalone from "../../../../src/standalone";
|
||||
|
||||
prettierStandalone.formatWithCursor(" 1", { cursorOffset: 2, parser: "babel" });
|
||||
prettierStandalone.formatWithCursor(" 1", {
|
||||
cursorOffset: 2,
|
||||
parser: "babel",
|
||||
// @ts-expect-error
|
||||
rangeStart: 2,
|
||||
});
|
||||
prettierStandalone.formatWithCursor(" 1", {
|
||||
cursorOffset: 2,
|
||||
parser: "babel",
|
||||
// @ts-expect-error
|
||||
rangeEnd: 2,
|
||||
});
|
||||
prettierStandalone.format(" 1", { parser: "babel" });
|
||||
prettierStandalone.check(" console.log(b)");
|
||||
prettierStandalone.getSupportInfo();
|
||||
@@ -0,0 +1,29 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import url from "node:url";
|
||||
import { default as ts } from "typescript";
|
||||
|
||||
describe("Unit tests for dts files", () => {
|
||||
test("no errors", () => {
|
||||
const testCasesDirPath = url.fileURLToPath(
|
||||
new URL("cases", import.meta.url)
|
||||
);
|
||||
const testCaseFiles = fs
|
||||
.readdirSync(testCasesDirPath)
|
||||
.map((file) => path.join(testCasesDirPath, file));
|
||||
|
||||
/** @type {import("typescript").CompilerOptions} */
|
||||
const compilerOptions = {
|
||||
noEmit: true,
|
||||
strict: true,
|
||||
esModuleInterop: true,
|
||||
};
|
||||
|
||||
const program = ts.createProgram(testCaseFiles, compilerOptions);
|
||||
|
||||
/** @type {import("typescript").Diagnostic[]} */
|
||||
const diagnostics = ts.getPreEmitDiagnostics(program);
|
||||
|
||||
expect(diagnostics).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -6811,6 +6811,7 @@ __metadata:
|
||||
strip-ansi: 7.0.1
|
||||
tempy: 3.0.0
|
||||
to-fast-properties: 4.0.0
|
||||
ts-expect: 1.3.0
|
||||
typescript: 4.9.5
|
||||
unicode-regex: 3.0.0
|
||||
unified: 9.2.2
|
||||
@@ -7977,6 +7978,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-expect@npm:1.3.0":
|
||||
version: 1.3.0
|
||||
resolution: "ts-expect@npm:1.3.0"
|
||||
checksum: c007702906354ada640392c26373660a8a034506859b5c084de74376ca2c6fe092c5909235d1bad8ed67423e7ab023dae4dc3032dcdcce70852c0211c5238013
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tsconfig-paths@npm:^3.14.1":
|
||||
version: 3.14.1
|
||||
resolution: "tsconfig-paths@npm:3.14.1"
|
||||
|
||||
Reference in new issue
Block a user