Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@prettier/cli

Package Overview
Dependencies
Maintainers
14
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@prettier/cli - npm Package Compare versions

Comparing version 0.1.5 to 0.2.0

335

dist/bin.js
#!/usr/bin/env node
import { bin, color } from "specialist";
import { PRETTIER_VERSION } from "./constants.js";
import { normalizeOptions } from "./utils.js";
import { toKebabCase } from "kasi";
import { bin, color, parseArgv } from "specialist";
import { PRETTIER_VERSION, IS_BUN } from "./constants.js";
import { getPlugin, isNumber, normalizeOptions, normalizeFormatOptions, normalizePluginOptions } from "./utils.js";
import { run } from "./index.js";
//TODO: --find-cache
bin("prettier", "Prettier is an opinionated code formatter")
/* OPTIONS */
.autoExit(true)
.autoUpdateNotifier(false)
.colors(true)
.package("prettier", PRETTIER_VERSION)
/* USAGES */
.usage(`${color.cyan("prettier")} ${color.yellow("[file/dir/glob...]")} ${color.green("[options]")}`)
.usage(`${color.cyan("prettier")} ${color.yellow('"src/**/*.js"')} ${color.green("--check")} ${color.green("--parallel")}`)
.usage(`${color.cyan("prettier")} ${color.yellow('"src/**/*.js"')} ${color.green("-l")} ${color.green("--no-cache")}`)
.usage(`${color.cyan("prettier")} ${color.yellow('"src/**/*.js"')} ${color.green("--write")} ${color.green("--parallel")}`)
.usage(`${color.cyan("prettier")} ${color.yellow("./path/to/target/file.js")} ${color.green("--cache-location")} ${color.blue("./path/to/cache/file.json")}`)
/* OUTPUT OPTIONS */
.option("--check, -c", "Check if the given files are formatted, print a human-friendly summary (see also --list-different)", { section: "Output" })
.option("--list-different, -l", "Print the names of files that are different from Prettier's formatting (see also --check)", { section: "Output" })
.option("--write, -w", "Edit files in-place (Beware!)", { section: "Output" })
/* FORMAT OPTIONS */
.option("--arrow-parens <always|avoid>", 'Include parentheses around a sole arrow function parameter\nDefaults to "always"', { section: "Format", enum: ["always", "avoid"] })
.option("--bracket-same-line", 'Put ">" of opening tags on the last line instead of on a new line\nDefaults to "false"', { section: "Format" })
.option("--no-bracket-spacing", 'Do not print spaces between brackets\nDefaults to "true"', { section: "Format" })
.option("--embedded-language-formatting <auto|off>", 'Control how Prettier formats quoted code embedded in the file\nDefaults to "auto"', { section: "Format", enum: ["auto", "off"] })
.option("--end-of-line <lf|crlf|cr|auto>", 'Which end of line characters to apply\nDefaults to "lf"', {
section: "Format",
enum: ["lf", "crlf", "cr", "auto"],
})
.option("--html-whitespace-sensitivity <css|strict|ignore>", 'How to handle whitespaces in HTML\nDefaults to "css"', {
section: "Format",
enum: ["css", "strict", "ignore"],
})
.option("--jsx-single-quote", 'Use single quotes in JSX\nDefaults to "false"', { section: "Format" })
.option("--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>", "Which parser to use", { section: "Format", enum: ["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"] })
.option("--print-width <int>", 'The line length where Prettier will try wrap\nDefaults to "80"', {
section: "Format",
})
.option("--prose-wrap <always|never|preserve>", 'How to wrap prose\nDefaults to "preserve"', {
section: "Format",
enum: ["always", "never", "preserve"],
})
.option("--quote-props <as-needed|consistent|preserve>", 'Change when properties in objects are quoted\nDefaults to "as-needed"', { section: "Format", enum: ["as-needed", "consistent", "preserve"] })
.option("--no-semi", 'Do not print semicolons, except at the beginning of lines which may need them\nDefaults to "true"', { section: "Format" })
.option("--single-attribute-per-line", 'Enforce single attribute per line in HTML, Vue and JSX\nDefaults to "false"', { section: "Format" })
.option("--single-quote", 'Use single quotes instead of double quotes\nDefaults to "false"', { section: "Format" })
.option("--tab-width <int>", 'Number of spaces per indentation level\nDefaults to "2"', { section: "Format" })
.option("--trailing-comma <all|es5|none>", 'Print trailing commas wherever possible when multi-line\nDefaults to "all"', { section: "Format", enum: ["all", "es5", "none"] })
.option("--use-tabs", 'Indent with tabs instead of spaces\nDefaults to "false"', { section: "Format" })
.option("--vue-indent-script-and-style", 'Indent script and style tags in Vue files\nDefaults to "false"', {
section: "Format",
})
/* CONFIG OPTIONS */
// .option(
// "--config <path>",
// "Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js)",
// { section: "Config" },
// )
.option("--no-config", "Do not look for a configuration file", {
section: "Config",
default: true,
})
// .option(
// "--config-precedence <cli-override|file-override|prefer-file>",
// 'Define in which order config files and CLI options should be evaluated.\nDefaults to "cli-override"',
// { section: "Config" },
// )
.option("--no-editorconfig", "Don't take .editorconfig into account when parsing configuration", {
section: "Config",
default: true,
})
// .option(
// "--find-config-path <path>",
// "Find and print the path to a configuration file for the given input file",
// { section: "Config" },
// )
// .option(
// "--ignore-path <path...>",
// "Path to a file with patterns describing files to ignore\nMultiple values are accepted\nDefaults to [.gitignore, .prettierignore]",
// { section: "Config", eager: true },
// )
// .option(
// "--plugin <path...>",
// "Add a plugin\nMultiple plugins are accepted\nDefaults to []",
// { section: "Config", eager: true },
// )
// .option(
// "--with-node-modules",
// 'Process files inside the "node_modules" directory',
// { section: "Config" },
// )
/* EDITOR OPTIONS */
// .option(
// "--cursor-offset <int>",
// 'Print (to stderr) where a cursor at the given position would move to after formatting\nThis option cannot be used with --range-start and --range-end\nDefaults to "-1"',
// { section: "Editor" },
// )
// .option(
// "--range-end <int>",
// 'Format code ending at a given character offset (exclusive)\nThe range will extend forwards to the end of the selected statement\nThis option cannot be used with --cursor-offset\nDefaults to "Infinity"',
// { section: "Editor" },
// )
// .option(
// "--range-start <int>",
// 'Format code starting at a given character offset\nThe range will extend backwards to the start of the first line containing the selected statement\nThis option cannot be used with --cursor-offset\nDefaults to "0"',
// { section: "Editor" },
// )
/* OTHER OPTIONS */
.option("--no-cache", "Do not use the built-in caching mechanism", {
default: true,
})
.option("--cache-location <path>", "Path to the cache file")
.option("--no-color", "Do not colorize output messages")
.option("--no-error-on-unmatched-pattern", "Prevent errors when pattern is unmatched", { default: true })
// .option(
// "--file-info <path>",
// "Extract the following info (as JSON) for a given file path. Reported fields:\n* ignored (boolean) - true if file path is filtered by --ignore-path\n* inferredParser (string | null) - name of parser inferred from file path",
// )
.option("--ignore-unknown, -u", "Ignore unknown files")
.option("--insert-pragma", 'Insert @format pragma into file\'s first docblock comment\nDefaults to "false"')
.option("--log-level <silent|error|warn|log|debug>", 'What level of logs to report\nDefaults to "log"', {
enum: ["silent", "error", "warn", "log", "debug"],
})
.option("--no-parallel", 'Process files in parallel\nDefaults to "true"', {
default: true,
})
.option("--parallel-workers <int>", 'Number of parallel workers to use\nDefaults to "0"')
.option("--require-pragma", 'Require either "@prettier" or "@format" to be present in the file\'s first docblock comment in order for it to be formatted\nDefaults to "false"')
// .option(
// "--stdin-filepath <path>",
// "Path to the file to pretend that stdin comes from",
// )
// .option("--support-info", "Print support information as JSON")
/* DEFAULT COMMAND */
.argument("[file/dir/glob...]", "Files, directories or globs to format")
.action((options, files) => {
return run(normalizeOptions(options, files));
})
/* RUN */
.run();
const makeBin = () => {
return (bin("prettier", "An opinionated code formatter")
/* OPTIONS */
.autoExit(true)
.autoUpdateNotifier(false)
.colors(true)
.package("prettier", PRETTIER_VERSION)
/* USAGES */
.usage(`${color.cyan("prettier")} ${color.yellow("[file/dir/glob...]")} ${color.green("[options]")}`)
.usage(`${color.cyan("prettier")} ${color.yellow('"src/**/*.js"')} ${color.green("--check")} ${color.green("--parallel")}`)
.usage(`${color.cyan("prettier")} ${color.yellow('"src/**/*.js"')} ${color.green("-l")} ${color.green("--no-cache")}`)
.usage(`${color.cyan("prettier")} ${color.yellow('"src/**/*.js"')} ${color.green("--write")} ${color.green("--parallel")}`)
.usage(`${color.cyan("prettier")} ${color.yellow("./path/to/target/file.js")} ${color.green("--cache-location")} ${color.blue("./path/to/cache/file.json")}`)
/* OUTPUT OPTIONS */
.option("--check, -c", "Check if the given files are formatted, print a human-friendly summary (see also --list-different)", { section: "Output" })
.option("--list-different, -l", "Print the names of files that are different from Prettier's formatting (see also --check)", { section: "Output" })
.option("--write, -w", "Edit files in-place (Beware!)", { section: "Output" })
/* FORMAT OPTIONS */
.option("--experimental-ternaries", 'Use curious ternaries, with the question mark after the condition\nDefaults to "false"', { section: "Format" })
.option("--arrow-parens <always|avoid>", 'Include parentheses around a sole arrow function parameter\nDefaults to "always"', {
section: "Format",
enum: ["always", "avoid"],
})
.option("--bracket-same-line", 'Put ">" of opening tags on the last line instead of on a new line\nDefaults to "false"', { section: "Format" })
.option("--no-bracket-spacing", 'Do not print spaces between brackets\nDefaults to "true"', { section: "Format" })
.option("--embedded-language-formatting <auto|off>", 'Control how Prettier formats quoted code embedded in the file\nDefaults to "auto"', {
section: "Format",
enum: ["auto", "off"],
})
.option("--end-of-line <lf|crlf|cr|auto>", 'Which end of line characters to apply\nDefaults to "lf"', {
section: "Format",
enum: ["lf", "crlf", "cr", "auto"],
})
.option("--html-whitespace-sensitivity <css|strict|ignore>", 'How to handle whitespaces in HTML\nDefaults to "css"', {
section: "Format",
enum: ["css", "strict", "ignore"],
})
.option("--jsx-single-quote", 'Use single quotes in JSX\nDefaults to "false"', { section: "Format" })
.option("--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>", "Which parser to use", { section: "Format", enum: ["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"] })
.option("--print-width <int>", 'The line length where Prettier will try wrap\nDefaults to "80"', {
section: "Format",
})
.option("--prose-wrap <always|never|preserve>", 'How to wrap prose\nDefaults to "preserve"', {
section: "Format",
enum: ["always", "never", "preserve"],
})
.option("--quote-props <as-needed|consistent|preserve>", 'Change when properties in objects are quoted\nDefaults to "as-needed"', {
section: "Format",
enum: ["as-needed", "consistent", "preserve"],
})
.option("--no-semi", 'Do not print semicolons, except at the beginning of lines which may need them\nDefaults to "true"', { section: "Format" })
.option("--single-attribute-per-line", 'Enforce single attribute per line in HTML, Vue and JSX\nDefaults to "false"', { section: "Format" })
.option("--single-quote", 'Use single quotes instead of double quotes\nDefaults to "false"', { section: "Format" })
.option("--tab-width <int>", 'Number of spaces per indentation level\nDefaults to "2"', { section: "Format" })
.option("--trailing-comma <all|es5|none>", 'Print trailing commas wherever possible when multi-line\nDefaults to "all"', {
section: "Format",
enum: ["all", "es5", "none"],
})
.option("--use-tabs", 'Indent with tabs instead of spaces\nDefaults to "false"', { section: "Format" })
.option("--vue-indent-script-and-style", 'Indent script and style tags in Vue files\nDefaults to "false"', {
section: "Format",
})
/* CONFIG OPTIONS */
// .option(
// "--config <path>",
// "Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js)",
// { section: "Config" },
// )
.option("--no-config", "Do not look for a configuration file", {
section: "Config",
default: true,
})
.option("--no-editorconfig", "Don't take .editorconfig into account when parsing configuration", {
section: "Config",
default: true,
})
// .option(
// "--ignore-path <path...>",
// "Path to a file with patterns describing files to ignore\nMultiple values are accepted\nDefaults to [.gitignore, .prettierignore]",
// { section: "Config", eager: true },
// )
.option("--plugin <package...>", "Add a plugin\nMultiple plugins are accepted\nDefaults to []", { section: "Config" })
// .option(
// "--with-node-modules",
// 'Process files inside the "node_modules" directory',
// { section: "Config" },
// )
/* EDITOR OPTIONS */
.option("--cursor-offset <int>", 'Print (to stderr) where a cursor at the given position would move to after formatting\nDefaults to "-1"', {
section: "Editor",
})
.option("--range-end <int>", 'Format code ending at a given character offset (exclusive)\nThe range will extend forwards to the end of the selected statement\nDefaults to "Infinity"', { section: "Editor" })
.option("--range-start <int>", 'Format code starting at a given character offset\nThe range will extend backwards to the start of the first line containing the selected statement\nDefaults to "0"', { section: "Editor" })
/* OTHER OPTIONS */
.option("--no-cache", "Do not use the built-in caching mechanism", {
default: true,
})
.option("--cache-location <path>", "Path to the cache file")
.option("--no-color", "Do not colorize output messages")
.option("--no-error-on-unmatched-pattern", "Prevent errors when pattern is unmatched", { default: true })
// .option(
// "--file-info <path>",
// "Extract the following info (as JSON) for a given file path. Reported fields:\n* ignored (boolean) - true if file path is filtered by --ignore-path\n* inferredParser (string | null) - name of parser inferred from file path",
// )
.option("--ignore-unknown, -u", "Ignore unknown files")
.option("--insert-pragma", 'Insert @format pragma into file\'s first docblock comment\nDefaults to "false"')
.option("--log-level <silent|error|warn|log|debug>", 'What level of logs to report\nDefaults to "log"', {
enum: ["silent", "error", "warn", "log", "debug"],
})
.option("--no-parallel", 'Process files in parallel\nDefaults to "true"', {
default: !IS_BUN, //TOOD: always set this to "true", once "worker_threads" work in Bun
})
.option("--parallel-workers <int>", 'Number of parallel workers to use\nDefaults to "0"')
.option("--require-pragma", 'Require either "@prettier" or "@format" to be present in the file\'s first docblock comment in order for it to be formatted\nDefaults to "false"')
// .option(
// "--stdin-filepath <path>",
// "Path to the file to pretend that stdin comes from",
// )
// .option("--support-info", "Print support information as JSON")
/* DEFAULT COMMAND */
.argument("[file/dir/glob...]", "Files, directories or globs to format")
.action((options, files) => {
const baseOptions = normalizeOptions(options, files);
const pluginsOptions = {};
return run(baseOptions, pluginsOptions);
}));
};
const makePluggableBin = async () => {
let bin = makeBin();
const argv = process.argv.slice(2);
const args = parseArgv(argv);
const formatOptions = normalizeFormatOptions(args);
const pluginsStaticOptions = {};
const pluginsNames = formatOptions.plugins || [];
const optionsNames = [];
for (let i = 0, l = pluginsNames.length; i < l; i++) {
const pluginName = pluginsNames[i];
const plugin = await getPlugin(pluginName);
for (const option in plugin.options) {
optionsNames.push(option);
Object.assign(pluginsStaticOptions, plugin.defaultOptions);
const schema = plugin.options[option];
const type = schema.type;
const section = schema.category;
const deprecated = !!schema.deprecated;
const descriptionInfo = schema.description || "";
const initial = schema.default;
if (type === "int") {
//TODO: Support schema.range
//TODO: Ensure the value is cast to a valid integer
const descriptionDefault = isNumber(initial) ? `Defaults to "${initial}"` : "";
const description = `${descriptionInfo}\n${descriptionDefault}`.trim();
const variadic = !!schema.array;
const args = variadic ? "<int...>" : "<int>";
bin = bin.option(`--${toKebabCase(option)} ${args}`, description, { deprecated, section, default: initial });
}
else if (type === "boolean") {
//TODO: Support schema.array
const descriptionDefault = initial ? 'Defaults to "true"' : 'Defaults to "false"';
const description = `${descriptionInfo}\n${descriptionDefault}`.trim();
bin = bin.option(`--${toKebabCase(option)}`, description, { deprecated, section, default: initial });
}
else if (type === "string" || type === "path") {
const descriptionDefault = initial ? `Defaults to "${initial}"` : "";
const description = `${descriptionInfo}\n${descriptionDefault}`.trim();
const variadic = !!schema.array;
const args = variadic ? "<value...>" : "<value>";
bin = bin.option(`--${toKebabCase(option)} ${args}`, description, { deprecated, section, default: initial });
}
else if (type === "choice") {
const descriptionDefault = initial ? `Defaults to "${initial}"` : "";
const description = `${descriptionInfo}\n${descriptionDefault}`.trim();
const values = schema.choices.map((choice) => choice.value);
const args = values.length ? `<${values.join("|")}>` : "<value>";
bin = bin.option(`--${toKebabCase(option)} ${args}`, description, { deprecated, section, default: initial });
}
}
}
bin = bin.action((options, files) => {
const baseOptions = normalizeOptions(options, files);
const pluginsDynamicOptions = normalizePluginOptions(options, optionsNames);
const pluginsOptions = { ...pluginsStaticOptions, ...pluginsDynamicOptions };
return run(baseOptions, pluginsOptions);
});
return bin;
};
const runBin = async () => {
const bin = await makePluggableBin();
bin.run();
};
runBin();

