From 7f06777d6ca61d97745bae58da01292170bfd3c4 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 6 Sep 2024 00:38:43 +0200 Subject: [PATCH] Use a bit flags for theme options instead of an object with booleans (#14337) This PR is a small improvement to the theme options where it's just a simple number now instead of an object with booleans. --- .../src/compat/apply-config-to-theme.ts | 17 ++++----- packages/tailwindcss/src/index.ts | 22 ++++++------ packages/tailwindcss/src/theme.ts | 36 +++++++++---------- 3 files changed, 34 insertions(+), 41 deletions(-) diff --git a/packages/tailwindcss/src/compat/apply-config-to-theme.ts b/packages/tailwindcss/src/compat/apply-config-to-theme.ts index cac751e53..92d1c2c15 100644 --- a/packages/tailwindcss/src/compat/apply-config-to-theme.ts +++ b/packages/tailwindcss/src/compat/apply-config-to-theme.ts @@ -1,4 +1,5 @@ import type { DesignSystem } from '../design-system' +import { ThemeOptions } from '../theme' import { resolveConfig, type ConfigFile } from './config/resolve-config' import type { ResolvedConfig } from './config/types' @@ -24,11 +25,11 @@ export function applyConfigToTheme(designSystem: DesignSystem, configs: ConfigFi for (let [path, value] of themeableValues(theme)) { let name = keyPathToCssProperty(path) - designSystem.theme.add(`--${name}`, value as any, { - isInline: true, - isReference: true, - isDefault: true, - }) + designSystem.theme.add( + `--${name}`, + value as any, + ThemeOptions.INLINE | ThemeOptions.REFERENCE | ThemeOptions.DEFAULT, + ) } // If someone has updated `fontFamily.sans` or `fontFamily.mono` in a JS @@ -38,11 +39,7 @@ export function applyConfigToTheme(designSystem: DesignSystem, configs: ConfigFi // `--font-family-sans--feature-settings` (which the `--default-font-*` // variables reference) won't exist in the generated CSS. if (Object.hasOwn(theme, 'fontFamily')) { - let options = { - isInline: true, - isReference: false, - isDefault: true, - } + let options = ThemeOptions.INLINE | ThemeOptions.DEFAULT // Replace `--default-font-*` with `fontFamily.sans` values { diff --git a/packages/tailwindcss/src/index.ts b/packages/tailwindcss/src/index.ts index 985d6899c..fe68936ff 100644 --- a/packages/tailwindcss/src/index.ts +++ b/packages/tailwindcss/src/index.ts @@ -7,7 +7,7 @@ import { substituteFunctions, THEME_FUNCTION_INVOCATION } from './css-functions' import * as CSS from './css-parser' import { buildDesignSystem, type DesignSystem } from './design-system' import { registerPlugins, type CssPluginOptions, type Plugin } from './plugin-api' -import { Theme } from './theme' +import { Theme, ThemeOptions } from './theme' import { segment } from './utils/segment' const IS_VALID_UTILITY_NAME = /^[a-z][a-zA-Z0-9/%._-]*$/ @@ -26,21 +26,19 @@ function throwOnConfig(): never { } function parseThemeOptions(selector: string) { - let isReference = false - let isInline = false - let isDefault = false + let options = ThemeOptions.NONE for (let option of segment(selector.slice(6) /* '@theme'.length */, ' ')) { if (option === 'reference') { - isReference = true + options |= ThemeOptions.REFERENCE } else if (option === 'inline') { - isInline = true + options |= ThemeOptions.INLINE } else if (option === 'default') { - isDefault = true + options |= ThemeOptions.DEFAULT } } - return { isReference, isInline, isDefault } + return options } async function parseCss( @@ -267,7 +265,7 @@ async function parseCss( if (node.selector !== '@theme' && !node.selector.startsWith('@theme ')) return - let { isReference, isInline, isDefault } = parseThemeOptions(node.selector) + let themeOptions = parseThemeOptions(node.selector) // Record all custom properties in the `@theme` declaration walk(node.nodes, (child, { replaceWith }) => { @@ -281,7 +279,7 @@ async function parseCss( if (child.kind === 'comment') return if (child.kind === 'declaration' && child.property.startsWith('--')) { - theme.add(child.property, child.value ?? '', { isReference, isInline, isDefault }) + theme.add(child.property, child.value ?? '', themeOptions) return } @@ -297,7 +295,7 @@ async function parseCss( // Keep a reference to the first `@theme` rule to update with the full theme // later, and delete any other `@theme` rules. - if (!firstThemeRule && !isReference) { + if (!firstThemeRule && !(themeOptions & ThemeOptions.REFERENCE)) { firstThemeRule = node } else { replaceWith([]) @@ -341,7 +339,7 @@ async function parseCss( let nodes = [] for (let [key, value] of theme.entries()) { - if (value.isReference) continue + if (value.options & ThemeOptions.REFERENCE) continue nodes.push(decl(key, value.value)) } diff --git a/packages/tailwindcss/src/theme.ts b/packages/tailwindcss/src/theme.ts index 4a8f79b4e..7c2f5cb07 100644 --- a/packages/tailwindcss/src/theme.ts +++ b/packages/tailwindcss/src/theme.ts @@ -1,18 +1,16 @@ import { escape } from './utils/escape' -export class Theme { - constructor( - private values = new Map< - string, - { value: string; isReference: boolean; isInline: boolean; isDefault: boolean } - >(), - ) {} +export const enum ThemeOptions { + NONE = 0, + INLINE = 1 << 0, + REFERENCE = 1 << 1, + DEFAULT = 1 << 2, +} - add( - key: string, - value: string, - { isReference = false, isInline = false, isDefault = false } = {}, - ): void { +export class Theme { + constructor(private values = new Map()) {} + + add(key: string, value: string, options = ThemeOptions.NONE): void { if (key.endsWith('-*')) { if (value !== 'initial') { throw new Error(`Invalid theme value \`${value}\` for namespace \`${key}\``) @@ -24,15 +22,15 @@ export class Theme { } } - if (isDefault) { + if (options & ThemeOptions.DEFAULT) { let existing = this.values.get(key) - if (existing && !existing.isDefault) return + if (existing && !(existing.options & ThemeOptions.DEFAULT)) return } if (value === 'initial') { this.values.delete(key) } else { - this.values.set(key, { value, isReference, isInline, isDefault }) + this.values.set(key, { value, options }) } } @@ -68,7 +66,7 @@ export class Theme { } hasDefault(key: string): boolean { - return this.values.get(key)?.isDefault ?? false + return ((this.values.get(key)?.options ?? 0) & ThemeOptions.DEFAULT) === ThemeOptions.DEFAULT } entries() { @@ -111,7 +109,7 @@ export class Theme { let value = this.values.get(themeKey)! - if (value.isInline) { + if (value.options & ThemeOptions.INLINE) { return value.value } @@ -141,7 +139,7 @@ export class Theme { let nestedValue = this.values.get(nestedKey)! if (!nestedValue) continue - if (nestedValue.isInline) { + if (nestedValue.options & ThemeOptions.INLINE) { extra[name] = nestedValue.value } else { extra[name] = this.#var(nestedKey)! @@ -150,7 +148,7 @@ export class Theme { let value = this.values.get(themeKey)! - if (value.isInline) { + if (value.options & ThemeOptions.INLINE) { return [value.value, extra] }