Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import { toKebabCase } from "kasi";
import { bin, color, exit, parseArgv } from "specialist";
import { PRETTIER_VERSION, DEFAULT_PARSERS } from "./constants.js";
import { getPlugin, isBoolean, isNumber, isIntegerInRange, isString } from "./utils.js";
import { getPluginOrExit, isBoolean, isNumber, isIntegerInRange, isString } from "./utils.js";
import { normalizeOptions, normalizeFormatOptions, normalizePluginOptions } from "./utils.js";
import type { Bin, PluginsOptions } from "./types.js";
import type { Bin, PluginsOptions, PrettierPlugin } from "./types.js";

const makeBin = (): Bin => {
return (
Expand Down Expand Up @@ -208,7 +208,7 @@ const makePluggableBin = async (): Promise<Bin> => {

for (let i = 0, l = pluginsNames.length; i < l; i++) {
const pluginName = pluginsNames[i];
const plugin = await getPlugin(pluginName);
const plugin = await getPluginOrExit(pluginName);

for (const option in plugin.options) {
optionsNames.push(option);
Expand Down
4 changes: 2 additions & 2 deletions src/prettier_serial.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFile, writeFile } from "atomically";
import process from "node:process";
import prettier from "prettier/standalone";
import { getPlugins, getPluginsBuiltin, resolve } from "./utils.js";
import { getPluginsOrExit, getPluginsBuiltin, resolve } from "./utils.js";
import type { ContextOptions, LazyFormatOptions, PluginsOptions } from "./types.js";

async function check(
Expand Down Expand Up @@ -37,7 +37,7 @@ async function format(
): Promise<string> {
formatOptions = await resolve(formatOptions);
const pluginsBuiltin = await getPluginsBuiltin();
const plugins = await getPlugins(formatOptions.plugins || []);
const plugins = await getPluginsOrExit(formatOptions.plugins || []);
const pluginsOverride = contextOptions.configPrecedence !== "file-override";

const options = {
Expand Down
27 changes: 25 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ const getPlugin = memoize((name: string): Promise<PrettierPlugin> => {
return plugin;
});

async function getPluginOrExit(name: string): Promise<PrettierPlugin> {
try {
return await getPlugin(name);
} catch {
exit(`The plugin "${name}" could not be loaded`);
}
}

function getPluginPath(name: string): string {
const rootPath = path.join(process.cwd(), "index.js");
const pluginPath = getModulePath(name, rootPath);
Expand All @@ -146,9 +154,22 @@ function getPluginVersion(name: string): string | null {
}
}

function getPlugins(names: string[]): PromiseMaybe<PrettierPlugin[]> {
async function getPlugins(names: string[]): Promise<PrettierPlugin[]> {
if (!names.length) return [];
return (
await Promise.all(
names.map((name) => getPlugin(name))
)
);
}

async function getPluginsOrExit(names: string[]): Promise<PrettierPlugin[]> {
if (!names.length) return [];
return Promise.all(names.map(getPlugin));
return (
await Promise.all(
names.map((name) => getPluginOrExit(name))
)
);
}

const getPluginsBuiltin = once(async (): Promise<PrettierPlugin[]> => {
Expand Down Expand Up @@ -720,10 +741,12 @@ export {
getModule,
getModulePath,
getPlugin,
getPluginOrExit,
getPluginPath,
getPluginVersion,
getPlugins,
getPluginsBuiltin,
getPluginsOrExit,
getPluginsPaths,
getPluginsVersions,
getProjectPath,
Expand Down
4 changes: 4 additions & 0 deletions test/__fixtures__/plugin-options-string/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"plugins": ["./plugin.cjs"],
"fooString": "baz"
}
31 changes: 31 additions & 0 deletions test/__fixtures__/plugin-options-string/plugin.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use strict";

module.exports = {
languages: [
{
name: "foo",
parsers: ["foo-parser"],
extensions: [".foo"],
since: "1.0.0",
},
],
options: {
fooString: {
type: "string",
default: "bar",
description: "foo description",
},
},
parsers: {
"foo-parser": {
parse: (text) => ({ text }),
astFormat: "foo-ast",
},
},
printers: {
"foo-ast": {
print: (path, options) =>
options.fooString ? `foo:${options.fooString}` : path.getValue().text,
},
},
};
19 changes: 19 additions & 0 deletions test/__tests__/__snapshots__/plugin-options-string.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`show detailed external option with \`--help foo-string\` (stderr) 1`] = `""`;

exports[`show detailed external option with \`--help foo-string\` (stdout) 1`] = `
"--foo-string <string>

foo description

Default: bar"
`;

exports[`show detailed external option with \`--help foo-string\` (write) 1`] = `[]`;

exports[`show external options with \`--help\` 1`] = `
" --parser <flow,babel,babel-flow,babel-ts,typescript,acorn,espree,meriyah,css,less,scss,json,json5,json-stringify,graphql,markdown,mdx,vue,yaml,glimmer,html,angular,lwc,foo-parser>
--foo-string <value> foo description
Defaults to "bar""
`;
72 changes: 72 additions & 0 deletions test/__tests__/plugin-options-string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { runCli } from "../utils";

test("show external options with `--help`", async () => {
const originalStdout = await runCli("plugin-options-string", ["--help"])
.stdout;
const pluggedStdout = await runCli("plugin-options-string", [
"--help",
"--plugin=./plugin.cjs",
]).stdout;
const originalLines = originalStdout.split("\n");
const pluggedLines = pluggedStdout.split("\n");
const differentLines = pluggedLines.filter((line) =>
!originalLines.includes(line));
expect(differentLines.join("\n")).toMatchSnapshot();
});

// Note (43081j); we don't currently support `--help {optionName}`
describe.skip("show detailed external option with `--help foo-string`", () => {
runCli("plugin-options-string", [
"--plugin=./plugin.cjs",
"--help",
"foo-string",
]).test({
status: 0,
});
});

describe("external options from CLI should work", () => {
runCli(
"plugin-options-string",
[
"--plugin=./plugin.cjs",
"--stdin-filepath",
"example.foo",
"--foo-string",
"baz",
],
{ input: "hello-world" },
).test({
stdout: "foo:baz",
stderr: "",
status: 0,
write: [],
});
});

// TODO (43081j): this won't work until we fix #21
describe.skip("external options from config file should work", () => {
runCli(
"plugin-options-string",
["--config-path=./config.json", "--stdin-filepath", "example.foo"],
{ input: "hello-world" },
).test({
stdout: "foo:baz",
stderr: "",
status: 0,
write: [],
});
});

describe("Non exists plugin", () => {
runCli(
"plugin-options-string",
["--plugin=--foo--", "--stdin-filepath", "example.foo"],
{ input: "hello-world" },
).test({
stdout: "",
stderr: expect.stringMatching(/The plugin "--foo--" could not be loaded/u),
status: 1,
write: [],
});
});