From a4cd44d426016b83377a5771bdb1e3d12c5b8990 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 3 Apr 2025 14:26:02 -0400 Subject: [PATCH] Cleanup code a bit --- packages/@tailwindcss-node/package.json | 4 +- packages/@tailwindcss-node/src/compile.ts | 6 +- packages/@tailwindcss-vite/src/index.ts | 34 +++++++--- packages/tailwindcss/src/apply.ts | 6 +- packages/tailwindcss/src/ast.ts | 48 +++++++------ packages/tailwindcss/src/at-import.ts | 17 +++-- .../src/compat/apply-compat-hooks.ts | 5 +- .../tailwindcss/src/compat/plugin-api.test.ts | 4 +- .../tailwindcss/src/css-functions.test.ts | 11 +-- packages/tailwindcss/src/css-parser.ts | 25 ++++--- packages/tailwindcss/src/index.test.ts | 68 +++++++++++-------- packages/tailwindcss/src/index.ts | 17 +++-- packages/tailwindcss/src/variants.test.ts | 2 +- 13 files changed, 153 insertions(+), 94 deletions(-) diff --git a/packages/@tailwindcss-node/package.json b/packages/@tailwindcss-node/package.json index d3631b758..0844c2324 100644 --- a/packages/@tailwindcss-node/package.json +++ b/packages/@tailwindcss-node/package.json @@ -39,7 +39,7 @@ "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", - "tailwindcss": "workspace:*", - "lightningcss": "catalog:" + "lightningcss": "catalog:", + "tailwindcss": "workspace:*" } } diff --git a/packages/@tailwindcss-node/src/compile.ts b/packages/@tailwindcss-node/src/compile.ts index ef9dfbcba..85c4bd42f 100644 --- a/packages/@tailwindcss-node/src/compile.ts +++ b/packages/@tailwindcss-node/src/compile.ts @@ -2,7 +2,7 @@ import EnhancedResolve from 'enhanced-resolve' import { createJiti, type Jiti } from 'jiti' import fs from 'node:fs' import fsPromises from 'node:fs/promises' -import path, { dirname } from 'node:path' +import path from 'node:path' import { pathToFileURL } from 'node:url' import { __unstable__loadDesignSystem as ___unstable__loadDesignSystem, @@ -125,7 +125,7 @@ export async function loadModule( let module = await importModule(pathToFileURL(resolvedPath).href) return { - base: dirname(resolvedPath), + base: path.dirname(resolvedPath), module: module.default ?? module, } } @@ -144,7 +144,7 @@ export async function loadModule( onDependency(file) } return { - base: dirname(resolvedPath), + base: path.dirname(resolvedPath), module: module.default ?? module, } } diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index a484583a3..a62929069 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -34,7 +34,12 @@ export default function tailwindcss(): Plugin[] { function customJsResolver(id: string, base: string) { return jsResolver(id, base, true, isSSR) } - return new Root(id, config!.root, customCssResolver, customJsResolver) + return new Root( + id, + config!.root, + customCssResolver, + customJsResolver, + ) }) return [ @@ -68,14 +73,14 @@ export default function tailwindcss(): Plugin[] { let root = roots.get(id) - let generated = await root.generate(src, (file) => this.addWatchFile(file), I) - if (!generated) { + let result = await root.generate(src, (file) => this.addWatchFile(file), I) + if (!result) { roots.delete(id) return src } DEBUG && I.end('[@tailwindcss/vite] Generate CSS (serve)') - return { code: generated } + return result }, }, @@ -93,18 +98,18 @@ export default function tailwindcss(): Plugin[] { let root = roots.get(id) - let generated = await root.generate(src, (file) => this.addWatchFile(file), I) - if (!generated) { + let result = await root.generate(src, (file) => this.addWatchFile(file), I) + if (!result) { roots.delete(id) return src } DEBUG && I.end('[@tailwindcss/vite] Generate CSS (build)') DEBUG && I.start('[@tailwindcss/vite] Optimize CSS') - generated = optimize(generated, { minify }) + result.code = optimize(result.code, { minify }) DEBUG && I.end('[@tailwindcss/vite] Optimize CSS') - return { code: generated } + return result }, }, ] satisfies Plugin[] @@ -183,7 +188,12 @@ class Root { content: string, _addWatchFile: (file: string) => void, I: Instrumentation, - ): Promise { + ): Promise< + | { + code: string + } + | false + > { let inputPath = idToPath(this.id) function addWatchFile(file: string) { @@ -313,10 +323,12 @@ class Root { } DEBUG && I.start('Build CSS') - let result = this.compiler.build([...this.candidates]) + let code = this.compiler.build([...this.candidates]) DEBUG && I.end('Build CSS') - return result + return { + code, + } } private async addBuildDependency(path: string) { diff --git a/packages/tailwindcss/src/apply.ts b/packages/tailwindcss/src/apply.ts index 676b4f2ee..6038c4b8d 100644 --- a/packages/tailwindcss/src/apply.ts +++ b/packages/tailwindcss/src/apply.ts @@ -161,11 +161,13 @@ export function substituteAtApply(ast: AstNode[], designSystem: DesignSystem) { { // Parse the candidates to an AST that we can replace the `@apply` rule // with. - let candidateAst = compileCandidates(candidates, designSystem, { + let compiled = compileCandidates(candidates, designSystem, { onInvalidCandidate: (candidate) => { throw new Error(`Cannot apply unknown utility class: ${candidate}`) }, - }).astNodes + }) + + let candidateAst = compiled.astNodes // Collect the nodes to insert in place of the `@apply` rule. When a rule // was used, we want to insert its children instead of the rule because we diff --git a/packages/tailwindcss/src/ast.ts b/packages/tailwindcss/src/ast.ts index 3db0432dd..4c5cd40da 100644 --- a/packages/tailwindcss/src/ast.ts +++ b/packages/tailwindcss/src/ast.ts @@ -378,10 +378,12 @@ export function optimizeAst( } } + let fallback = decl(property, initialValue ?? 'initial') + if (inherits) { - propertyFallbacksRoot.push(decl(property, initialValue ?? 'initial')) + propertyFallbacksRoot.push(fallback) } else { - propertyFallbacksUniversal.push(decl(property, initialValue ?? 'initial')) + propertyFallbacksUniversal.push(fallback) } } @@ -632,11 +634,13 @@ export function optimizeAst( let fallbackAst = [] if (propertyFallbacksRoot.length > 0) { - fallbackAst.push(rule(':root, :host', propertyFallbacksRoot)) + let wrapper = rule(':root, :host', propertyFallbacksRoot) + fallbackAst.push(wrapper) } if (propertyFallbacksUniversal.length > 0) { - fallbackAst.push(rule('*, ::before, ::after, ::backdrop', propertyFallbacksUniversal)) + let wrapper = rule('*, ::before, ::after, ::backdrop', propertyFallbacksUniversal) + fallbackAst.push(wrapper) } if (fallbackAst.length > 0) { @@ -658,23 +662,25 @@ export function optimizeAst( return true }) + let layerPropertiesStatement = atRule('@layer', 'properties', []) + newAst.splice( firstValidNodeIndex < 0 ? newAst.length : firstValidNodeIndex, 0, - atRule('@layer', 'properties', []), + layerPropertiesStatement, ) - newAst.push( - rule('@layer properties', [ - atRule( - '@supports', - // We can't write a supports query for `@property` directly so we have to test for - // features that are added around the same time in Mozilla and Safari. - '((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))', - fallbackAst, - ), - ]), - ) + let block = rule('@layer properties', [ + atRule( + '@supports', + // We can't write a supports query for `@property` directly so we have to test for + // features that are added around the same time in Mozilla and Safari. + '((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))', + fallbackAst, + ), + ]) + + newAst.push(block) } } @@ -710,7 +716,8 @@ export function toCss(ast: AstNode[]) { // @layer base, components, utilities; // ``` if (node.nodes.length === 0) { - return `${indent}${node.name} ${node.params};\n` + let css = `${indent}${node.name} ${node.params};\n` + return css } css += `${indent}${node.name}${node.params ? ` ${node.params} ` : ' '}{\n` @@ -725,7 +732,7 @@ export function toCss(ast: AstNode[]) { css += `${indent}/*${node.value}*/\n` } - // These should've been handled already by `prepareAstForPrinting` which + // These should've been handled already by `optimizeAst` which // means we can safely ignore them here. We return an empty string // immediately to signal that something went wrong. else if (node.kind === 'context' || node.kind === 'at-root') { @@ -743,10 +750,7 @@ export function toCss(ast: AstNode[]) { let css = '' for (let node of ast) { - let result = stringify(node) - if (result !== '') { - css += result - } + css += stringify(node, 0) } return css diff --git a/packages/tailwindcss/src/at-import.ts b/packages/tailwindcss/src/at-import.ts index effd33e5b..343e9fbae 100644 --- a/packages/tailwindcss/src/at-import.ts +++ b/packages/tailwindcss/src/at-import.ts @@ -3,7 +3,13 @@ import { atRule, context, walk, WalkAction, type AstNode } from './ast' import * as CSS from './css-parser' import * as ValueParser from './value-parser' -type LoadStylesheet = (id: string, basedir: string) => Promise<{ base: string; content: string }> +type LoadStylesheet = ( + id: string, + basedir: string, +) => Promise<{ + base: string + content: string +}> export async function substituteAtImports( ast: AstNode[], @@ -148,15 +154,18 @@ function buildImportNodes( let root = importedAst if (layer !== null) { - root = [atRule('@layer', layer, root)] + let node = atRule('@layer', layer, root) + root = [node] } if (media !== null) { - root = [atRule('@media', media, root)] + let node = atRule('@media', media, root) + root = [node] } if (supports !== null) { - root = [atRule('@supports', supports[0] === '(' ? supports : `(${supports})`, root)] + let node = atRule('@supports', supports[0] === '(' ? supports : `(${supports})`, root) + root = [node] } return root diff --git a/packages/tailwindcss/src/compat/apply-compat-hooks.ts b/packages/tailwindcss/src/compat/apply-compat-hooks.ts index a781cdcb0..eb23cec18 100644 --- a/packages/tailwindcss/src/compat/apply-compat-hooks.ts +++ b/packages/tailwindcss/src/compat/apply-compat-hooks.ts @@ -30,7 +30,10 @@ export async function applyCompatibilityHooks({ path: string, base: string, resourceHint: 'plugin' | 'config', - ) => Promise<{ module: any; base: string }> + ) => Promise<{ + base: string + module: any + }> sources: { base: string; pattern: string; negated: boolean }[] }) { let features = Features.None diff --git a/packages/tailwindcss/src/compat/plugin-api.test.ts b/packages/tailwindcss/src/compat/plugin-api.test.ts index ca7d96dee..6a8f95c58 100644 --- a/packages/tailwindcss/src/compat/plugin-api.test.ts +++ b/packages/tailwindcss/src/compat/plugin-api.test.ts @@ -1508,10 +1508,10 @@ describe('addBase', () => { }, async loadStylesheet() { return { + base: '', content: css` @plugin "inside"; `, - base: '', } }, }) @@ -1533,6 +1533,7 @@ describe('addBase', () => { let compiler = await compile(input, { loadModule: async () => ({ + base: '/root', module: plugin(function ({ addBase }) { addBase({ ':root': { @@ -1542,7 +1543,6 @@ describe('addBase', () => { }, }) }), - base: '/root', }), }) diff --git a/packages/tailwindcss/src/css-functions.test.ts b/packages/tailwindcss/src/css-functions.test.ts index f63682f63..968bb7f43 100644 --- a/packages/tailwindcss/src/css-functions.test.ts +++ b/packages/tailwindcss/src/css-functions.test.ts @@ -412,8 +412,8 @@ describe('--theme(…)', () => { [], { loadModule: async () => ({ - module: () => {}, base: '/root', + module: () => {}, }), }, ), @@ -771,7 +771,10 @@ describe('theme(…)', () => { } `, { - loadModule: async () => ({ module: {}, base: '/root' }), + loadModule: async () => ({ + base: '/root', + module: {}, + }), }, ) @@ -1196,6 +1199,7 @@ describe('in plugins', () => { { async loadModule() { return { + base: '/root', module: plugin(({ addBase, addUtilities }) => { addBase({ '.my-base-rule': { @@ -1212,7 +1216,6 @@ describe('in plugins', () => { }, }) }), - base: '/root', } }, }, @@ -1253,6 +1256,7 @@ describe('in JS config files', () => { `, { loadModule: async () => ({ + base: '/root', module: { theme: { extend: { @@ -1279,7 +1283,6 @@ describe('in JS config files', () => { }), ], }, - base: '/root', }), }, ) diff --git a/packages/tailwindcss/src/css-parser.ts b/packages/tailwindcss/src/css-parser.ts index df10fa850..c492ed353 100644 --- a/packages/tailwindcss/src/css-parser.ts +++ b/packages/tailwindcss/src/css-parser.ts @@ -31,8 +31,11 @@ const AT_SIGN = 0x40 const EXCLAMATION_MARK = 0x21 export function parse(input: string) { - if (input[0] === '\uFEFF') input = input.slice(1) - input = input.replaceAll('\r\n', '\n') + // Note: it is important that any transformations of the input string + // *before* processing do NOT change the length of the string. This + // would invalidate the mechanism used to track source locations. + if (input[0] === '\uFEFF') input = ' ' + input.slice(1) + input = input.replaceAll('\r\n', ' \n') let ast: AstNode[] = [] let licenseComments: Comment[] = [] @@ -104,7 +107,8 @@ export function parse(input: string) { // Collect all license comments so that we can hoist them to the top of // the AST. if (commentString.charCodeAt(2) === EXCLAMATION_MARK) { - licenseComments.push(comment(commentString.slice(2, -2))) + let node = comment(commentString.slice(2, -2)) + licenseComments.push(node) } } @@ -503,7 +507,9 @@ export function parse(input: string) { // means that we have an at-rule that is not terminated with a semicolon at // the end of the input. if (buffer.charCodeAt(0) === AT_SIGN) { - ast.push(parseAtRule(buffer)) + let node = parseAtRule(buffer) + + ast.push(node) } // When we are done parsing then everything should be balanced. If we still @@ -525,6 +531,9 @@ export function parse(input: string) { } export function parseAtRule(buffer: string, nodes: AstNode[] = []): AtRule { + let name = buffer + let params = '' + // Assumption: The smallest at-rule in CSS right now is `@page`, this means // that we can always skip the first 5 characters and start at the // sixth (at index 5). @@ -545,13 +554,13 @@ export function parseAtRule(buffer: string, nodes: AstNode[] = []): AtRule { for (let i = 5 /* '@page'.length */; i < buffer.length; i++) { let currentChar = buffer.charCodeAt(i) if (currentChar === SPACE || currentChar === OPEN_PAREN) { - let name = buffer.slice(0, i).trim() - let params = buffer.slice(i).trim() - return atRule(name, params, nodes) + name = buffer.slice(0, i) + params = buffer.slice(i) + break } } - return atRule(buffer.trim(), '', nodes) + return atRule(name.trim(), params.trim(), nodes) } function parseDeclaration( diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index 00e73a90b..22dd6b053 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -126,11 +126,11 @@ describe('compiling CSS', () => { { async loadStylesheet(id) { return { + base: '', content: fs.readFileSync( path.resolve(__dirname, '..', id === 'tailwindcss' ? 'index.css' : id), 'utf-8', ), - base: '', } }, }, @@ -2320,6 +2320,7 @@ describe('Parsing theme values from CSS', () => { { async loadStylesheet() { return { + base: '', content: css` @theme { --color-tomato: #e10c04; @@ -2329,7 +2330,6 @@ describe('Parsing theme values from CSS', () => { @tailwind utilities; `, - base: '', } }, }, @@ -2407,6 +2407,7 @@ describe('Parsing theme values from CSS', () => { { async loadStylesheet() { return { + base: '', content: css` @theme { --color-tomato: #e10c04; @@ -2416,7 +2417,6 @@ describe('Parsing theme values from CSS', () => { @tailwind utilities; `, - base: '', } }, }, @@ -2704,6 +2704,7 @@ describe('Parsing theme values from CSS', () => { { loadModule: async () => { return { + base: '/root', module: plugin(({}) => {}, { theme: { extend: { @@ -2714,7 +2715,6 @@ describe('Parsing theme values from CSS', () => { }, }, }), - base: '/root', } }, }, @@ -2750,6 +2750,7 @@ describe('Parsing theme values from CSS', () => { { loadModule: async () => { return { + base: '/root', module: { theme: { extend: { @@ -2760,7 +2761,6 @@ describe('Parsing theme values from CSS', () => { }, }, }, - base: '/root', } }, }, @@ -2839,10 +2839,10 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', '&:hover, &:focus') }, - base: '/root', }), }, ), @@ -2857,10 +2857,10 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', '&:hover, &:focus') }, - base: '/root', }), }, ), @@ -2877,10 +2877,10 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', '&:hover, &:focus') }, - base: '/root', }), }, ), @@ -2899,6 +2899,7 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: plugin.withOptions((options) => { expect(options).toEqual({ color: 'red', @@ -2912,7 +2913,6 @@ describe('plugins', () => { }) } }), - base: '/root', }), }, ) @@ -2951,6 +2951,7 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: plugin.withOptions((options) => { expect(options).toEqual({ 'is-null': null, @@ -2971,7 +2972,6 @@ describe('plugins', () => { return () => {} }), - base: '/root', }), }, ) @@ -2991,6 +2991,7 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: plugin.withOptions((options) => { return ({ addUtilities }) => { addUtilities({ @@ -3000,7 +3001,6 @@ describe('plugins', () => { }) } }), - base: '/root', }), }, ), @@ -3029,6 +3029,7 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: plugin(({ addUtilities }) => { addUtilities({ '.text-primary': { @@ -3036,7 +3037,6 @@ describe('plugins', () => { }, }) }), - base: '/root', }), }, ), @@ -3054,7 +3054,10 @@ describe('plugins', () => { } `, { - loadModule: async () => ({ module: plugin(() => {}), base: '/root' }), + loadModule: async () => ({ + base: '/root', + module: plugin(() => {}), + }), }, ), ).rejects.toThrowErrorMatchingInlineSnapshot( @@ -3075,7 +3078,10 @@ describe('plugins', () => { } `, { - loadModule: async () => ({ module: plugin(() => {}), base: '/root' }), + loadModule: async () => ({ + base: '/root', + module: plugin(() => {}), + }), }, ), ).rejects.toThrowErrorMatchingInlineSnapshot(` @@ -3099,10 +3105,10 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', '&:hover, &:focus') }, - base: '/root', }), }, ) @@ -3131,10 +3137,10 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', ['&:hover', '&:focus']) }, - base: '/root', }), }, ) @@ -3164,13 +3170,13 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', { '&:hover': '@slot', '&:focus': '@slot', }) }, - base: '/root', }), }, ) @@ -3199,6 +3205,7 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', { '@media (hover: hover)': { @@ -3207,7 +3214,6 @@ describe('plugins', () => { '&:focus': '@slot', }) }, - base: '/root', }), }, ) @@ -3248,6 +3254,7 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('hocus', { '&': { @@ -3257,7 +3264,6 @@ describe('plugins', () => { }, }) }, - base: '/root', }), }, ) @@ -3286,10 +3292,10 @@ describe('plugins', () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addVariant }: PluginAPI) => { addVariant('dark', '&:is([data-theme=dark] *)') }, - base: '/root', }), }, ) @@ -4142,6 +4148,7 @@ test('addBase', async () => { `, { loadModule: async () => ({ + base: '/root', module: ({ addBase }: PluginAPI) => { addBase({ body: { @@ -4149,7 +4156,6 @@ test('addBase', async () => { }, }) }, - base: '/root', }), }, ) @@ -4201,6 +4207,7 @@ describe('`@reference "…" imports`', () => { let loadStylesheet = async (id: string, base: string) => { if (id === './foo/baz.css') { return { + base: '/root/foo', content: css` .foo { color: red; @@ -4213,14 +4220,13 @@ describe('`@reference "…" imports`', () => { } @custom-variant hocus (&:hover, &:focus); `, - base: '/root/foo', } } return { + base: '/root/foo', content: css` @import './foo/baz.css'; `, - base: '/root/foo', } } @@ -4249,19 +4255,19 @@ describe('`@reference "…" imports`', () => { let loadStylesheet = async (id: string, base: string) => { if (id === './foo/baz.css') { return { + base: '/root/foo', content: css` @layer utilities { @tailwind utilities; } `, - base: '/root/foo', } } return { + base: '/root/foo', content: css` @import './foo/baz.css'; `, - base: '/root/foo', } } @@ -4311,6 +4317,7 @@ describe('`@reference "…" imports`', () => { ['animate-spin', 'match-utility-initial', 'match-components-initial'], { loadModule: async () => ({ + base: '/root', module: ({ addBase, addUtilities, @@ -4344,7 +4351,6 @@ describe('`@reference "…" imports`', () => { { values: { initial: 'initial' } }, ) }, - base: '/root', }), }, ), @@ -4366,22 +4372,23 @@ describe('`@reference "…" imports`', () => { switch (id) { case './one.css': { return { + base: '/root', content: css` @import './two.css' layer(two); `, - base: '/root', } } case './two.css': { return { + base: '/root', content: css` @import './three.css' layer(three); `, - base: '/root', } } case './three.css': { return { + base: '/root', content: css` .foo { color: red; @@ -4400,10 +4407,11 @@ describe('`@reference "…" imports`', () => { } } `, - base: '/root', } } } + + throw new Error('unreachable') } await expect( @@ -4438,6 +4446,7 @@ describe('`@reference "…" imports`', () => { test('supports `@import "…" reference` syntax', async () => { let loadStylesheet = async () => { return { + base: '/root/foo', content: css` .foo { color: red; @@ -4450,7 +4459,6 @@ describe('`@reference "…" imports`', () => { } @custom-variant hocus (&:hover, &:focus); `, - base: '/root/foo', } } diff --git a/packages/tailwindcss/src/index.ts b/packages/tailwindcss/src/index.ts index e8f34e366..792f7452f 100644 --- a/packages/tailwindcss/src/index.ts +++ b/packages/tailwindcss/src/index.ts @@ -56,8 +56,17 @@ type CompileOptions = { id: string, base: string, resourceHint: 'plugin' | 'config', - ) => Promise<{ module: Plugin | Config; base: string }> - loadStylesheet?: (id: string, base: string) => Promise<{ content: string; base: string }> + ) => Promise<{ + base: string + module: Plugin | Config + }> + loadStylesheet?: ( + id: string, + base: string, + ) => Promise<{ + base: string + content: string + }> } function throwOnLoadModule(): never { @@ -593,8 +602,8 @@ async function parseCss( for (let [key, value] of designSystem.theme.entries()) { if (value.options & ThemeOptions.REFERENCE) continue - - nodes.push(decl(escape(key), value.value)) + let node = decl(escape(key), value.value) + nodes.push(node) } let keyframesRules = designSystem.theme.getKeyframes() diff --git a/packages/tailwindcss/src/variants.test.ts b/packages/tailwindcss/src/variants.test.ts index 5da1dcac7..e1a1388f6 100644 --- a/packages/tailwindcss/src/variants.test.ts +++ b/packages/tailwindcss/src/variants.test.ts @@ -2526,7 +2526,7 @@ test('matchVariant sorts deterministically', async () => { for (let classList of classLists) { let output = await compileCss('@tailwind utilities; @plugin "./plugin.js";', classList, { - loadModule(id: string) { + async loadModule(id: string) { return { base: '/', module: createPlugin(({ matchVariant }) => {