From d70f7b989bdaf26cfcf2800a1dd1aced5d44f486 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 29 Mar 2023 17:48:29 +0800 Subject: [PATCH] Fix inconsistent option normalization (#14622) --- src/cli/cli-options.evaluate.js | 245 +++++++++++++++++ src/cli/constants.evaluate.js | 255 +----------------- src/cli/options/get-context-options.js | 16 +- src/cli/prettier-internal.js | 3 +- src/cli/utils.js | 3 +- ...-options.js => common-options.evaluate.js} | 0 src/index.js | 12 +- src/language-css/options.js | 2 +- src/language-graphql/options.js | 2 +- src/language-html/options.js | 2 +- src/language-js/options.js | 2 +- src/language-markdown/options.js | 2 +- src/language-yaml/options.js | 2 +- src/main/core-options.evaluate.js | 26 +- src/main/option-categories.js | 7 + src/main/support.js | 62 +++-- src/utils/arrayify.js | 7 - tests/integration/__tests__/bundle.js | 6 +- 18 files changed, 330 insertions(+), 324 deletions(-) create mode 100644 src/cli/cli-options.evaluate.js rename src/common/{common-options.js => common-options.evaluate.js} (100%) create mode 100644 src/main/option-categories.js delete mode 100644 src/utils/arrayify.js diff --git a/src/cli/cli-options.evaluate.js b/src/cli/cli-options.evaluate.js new file mode 100644 index 000000000..1b5eb5726 --- /dev/null +++ b/src/cli/cli-options.evaluate.js @@ -0,0 +1,245 @@ +import { outdent } from "outdent"; +import { optionCategories } from "./prettier-internal.js"; + +/** + * { + * [optionName]: { + * // The type of the option. For 'choice', see also `choices` below. + * // 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: "boolean" | "choice" | "int" | string; + * + * // Default value to be passed to the minimist option `default`. + * default?: any; + * + * // Alias name to be passed to the minimist option `alias`. + * alias?: string; + * + * // For grouping options by category in --help. + * category?: string; + * + * // Description to be displayed in --help. If omitted, the option won't be + * // shown at all in --help (but see also `oppositeDescription` below). + * description?: string; + * + * // Description for `--no-${name}` to be displayed in --help. If omitted, + * // `--no-${name}` won't be shown. + * oppositeDescription?: string; + * + * // Indicate if this option is simply passed to the API. + * // true: use camelified name as the API option name. + * // string: use this value as the API option name. + * forwardToApi?: boolean | string; + * + * // Indicate that a CLI flag should be an array when forwarded to the API. + * array?: boolean; + * + * // Specify available choices for validation. They will also be displayed + * // in --help as . + * // Use an object instead of a string if a choice is deprecated and should + * // be treated as `redirect` instead, or if you'd like to add description for + * // the choice. + * choices?: Array< + * | string + * | { value: string, description?: string, deprecated?: boolean, redirect?: string } + * >; + * + * // If the option has a value that is an exception to the regular value + * // constraints, indicate that value here (or use a function for more + * // flexibility). + * exception?: ((value: any) => boolean); + * + * // 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; + * } + * } + * + * Note: The options below are sorted alphabetically. + */ +/* eslint sort-keys: "error" */ +const options = { + cache: { + default: false, + description: "Only format changed files. Cannot use with --stdin-filepath.", + type: "boolean", + }, + cacheLocation: { + description: "Path to the cache file.", + type: "path", + }, + cacheStrategy: { + choices: [ + { + description: "Use the file metadata such as timestamps as cache keys", + value: "metadata", + }, + { + description: "Use the file content as cache keys", + value: "content", + }, + ], + description: "Strategy for the cache to use for detecting changed files.", + type: "choice", + }, + check: { + alias: "c", + category: optionCategories.CATEGORY_OUTPUT, + description: outdent` + Check if the given files are formatted, print a human-friendly summary + message and paths to unformatted files (see also --list-different). + `, + type: "boolean", + }, + color: { + // The supports-color package (a sub sub dependency) looks directly at + // `process.argv` for `--no-color` and such-like options. The reason it is + // listed here is to avoid "Ignored unknown option: --no-color" warnings. + // See https://github.com/chalk/supports-color/#info for more information. + default: true, + description: "Colorize error messages.", + oppositeDescription: "Do not colorize error messages.", + type: "boolean", + }, + config: { + category: optionCategories.CATEGORY_CONFIG, + description: + "Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).", + exception: (value) => value === false, + oppositeDescription: "Do not look for a configuration file.", + type: "path", + }, + configPrecedence: { + category: optionCategories.CATEGORY_CONFIG, + choices: [ + { + description: "CLI options take precedence over config file", + value: "cli-override", + }, + { + description: "Config file take precedence over CLI options", + value: "file-override", + }, + { + description: outdent` + If a config file is found will evaluate it and ignore other CLI options. + If no config file is found CLI options will evaluate as normal. + `, + value: "prefer-file", + }, + ], + default: "cli-override", + description: + "Define in which order config files and CLI options should be evaluated.", + type: "choice", + }, + debugBenchmark: { + // Run the formatting benchmarks. Requires 'benchmark' module to be installed. + type: "boolean", + }, + debugCheck: { + // Run the formatting once again on the formatted output, throw if different. + type: "boolean", + }, + debugPrintAst: { + type: "boolean", + }, + debugPrintComments: { + type: "boolean", + }, + debugPrintDoc: { + type: "boolean", + }, + debugRepeat: { + // Repeat the formatting a few times and measure the average duration. + default: 0, + type: "int", + }, + editorconfig: { + category: optionCategories.CATEGORY_CONFIG, + default: true, + description: "Take .editorconfig into account when parsing configuration.", + oppositeDescription: + "Don't take .editorconfig into account when parsing configuration.", + type: "boolean", + }, + errorOnUnmatchedPattern: { + oppositeDescription: "Prevent errors when pattern is unmatched.", + type: "boolean", + }, + fileInfo: { + description: outdent` + Extract the following info (as JSON) for a given file path. Reported fields: + * ignored (boolean) - true if file path is filtered by --ignore-path + * inferredParser (string | null) - name of parser inferred from file path + `, + type: "path", + }, + findConfigPath: { + category: optionCategories.CATEGORY_CONFIG, + description: + "Find and print the path to a configuration file for the given input file.", + type: "path", + }, + help: { + alias: "h", + description: outdent` + Show CLI usage, or details about the given flag. + Example: --help write + `, + exception: (value) => value === "", + type: "flag", + }, + ignorePath: { + category: optionCategories.CATEGORY_CONFIG, + default: ".prettierignore", + description: "Path to a file with patterns describing files to ignore.", + type: "path", + }, + ignoreUnknown: { + alias: "u", + description: "Ignore unknown files.", + type: "boolean", + }, + listDifferent: { + alias: "l", + category: optionCategories.CATEGORY_OUTPUT, + description: + "Print the names of files that are different from Prettier's formatting (see also --check).", + type: "boolean", + }, + logLevel: { + choices: ["silent", "error", "warn", "log", "debug"], + default: "log", + description: "What level of logs to report.", + type: "choice", + }, + pluginSearch: { + oppositeDescription: "Disable plugin autoloading.", + type: "boolean", + }, + supportInfo: { + description: "Print support information as JSON.", + type: "boolean", + }, + version: { + alias: "v", + description: "Print Prettier version.", + type: "boolean", + }, + withNodeModules: { + category: optionCategories.CATEGORY_CONFIG, + description: "Process files inside 'node_modules' directory.", + type: "boolean", + }, + write: { + alias: "w", + category: optionCategories.CATEGORY_OUTPUT, + description: "Edit files in-place. (Beware!)", + type: "boolean", + }, +}; + +export default options; diff --git a/src/cli/constants.evaluate.js b/src/cli/constants.evaluate.js index 8206ee898..863c5a1af 100644 --- a/src/cli/constants.evaluate.js +++ b/src/cli/constants.evaluate.js @@ -1,255 +1,14 @@ import { outdent } from "outdent"; -import { coreOptions } from "./prettier-internal.js"; +import { optionCategories } from "./prettier-internal.js"; const categoryOrder = [ - coreOptions.CATEGORY_OUTPUT, - coreOptions.CATEGORY_FORMAT, - coreOptions.CATEGORY_CONFIG, - coreOptions.CATEGORY_EDITOR, - coreOptions.CATEGORY_OTHER, + optionCategories.CATEGORY_OUTPUT, + optionCategories.CATEGORY_FORMAT, + optionCategories.CATEGORY_CONFIG, + optionCategories.CATEGORY_EDITOR, + optionCategories.CATEGORY_OTHER, ]; -/** - * { - * [optionName]: { - * // The type of the option. For 'choice', see also `choices` below. - * // 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: "boolean" | "choice" | "int" | string; - * - * // Default value to be passed to the minimist option `default`. - * default?: any; - * - * // Alias name to be passed to the minimist option `alias`. - * alias?: string; - * - * // For grouping options by category in --help. - * category?: string; - * - * // Description to be displayed in --help. If omitted, the option won't be - * // shown at all in --help (but see also `oppositeDescription` below). - * description?: string; - * - * // Description for `--no-${name}` to be displayed in --help. If omitted, - * // `--no-${name}` won't be shown. - * oppositeDescription?: string; - * - * // Indicate if this option is simply passed to the API. - * // true: use camelified name as the API option name. - * // string: use this value as the API option name. - * forwardToApi?: boolean | string; - * - * // Indicate that a CLI flag should be an array when forwarded to the API. - * array?: boolean; - * - * // Specify available choices for validation. They will also be displayed - * // in --help as . - * // Use an object instead of a string if a choice is deprecated and should - * // be treated as `redirect` instead, or if you'd like to add description for - * // the choice. - * choices?: Array< - * | string - * | { value: string, description?: string, deprecated?: boolean, redirect?: string } - * >; - * - * // If the option has a value that is an exception to the regular value - * // constraints, indicate that value here (or use a function for more - * // flexibility). - * exception?: ((value: any) => boolean); - * - * // 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; - * } - * } - * - * Note: The options below are sorted alphabetically. - */ -/* eslint sort-keys: "error" */ -const options = { - cache: { - default: false, - description: "Only format changed files. Cannot use with --stdin-filepath.", - type: "boolean", - }, - "cache-location": { - description: "Path to the cache file.", - type: "path", - }, - "cache-strategy": { - choices: [ - { - description: "Use the file metadata such as timestamps as cache keys", - value: "metadata", - }, - { - description: "Use the file content as cache keys", - value: "content", - }, - ], - description: "Strategy for the cache to use for detecting changed files.", - type: "choice", - }, - check: { - alias: "c", - category: coreOptions.CATEGORY_OUTPUT, - description: outdent` - Check if the given files are formatted, print a human-friendly summary - message and paths to unformatted files (see also --list-different). - `, - type: "boolean", - }, - color: { - // The supports-color package (a sub sub dependency) looks directly at - // `process.argv` for `--no-color` and such-like options. The reason it is - // listed here is to avoid "Ignored unknown option: --no-color" warnings. - // See https://github.com/chalk/supports-color/#info for more information. - default: true, - description: "Colorize error messages.", - oppositeDescription: "Do not colorize error messages.", - type: "boolean", - }, - config: { - category: coreOptions.CATEGORY_CONFIG, - description: - "Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).", - exception: (value) => value === false, - oppositeDescription: "Do not look for a configuration file.", - type: "path", - }, - "config-precedence": { - category: coreOptions.CATEGORY_CONFIG, - choices: [ - { - description: "CLI options take precedence over config file", - value: "cli-override", - }, - { - description: "Config file take precedence over CLI options", - value: "file-override", - }, - { - description: outdent` - If a config file is found will evaluate it and ignore other CLI options. - If no config file is found CLI options will evaluate as normal. - `, - value: "prefer-file", - }, - ], - default: "cli-override", - description: - "Define in which order config files and CLI options should be evaluated.", - type: "choice", - }, - "debug-benchmark": { - // Run the formatting benchmarks. Requires 'benchmark' module to be installed. - type: "boolean", - }, - "debug-check": { - // Run the formatting once again on the formatted output, throw if different. - type: "boolean", - }, - "debug-print-ast": { - type: "boolean", - }, - "debug-print-comments": { - type: "boolean", - }, - "debug-print-doc": { - type: "boolean", - }, - "debug-repeat": { - // Repeat the formatting a few times and measure the average duration. - default: 0, - type: "int", - }, - editorconfig: { - category: coreOptions.CATEGORY_CONFIG, - default: true, - description: "Take .editorconfig into account when parsing configuration.", - oppositeDescription: - "Don't take .editorconfig into account when parsing configuration.", - type: "boolean", - }, - "error-on-unmatched-pattern": { - oppositeDescription: "Prevent errors when pattern is unmatched.", - type: "boolean", - }, - "file-info": { - description: outdent` - Extract the following info (as JSON) for a given file path. Reported fields: - * ignored (boolean) - true if file path is filtered by --ignore-path - * inferredParser (string | null) - name of parser inferred from file path - `, - type: "path", - }, - "find-config-path": { - category: coreOptions.CATEGORY_CONFIG, - description: - "Find and print the path to a configuration file for the given input file.", - type: "path", - }, - help: { - alias: "h", - description: outdent` - Show CLI usage, or details about the given flag. - Example: --help write - `, - exception: (value) => value === "", - type: "flag", - }, - "ignore-path": { - category: coreOptions.CATEGORY_CONFIG, - default: ".prettierignore", - description: "Path to a file with patterns describing files to ignore.", - type: "path", - }, - "ignore-unknown": { - alias: "u", - description: "Ignore unknown files.", - type: "boolean", - }, - "list-different": { - alias: "l", - category: coreOptions.CATEGORY_OUTPUT, - description: - "Print the names of files that are different from Prettier's formatting (see also --check).", - type: "boolean", - }, - "log-level": { - choices: ["silent", "error", "warn", "log", "debug"], - default: "log", - description: "What level of logs to report.", - type: "choice", - }, - "plugin-search": { - oppositeDescription: "Disable plugin autoloading.", - type: "boolean", - }, - "support-info": { - description: "Print support information as JSON.", - type: "boolean", - }, - version: { - alias: "v", - description: "Print Prettier version.", - type: "boolean", - }, - "with-node-modules": { - category: coreOptions.CATEGORY_CONFIG, - description: "Process files inside 'node_modules' directory.", - type: "boolean", - }, - write: { - alias: "w", - category: coreOptions.CATEGORY_OUTPUT, - description: "Edit files in-place. (Beware!)", - type: "boolean", - }, -}; - const usageSummary = outdent` Usage: prettier [options] [file/dir/glob ...] @@ -257,4 +16,4 @@ const usageSummary = outdent` Stdin is read if it is piped to Prettier and no files are given. `; -export { categoryOrder, options, usageSummary }; +export { categoryOrder, usageSummary }; diff --git a/src/cli/options/get-context-options.js b/src/cli/options/get-context-options.js index c5af24e6d..694c4022a 100644 --- a/src/cli/options/get-context-options.js +++ b/src/cli/options/get-context-options.js @@ -1,22 +1,21 @@ import dashify from "dashify"; import { getSupportInfo } from "../../index.js"; import { - coreOptions, + optionCategories, getSupportInfoWithoutPlugins, + normalizeOptionSettings, } from "../prettier-internal.js"; -import { options as cliOptionsMap } from "../constants.evaluate.js"; -import { arrayify } from "../utils.js"; +import cliOptions from "../cli-options.evaluate.js"; -const detailedCliOptions = arrayify(cliOptionsMap, "name").map((option) => +const detailedCliOptions = normalizeOptionSettings(cliOptions).map((option) => normalizeDetailedOption(option) ); function apiOptionToCliOption(apiOption) { const cliOption = { ...apiOption, - name: apiOption.cliName || dashify(apiOption.name), - description: apiOption.cliDescription || apiOption.description, - category: apiOption.cliCategory || coreOptions.CATEGORY_FORMAT, + description: apiOption.cliDescription ?? apiOption.description, + category: apiOption.cliCategory ?? optionCategories.CATEGORY_FORMAT, forwardToApi: apiOption.name, }; @@ -34,8 +33,9 @@ function apiOptionToCliOption(apiOption) { function normalizeDetailedOption(option) { return { - category: coreOptions.CATEGORY_OTHER, + category: optionCategories.CATEGORY_OTHER, ...option, + name: option.cliName ?? dashify(option.name), choices: option.choices?.map((choice) => { const newChoice = { description: "", diff --git a/src/cli/prettier-internal.js b/src/cli/prettier-internal.js index 27446b849..3599a89d6 100644 --- a/src/cli/prettier-internal.js +++ b/src/cli/prettier-internal.js @@ -3,11 +3,12 @@ import { __internal as sharedWithCli } from "../index.js"; export const { errors, - coreOptions, + optionCategories, createIsIgnoredFunction, formatOptionsHiddenDefaults, normalizeOptions, getSupportInfoWithoutPlugins, + normalizeOptionSettings, vnopts, fastGlob, } = sharedWithCli; diff --git a/src/cli/utils.js b/src/cli/utils.js index 08d43adc0..199b5f316 100644 --- a/src/cli/utils.js +++ b/src/cli/utils.js @@ -89,8 +89,7 @@ const normalizeToPosix = ? (filepath) => filepath.replaceAll("\\", "/") : (filepath) => filepath; -export const { arrayify, isNonEmptyArray, partition, omit } = - sharedWithCli.utils; +export const { isNonEmptyArray, partition, omit } = sharedWithCli.utils; export { printToScreen, groupBy, diff --git a/src/common/common-options.js b/src/common/common-options.evaluate.js similarity index 100% rename from src/common/common-options.js rename to src/common/common-options.evaluate.js diff --git a/src/index.js b/src/index.js index 4a29a704d..7cd0b4eea 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,10 @@ import vnopts from "vnopts"; import fastGlob from "fast-glob"; import * as core from "./main/core.js"; -import { getSupportInfo as getSupportInfoWithoutPlugins } from "./main/support.js"; +import { + getSupportInfo as getSupportInfoWithoutPlugins, + normalizeOptionSettings, +} from "./main/support.js"; import getFileInfoWithoutPlugins from "./common/get-file-info.js"; import { loadBuiltinPlugins, @@ -15,11 +18,10 @@ import { clearCache as clearConfigCache, } from "./config/resolve-config.js"; import * as errors from "./common/errors.js"; -import * as coreOptions from "./main/core-options.evaluate.js"; +import * as optionCategories from "./main/option-categories.js"; import { createIsIgnoredFunction } from "./utils/ignore.js"; import { formatOptionsHiddenDefaults } from "./main/normalize-format-options.js"; import normalizeOptions from "./main/normalize-options.js"; -import arrayify from "./utils/arrayify.js"; import partition from "./utils/partition.js"; import isNonEmptyArray from "./utils/is-non-empty-array.js"; import omit from "./utils/object-omit.js"; @@ -84,15 +86,15 @@ const getSupportInfo = withPlugins(getSupportInfoWithoutPlugins, 0); // Internal shared with cli const sharedWithCli = { errors, - coreOptions, + optionCategories, createIsIgnoredFunction, formatOptionsHiddenDefaults, normalizeOptions, getSupportInfoWithoutPlugins, + normalizeOptionSettings, vnopts, fastGlob, utils: { - arrayify, isNonEmptyArray, partition, omit, diff --git a/src/language-css/options.js b/src/language-css/options.js index 38f415403..02a5e1935 100644 --- a/src/language-css/options.js +++ b/src/language-css/options.js @@ -1,4 +1,4 @@ -import commonOptions from "../common/common-options.js"; +import commonOptions from "../common/common-options.evaluate.js"; // format based on https://github.com/prettier/prettier/blob/main/src/main/core-options.evaluate.js const options = { diff --git a/src/language-graphql/options.js b/src/language-graphql/options.js index 7e9a9aa14..dc3314cef 100644 --- a/src/language-graphql/options.js +++ b/src/language-graphql/options.js @@ -1,4 +1,4 @@ -import commonOptions from "../common/common-options.js"; +import commonOptions from "../common/common-options.evaluate.js"; // format based on https://github.com/prettier/prettier/blob/main/src/main/core-options.evaluate.js const options = { diff --git a/src/language-html/options.js b/src/language-html/options.js index 0e99808c1..1fc7a1a91 100644 --- a/src/language-html/options.js +++ b/src/language-html/options.js @@ -1,4 +1,4 @@ -import commonOptions from "../common/common-options.js"; +import commonOptions from "../common/common-options.evaluate.js"; const CATEGORY_HTML = "HTML"; diff --git a/src/language-js/options.js b/src/language-js/options.js index e714a620a..403357ab1 100644 --- a/src/language-js/options.js +++ b/src/language-js/options.js @@ -1,4 +1,4 @@ -import commonOptions from "../common/common-options.js"; +import commonOptions from "../common/common-options.evaluate.js"; const CATEGORY_JAVASCRIPT = "JavaScript"; diff --git a/src/language-markdown/options.js b/src/language-markdown/options.js index ccdb65a8a..6d349bb2d 100644 --- a/src/language-markdown/options.js +++ b/src/language-markdown/options.js @@ -1,4 +1,4 @@ -import commonOptions from "../common/common-options.js"; +import commonOptions from "../common/common-options.evaluate.js"; // format based on https://github.com/prettier/prettier/blob/main/src/main/core-options.evaluate.js const options = { diff --git a/src/language-yaml/options.js b/src/language-yaml/options.js index 322973dfd..0104457f5 100644 --- a/src/language-yaml/options.js +++ b/src/language-yaml/options.js @@ -1,4 +1,4 @@ -import commonOptions from "../common/common-options.js"; +import commonOptions from "../common/common-options.evaluate.js"; // format based on https://github.com/prettier/prettier/blob/main/src/main/core-options.evaluate.js const options = { diff --git a/src/main/core-options.evaluate.js b/src/main/core-options.evaluate.js index 5a487e499..b80e809a7 100644 --- a/src/main/core-options.evaluate.js +++ b/src/main/core-options.evaluate.js @@ -1,12 +1,11 @@ import { outdent } from "outdent"; - -const CATEGORY_CONFIG = "Config"; -const CATEGORY_EDITOR = "Editor"; -const CATEGORY_FORMAT = "Format"; -const CATEGORY_OTHER = "Other"; -const CATEGORY_OUTPUT = "Output"; -const CATEGORY_GLOBAL = "Global"; -const CATEGORY_SPECIAL = "Special"; +import { + CATEGORY_CONFIG, + CATEGORY_EDITOR, + CATEGORY_OTHER, + CATEGORY_GLOBAL, + CATEGORY_SPECIAL, +} from "./option-categories.js"; /** * @typedef {Object} OptionInfo @@ -235,13 +234,4 @@ const options = { }, }; -export { - CATEGORY_CONFIG, - CATEGORY_EDITOR, - CATEGORY_FORMAT, - CATEGORY_OTHER, - CATEGORY_OUTPUT, - CATEGORY_GLOBAL, - CATEGORY_SPECIAL, - options, -}; +export default options; diff --git a/src/main/option-categories.js b/src/main/option-categories.js new file mode 100644 index 000000000..afd2deb47 --- /dev/null +++ b/src/main/option-categories.js @@ -0,0 +1,7 @@ +export const CATEGORY_CONFIG = "Config"; +export const CATEGORY_EDITOR = "Editor"; +export const CATEGORY_FORMAT = "Format"; +export const CATEGORY_OTHER = "Other"; +export const CATEGORY_OUTPUT = "Output"; +export const CATEGORY_GLOBAL = "Global"; +export const CATEGORY_SPECIAL = "Special"; diff --git a/src/main/support.js b/src/main/support.js index 31e550d51..923e04c54 100644 --- a/src/main/support.js +++ b/src/main/support.js @@ -1,4 +1,4 @@ -import { options as coreOptions } from "./core-options.evaluate.js"; +import coreOptions from "./core-options.evaluate.js"; /** * @typedef {import("./core-options.evaluate.js").OptionInfo} OptionInfo @@ -18,32 +18,24 @@ function getSupportInfo({ plugins = [], showDeprecated = false } = {}) { const languages = plugins.flatMap((plugin) => plugin.languages ?? []); const options = []; - for (const [name, originalOption] of Object.entries( + for (const option of normalizeOptionSettings( Object.assign({}, ...plugins.map(({ options }) => options), coreOptions) )) { - if (!showDeprecated && originalOption.deprecated) { + if (!showDeprecated && option.deprecated) { continue; } - const option = { name, ...originalOption }; - - // This work this way because we used support `[{value: [], since: '0.0.0'}]` - if (Array.isArray(option.default)) { - option.default = option.default.at(-1).value; - } - if (Array.isArray(option.choices)) { - const choices = showDeprecated - ? [...option.choices] - : option.choices.filter((choice) => !choice.deprecated); - - if (option.name === "parser") { - choices.push( - ...collectParsersFromLanguages(choices, languages, plugins) - ); + if (!showDeprecated) { + option.choices = option.choices.filter((choice) => !choice.deprecated); } - option.choices = choices; + if (option.name === "parser") { + option.choices = [ + ...option.choices, + ...collectParsersFromLanguages(option.choices, languages, plugins), + ]; + } } option.pluginDefaults = Object.fromEntries( @@ -63,19 +55,39 @@ function* collectParsersFromLanguages(parserChoices, languages, plugins) { for (const language of languages) { if (language.parsers) { - for (const value of language.parsers) { - if (!existingParsers.has(value)) { - existingParsers.add(value); - const plugin = plugins.find((plugin) => plugin.parsers?.[value]); + for (const parserName of language.parsers) { + if (!existingParsers.has(parserName)) { + existingParsers.add(parserName); + const plugin = plugins.find( + (plugin) => + plugin.parsers && Object.hasOwn(plugin.parsers, parserName) + ); + let description = language.name; if (plugin?.name) { description += ` (plugin: ${plugin.name})`; } - yield { value, description }; + yield { value: parserName, description }; } } } } } -export { getSupportInfo }; +function normalizeOptionSettings(settings) { + const options = []; + for (const [name, originalOption] of Object.entries(settings)) { + const option = { name, ...originalOption }; + + // This work this way because we used support `[{value: [], since: '0.0.0'}]` + if (Array.isArray(option.default)) { + option.default = option.default.at(-1).value; + } + + options.push(option); + } + + return options; +} + +export { getSupportInfo, normalizeOptionSettings }; diff --git a/src/utils/arrayify.js b/src/utils/arrayify.js deleted file mode 100644 index 45e776357..000000000 --- a/src/utils/arrayify.js +++ /dev/null @@ -1,7 +0,0 @@ -const arrayify = (object, keyName) => - Object.entries(object).map(([key, value]) => ({ - [keyName]: key, - ...value, - })); - -export default arrayify; diff --git a/tests/integration/__tests__/bundle.js b/tests/integration/__tests__/bundle.js index de20a7e9b..e83fe0a2f 100644 --- a/tests/integration/__tests__/bundle.js +++ b/tests/integration/__tests__/bundle.js @@ -5,7 +5,7 @@ import fastGlob from "fast-glob"; import { projectRoot } from "../env.js"; import prettier from "../../config/prettier-entry.js"; import createSandBox from "../../config/utils/create-sandbox.cjs"; -import * as coreOptions from "../../../src/main/core-options.evaluate.js"; +import coreOptions from "../../../src/main/core-options.evaluate.js"; import codeSamples from "../../../website/playground/codeSamples.mjs"; import jestPathSerializer from "../path-serializer.js"; @@ -13,9 +13,7 @@ const { require, importModule } = createEsmUtils(import.meta); expect.addSnapshotSerializer(jestPathSerializer); -const parserNames = coreOptions.options.parser.choices.map( - ({ value }) => value -); +const parserNames = coreOptions.parser.choices.map(({ value }) => value); const distDirectory = path.join(projectRoot, "dist"); // Files including U+FFEE can't load in Chrome Extension