Skip to content

Commit 41e383a

Browse files
Make the @property stuff disable-able
1 parent 1e811d1 commit 41e383a

File tree

4 files changed

+183
-38
lines changed

4 files changed

+183
-38
lines changed

packages/tailwindcss/src/ast.ts

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Polyfills } from '.'
12
import { parseAtRule } from './css-parser'
23
import type { DesignSystem } from './design-system'
34
import { Theme, ThemeOptions } from './theme'
@@ -258,7 +259,11 @@ export function walkDepth(
258259

259260
// Optimize the AST for printing where all the special nodes that require custom
260261
// handling are handled such that the printing is a 1-to-1 transformation.
261-
export function optimizeAst(ast: AstNode[], designSystem: DesignSystem) {
262+
export function optimizeAst(
263+
ast: AstNode[],
264+
designSystem: DesignSystem,
265+
polyfills: Polyfills = Polyfills.All,
266+
) {
262267
let atRoots: AstNode[] = []
263268
let seenAtProperties = new Set<string>()
264269
let cssThemeVariables = new DefaultMap<
@@ -387,23 +392,25 @@ export function optimizeAst(ast: AstNode[], designSystem: DesignSystem) {
387392
// Collect fallbacks for `@property` rules for Firefox support
388393
// We turn these into rules on `:root` or `*` and some pseudo-elements
389394
// based on the value of `inherits``
390-
let property = node.params
391-
let initialValue = null
392-
let inherits = false
393-
394-
for (let prop of node.nodes) {
395-
if (prop.kind !== 'declaration') continue
396-
if (prop.property === 'initial-value') {
397-
initialValue = prop.value
398-
} else if (prop.property === 'inherits') {
399-
inherits = prop.value === 'true'
395+
if (polyfills & Polyfills.PolyfillAtProperty) {
396+
let property = node.params
397+
let initialValue = null
398+
let inherits = false
399+
400+
for (let prop of node.nodes) {
401+
if (prop.kind !== 'declaration') continue
402+
if (prop.property === 'initial-value') {
403+
initialValue = prop.value
404+
} else if (prop.property === 'inherits') {
405+
inherits = prop.value === 'true'
406+
}
400407
}
401-
}
402408

403-
if (inherits) {
404-
propertyFallbacksRoot.push(decl(property, initialValue ?? 'initial'))
405-
} else {
406-
propertyFallbacksUniversal.push(decl(property, initialValue ?? 'initial'))
409+
if (inherits) {
410+
propertyFallbacksRoot.push(decl(property, initialValue ?? 'initial'))
411+
} else {
412+
propertyFallbacksUniversal.push(decl(property, initialValue ?? 'initial'))
413+
}
407414
}
408415

409416
seenAtProperties.add(node.params)
@@ -549,25 +556,27 @@ export function optimizeAst(ast: AstNode[], designSystem: DesignSystem) {
549556
}
550557

551558
// Fallbacks
552-
{
553-
let fallbackAst = []
559+
if (polyfills & Polyfills.PolyfillAtProperty) {
560+
{
561+
let fallbackAst = []
554562

555-
if (propertyFallbacksRoot.length > 0) {
556-
fallbackAst.push(rule(':root', propertyFallbacksRoot))
557-
}
563+
if (propertyFallbacksRoot.length > 0) {
564+
fallbackAst.push(rule(':root, :host', propertyFallbacksRoot))
565+
}
558566

559-
if (propertyFallbacksUniversal.length > 0) {
560-
fallbackAst.push(rule('*, ::before, ::after, ::backdrop', propertyFallbacksUniversal))
561-
}
567+
if (propertyFallbacksUniversal.length > 0) {
568+
fallbackAst.push(rule('*, ::before, ::after, ::backdrop', propertyFallbacksUniversal))
569+
}
562570

563-
if (fallbackAst.length > 0) {
564-
newAst.push(
565-
atRule(
566-
'@supports',
567-
'((-webkit-hyphens: none) and (not (margin-trim: 1lh))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))',
568-
[atRule('@layer', 'base', fallbackAst)],
569-
),
570-
)
571+
if (fallbackAst.length > 0) {
572+
newAst.push(
573+
atRule(
574+
'@supports',
575+
'((-webkit-hyphens: none) and (not (margin-trim: 1lh))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b))))',
576+
[atRule('@layer', 'base', fallbackAst)],
577+
),
578+
)
579+
}
571580
}
572581
}
573582

packages/tailwindcss/src/design-system.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Polyfills } from '.'
12
import { optimizeAst, toCss } from './ast'
23
import { parseCandidate, parseVariant, type Candidate, type Variant } from './candidate'
34
import { compileAstNodes, compileCandidates } from './compile'
@@ -94,7 +95,8 @@ export function buildDesignSystem(theme: Theme): DesignSystem {
9495
},
9596
})
9697

97-
astNodes = optimizeAst(astNodes, designSystem)
98+
// Disable all polyfills to not unnecessarily pollute IntelliSense output
99+
astNodes = optimizeAst(astNodes, designSystem, Polyfills.None)
98100

99101
if (astNodes.length === 0 || wasInvalid) {
100102
result.push(null)

packages/tailwindcss/src/index.test.ts

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from 'node:fs'
22
import path from 'node:path'
33
import { describe, expect, it, test } from 'vitest'
4-
import { compile } from '.'
4+
import { compile, Polyfills } from '.'
55
import type { PluginAPI } from './compat/plugin-api'
66
import plugin from './plugin'
77
import { compileCss, optimizeCss, run } from './test-utils/run'
@@ -4897,3 +4897,126 @@ describe('`color-mix(…)` polyfill', () => {
48974897
`)
48984898
})
48994899
})
4900+
4901+
describe('`@property` polyfill', async () => {
4902+
it('emits fallbacks', async () => {
4903+
await expect(
4904+
compileCss(
4905+
css`
4906+
@tailwind utilities;
4907+
4908+
@property --no-inherit-no-value {
4909+
syntax: '*';
4910+
inherits: false;
4911+
}
4912+
@property --no-inherit-value {
4913+
syntax: '*';
4914+
inherits: false;
4915+
initial-value: red;
4916+
}
4917+
@property --inherit-no-value {
4918+
syntax: '*';
4919+
inherits: true;
4920+
}
4921+
@property --inherit-value {
4922+
syntax: '*';
4923+
inherits: true;
4924+
initial-value: red;
4925+
}
4926+
`,
4927+
[],
4928+
),
4929+
).resolves.toMatchInlineSnapshot(`
4930+
"@property --no-inherit-no-value {
4931+
syntax: "*";
4932+
inherits: false
4933+
}
4934+
4935+
@property --no-inherit-value {
4936+
syntax: "*";
4937+
inherits: false;
4938+
initial-value: red;
4939+
}
4940+
4941+
@property --inherit-no-value {
4942+
syntax: "*";
4943+
inherits: true
4944+
}
4945+
4946+
@property --inherit-value {
4947+
syntax: "*";
4948+
inherits: true;
4949+
initial-value: red;
4950+
}
4951+
4952+
@supports (((-webkit-hyphens: none)) and (not (margin-trim: 1lh))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
4953+
@layer base {
4954+
:root, :host {
4955+
--inherit-no-value: initial;
4956+
--inherit-value: red;
4957+
}
4958+
4959+
*, :before, :after, ::backdrop {
4960+
--no-inherit-no-value: initial;
4961+
--no-inherit-value: red;
4962+
}
4963+
}
4964+
}"
4965+
`)
4966+
})
4967+
4968+
it.only('can be disabled to not emit fallbacks (necessary for CSS modules)', async () => {
4969+
await expect(
4970+
compileCss(
4971+
css`
4972+
@tailwind utilities;
4973+
4974+
@property --no-inherit-no-value {
4975+
syntax: '*';
4976+
inherits: false;
4977+
}
4978+
@property --no-inherit-value {
4979+
syntax: '*';
4980+
inherits: false;
4981+
initial-value: red;
4982+
}
4983+
@property --inherit-no-value {
4984+
syntax: '*';
4985+
inherits: true;
4986+
}
4987+
@property --inherit-value {
4988+
syntax: '*';
4989+
inherits: true;
4990+
initial-value: red;
4991+
}
4992+
`,
4993+
[],
4994+
{
4995+
polyfills: Polyfills.None,
4996+
},
4997+
),
4998+
).resolves.toMatchInlineSnapshot(`
4999+
"@property --no-inherit-no-value {
5000+
syntax: "*";
5001+
inherits: false
5002+
}
5003+
5004+
@property --no-inherit-value {
5005+
syntax: "*";
5006+
inherits: false;
5007+
initial-value: red;
5008+
}
5009+
5010+
@property --inherit-no-value {
5011+
syntax: "*";
5012+
inherits: true
5013+
}
5014+
5015+
@property --inherit-value {
5016+
syntax: "*";
5017+
inherits: true;
5018+
initial-value: red;
5019+
}"
5020+
`)
5021+
})
5022+
})

packages/tailwindcss/src/index.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,19 @@ export type Config = UserConfig
3737

3838
const IS_VALID_PREFIX = /^[a-z]+$/
3939

40+
export const enum Polyfills {
41+
None = 0,
42+
43+
// Control if fallbacks for `@property` rules are emitted
44+
PolyfillAtProperty = 1 << 0,
45+
46+
// Enable all
47+
All = PolyfillAtProperty,
48+
}
49+
4050
type CompileOptions = {
4151
base?: string
52+
polyfills?: Polyfills
4253
loadModule?: (
4354
id: string,
4455
base: string,
@@ -697,7 +708,7 @@ export async function compileAst(
697708
}
698709

699710
if (!utilitiesNode) {
700-
compiled ??= optimizeAst(ast, designSystem)
711+
compiled ??= optimizeAst(ast, designSystem, opts.polyfills)
701712
return compiled
702713
}
703714

@@ -723,7 +734,7 @@ export async function compileAst(
723734
// If no new candidates were added, we can return the original CSS. This
724735
// currently assumes that we only add new candidates and never remove any.
725736
if (!didChange) {
726-
compiled ??= optimizeAst(ast, designSystem)
737+
compiled ??= optimizeAst(ast, designSystem, opts.polyfills)
727738
return compiled
728739
}
729740

@@ -735,15 +746,15 @@ export async function compileAst(
735746
// CSS. This currently assumes that we only add new ast nodes and never
736747
// remove any.
737748
if (!didAddExternalVariable && previousAstNodeCount === newNodes.length) {
738-
compiled ??= optimizeAst(ast, designSystem)
749+
compiled ??= optimizeAst(ast, designSystem, opts.polyfills)
739750
return compiled
740751
}
741752

742753
previousAstNodeCount = newNodes.length
743754

744755
utilitiesNode.nodes = newNodes
745756

746-
compiled = optimizeAst(ast, designSystem)
757+
compiled = optimizeAst(ast, designSystem, opts.polyfills)
747758
return compiled
748759
},
749760
}

0 commit comments

Comments
 (0)