From 20f001cb3c35e82431078c66e568ead8906c016c Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 22 Aug 2024 13:12:48 -0400 Subject: [PATCH] Allow resolve config to take in optional paths alongside configs --- .../src/compat/config/resolve-config.test.ts | 128 ++++++++++-------- .../src/compat/config/resolve-config.ts | 25 ++-- packages/tailwindcss/src/plugin-api.ts | 4 +- 3 files changed, 90 insertions(+), 67 deletions(-) diff --git a/packages/tailwindcss/src/compat/config/resolve-config.test.ts b/packages/tailwindcss/src/compat/config/resolve-config.test.ts index 4669107bb..2ce588f4d 100644 --- a/packages/tailwindcss/src/compat/config/resolve-config.test.ts +++ b/packages/tailwindcss/src/compat/config/resolve-config.test.ts @@ -8,27 +8,33 @@ test('top level theme keys are replaced', ({ expect }) => { let config = resolveConfig(design, [ { - theme: { - colors: { - red: 'red', - }, + config: { + theme: { + colors: { + red: 'red', + }, - fontFamily: { - sans: 'SF Pro Display', + fontFamily: { + sans: 'SF Pro Display', + }, }, }, }, { - theme: { - colors: { - green: 'green', + config: { + theme: { + colors: { + green: 'green', + }, }, }, }, { - theme: { - colors: { - blue: 'blue', + config: { + theme: { + colors: { + blue: 'blue', + }, }, }, }, @@ -51,21 +57,25 @@ test('theme can be extended', ({ expect }) => { let config = resolveConfig(design, [ { - theme: { - colors: { - red: 'red', - }, + config: { + theme: { + colors: { + red: 'red', + }, - fontFamily: { - sans: 'SF Pro Display', + fontFamily: { + sans: 'SF Pro Display', + }, }, }, }, { - theme: { - extend: { - colors: { - blue: 'blue', + config: { + theme: { + extend: { + colors: { + blue: 'blue', + }, }, }, }, @@ -92,31 +102,37 @@ test('theme keys can reference other theme keys using the theme function regardl let config = resolveConfig(design, [ { - theme: { - colors: { - red: 'red', - }, - placeholderColor: { - green: 'green', + config: { + theme: { + colors: { + red: 'red', + }, + placeholderColor: { + green: 'green', + }, }, }, }, { - theme: { - extend: { - colors: ({ theme }) => ({ - ...theme('placeholderColor'), - blue: 'blue', - }), + config: { + theme: { + extend: { + colors: ({ theme }) => ({ + ...theme('placeholderColor'), + blue: 'blue', + }), + }, }, }, }, { - theme: { - extend: { - caretColor: ({ theme }) => theme('accentColor'), - accentColor: ({ theme }) => theme('backgroundColor'), - backgroundColor: ({ theme }) => theme('colors'), + config: { + theme: { + extend: { + caretColor: ({ theme }) => theme('accentColor'), + accentColor: ({ theme }) => theme('backgroundColor'), + backgroundColor: ({ theme }) => theme('colors'), + }, }, }, }, @@ -156,23 +172,25 @@ test('theme keys can read from the CSS theme', ({ expect }) => { let config = resolveConfig(design, [ { - theme: { - colors: ({ theme }) => ({ - // Reads from the --color-* namespace - ...theme('color'), - red: 'red', - }), - accentColor: ({ theme }) => ({ - // Reads from the --color-* namespace through `colors` - ...theme('colors'), - }), - placeholderColor: ({ theme }) => ({ - // Reads from the --color-* namespace through `colors` - primary: theme('colors.green'), + config: { + theme: { + colors: ({ theme }) => ({ + // Reads from the --color-* namespace + ...theme('color'), + red: 'red', + }), + accentColor: ({ theme }) => ({ + // Reads from the --color-* namespace through `colors` + ...theme('colors'), + }), + placeholderColor: ({ theme }) => ({ + // Reads from the --color-* namespace through `colors` + primary: theme('colors.green'), - // Reads from the --color-* namespace directly - secondary: theme('color.green'), - }), + // Reads from the --color-* namespace directly + secondary: theme('color.green'), + }), + }, }, }, ]) diff --git a/packages/tailwindcss/src/compat/config/resolve-config.ts b/packages/tailwindcss/src/compat/config/resolve-config.ts index 07f592259..f39269d44 100644 --- a/packages/tailwindcss/src/compat/config/resolve-config.ts +++ b/packages/tailwindcss/src/compat/config/resolve-config.ts @@ -9,6 +9,11 @@ import { type UserConfig, } from './types' +export interface ConfigFile { + path?: string + config: UserConfig +} + interface ResolutionContext { design: DesignSystem configs: UserConfig[] @@ -23,7 +28,7 @@ let minimal: ResolvedConfig = { plugins: [], } -export function resolveConfig(design: DesignSystem, configs: UserConfig[]): ResolvedConfig { +export function resolveConfig(design: DesignSystem, files: ConfigFile[]): ResolvedConfig { let ctx: ResolutionContext = { design, configs: [], @@ -35,8 +40,8 @@ export function resolveConfig(design: DesignSystem, configs: UserConfig[]): Reso result: structuredClone(minimal), } - for (let config of configs) { - resolveInternal(ctx, config) + for (let file of files) { + resolveInternal(ctx, file) } // Merge themes @@ -80,11 +85,11 @@ export interface PluginUtils { theme(keypath: string, defaultValue?: any): any } -function resolveInternal(ctx: ResolutionContext, user: UserConfig): void { +function resolveInternal(ctx: ResolutionContext, { config, path }: ConfigFile): void { let plugins: PluginWithConfig[] = [] // Normalize plugins so they share the same shape - for (let plugin of user.plugins ?? []) { + for (let plugin of config.plugins ?? []) { if ('__isOptionsFunction' in plugin) { // Happens with `plugin.withOptions()` when no options were passed: // e.g. `require("my-plugin")` instead of `require("my-plugin")(options)` @@ -103,12 +108,12 @@ function resolveInternal(ctx: ResolutionContext, user: UserConfig): void { } // Apply configs from presets - if (Array.isArray(user.presets) && user.presets.length === 0) { + if (Array.isArray(config.presets) && config.presets.length === 0) { throw new Error('The empty preset `[]` is not supported') } - for (let preset of user.presets ?? []) { - resolveInternal(ctx, preset) + for (let preset of config.presets ?? []) { + resolveInternal(ctx, { path, config: preset }) } // Apply configs from plugins @@ -116,12 +121,12 @@ function resolveInternal(ctx: ResolutionContext, user: UserConfig): void { ctx.plugins.push(plugin) if (plugin.config) { - resolveInternal(ctx, plugin.config) + resolveInternal(ctx, { path, config: plugin.config }) } } // Then apply the "user" config - ctx.configs.push(user) + ctx.configs.push(config) } function mergeTheme(ctx: ResolutionContext) { diff --git a/packages/tailwindcss/src/plugin-api.ts b/packages/tailwindcss/src/plugin-api.ts index 1a161f956..97b552f43 100644 --- a/packages/tailwindcss/src/plugin-api.ts +++ b/packages/tailwindcss/src/plugin-api.ts @@ -332,8 +332,8 @@ export function registerPlugins( ast: AstNode[], ) { let resolvedConfig = resolveConfig(designSystem, [ - createCompatConfig(designSystem.theme), - { plugins }, + { config: createCompatConfig(designSystem.theme) }, + { config: { plugins } }, ]) let pluginApi = buildPluginApi(designSystem, ast, resolvedConfig)