Skip to content
Open
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
70 changes: 46 additions & 24 deletions src/config_prettier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import zeptomatch from "zeptomatch";
import Known from "./known.js";
import { fastJoinedPath, fastRelativeChildPath, getModulePath } from "./utils.js";
import { isObject, isString, isTruthy, isUndefined, memoize, noop, normalizePrettierOptions, omit, zipObjectUnless } from "./utils.js";
import type { PrettierConfig, PrettierConfigWithOverrides, PromiseMaybe } from "./types.js";
import type { PrettierConfig, PrettierConfigResolver, PrettierConfigWithOverrides, PromiseMaybe } from "./types.js";

const Loaders = {
auto: (filePath: string): Promise<unknown> => {
Expand Down Expand Up @@ -87,12 +87,17 @@ const Ext2Loader: Record<string, (filePath: string) => Promise<unknown>> = {
mjs: Loaders.js,
};

const normalizeConfig = (config: unknown, folderPath: string): PrettierConfigWithOverrides | undefined => {
return isObject(config) ? { ...config, ...normalizePrettierOptions(config, folderPath) } : undefined;
};

const getPrettierConfig = (folderPath: string, fileName: string): PromiseMaybe<PrettierConfigWithOverrides | undefined> => {
const filePath = fastJoinedPath(folderPath, fileName);
if (!Known.hasFilePath(filePath)) return;
const loader = File2Loader[fileName] || File2Loader["default"];
const normalize = (config: unknown) => (isObject(config) ? { ...config, ...normalizePrettierOptions(config, folderPath) } : undefined);
return loader(filePath).then(normalize).catch(noop);
return loader(filePath)
.then((config: unknown) => normalizeConfig(config, folderPath))
.catch(noop);
};

const getPrettierConfigs = memoize(async (folderPath: string, filesNames: string[]): Promise<PrettierConfigWithOverrides[] | undefined> => {
Expand All @@ -108,6 +113,41 @@ const getPrettierConfigsMap = async (foldersPaths: string[], filesNames: string[
return map;
};

const getPrettierConfigResolver = (configs: PrettierConfigWithOverrides[]): PrettierConfigResolver => {
return (filePath: string): PrettierConfig => {
let resolved: PrettierConfig = {};

for (let ci = 0, cl = configs.length; ci < cl; ci++) {
const config = configs[ci];
const formatOptions = omit(config, ["overrides"]);
resolved = ci ? { ...resolved, ...formatOptions } : formatOptions;

const overrides = config.overrides;
if (overrides) {
for (let oi = 0, ol = overrides.length; oi < ol; oi++) {
const override = overrides[oi];
const filePathRelative = fastRelativeChildPath(override.folder, filePath);
if (!filePathRelative) continue;
if (!zeptomatch(override.filesPositive, filePathRelative)) continue;
if (zeptomatch(override.filesNegative, filePathRelative)) continue;
resolved = { ...resolved, ...override.options };
}
}
}

return resolved;
};
};

const getPrettierConfigBys = (foldersPaths: string[], filesContents: unknown[]): PrettierConfigResolver | undefined => {
if (!foldersPaths.length) return;
const configsRaw = foldersPaths.map((folderPath, index) => normalizeConfig(filesContents[index], folderPath));
const configs = configsRaw.filter(isTruthy);

if (!configs.length) return;
return getPrettierConfigResolver(configs);
};

const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: string[]): Promise<PrettierConfigWithOverrides[]> => {
const config = (await getPrettierConfigs(folderPath, filesNames))?.[0];
const folderPathUp = path.dirname(folderPath);
Expand All @@ -119,27 +159,9 @@ const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: stri
const getPrettierConfigResolved = async (filePath: string, filesNames: string[]): Promise<PrettierConfig> => {
const folderPath = path.dirname(filePath);
const configs = await getPrettierConfigsUp(folderPath, filesNames);
let resolved: PrettierConfig = {};

for (let ci = 0, cl = configs.length; ci < cl; ci++) {
const config = configs[ci];
const formatOptions = omit(config, ["overrides"]);
resolved = ci ? { ...resolved, ...formatOptions } : formatOptions;

const overrides = config.overrides;
if (overrides) {
for (let oi = 0, ol = overrides.length; oi < ol; oi++) {
const override = overrides[oi];
const filePathRelative = fastRelativeChildPath(override.folder, filePath);
if (!filePathRelative) continue;
if (!zeptomatch(override.filesPositive, filePathRelative)) continue;
if (zeptomatch(override.filesNegative, filePathRelative)) continue;
resolved = { ...resolved, ...override.options };
}
}
}

return resolved;
const resolver = getPrettierConfigResolver(configs);
return resolver(filePath);
};

export { Loaders, File2Loader, Ext2Loader, getPrettierConfig, getPrettierConfigsMap, getPrettierConfigsUp, getPrettierConfigResolved };
export { Loaders, File2Loader, Ext2Loader, getPrettierConfig, getPrettierConfigsMap, getPrettierConfigBys, getPrettierConfigsUp, getPrettierConfigResolved };
11 changes: 8 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import process from "node:process";
import Cache from "./cache.js";
import { getEditorConfigsMap, getEditorConfigResolved, getEditorConfigFormatOptions } from "./config_editorconfig.js";
import { getIgnoresContentMap, getIgnoreBys, getIgnoreResolved } from "./config_ignore.js";
import { Loaders, File2Loader, getPrettierConfigsMap, getPrettierConfigResolved } from "./config_prettier.js";
import { Loaders, File2Loader, getPrettierConfigsMap, getPrettierConfigBys, getPrettierConfigResolved } from "./config_prettier.js";
import { PRETTIER_VERSION, CLI_VERSION } from "./constants.js";
import Known from "./known.js";
import Logger from "./logger.js";
Expand Down Expand Up @@ -109,7 +109,8 @@ async function runGlobs(options: Options, pluginsDefaultOptions: PluginsOptions,
const prettierManualFilesPaths = prettierManualFilesNames.map((fileName) => path.resolve(fileName));
const prettierManualFilesContents = await Promise.all(prettierManualFilesPaths.map((filePath) => fs.readFile(filePath, "utf8")));
const prettierManualConfigs = await Promise.all(prettierManualFilesPaths.map(Loaders.auto));
const prettierManualConfig = prettierManualConfigs.length ? Object.assign({}, ...prettierManualConfigs) : undefined;
const prettierManualFoldersPaths = prettierManualFilesPaths.map(path.dirname);
const prettierManualConfig = getPrettierConfigBys(prettierManualFoldersPaths, prettierManualConfigs);

const cliContextConfig = options.contextOptions;
const cliFormatConfig = options.formatOptions;
Expand All @@ -130,7 +131,11 @@ async function runGlobs(options: Options, pluginsDefaultOptions: PluginsOptions,
if (!isForceIncluded && isExcluded) return;
const getFormatOptions = async (): Promise<FormatOptions> => {
const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(filePath, editorConfigNames)) : {};
const prettierConfig = prettierManualConfig || (options.config ? await getPrettierConfigResolved(filePath, prettierConfigNames) : {});
const prettierConfig = prettierManualConfig
? prettierManualConfig(filePath)
: options.config
? await getPrettierConfigResolved(filePath, prettierConfigNames)
: {};
const formatOptions = { ...editorConfig, ...prettierConfig, ...options.formatOptions };
return formatOptions;
};
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ type Prettier = typeof import("./prettier_serial.js");

type PrettierConfig = FormatOptions;

type PrettierConfigResolver = (filePath: string) => PrettierConfig;

type PrettierConfigWithOverrides = PrettierConfig & {
overrides?: {
filesPositive: string[];
Expand All @@ -108,6 +110,7 @@ export type {
PluginsOptions,
Prettier,
PrettierConfig,
PrettierConfigResolver,
PrettierConfigWithOverrides,
PrettierPlugin,
PromiseMaybe,
Expand Down