@@ -19,2 +19,3 @@ /// <reference types="node" />

private version;
private rootPath;
private storePath;

@@ -29,4 +30,4 @@ private store;

get(filePath: string): FileData;
set(filePath: string, filePathHash: string, fileFormatted: boolean, fileContentExpected: string): void;
set(filePath: string, fileHashPath: string, fileFormatted: boolean, fileContentExpected: string): void;
}
export default Cache;
import fs from "node:fs";
import path from "node:path";
import { getCachePath, isArray, isBoolean, isObject, isString, sha1hex, sha1base64 } from "./utils.js";
import { fastRelativePath, getCachePath, isArray, isBoolean, isObject, isString, sha1hex, sha1base64 } from "./utils.js";
//TODO: Maybe remember thrown errors also, if they are under a certain size
//TODO: Use some kind of relative path as the file key, if in CI enviornments parts of the path can be kinda random, or if the cache file is committed
class Cache {

@@ -10,2 +9,3 @@ constructor(version, rootPath, options, logger) {

this.logger = logger;
this.rootPath = rootPath;
this.storePath = options.cacheLocation || path.join(getCachePath(rootPath), `${sha1hex(rootPath)}.json`);

@@ -50,6 +50,7 @@ this.store = this.read();

get(filePath) {
const filePathHash = sha1base64(filePath);
const save = this.set.bind(this, filePath, filePathHash);
const fileRelativePath = fastRelativePath(this.rootPath, filePath);
const fileHashPath = sha1base64(fileRelativePath);
const save = this.set.bind(this, filePath, fileHashPath);
try {
const file = this.store[this.version]?.files?.[filePathHash];
const file = this.store[this.version]?.files?.[fileHashPath];
if (!file || !isArray(file) || file.length !== 2)

@@ -71,3 +72,3 @@ return { save };

}
set(filePath, filePathHash, fileFormatted, fileContentExpected) {
set(filePath, fileHashPath, fileFormatted, fileContentExpected) {
var _a, _b;

@@ -80,3 +81,3 @@ try {

version.modified = Date.now();
files[filePathHash] = [hash, fileFormatted];
files[fileHashPath] = [hash, fileFormatted];
this.dirty = true;

@@ -83,0 +84,0 @@ }

import * as EditorConfig from "tiny-editorconfig";
import type { Config, ConfigWithOverrides } from "tiny-editorconfig";
import type { FormatOptions } from "./types.js";
declare const getEditorConfig: ((arg: string) => Promise<EditorConfig.ConfigWithOverrides | undefined>) & {
cache: Map<string, Promise<EditorConfig.ConfigWithOverrides | undefined>>;
import type { FormatOptions, PromiseMaybe } from "./types.js";
declare const getEditorConfig: ((folderPath: string, filesNames: string[]) => PromiseMaybe<EditorConfig.ConfigWithOverrides | undefined>) & {
cache: Map<string, PromiseMaybe<EditorConfig.ConfigWithOverrides | undefined>>;
};
declare const getEditorConfigsMap: (foldersPaths: string[]) => Promise<Partial<Record<string, ConfigWithOverrides>>>;
declare const getEditorConfigsUp: ((arg: string) => Promise<EditorConfig.ConfigWithOverrides[]>) & {
declare const getEditorConfigsMap: (foldersPaths: string[], filesNames: string[]) => Promise<Partial<Record<string, ConfigWithOverrides>>>;
declare const getEditorConfigsUp: ((folderPath: string, filesNames: string[]) => Promise<EditorConfig.ConfigWithOverrides[]>) & {
cache: Map<string, Promise<EditorConfig.ConfigWithOverrides[]>>;
};
declare const getEditorConfigResolved: (filePath: string) => Promise<Config>;
declare const getEditorConfigResolved: (filePath: string, filesNames: string[]) => Promise<Config>;
declare const getEditorConfigFormatOptions: (config: Config) => FormatOptions;
export { getEditorConfig, getEditorConfigsMap, getEditorConfigsUp, getEditorConfigResolved, getEditorConfigFormatOptions, };
export { getEditorConfig, getEditorConfigsMap, getEditorConfigsUp, getEditorConfigResolved, getEditorConfigFormatOptions };

@@ -5,25 +5,21 @@ import fs from "node:fs/promises";

import Known from "./known.js";
import { fastJoinedPath, findLastIndex, memoize, zipObject } from "./utils.js";
const getEditorConfig = memoize(async (folderPath) => {
const filePath = fastJoinedPath(folderPath, ".editorconfig");
if (!Known.hasFile(filePath))
return;
try {
const fileContent = await fs.readFile(filePath, "utf8");
const config = EditorConfig.parse(fileContent);
return config;
import { fastJoinedPath, findLastIndex, isUndefined, memoize, noop, zipObjectUnless } from "./utils.js";
const getEditorConfig = memoize((folderPath, filesNames) => {
for (let i = 0, l = filesNames.length; i < l; i++) {
const fileName = filesNames[i];
const filePath = fastJoinedPath(folderPath, fileName);
if (!Known.hasFilePath(filePath))
continue;
return fs.readFile(filePath, "utf8").then(EditorConfig.parse).catch(noop);
}
catch {
return;
}
});
const getEditorConfigsMap = async (foldersPaths) => {
const configs = await Promise.all(foldersPaths.map(getEditorConfig));
const map = zipObject(foldersPaths, configs);
const getEditorConfigsMap = async (foldersPaths, filesNames) => {
const configs = await Promise.all(foldersPaths.map((folderPath) => getEditorConfig(folderPath, filesNames)));
const map = zipObjectUnless(foldersPaths, configs, isUndefined);
return map;
};
const getEditorConfigsUp = memoize(async (folderPath) => {
const config = await getEditorConfig(folderPath);
const getEditorConfigsUp = memoize(async (folderPath, filesNames) => {
const config = await getEditorConfig(folderPath, filesNames);
const folderPathUp = path.dirname(folderPath);
const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp) : [];
const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp, filesNames) : [];
const configs = config ? [...configsUp, config] : configsUp;

@@ -33,5 +29,5 @@ const lastRootIndex = findLastIndex(configs, (config) => config.root);

});
const getEditorConfigResolved = async (filePath) => {
const getEditorConfigResolved = async (filePath, filesNames) => {
const folderPath = path.dirname(filePath);
const configs = await getEditorConfigsUp(folderPath);
const configs = await getEditorConfigsUp(folderPath, filesNames);
const config = EditorConfig.resolve(configs, filePath);

@@ -53,2 +49,2 @@ return config;

};
export { getEditorConfig, getEditorConfigsMap, getEditorConfigsUp, getEditorConfigResolved, getEditorConfigFormatOptions, };
export { getEditorConfig, getEditorConfigsMap, getEditorConfigsUp, getEditorConfigResolved, getEditorConfigFormatOptions };
import type { Ignore } from "./types.js";
declare const getIgnoresContent: ((arg: string) => Promise<[(string | undefined)?, (string | undefined)?] | undefined>) & {
cache: Map<string, Promise<[(string | undefined)?, (string | undefined)?] | undefined>>;
declare const getIgnoresContent: ((folderPath: string, filesNames: string[]) => Promise<string[] | undefined>) & {
cache: Map<string, Promise<string[] | undefined>>;
};
declare const getIgnoresContentMap: (foldersPaths: string[]) => Promise<Partial<Record<string, [string?, string?]>>>;
declare const getIgnoreBy: (folderPath: string, fileContent: string) => Ignore;
declare const getIgnores: ((arg: string) => Promise<Ignore | undefined>) & {
declare const getIgnoresContentMap: (foldersPaths: string[], filesNames: string[]) => Promise<Partial<Record<string, string[]>>>;
declare const getIgnoreBy: (folderPath: string, filesContents: string[]) => Ignore;
declare const getIgnores: ((folderPath: string, filesNames: string[]) => Promise<Ignore | undefined>) & {
cache: Map<string, Promise<Ignore | undefined>>;
};
declare const getIgnoresUp: ((arg: string) => Promise<Ignore | undefined>) & {
declare const getIgnoresUp: ((folderPath: string, filesNames: string[]) => Promise<Ignore | undefined>) & {
cache: Map<string, Promise<Ignore | undefined>>;
};
declare const getIgnoreResolved: (filePath: string) => Promise<boolean>;
declare const getIgnoreResolved: (filePath: string, filesNames: string[]) => Promise<boolean>;
export { getIgnoreBy, getIgnores, getIgnoresContent, getIgnoresContentMap, getIgnoresUp, getIgnoreResolved };

@@ -1,55 +0,42 @@

import ignore from "ignore";
import fastIgnore from "fast-ignore";
import fs from "node:fs/promises";
import path from "node:path";
import Known from "./known.js";
import { fastJoinedPath, fastRelativeChildPath, memoize, someOf, zipObject } from "./utils.js";
const getIgnoreContentBy = async (folderPath, fileName) => {
import { fastJoinedPath, fastRelativeChildPath, isString, isUndefined, memoize, noop, someOf, zipObjectUnless } from "./utils.js";
const getIgnoreContent = (folderPath, fileName) => {
const filePath = fastJoinedPath(folderPath, fileName);
if (!Known.hasFile(filePath))
if (!Known.hasFilePath(filePath))
return;
try {
return await fs.readFile(filePath, "utf8");
}
catch {
return;
}
return fs.readFile(filePath, "utf8").catch(noop);
};
const getIgnoresContent = memoize(async (folderPath) => {
const git = await getIgnoreContentBy(folderPath, ".gitignore");
const prettier = await getIgnoreContentBy(folderPath, ".prettierignore");
const contents = git ? (prettier ? [git, prettier] : [git]) : prettier ? [prettier] : [];
const getIgnoresContent = memoize(async (folderPath, filesNames) => {
const contentsRaw = await Promise.all(filesNames.map((fileName) => getIgnoreContent(folderPath, fileName)));
const contents = contentsRaw.filter(isString);
if (!contents.length)
return;
return [git, prettier];
return contents;
});
const getIgnoresContentMap = async (foldersPaths) => {
const ignoresContent = await Promise.all(foldersPaths.map(getIgnoresContent));
const map = zipObject(foldersPaths, ignoresContent);
const getIgnoresContentMap = async (foldersPaths, filesNames) => {
const contents = await Promise.all(foldersPaths.map((folderPath) => getIgnoresContent(folderPath, filesNames)));
const map = zipObjectUnless(foldersPaths, contents, isUndefined);
return map;
};
const getIgnoreBy = (folderPath, fileContent) => {
const instance = ignore().add(fileContent);
const ignores = instance.ignores.bind(instance);
const getIgnoreBy = (folderPath, filesContents) => {
const ignore = fastIgnore(filesContents);
return (filePath) => {
const fileRelativePath = fastRelativeChildPath(folderPath, filePath);
return !!fileRelativePath && ignores(fileRelativePath);
return !!fileRelativePath && ignore(fileRelativePath);
};
};
const getIgnores = memoize(async (folderPath) => {
const contents = await getIgnoresContent(folderPath);
if (!contents)
const getIgnores = memoize(async (folderPath, filesNames) => {
const contents = await getIgnoresContent(folderPath, filesNames);
if (!contents?.length)
return;
const [gitContent, prettierContent] = contents;
const git = gitContent ? getIgnoreBy(folderPath, gitContent) : undefined;
const prettier = prettierContent ? getIgnoreBy(folderPath, prettierContent) : undefined;
const ignores = git ? (prettier ? [git, prettier] : [git]) : prettier ? [prettier] : [];
if (!ignores.length)
return;
const ignore = someOf(ignores);
const ignore = getIgnoreBy(folderPath, contents);
return ignore;
});
const getIgnoresUp = memoize(async (folderPath) => {
const ignore = await getIgnores(folderPath);
const getIgnoresUp = memoize(async (folderPath, filesNames) => {
const ignore = await getIgnores(folderPath, filesNames);
const folderPathUp = path.dirname(folderPath);
const ignoreUp = folderPath !== folderPathUp ? await getIgnoresUp(folderPathUp) : undefined;
const ignoreUp = folderPath !== folderPathUp ? await getIgnoresUp(folderPathUp, filesNames) : undefined;
const ignores = ignore ? (ignoreUp ? [ignore, ignoreUp] : [ignore]) : ignoreUp ? [ignoreUp] : [];

@@ -61,7 +48,8 @@ if (!ignores.length)

});
const getIgnoreResolved = async (filePath) => {
const getIgnoreResolved = async (filePath, filesNames) => {
const folderPath = path.dirname(filePath);
const ignore = await getIgnoresUp(folderPath);
return !!ignore?.(filePath);
const ignore = await getIgnoresUp(folderPath, filesNames);
const ignored = !!ignore?.(filePath);
return ignored;
};
export { getIgnoreBy, getIgnores, getIgnoresContent, getIgnoresContentMap, getIgnoresUp, getIgnoreResolved };

@@ -1,10 +0,8 @@

import type { PrettierConfig, PrettierConfigWithOverrides } from "./types.js";
declare const getPrettierConfig: ((arg: string) => Promise<PrettierConfigWithOverrides | undefined>) & {
cache: Map<string, Promise<PrettierConfigWithOverrides | undefined>>;
};
declare const getPrettierConfigsMap: (foldersPaths: string[]) => Promise<Partial<Record<string, PrettierConfig>>>;
declare const getPrettierConfigsUp: ((arg: string) => Promise<PrettierConfigWithOverrides[]>) & {
import type { PrettierConfig, PrettierConfigWithOverrides, PromiseMaybe } from "./types.js";
declare const getPrettierConfig: (folderPath: string, fileName: string) => PromiseMaybe<PrettierConfigWithOverrides | undefined>;
declare const getPrettierConfigsMap: (foldersPaths: string[], filesNames: string[]) => Promise<Partial<Record<string, PrettierConfig[]>>>;
declare const getPrettierConfigsUp: ((folderPath: string, filesNames: string[]) => Promise<PrettierConfigWithOverrides[]>) & {
cache: Map<string, Promise<PrettierConfigWithOverrides[]>>;
};
declare const getPrettierConfigResolved: (filePath: string) => Promise<PrettierConfig>;
declare const getPrettierConfigResolved: (filePath: string, filesNames: string[]) => Promise<PrettierConfig>;
export { getPrettierConfig, getPrettierConfigsMap, getPrettierConfigsUp, getPrettierConfigResolved };
import yaml from "js-yaml";
import fs from "node:fs/promises";
import sfs from "node:fs";
import fs from "node:fs";
import path from "node:path";

@@ -9,80 +8,79 @@ import JSONC from "tiny-jsonc";

import { fastJoinedPath, fastRelativeChildPath } from "./utils.js";
import { isObject, memoize, normalizePrettierOptions, omit, zipObject } from "./utils.js";
import { isObject, isTruthy, isUndefined, memoize, noop, normalizePrettierOptions, omit, zipObjectUnless } from "./utils.js";
//TODO: Maybe completely drop support for JSON5, or implement it properly
//TODO: Maybe add support for TOML
//TODO: Check which of these file names have been found in the repo just once
const loaders = [
{
files: ["package.json"],
loader: async (filePath) => {
const fileContent = await fs.readFile(filePath, "utf8");
const pkg = JSON.parse(fileContent);
const config = isObject(pkg) && "prettier" in pkg ? pkg.prettier : undefined;
return config;
},
const Loaders = {
js: async (filePath) => {
const module = await import(filePath);
return module.default || module.exports || module.config || module.prettier; //TODO: Streamline this
},
{
files: [".prettierrc", ".prettierrc.yml", ".prettierrc.yaml"],
loader: async (filePath) => {
const fileContent = await fs.readFile(filePath, "utf8");
return yaml.load(fileContent, {
schema: yaml.JSON_SCHEMA,
});
},
json: async (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf8");
const config = JSON.parse(fileContent);
return config;
},
{
files: [".prettierrc.json", ".prettierrc.jsonc", ".prettierrc.json5"],
loader: async (filePath) => {
const fileContent = await fs.readFile(filePath, "utf8");
const config = JSONC.parse(fileContent);
return config;
},
jsonc: async (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf8");
const config = JSONC.parse(fileContent);
return config;
},
{
files: [".prettierrc.js", "prettier.config.js", ".prettierrc.cjs", "prettier.config.cjs", ".prettierrc.mjs", "prettier.config.mjs"], // prettier-ignore
loader: async (filePath) => {
const exists = sfs.existsSync(filePath);
if (!exists)
return;
const module = await import(filePath);
return module.default || module.exports || module.config || module.prettier; //TODO: Streamline this
},
package: async (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf8");
const pkg = JSON.parse(fileContent);
const config = isObject(pkg) && "prettier" in pkg ? pkg.prettier : undefined;
return config;
},
];
const getPrettierConfig = memoize(async (folderPath) => {
for (let li = 0, ll = loaders.length; li < ll; li++) {
const { files, loader } = loaders[li];
for (let fi = 0, fl = files.length; fi < fl; fi++) {
const filePath = fastJoinedPath(folderPath, files[fi]);
if (!Known.hasFile(filePath))
continue;
try {
const config = await loader(filePath);
if (!config)
continue;
if (!isObject(config))
continue;
return normalizePrettierOptions(config, folderPath);
}
catch {
continue;
}
}
}
yaml: async (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf8");
return yaml.load(fileContent, {
schema: yaml.JSON_SCHEMA,
});
},
};
const File2Loader = {
default: Loaders.yaml,
"package.json": Loaders.package,
".prettierrc": Loaders.yaml,
".prettierrc.yml": Loaders.yaml,
".prettierrc.yaml": Loaders.yaml,
".prettierrc.json": Loaders.json,
".prettierrc.jsonc": Loaders.jsonc,
".prettierrc.json5": Loaders.jsonc,
".prettierrc.js": Loaders.js,
".prettierrc.cjs": Loaders.js,
".prettierrc.mjs": Loaders.js,
"prettier.config.js": Loaders.js,
"prettier.config.cjs": Loaders.js,
"prettier.config.mjs": Loaders.js,
};
const getPrettierConfig = (folderPath, fileName) => {
const filePath = fastJoinedPath(folderPath, fileName);
if (!Known.hasFilePath(filePath))
return;
const loader = File2Loader[fileName] || File2Loader["default"];
const normalize = (config) => (isObject(config) ? normalizePrettierOptions(config, folderPath) : undefined);
return loader(filePath).then(normalize).catch(noop);
};
const getPrettierConfigs = memoize(async (folderPath, filesNames) => {
const configsRaw = await Promise.all(filesNames.map((fileName) => getPrettierConfig(folderPath, fileName)));
const configs = configsRaw.filter(isTruthy);
if (!configs.length)
return;
return configs;
});
const getPrettierConfigsMap = async (foldersPaths) => {
const configs = await Promise.all(foldersPaths.map(getPrettierConfig));
const map = zipObject(foldersPaths, configs);
const getPrettierConfigsMap = async (foldersPaths, filesNames) => {
const configs = await Promise.all(foldersPaths.map((folderPath) => getPrettierConfigs(folderPath, filesNames)));
const map = zipObjectUnless(foldersPaths, configs, isUndefined);
return map;
};
const getPrettierConfigsUp = memoize(async (folderPath) => {
const config = await getPrettierConfig(folderPath);
const getPrettierConfigsUp = memoize(async (folderPath, filesNames) => {
const config = (await getPrettierConfigs(folderPath, filesNames))?.[0];
const folderPathUp = path.dirname(folderPath);
const configsUp = folderPath !== folderPathUp ? await getPrettierConfigsUp(folderPathUp) : [];
const configsUp = folderPath !== folderPathUp ? await getPrettierConfigsUp(folderPathUp, filesNames) : [];
const configs = config ? [...configsUp, config] : configsUp;
return configs;
});
const getPrettierConfigResolved = async (filePath) => {
const getPrettierConfigResolved = async (filePath, filesNames) => {
const folderPath = path.dirname(filePath);
const configs = await getPrettierConfigsUp(folderPath);
const configs = await getPrettierConfigsUp(folderPath, filesNames);
let resolved = {};

@@ -89,0 +87,0 @@ for (let ci = 0, cl = configs.length; ci < cl; ci++) {

declare const PRETTIER_VERSION: any;
declare const CLI_VERSION = "0.1.2";
export { PRETTIER_VERSION, CLI_VERSION };
declare const CLI_VERSION: any;
declare const IS_BUN: boolean;
export { PRETTIER_VERSION, CLI_VERSION, IS_BUN };
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const pkg = require("prettier/package.json");
const PRETTIER_VERSION = pkg.version;
const CLI_VERSION = "0.1.2"; //TODO: Hard-coding this is error-prone
export { PRETTIER_VERSION, CLI_VERSION };
const prettierPackage = require("prettier/package.json");
const cliPackage = require("@prettier/cli/package.json");
const PRETTIER_VERSION = prettierPackage.version;
const CLI_VERSION = cliPackage.version;
const IS_BUN = !!process.versions["bun"];
export { PRETTIER_VERSION, CLI_VERSION, IS_BUN };

@@ -1,3 +0,3 @@

import type { Options } from "./types.js";
declare function run(options: Options): Promise<void>;
import type { Options, PluginsOptions } from "./types.js";
declare function run(options: Options, pluginsOptions: PluginsOptions): Promise<void>;
export { run };
import isBinaryPath from "is-binary-path";
import stringify from "json-sorted-stringify";
import path from "node:path";
import process from "node:process";

@@ -12,5 +13,5 @@ import Cache from "./cache.js";

import { makePrettier } from "./prettier.js";
import { getExpandedFoldersPaths, getFoldersChildrenPaths, getProjectPath, getTargetsPaths } from "./utils.js";
import { getExpandedFoldersPaths, getFoldersChildrenPaths, getPluginsVersions, getProjectPath, getTargetsPaths } from "./utils.js";
import { fastRelativePath, isString, isUndefined, negate, pluralize } from "./utils.js";
async function run(options) {
async function run(options, pluginsOptions) {
const logger = new Logger(options.logLevel);

@@ -21,3 +22,3 @@ const spinner = options.check ? logger.spinner.log() : undefined;

const projectPath = getProjectPath(rootPath);
const [filesPaths, filesFoundPaths, foldersFoundPaths] = await getTargetsPaths(rootPath, options.globs);
const [filesPaths, filesNames, filesFoundPaths, foldersFoundPaths] = await getTargetsPaths(rootPath, options.globs);
const filesPathsTargets = filesPaths.filter(negate(isBinaryPath)).sort();

@@ -27,25 +28,31 @@ const [foldersPathsTargetsUnsorted, foldersExtraPaths] = getExpandedFoldersPaths(foldersFoundPaths, projectPath);

const filesExtraPaths = await getFoldersChildrenPaths([rootPath, ...foldersExtraPaths]);
Known.addFiles(filesFoundPaths);
Known.addFiles(filesExtraPaths);
Known.addFolders(foldersFoundPaths);
Known.addFolders(foldersExtraPaths);
const filesExtraNames = filesExtraPaths.map((filePath) => path.basename(filePath));
Known.addFilesPaths(filesFoundPaths);
Known.addFilesPaths(filesExtraPaths);
Known.addFilesNames(filesNames);
Known.addFilesNames(filesExtraNames);
const prettierVersion = PRETTIER_VERSION;
const cliVersion = CLI_VERSION;
const pluginsVersions = ""; //TODO
const editorConfigs = options.editorConfig ? await getEditorConfigsMap(foldersPathsTargets) : {};
const ignoreContents = await getIgnoresContentMap(foldersPathsTargets);
const prettierConfigs = options.config ? await getPrettierConfigsMap(foldersPathsTargets) : {};
const cliConfig = options.formatOptions;
const cacheVersion = stringify({ prettierVersion, cliVersion, pluginsVersions, editorConfigs, ignoreContents, prettierConfigs, cliConfig }); // prettier-ignore
Known.reset();
const cache = new Cache(cacheVersion, projectPath, options, logger);
const pluginsNames = options.formatOptions.plugins || [];
const pluginsVersions = getPluginsVersions(pluginsNames);
const editorConfigNames = [".editorconfig"].filter(Known.hasFileName);
const ignoreNames = [".gitignore", ".prettierignore"].filter(Known.hasFileName);
const prettierConfigNames = ["package.json", ".prettierrc", ".prettierrc.yml", ".prettierrc.yaml", ".prettierrc.json", ".prettierrc.jsonc", ".prettierrc.json5", ".prettierrc.js", "prettier.config.js", ".prettierrc.cjs", "prettier.config.cjs", ".prettierrc.mjs", "prettier.config.mjs"].filter(Known.hasFileName); // prettier-ignore
const editorConfigs = options.editorConfig ? await getEditorConfigsMap(foldersPathsTargets, editorConfigNames) : {};
const ignoreContents = await getIgnoresContentMap(foldersPathsTargets, ignoreNames);
const prettierConfigs = options.config ? await getPrettierConfigsMap(foldersPathsTargets, prettierConfigNames) : {};
const cliContextConfig = options.contextOptions;
const cliFormatConfig = options.formatOptions;
const cacheVersion = stringify({ prettierVersion, cliVersion, pluginsNames, pluginsVersions, editorConfigs, prettierConfigs, cliContextConfig, cliFormatConfig, pluginsOptions }); // prettier-ignore
const shouldCache = isUndefined(cliContextConfig.cursorOffset);
const cache = shouldCache ? new Cache(cacheVersion, projectPath, options, logger) : undefined;
const prettier = await makePrettier(options, cache);
//TODO: Maybe do work in chunks here, as keeping too many formatted files in memory can be a problem
const filesResults = await Promise.allSettled(filesPathsTargets.map(async (filePath) => {
const ignored = await getIgnoreResolved(filePath);
const ignored = await getIgnoreResolved(filePath, ignoreNames);
if (ignored)
return;
const getFormatOptions = async () => {
const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(filePath)) : {}; // prettier-ignore
const prettierConfig = options.config ? await getPrettierConfigResolved(filePath) : {};
const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(filePath, editorConfigNames)) : {};
const prettierConfig = options.config ? await getPrettierConfigResolved(filePath, prettierConfigNames) : {};
const formatOptions = { ...editorConfig, ...prettierConfig, ...options.formatOptions };

@@ -56,9 +63,9 @@ return formatOptions;

if (options.check || options.list) {
return await prettier.checkWithPath(filePath, getFormatOptions);
return await prettier.checkWithPath(filePath, getFormatOptions, cliContextConfig, pluginsOptions);
}
else if (options.write) {
return await prettier.writeWithPath(filePath, getFormatOptions);
return await prettier.writeWithPath(filePath, getFormatOptions, cliContextConfig, pluginsOptions);
}
else {
return await prettier.formatWithPath(filePath, getFormatOptions);
return await prettier.formatWithPath(filePath, getFormatOptions, cliContextConfig, pluginsOptions);
}

@@ -71,3 +78,4 @@ }

spinner?.stop("Checking formatting...");
let totalFound = filesResults.length;
let totalMatched = filesResults.length;
let totalIgnored = 0;
let totalFormatted = 0;

@@ -80,4 +88,4 @@ let totalUnformatted = 0;

if (isUndefined(fileResult.value)) {
totalFound -= 1;
continue;
totalMatched -= 1;
totalIgnored += 1;
}

@@ -120,3 +128,9 @@ else if (isString(fileResult.value)) {

}
if (!totalFound) {
logger.prefixed.debug(`Files found: ${totalMatched + totalIgnored}`);
logger.prefixed.debug(`Files matched: ${totalMatched}`);
logger.prefixed.debug(`Files ignored: ${totalIgnored}`);
logger.prefixed.debug(`Files formatted: ${totalFormatted}`);
logger.prefixed.debug(`Files unformatted: ${totalUnformatted}`);
logger.prefixed.debug(`Files errored: ${totalErrored}`);
if (!totalMatched) {
if (options.errorOnUnmatchedPattern) {

@@ -133,5 +147,3 @@ logger.prefixed.error(`No files matching the given patterns were found`);

// if (options.check) {
// logger.prefixed.error(
// `Parsing issues found in ${totalErrored} ${pluralize("file", totalErrored)}. Check files to fix.`,
// );
// logger.prefixed.error(`Parsing issues found in ${totalErrored} ${pluralize("file", totalErrored)}. Check files to fix.`);
// }

@@ -144,5 +156,5 @@ // }

}
cache.write();
process.exitCode = (!totalFound && options.errorOnUnmatchedPattern) || totalErrored || (totalUnformatted && !options.write) ? 1 : 0; // prettier-ignore
cache?.write();
process.exitCode = (!totalMatched && options.errorOnUnmatchedPattern) || totalErrored || (totalUnformatted && !options.write) ? 1 : 0;
}
export { run };
declare class Known {
private files;
private folders;
addFiles(filesPaths: Array<string> | Set<string>): void;
addFolders(folderPaths: Array<string> | Set<string>): void;
hasFile(filePath: string): boolean;
hasFolder(folderPath: string): boolean;
reset(): void;
private filesPaths;
private filesNames;
addFilesPaths: (filesPaths: Array<string> | Set<string>) => void;
addFilesNames: (filesNames: Array<string> | Set<string>) => void;
hasFilePath: (filePath: string) => boolean;
hasFileName: (fileName: string) => boolean;
reset: () => void;
}
declare const _default: Known;
export default _default;
//FIXME: This shouldn't be a singleton, but passing it through the whole CLI is a bit of a pain right now
class Known {
constructor() {
this.files = new Set();
this.folders = new Set();
}
addFiles(filesPaths) {
if (!this.files.size) {
this.files = new Set(filesPaths);
}
else {
for (const filePath of filesPaths) {
this.files.add(filePath);
this.filesPaths = new Set();
this.filesNames = new Set();
this.addFilesPaths = (filesPaths) => {
if (!this.filesPaths.size) {
this.filesPaths = new Set(filesPaths);
}
}
}
addFolders(folderPaths) {
if (!this.folders.size) {
this.folders = new Set(folderPaths);
}
else {
for (const folderPath of folderPaths) {
this.folders.add(folderPath);
else {
for (const filePath of filesPaths) {
this.filesPaths.add(filePath);
}
}
}
};
this.addFilesNames = (filesNames) => {
if (!this.filesNames.size) {
this.filesNames = new Set(filesNames);
}
else {
for (const fileName of filesNames) {
this.filesNames.add(fileName);
}
}
};
this.hasFilePath = (filePath) => {
return this.filesPaths.has(filePath);
};
this.hasFileName = (fileName) => {
return this.filesNames.has(fileName);
};
this.reset = () => {
this.filesPaths = new Set();
this.filesNames = new Set();
};
}
hasFile(filePath) {
return this.files.has(filePath);
}
hasFolder(folderPath) {
return this.folders.has(folderPath);
}
reset() {
this.files = new Set();
this.folders = new Set();
}
}
export default new Known();

@@ -8,3 +8,3 @@ import { readFile, writeFile } from "atomically";

write: prettier.write,
async checkWithPath(filePath, formatOptions) {
async checkWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
const data = await cache.get(filePath);

@@ -14,7 +14,7 @@ if (isBoolean(data?.formatted))

const fileContent = data?.content?.toString() ?? (await readFile(filePath, "utf8"));
const formatted = await prettier.check(filePath, fileContent, formatOptions);
const formatted = await prettier.check(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
await data?.save(formatted, fileContent);
return formatted;
},
async formatWithPath(filePath, formatOptions) {
async formatWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
const data = await cache.get(filePath);

@@ -24,3 +24,3 @@ const fileContent = data?.content?.toString() ?? (await readFile(filePath, "utf8"));

return fileContent;
const fileContentFormatted = await prettier.format(filePath, fileContent, formatOptions);
const fileContentFormatted = await prettier.format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
if (fileContent === fileContentFormatted) {

@@ -35,3 +35,3 @@ await data?.save(true, fileContent);

},
async writeWithPath(filePath, formatOptions) {
async writeWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
const data = await cache.get(filePath);

@@ -41,3 +41,3 @@ if (data?.formatted)

const fileContent = data?.content?.toString() ?? (await readFile(filePath, "utf8"));
const fileContentFormatted = await prettier.format(filePath, fileContent, formatOptions);
const fileContentFormatted = await prettier.format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
if (fileContent === fileContentFormatted) {

@@ -44,0 +44,0 @@ await data?.save(true, fileContent);

@@ -9,21 +9,22 @@ import os from "node:os";

methods: new URL("./prettier_serial.js", import.meta.url),
warmup: true,
});
return {
async check(filePath, fileContent, formatOptions) {
return pool.exec("check", [filePath, fileContent, await resolve(formatOptions)]);
async check(filePath, fileContent, formatOptions, contextOptions, pluginsOptions) {
return pool.exec("check", [filePath, fileContent, await resolve(formatOptions), contextOptions, pluginsOptions]);
},
async checkWithPath(filePath, formatOptions) {
return pool.exec("checkWithPath", [filePath, await resolve(formatOptions)]);
async checkWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
return pool.exec("checkWithPath", [filePath, await resolve(formatOptions), contextOptions, pluginsOptions]);
},
async format(filePath, fileContent, formatOptions) {
return pool.exec("format", [filePath, fileContent, await resolve(formatOptions)]);
async format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions) {
return pool.exec("format", [filePath, fileContent, await resolve(formatOptions), contextOptions, pluginsOptions]);
},
async formatWithPath(filePath, formatOptions) {
return pool.exec("formatWithPath", [filePath, await resolve(formatOptions)]);
async formatWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
return pool.exec("formatWithPath", [filePath, await resolve(formatOptions), contextOptions, pluginsOptions]);
},
async write(filePath, fileContent, formatOptions) {
return pool.exec("write", [filePath, fileContent, await resolve(formatOptions)]);
async write(filePath, fileContent, formatOptions, contextOptions, pluginsOptions) {
return pool.exec("write", [filePath, fileContent, await resolve(formatOptions), contextOptions, pluginsOptions]);
},
async writeWithPath(filePath, formatOptions) {
return pool.exec("writeWithPath", [filePath, await resolve(formatOptions)]);
async writeWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
return pool.exec("writeWithPath", [filePath, await resolve(formatOptions), contextOptions, pluginsOptions]);
},

@@ -30,0 +31,0 @@ };

@@ -1,8 +0,8 @@

import type { LazyFormatOptions } from "./types.js";
declare function check(filePath: string, fileContent: string, formatOptions: LazyFormatOptions): Promise<boolean>;
declare function checkWithPath(filePath: string, formatOptions: LazyFormatOptions): Promise<boolean>;
declare function format(filePath: string, fileContent: string, formatOptions: LazyFormatOptions): Promise<string>;
declare function formatWithPath(filePath: string, formatOptions: LazyFormatOptions): Promise<string>;
declare function write(filePath: string, fileContent: string, formatOptions: LazyFormatOptions): Promise<boolean>;
declare function writeWithPath(filePath: string, formatOptions: LazyFormatOptions): Promise<boolean>;
import type { ContextOptions, LazyFormatOptions, PluginsOptions } from "./types.js";
declare function check(filePath: string, fileContent: string, formatOptions: LazyFormatOptions, contextOptions: ContextOptions, pluginsOptions: PluginsOptions): Promise<boolean>;
declare function checkWithPath(filePath: string, formatOptions: LazyFormatOptions, contextOptions: ContextOptions, pluginsOptions: PluginsOptions): Promise<boolean>;
declare function format(filePath: string, fileContent: string, formatOptions: LazyFormatOptions, contextOptions: ContextOptions, pluginsOptions: PluginsOptions): Promise<string>;
declare function formatWithPath(filePath: string, formatOptions: LazyFormatOptions, contextOptions: ContextOptions, pluginsOptions: PluginsOptions): Promise<string>;
declare function write(filePath: string, fileContent: string, formatOptions: LazyFormatOptions, contextOptions: ContextOptions, pluginsOptions: PluginsOptions): Promise<boolean>;
declare function writeWithPath(filePath: string, formatOptions: LazyFormatOptions, contextOptions: ContextOptions, pluginsOptions: PluginsOptions): Promise<boolean>;
export { check, checkWithPath, format, formatWithPath, write, writeWithPath };
import { readFile, writeFile } from "atomically";
import process from "node:process";
import prettier from "prettier/standalone";

@@ -16,15 +17,19 @@ import prettierAcorn from "prettier/plugins/acorn";

import prettierYaml from "prettier/plugins/yaml";
import { resolve } from "./utils.js";
import { getPlugins, resolve } from "./utils.js";
//TODO: Avoid loading plugins until they are actually needed
async function check(filePath, fileContent, formatOptions) {
const fileContentFormatted = await format(filePath, fileContent, formatOptions);
async function check(filePath, fileContent, formatOptions, contextOptions, pluginsOptions) {
const fileContentFormatted = await format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
return fileContent === fileContentFormatted;
}
async function checkWithPath(filePath, formatOptions) {
async function checkWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
const fileContent = await readFile(filePath, "utf8");
return check(filePath, fileContent, formatOptions);
return check(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
}
async function format(filePath, fileContent, formatOptions) {
return prettier.format(fileContent, {
...(await resolve(formatOptions)),
async function format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions) {
formatOptions = await resolve(formatOptions);
const plugins = await getPlugins(formatOptions.plugins || []);
const options = {
...formatOptions,
...pluginsOptions,
...contextOptions,
filepath: filePath,

@@ -45,11 +50,17 @@ plugins: [

prettierYaml,
...plugins,
],
});
};
const result = await prettier.formatWithCursor(fileContent, options); //FIXME: Prettier's own types are incorrect here
if (result.cursorOffset >= 0) {
process.stderr.write(`${result.cursorOffset}\n`); //TODO: This should be implemented differently, pretty ugly doing it like this
}
return result.formatted;
}
async function formatWithPath(filePath, formatOptions) {
async function formatWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
const fileContent = await readFile(filePath, "utf8");
return format(filePath, fileContent, formatOptions);
return format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
}
async function write(filePath, fileContent, formatOptions) {
const fileContentFormatted = await format(filePath, fileContent, formatOptions);
async function write(filePath, fileContent, formatOptions, contextOptions, pluginsOptions) {
const fileContentFormatted = await format(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
if (fileContent === fileContentFormatted)

@@ -60,6 +71,6 @@ return true;

}
async function writeWithPath(filePath, formatOptions) {
async function writeWithPath(filePath, formatOptions, contextOptions, pluginsOptions) {
const fileContent = await readFile(filePath, "utf8");
return write(filePath, fileContent, formatOptions);
return write(filePath, fileContent, formatOptions, contextOptions, pluginsOptions);
}
export { check, checkWithPath, format, formatWithPath, write, writeWithPath };
import type Cache from "./cache.js";
import type { Options, Prettier } from "./types.js";
declare function makePrettier(options: Options, cache: Cache): Promise<Prettier>;
declare function makePrettier(options: Options, cache?: Cache): Promise<Prettier>;
export { makePrettier };

@@ -5,3 +5,3 @@ import { makeCached } from "./prettier_cached.js";

const { makeParallel } = await import("./prettier_parallel.js");
if (options.cache) {
if (options.cache && cache) {
return makeCached(options, cache, makeParallel(options));

@@ -15,3 +15,3 @@ }

const { makeLazy } = await import("./prettier_lazy.js");
if (options.cache) {
if (options.cache && cache) {
return makeCached(options, cache, makeLazy(options));

@@ -18,0 +18,0 @@ }

@@ -0,2 +1,9 @@

type Bin = ReturnType<typeof import("tiny-bin").default>;
type ContextOptions = {
cursorOffset?: number;
rangeEnd?: number;
rangeStart?: number;
};
type FormatOptions = {
experimentalTernaries?: boolean;
arrowParens?: "avoid" | "always";

@@ -11,2 +18,3 @@ bracketSameLine?: boolean;

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";
plugins?: string[];
printWidth?: number;

@@ -26,2 +34,3 @@ proseWrap?: "always" | "never" | "preserve";

type Ignore = (filePath: string) => boolean;
type Key = string | number | symbol;
type LazyFormatOptions = FunctionMaybe<PromiseMaybe<FormatOptions>>;

@@ -43,4 +52,8 @@ type LogLevel = "error" | "warn" | "log" | "debug" | "silent";

parallelWorkers: number;
contextOptions: ContextOptions;
formatOptions: FormatOptions;
};
type PluginsOptions = {
[option: string]: unknown;
};
type Prettier = typeof import("./prettier_serial.js");

@@ -56,3 +69,4 @@ type PrettierConfig = FormatOptions;

};
type PrettierPlugin = import("prettier").Plugin;
type PromiseMaybe<T> = T | Promise<T>;
export type { FormatOptions, FunctionMaybe, Ignore, LazyFormatOptions, LogLevel, Options, Prettier, PrettierConfig, PrettierConfigWithOverrides, PromiseMaybe, };
export type { Bin, ContextOptions, FormatOptions, FunctionMaybe, Ignore, Key, LazyFormatOptions, LogLevel, Options, PluginsOptions, Prettier, PrettierConfig, PrettierConfigWithOverrides, PrettierPlugin, PromiseMaybe, };

@@ -1,2 +0,6 @@

import type { FormatOptions, FunctionMaybe, Options, PrettierConfigWithOverrides } from "./types.js";
import type { FormatOptions, FunctionMaybe, Key, Options, PrettierConfigWithOverrides, PrettierPlugin } from "./types.js";
import type { PluginsOptions, PromiseMaybe } from "./types.js";
declare function memoize<Args extends unknown[], Return>(fn: (...args: Args) => Return): ((...args: Args) => Return) & {
cache: Map<Args[0], Return>;
};
declare function castArray<T>(value: T | T[]): T[];

@@ -13,2 +17,10 @@ declare function everyOf<T>(fns: ((arg: T) => unknown)[]): (arg: T) => boolean;

declare function getGlobPaths(rootPath: string, globs: string[]): Promise<import("tiny-readdir-glob/dist/types.js").Result>;
declare const getPlugin: ((name: string) => Promise<import("prettier").Plugin<any>>) & {
cache: Map<string, Promise<import("prettier").Plugin<any>>>;
};
declare function getPluginPath(name: string): string;
declare function getPluginVersion(name: string): string;
declare function getPlugins(names: string[]): PromiseMaybe<PrettierPlugin[]>;
declare function getPluginsPaths(names: string[]): string[];
declare function getPluginsVersions(names: string[]): string[];
declare function getProjectPath(rootPath: string): string;

@@ -18,2 +30,3 @@ declare function getTargetsPaths(rootPath: string, globs: string[]): Promise<string[][]>;

declare function isBoolean(value: unknown): value is boolean;
declare function isFalsy<T>(value: T): value is Extract<T, 0 | -0 | 0n | -0n | "" | false | null | undefined | void>;
declare function isFunction(value: unknown): value is Function;

@@ -25,9 +38,9 @@ declare function isInteger(value: unknown): value is number;

declare function isString(value: unknown): value is string;
declare function isTruthy<T>(value: T): value is Exclude<T, 0 | -0 | 0n | -0n | "" | false | null | undefined | void>;
declare function isUndefined(value: unknown): value is undefined;
declare function memoize<T, Return>(fn: (arg: T) => Return): ((arg: T) => Return) & {
cache: Map<T, Return>;
};
declare function negate<T extends unknown[]>(fn: (...args: T) => boolean): (...args: T) => boolean;
declare function noop(): undefined;
declare function normalizeOptions(options: unknown, targets: unknown[]): Options;
declare function normalizeFormatOptions(options: unknown): FormatOptions;
declare function normalizePluginOptions(options: unknown, names: string[]): PluginsOptions;
declare function normalizePrettierOptions(options: unknown, folderPath: string): PrettierConfigWithOverrides;

@@ -41,3 +54,4 @@ declare function omit<T extends object, K extends keyof T>(object: T, keys: K[]): Omit<T, K>;

declare function someOf<T>(fns: ((arg: T) => unknown)[]): (arg: T) => boolean;
declare function zipObject<T extends number | string | symbol, U>(keys: T[], values: U[]): Partial<Record<T, U>>;
export { castArray, everyOf, fastJoinedPath, fastRelativePath, fastRelativeChildPath, findLastIndex, getCachePath, getFolderChildrenPaths, getFoldersChildrenPaths, getExpandedFoldersPaths, getGlobPaths, getProjectPath, getTargetsPaths, isArray, isBoolean, isFunction, isInteger, isNumber, isObject, isPromise, isString, isUndefined, memoize, negate, normalizeOptions, normalizeFormatOptions, normalizePrettierOptions, omit, once, pluralize, resolve, sha1hex, sha1base64, someOf, zipObject, };
declare function zipObject<T extends Key, U>(keys: T[], values: U[]): Partial<Record<T, U>>;
declare function zipObjectUnless<T extends Key, U>(keys: T[], values: U[], unless: (value: U) => boolean): Partial<Record<T, U>>;
export { castArray, everyOf, fastJoinedPath, fastRelativePath, fastRelativeChildPath, findLastIndex, getCachePath, getFolderChildrenPaths, getFoldersChildrenPaths, getExpandedFoldersPaths, getGlobPaths, getPlugin, getPluginPath, getPluginVersion, getPlugins, getPluginsPaths, getPluginsVersions, getProjectPath, getTargetsPaths, isArray, isBoolean, isFalsy, isFunction, isInteger, isNumber, isObject, isPromise, isString, isTruthy, isUndefined, memoize, negate, noop, normalizeOptions, normalizeFormatOptions, normalizePluginOptions, normalizePrettierOptions, omit, once, pluralize, resolve, sha1hex, sha1base64, someOf, zipObject, zipObjectUnless, };

@@ -0,7 +1,27 @@

import findUp from "find-up-json";
import { moduleResolve } from "import-meta-resolve";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
import url from "node:url";
import { exit } from "specialist";
import readdir from "tiny-readdir-glob";
import zeptomatch from "zeptomatch";
//FIXME: Ensure all arguments are actually taken into account
//TODO: Publish something like this as a standalone module, rather than manually hoisting this up
function memoize(fn) {
const memoized = (...args) => {
const { cache } = memoized;
const id = args[0];
const cached = cache.get(id);
if (!isUndefined(cached) || cache.has(id))
return cached;
const result = fn(...args);
cache.set(id, result);
return result;
};
memoized.cache = new Map();
return memoized;
}
function castArray(value) {

@@ -79,5 +99,39 @@ return isArray(value) ? value : [value];

followSymlinks: false,
ignore: "**/{.git,.sl,.svn,.hg,node_modules}",
ignore: "**/{.git,.sl,.svn,.hg,node_modules,.DS_Store,Thumbs.db}",
});
}
const getPlugin = memoize(async (name) => {
const pluginPath = getPluginPath(name);
const pluginExports = await import(pluginPath);
const plugin = pluginExports.default || pluginExports;
return plugin;
});
function getPluginPath(name) {
const rootPath = path.join(process.cwd(), "index.js");
const rootUrl = url.pathToFileURL(rootPath);
const pluginUrl = moduleResolve(name, rootUrl);
const pluginPath = url.fileURLToPath(pluginUrl);
return pluginPath;
}
function getPluginVersion(name) {
const pluginPath = getPluginPath(name);
const parentPath = path.dirname(pluginPath);
const pkg = findUp("package.json", parentPath);
if (!pkg || !pkg.content.version)
throw new Error(`Version not found for plugin: "${name}"`);
return pkg.content.version;
}
function getPlugins(names) {
if (!names.length)
return [];
return Promise.all(names.map(getPlugin));
}
function getPluginsPaths(names) {
const pluginsPaths = names.map(getPluginPath);
return pluginsPaths;
}
function getPluginsVersions(names) {
const pluginsVersions = names.map(getPluginVersion);
return pluginsVersions;
}
function getProjectPath(rootPath) {

@@ -111,2 +165,3 @@ function isProjectPath(folderPath) {

const targetFiles = [];
const targetFilesNames = [];
const targetGlobs = [];

@@ -117,2 +172,3 @@ for (const glob of globs) {

targetFiles.push(filePath);
targetFilesNames.push(path.basename(filePath));
}

@@ -125,5 +181,6 @@ else {

const filesPaths = [...targetFiles, ...result.files];
const filesNames = [...targetFilesNames, ...result.filesFoundNames];
const filesFoundPaths = result.filesFound;
const foldersFoundPaths = [rootPath, ...result.directoriesFound];
return [filesPaths, filesFoundPaths, foldersFoundPaths];
return [filesPaths, filesNames, filesFoundPaths, foldersFoundPaths];
}

@@ -136,2 +193,5 @@ function isArray(value) {

}
function isFalsy(value) {
return !value;
}
function isFile(targetPath) {

@@ -171,18 +231,8 @@ try {

}
function isTruthy(value) {
return !!value;
}
function isUndefined(value) {
return typeof value === "undefined";
}
function memoize(fn) {
const memoized = (arg) => {
const { cache } = memoized;
const cached = cache.get(arg);
if (!isUndefined(cached) || cache.has(arg))
return cached;
const result = fn(arg);
cache.set(arg, result);
return result;
};
memoized.cache = new Map();
return memoized;
}
function negate(fn) {

@@ -193,2 +243,5 @@ return (...args) => {

}
function noop() {
return;
}
function normalizeOptions(options, targets) {

@@ -198,3 +251,3 @@ if (!isObject(options))

const targetsGlobs = targets.filter(isString);
const targetsStatic = "--" in options && Array.isArray(options["--"]) ? options["--"].filter(isString).map(zeptomatch.escape) : []; // prettier-ignore
const targetsStatic = "--" in options && Array.isArray(options["--"]) ? options["--"].filter(isString).map(zeptomatch.escape) : [];
const globs = [...targetsGlobs, ...targetsStatic];

@@ -215,8 +268,9 @@ if (!globs.length)

const cache = "cache" in options ? !!options.cache : true;
const cacheLocation = "cacheLocation" in options && isString(options.cacheLocation) ? options.cacheLocation : undefined; // prettier-ignore
const cacheLocation = "cacheLocation" in options && isString(options.cacheLocation) ? options.cacheLocation : undefined;
const errorOnUnmatchedPattern = "errorOnUnmatchedPattern" in options ? !!options.errorOnUnmatchedPattern : true;
const ignoreUnknown = "ignoreUnknown" in options && isBoolean(options.ignoreUnknown) ? !!options.ignoreUnknown : globs.some(isGlobStatic); // prettier-ignore
const ignoreUnknown = "ignoreUnknown" in options && isBoolean(options.ignoreUnknown) ? !!options.ignoreUnknown : globs.some(isGlobStatic);
const logLevel = "logLevel" in options ? (options.logLevel || "log") : "log";
const parallel = "parallel" in options && !!options.parallel;
const parallelWorkers = ("parallelWorkers" in options && Math.round(Number(options.parallelWorkers))) || 0;
const contextOptions = normalizeContextOptions(options);
const formatOptions = normalizeFormatOptions(options);

@@ -237,5 +291,30 @@ return {

parallelWorkers,
contextOptions,
formatOptions,
};
}
function normalizeContextOptions(options) {
if (!isObject(options))
exit("Invalid options object");
const contextOptions = {};
if ("cursorOffset" in options) {
const value = Number(options.cursorOffset);
if (isInteger(value) && value >= 0) {
contextOptions.cursorOffset = value;
}
}
if ("rangeEnd" in options) {
const value = Number(options.rangeEnd);
if (isInteger(value) && value >= 0) {
contextOptions.rangeEnd = value;
}
}
if ("rangeStart" in options) {
const value = Number(options.rangeStart);
if (isInteger(value) && value >= 0) {
contextOptions.rangeStart = value;
}
}
return contextOptions;
}
function normalizeFormatOptions(options) {

@@ -245,2 +324,8 @@ if (!isObject(options))

const formatOptions = {};
if ("experimentalTernaries" in options) {
const value = options.experimentalTernaries;
if (isBoolean(value)) {
formatOptions.experimentalTernaries = value;
}
}
if ("arrowParens" in options) {

@@ -301,2 +386,15 @@ const value = options.arrowParens;

}
if ("plugin" in options) {
const value = options.plugin;
if (isArray(value) && value.every(isString)) {
formatOptions.plugins = value;
}
else if (isString(value)) {
formatOptions.plugins = [value];
}
else if (!isUndefined(value)) {
//TODO: Figure out what to do here, probably just bailing out of parallelization?
exit("Non-string plugin specifiers are not supported yet");
}
}
if ("printWidth" in options) {

@@ -370,2 +468,15 @@ const value = Number(options.printWidth);

}
function normalizePluginOptions(options, names) {
if (!isObject(options))
exit("Invalid options object");
const config = {};
for (let i = 0, l = names.length; i < l; i++) {
const name = names[i];
const value = options[name];
if (isUndefined(value))
continue;
config[name] = value;
}
return config;
}
function normalizePrettierOptions(options, folderPath) {

@@ -443,2 +554,12 @@ if (!isObject(options))

}
export { castArray, everyOf, fastJoinedPath, fastRelativePath, fastRelativeChildPath, findLastIndex, getCachePath, getFolderChildrenPaths, getFoldersChildrenPaths, getExpandedFoldersPaths, getGlobPaths, getProjectPath, getTargetsPaths, isArray, isBoolean, isFunction, isInteger, isNumber, isObject, isPromise, isString, isUndefined, memoize, negate, normalizeOptions, normalizeFormatOptions, normalizePrettierOptions, omit, once, pluralize, resolve, sha1hex, sha1base64, someOf, zipObject, };
function zipObjectUnless(keys, values, unless) {
const map = {};
for (let i = 0, l = keys.length; i < l; i++) {
const value = values[i];
if (!unless(value)) {
map[keys[i]] = value;
}
}
return map;
}
export { castArray, everyOf, fastJoinedPath, fastRelativePath, fastRelativeChildPath, findLastIndex, getCachePath, getFolderChildrenPaths, getFoldersChildrenPaths, getExpandedFoldersPaths, getGlobPaths, getPlugin, getPluginPath, getPluginVersion, getPlugins, getPluginsPaths, getPluginsVersions, getProjectPath, getTargetsPaths, isArray, isBoolean, isFalsy, isFunction, isInteger, isNumber, isObject, isPromise, isString, isTruthy, isUndefined, memoize, negate, noop, normalizeOptions, normalizeFormatOptions, normalizePluginOptions, normalizePrettierOptions, omit, once, pluralize, resolve, sha1hex, sha1base64, someOf, zipObject, zipObjectUnless, };

@@ -6,3 +6,3 @@ {

"license": "MIT",
"version": "0.1.5",
"version": "0.2.0",
"type": "module",

@@ -15,3 +15,4 @@ "bin": {

".": "./dist/index.js",
"./bin": "./dist/bin.js"
"./bin": "./dist/bin.js",
"./package.json": "./package.json"
},

@@ -31,13 +32,16 @@ "files": [

"atomically": "^2.0.2",
"ignore": "^5.3.0",
"fast-ignore": "^1.1.1",
"find-up-json": "^2.0.2",
"import-meta-resolve": "^4.0.0",
"is-binary-path": "^2.1.0",
"js-yaml": "^4.1.0",
"json-sorted-stringify": "^1.0.0",
"kasi": "^1.1.0",
"pioppo": "^1.1.0",
"specialist": "^1.3.0",
"specialist": "^1.4.0",
"tiny-editorconfig": "^1.0.0",
"tiny-jsonc": "^1.0.1",
"tiny-readdir-glob": "^1.0.4",
"tiny-readdir-glob": "^1.1.0",
"tiny-spinner": "^2.0.3",
"worktank": "^2.5.2",
"worktank": "^2.6.0",
"zeptomatch": "^1.2.2"

@@ -44,0 +48,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc