Skip to content

Commit 114c874

Browse files
authored
fix: retain unknown keys in overrides (#91)
An alternative to #73. Closes #70. This updates `normalizeFormatOptions` to iterate over own keys rather than specific `in` checks. This way, we retain extra keys while still validating the known ones. Doing it here means overrides and configs alike both retain keys.
1 parent acc89bb commit 114c874

1 file changed

Lines changed: 45 additions & 159 deletions

File tree

src/utils.ts

Lines changed: 45 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import zeptomatch from "zeptomatch";
1616
import zeptomatchEscape from "zeptomatch-escape";
1717
import zeptomatchIsStatic from "zeptomatch-is-static";
1818
import type { ContextOptions, FormatOptions, FunctionMaybe, Key, LogLevel, Options, PrettierConfigWithOverrides, PrettierPlugin } from "./types.js";
19-
import type { PluginsOptions, PromiseMaybe } from "./types.js";
19+
import type { PluginsOptions } from "./types.js";
2020

2121
function castArray<T>(value: T | T[]): T[] {
2222
return isArray(value) ? value : [value];
@@ -442,93 +442,56 @@ function normalizeContextOptions(options: unknown): ContextOptions {
442442
return contextOptions;
443443
}
444444

445+
const formatOptionsValidators: Record<string, (value: unknown) => unknown> = {
446+
experimentalOperatorPosition: (value) => (value === "start" || value === "end" ? value : undefined),
447+
experimentalTernaries: (value) => (isBoolean(value) ? value : undefined),
448+
arrowParens: (value) => (value === "avoid" || value === "always" ? value : undefined),
449+
bracketSameLine: (value) => (isBoolean(value) ? value : undefined),
450+
bracketSpacing: (value) => (isBoolean(value) ? value : undefined),
451+
embeddedLanguageFormatting: (value) => (value === "auto" || value === "off" ? value : undefined),
452+
endOfLine: (value) => (value === "lf" || value === "crlf" || value === "cr" || value === "auto" ? value : undefined),
453+
htmlWhitespaceSensitivity: (value) => (value === "css" || value === "strict" || value === "ignore" ? value : undefined),
454+
insertPragma: (value) => (isBoolean(value) ? value : undefined),
455+
jsxSingleQuote: (value) => (isBoolean(value) ? value : undefined),
456+
objectWrap: (value) => (value === "preserve" || value === "collapse" ? value : undefined),
457+
// New parsers that we don't know about can be added by plugins
458+
parser: (value) => (isString(value) ? value : undefined),
459+
printWidth: (value) => {
460+
const number = Number(value);
461+
return isInteger(number) && number >= 0 ? number : undefined;
462+
},
463+
proseWrap: (value) => (value === "always" || value === "never" || value === "preserve" ? value : undefined),
464+
quoteProps: (value) => (value === "as-needed" || value === "consistent" || value === "preserve" ? value : undefined),
465+
requirePragma: (value) => (isBoolean(value) ? value : undefined),
466+
semi: (value) => (isBoolean(value) ? value : undefined),
467+
singleAttributePerLine: (value) => (isBoolean(value) ? value : undefined),
468+
singleQuote: (value) => (isBoolean(value) ? value : undefined),
469+
tabWidth: (value) => {
470+
const number = Number(value);
471+
return isInteger(number) && number >= 0 ? number : undefined;
472+
},
473+
trailingComma: (value) => (value === "all" || value === "es5" || value === "none" ? value : undefined),
474+
useTabs: (value) => (isBoolean(value) ? value : undefined),
475+
vueIndentScriptAndStyle: (value) => (isBoolean(value) ? value : undefined),
476+
};
477+
445478
function normalizeFormatOptions(options: unknown): FormatOptions {
446479
if (!isObject(options)) exit("Invalid options object");
447480

448481
const formatOptions: FormatOptions = {};
449482

450-
if ("experimentalOperatorPosition" in options) {
451-
const value = options.experimentalOperatorPosition;
452-
if (value === "start" || value === "end") {
453-
formatOptions.experimentalOperatorPosition = value;
454-
}
455-
}
456-
457-
if ("experimentalTernaries" in options) {
458-
const value = options.experimentalTernaries;
459-
if (isBoolean(value)) {
460-
formatOptions.experimentalTernaries = value;
461-
}
462-
}
463-
464-
if ("arrowParens" in options) {
465-
const value = options.arrowParens;
466-
if (value === "avoid" || value === "always") {
467-
formatOptions.arrowParens = value;
468-
}
469-
}
470-
471-
if ("bracketSameLine" in options) {
472-
const value = options.bracketSameLine;
473-
if (isBoolean(value)) {
474-
formatOptions.bracketSameLine = value;
475-
}
476-
}
477-
478-
if ("bracketSpacing" in options) {
479-
const value = options.bracketSpacing;
480-
if (isBoolean(value)) {
481-
formatOptions.bracketSpacing = value;
482-
}
483-
}
484-
485-
if ("embeddedLanguageFormatting" in options) {
486-
const value = options.embeddedLanguageFormatting;
487-
if (value === "auto" || value === "off") {
488-
formatOptions.embeddedLanguageFormatting = value;
489-
}
490-
}
491-
492-
if ("endOfLine" in options) {
493-
const value = options.endOfLine;
494-
if (value === "lf" || value === "crlf" || value === "cr" || value === "auto") {
495-
formatOptions.endOfLine = value;
496-
}
497-
}
498-
499-
if ("htmlWhitespaceSensitivity" in options) {
500-
const value = options.htmlWhitespaceSensitivity;
501-
if (value === "css" || value === "strict" || value === "ignore") {
502-
formatOptions.htmlWhitespaceSensitivity = value;
503-
}
504-
}
505-
506-
if ("insertPragma" in options) {
507-
const value = options.insertPragma;
508-
if (isBoolean(value)) {
509-
formatOptions.insertPragma = value;
510-
}
511-
}
512-
513-
if ("jsxSingleQuote" in options) {
514-
const value = options.jsxSingleQuote;
515-
if (isBoolean(value)) {
516-
formatOptions.jsxSingleQuote = value;
517-
}
518-
}
483+
for (const [key, value] of Object.entries(options)) {
484+
// Handled separately below, since "plugin" and "plugins" both map to "plugins"
485+
if (key === "plugin" || key === "plugins") continue;
519486

520-
if ("objectWrap" in options) {
521-
const value = options.objectWrap;
522-
if (value === "preserve" || value === "collapse") {
523-
formatOptions.objectWrap = value;
524-
}
525-
}
526-
527-
if ("parser" in options) {
528-
const value = options.parser;
529-
if (isString(value)) {
530-
// New parsers that we don't about can be added by plugins
531-
formatOptions.parser = value as FormatOptions["parser"];
487+
const validator = formatOptionsValidators[key];
488+
if (validator) {
489+
const normalized = validator(value);
490+
if (!isUndefined(normalized)) {
491+
formatOptions[key] = normalized;
492+
}
493+
} else {
494+
formatOptions[key] = value;
532495
}
533496
}
534497

@@ -544,83 +507,6 @@ function normalizeFormatOptions(options: unknown): FormatOptions {
544507
}
545508
}
546509

547-
if ("printWidth" in options) {
548-
const value = Number(options.printWidth);
549-
if (isInteger(value) && value >= 0) {
550-
formatOptions.printWidth = value;
551-
}
552-
}
553-
554-
if ("proseWrap" in options) {
555-
const value = options.proseWrap;
556-
if (value === "always" || value === "never" || value === "preserve") {
557-
formatOptions.proseWrap = value;
558-
}
559-
}
560-
561-
if ("quoteProps" in options) {
562-
const value = options.quoteProps;
563-
if (value === "as-needed" || value === "consistent" || value === "preserve") {
564-
formatOptions.quoteProps = value;
565-
}
566-
}
567-
568-
if ("requirePragma" in options) {
569-
const value = options.requirePragma;
570-
if (isBoolean(value)) {
571-
formatOptions.requirePragma = value;
572-
}
573-
}
574-
575-
if ("semi" in options) {
576-
const value = options.semi;
577-
if (isBoolean(value)) {
578-
formatOptions.semi = value;
579-
}
580-
}
581-
582-
if ("singleAttributePerLine" in options) {
583-
const value = options.singleAttributePerLine;
584-
if (isBoolean(value)) {
585-
formatOptions.singleAttributePerLine = value;
586-
}
587-
}
588-
589-
if ("singleQuote" in options) {
590-
const value = options.singleQuote;
591-
if (isBoolean(value)) {
592-
formatOptions.singleQuote = value;
593-
}
594-
}
595-
596-
if ("tabWidth" in options) {
597-
const value = Number(options.tabWidth);
598-
if (isInteger(value) && value >= 0) {
599-
formatOptions.tabWidth = value;
600-
}
601-
}
602-
603-
if ("trailingComma" in options) {
604-
const value = options.trailingComma;
605-
if (value === "all" || value === "es5" || value === "none") {
606-
formatOptions.trailingComma = value;
607-
}
608-
}
609-
610-
if ("useTabs" in options) {
611-
const value = options.useTabs;
612-
if (isBoolean(value)) {
613-
formatOptions.useTabs = value;
614-
}
615-
}
616-
617-
if ("vueIndentScriptAndStyle" in options) {
618-
const value = options.vueIndentScriptAndStyle;
619-
if (isBoolean(value)) {
620-
formatOptions.vueIndentScriptAndStyle = value;
621-
}
622-
}
623-
624510
return formatOptions;
625511
}
626512

0 commit comments

Comments
 (0)