diff --git a/packages/website/src/components/config/ConfigEditor.module.css b/packages/website/src/components/config/ConfigEditor.module.css index 1329e5af9a7..b2f25dfcbe0 100644 --- a/packages/website/src/components/config/ConfigEditor.module.css +++ b/packages/website/src/components/config/ConfigEditor.module.css @@ -39,6 +39,10 @@ margin: 0.2rem 0; } +.searchResultDescription { + flex: 1 0 75%; +} + .searchResult:nth-child(even), .searchResultGroup:nth-child(even) { background: var(--ifm-color-emphasis-100); diff --git a/packages/website/src/components/config/ConfigEditor.tsx b/packages/website/src/components/config/ConfigEditor.tsx index 43bfcadd9bc..4f0f9d93995 100644 --- a/packages/website/src/components/config/ConfigEditor.tsx +++ b/packages/website/src/components/config/ConfigEditor.tsx @@ -7,11 +7,14 @@ import Text from '../inputs/Text'; import Checkbox from '../inputs/Checkbox'; import useFocus from '../hooks/useFocus'; import Modal from '@site/src/components/modals/Modal'; +import Dropdown from '@site/src/components/inputs/Dropdown'; export interface ConfigOptionsField { key: string; + type: 'boolean' | 'string'; label?: string; defaults?: unknown[]; + enum?: string[]; } export interface ConfigOptionsType { @@ -33,6 +36,11 @@ function reducerObject( state: ConfigEditorValues, action: | { type: 'init'; config?: ConfigEditorValues } + | { + type: 'set'; + name: string; + value: unknown; + } | { type: 'toggle'; checked: boolean; @@ -44,6 +52,15 @@ function reducerObject( case 'init': { return action.config ?? {}; } + case 'set': { + const newState = { ...state }; + if (action.value === '') { + delete newState[action.name]; + } else { + newState[action.name] = action.value; + } + return newState; + } case 'toggle': { const newState = { ...state }; if (action.checked) { @@ -110,28 +127,44 @@ function ConfigEditor(props: ConfigEditorProps): JSX.Element {
{group.fields.map(item => ( ))}
diff --git a/packages/website/src/components/config/ConfigEslint.tsx b/packages/website/src/components/config/ConfigEslint.tsx index a25046b7110..f14d00ec5b7 100644 --- a/packages/website/src/components/config/ConfigEslint.tsx +++ b/packages/website/src/components/config/ConfigEslint.tsx @@ -45,6 +45,7 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element { .map(item => ({ key: item.name, label: item.description, + type: 'boolean', defaults: ['error', 2, 'warn', 1, ['error'], ['warn'], [2], [1]], })), }, @@ -55,6 +56,7 @@ function ConfigEslint(props: ConfigEslintProps): JSX.Element { .map(item => ({ key: item.name, label: item.description, + type: 'boolean', defaults: ['error', 2, 'warn', 1, ['error'], ['warn'], [2], [1]], })), }, diff --git a/packages/website/src/components/config/ConfigTypeScript.tsx b/packages/website/src/components/config/ConfigTypeScript.tsx index 8d64045ac4b..91a4781d14f 100644 --- a/packages/website/src/components/config/ConfigTypeScript.tsx +++ b/packages/website/src/components/config/ConfigTypeScript.tsx @@ -11,10 +11,6 @@ interface ConfigTypeScriptProps { readonly config?: string; } -function checkOptions(item: [string, unknown]): item is [string, boolean] { - return typeof item[1] === 'boolean'; -} - function ConfigTypeScript(props: ConfigTypeScriptProps): JSX.Element { const [tsConfigOptions, updateOptions] = useState([]); const [configObject, updateConfigObject] = useState(); @@ -36,10 +32,20 @@ function ConfigTypeScript(props: ConfigTypeScriptProps): JSX.Element { heading: category, fields: [], }; - group[category].fields.push({ - key: item.name, - label: item.description!.message, - }); + if (item.type === 'boolean') { + group[category].fields.push({ + key: item.name, + type: 'boolean', + label: item.description!.message, + }); + } else if (item.type instanceof Map) { + group[category].fields.push({ + key: item.name, + type: 'string', + label: item.description!.message, + enum: ['', ...Array.from(item.type.keys())], + }); + } return group; }, {}, @@ -51,9 +57,7 @@ function ConfigTypeScript(props: ConfigTypeScriptProps): JSX.Element { const onClose = useCallback( (newConfig: Record) => { - const cfg = Object.fromEntries( - Object.entries(newConfig).filter(checkOptions), - ); + const cfg = { ...newConfig }; if (!shallowEqual(cfg, configObject?.compilerOptions)) { props.onClose({ tsconfig: toJson({ ...(configObject ?? {}), compilerOptions: cfg }), diff --git a/packages/website/src/components/config/utils.ts b/packages/website/src/components/config/utils.ts index 77d06c66b0b..749487ea1aa 100644 --- a/packages/website/src/components/config/utils.ts +++ b/packages/website/src/components/config/utils.ts @@ -8,6 +8,9 @@ export interface OptionDeclarations { type?: unknown; category?: { message: string }; description?: { message: string }; + element?: { + type: unknown; + }; } export function parseESLintRC(code?: string): EslintRC { @@ -84,7 +87,6 @@ export function toJsonConfig(cfg: unknown, prop: string): string { export function getTypescriptOptions(): OptionDeclarations[] { const allowedCategories = [ 'Command-line Options', - 'Modules', 'Projects', 'Compiler Diagnostics', 'Editor Support', @@ -93,13 +95,24 @@ export function getTypescriptOptions(): OptionDeclarations[] { 'Source Map Options', ]; + const filteredNames = [ + 'moduleResolution', + 'moduleDetection', + 'plugins', + 'typeRoots', + 'jsx', + ]; + // @ts-expect-error: definition is not fully correct return (window.ts.optionDeclarations as OptionDeclarations[]).filter( item => - item.type === 'boolean' && + (item.type === 'boolean' || + item.type === 'list' || + item.type instanceof Map) && item.description && item.category && - !allowedCategories.includes(item.category.message), + !allowedCategories.includes(item.category.message) && + !filteredNames.includes(item.name), ); } diff --git a/packages/website/src/components/editor/config.ts b/packages/website/src/components/editor/config.ts index 679baa8a0f2..b1d013ff28f 100644 --- a/packages/website/src/components/editor/config.ts +++ b/packages/website/src/components/editor/config.ts @@ -13,6 +13,12 @@ export function createCompilerOptions( module: window.ts.ModuleKind.ESNext as number, ...tsConfig, jsx: jsx ? window.ts.JsxEmit.Preserve : window.ts.JsxEmit.None, + moduleResolution: undefined, + plugins: undefined, + typeRoots: undefined, + paths: undefined, + moduleDetection: undefined, + baseUrl: undefined, }; } @@ -58,10 +64,27 @@ export function getEslintSchema( export function getTsConfigSchema(): JSONSchema4 { const properties = getTypescriptOptions().reduce((options, item) => { - options[item.name] = { - type: item.type, - description: item.description!.message, - }; + if (item.type === 'boolean') { + options[item.name] = { + type: 'boolean', + description: item.description!.message, + }; + } else if (item.type === 'list' && item.element?.type instanceof Map) { + options[item.name] = { + type: 'array', + items: { + type: 'string', + enum: Array.from(item.element.type.keys()), + }, + description: item.description!.message, + }; + } else if (item.type instanceof Map) { + options[item.name] = { + type: 'string', + description: item.description!.message, + enum: Array.from(item.type.keys()), + }; + } return options; }, {});