mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Make custom @at-root private API (#14618)
This PR makes the internal `@at-root` API private. Before this PR you could use `@at-root` in your own CSS, which means that it was part of the public API. If you (accidentally) used it in variants, you could generate CSS that was completely broken. This now introduces a new private `AtRoot` node (similar to the recently introduced `Context` node) and can only be constructed within the framework.
This commit is contained in:
parent
7be5346e2e
commit
68c32d1a60
@ -22,7 +22,12 @@ export type Context = {
|
||||
nodes: AstNode[]
|
||||
}
|
||||
|
||||
export type AstNode = Rule | Declaration | Comment | Context
|
||||
export type AtRoot = {
|
||||
kind: 'at-root'
|
||||
nodes: AstNode[]
|
||||
}
|
||||
|
||||
export type AstNode = Rule | Declaration | Comment | Context | AtRoot
|
||||
|
||||
export function rule(selector: string, nodes: AstNode[]): Rule {
|
||||
return {
|
||||
@ -56,6 +61,13 @@ export function context(context: Record<string, string>, nodes: AstNode[]): Cont
|
||||
}
|
||||
}
|
||||
|
||||
export function atRoot(nodes: AstNode[]): AtRoot {
|
||||
return {
|
||||
kind: 'at-root',
|
||||
nodes,
|
||||
}
|
||||
}
|
||||
|
||||
export enum WalkAction {
|
||||
/** Continue walking, which is the default */
|
||||
Continue,
|
||||
@ -128,14 +140,6 @@ export function toCss(ast: AstNode[]) {
|
||||
|
||||
// Rule
|
||||
if (node.kind === 'rule') {
|
||||
// Pull out `@at-root` rules to append later
|
||||
if (node.selector === '@at-root') {
|
||||
for (let child of node.nodes) {
|
||||
atRoots += stringify(child, 0)
|
||||
}
|
||||
return css
|
||||
}
|
||||
|
||||
if (node.selector === '@tailwind utilities') {
|
||||
for (let child of node.nodes) {
|
||||
css += stringify(child, depth)
|
||||
@ -204,6 +208,14 @@ export function toCss(ast: AstNode[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// AtRoot Node
|
||||
else if (node.kind === 'at-root') {
|
||||
for (let child of node.nodes) {
|
||||
atRoots += stringify(child, 0)
|
||||
}
|
||||
return css
|
||||
}
|
||||
|
||||
// Declaration
|
||||
else if (node.property !== '--tw-sort' && node.value !== undefined && node.value !== null) {
|
||||
css += `${indent}${node.property}: ${node.value}${node.important ? ' !important' : ''};\n`
|
||||
|
||||
@ -293,9 +293,9 @@ function compileBaseUtility(candidate: Candidate, designSystem: DesignSystem) {
|
||||
|
||||
function applyImportant(ast: AstNode[]): void {
|
||||
for (let node of ast) {
|
||||
// Skip any `@at-root` rules — we don't want to make the contents of things
|
||||
// Skip any `AtRoot` nodes — we don't want to make the contents of things
|
||||
// like `@keyframes` or `@property` important.
|
||||
if (node.kind === 'rule' && node.selector === '@at-root') {
|
||||
if (node.kind === 'at-root') {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -328,10 +328,6 @@ function getPropertySort(nodes: AstNode[]) {
|
||||
let idx = GLOBAL_PROPERTY_ORDER.indexOf(node.property)
|
||||
if (idx !== -1) propertySort.add(idx)
|
||||
} else if (node.kind === 'rule') {
|
||||
// Don't consider properties within `@at-root` when determining the sort
|
||||
// order for a rule.
|
||||
if (node.selector === '@at-root') continue
|
||||
|
||||
for (let child of node.nodes) {
|
||||
q.push(child)
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { version } from '../package.json'
|
||||
import { substituteAtApply } from './apply'
|
||||
import {
|
||||
atRoot,
|
||||
comment,
|
||||
context,
|
||||
decl,
|
||||
@ -361,13 +362,10 @@ async function parseCss(
|
||||
continue
|
||||
}
|
||||
|
||||
// Wrap `@keyframes` in `@at-root` so they are hoisted out of `:root`
|
||||
// when printing.
|
||||
// Wrap `@keyframes` in `AtRoot` so they are hoisted out of `:root` when
|
||||
// printing.
|
||||
nodes.push(
|
||||
Object.assign(keyframesRule, {
|
||||
selector: '@at-root',
|
||||
nodes: [rule(keyframesRule.selector, keyframesRule.nodes)],
|
||||
}),
|
||||
Object.assign(keyframesRule, atRoot([rule(keyframesRule.selector, keyframesRule.nodes)])),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { decl, rule, type AstNode, type Rule } from './ast'
|
||||
import { atRoot, decl, rule, type AstNode } from './ast'
|
||||
import type { Candidate, CandidateModifier, NamedUtilityValue } from './candidate'
|
||||
import type { Theme, ThemeKey } from './theme'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
@ -84,10 +84,6 @@ export class Utilities {
|
||||
}
|
||||
}
|
||||
|
||||
function atRoot(rules: Rule[]) {
|
||||
return rule('@at-root', rules)
|
||||
}
|
||||
|
||||
function property(ident: string, initialValue?: string, syntax?: string) {
|
||||
return rule(`@property ${ident}`, [
|
||||
decl('syntax', syntax ? `"${syntax}"` : `"*"`),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { WalkAction, decl, rule, walk, type AstNode, type Rule } from './ast'
|
||||
import { WalkAction, atRoot, decl, rule, walk, type AstNode, type Rule } from './ast'
|
||||
import { type Variant } from './candidate'
|
||||
import type { Theme } from './theme'
|
||||
import { DefaultMap } from './utils/default-map'
|
||||
@ -380,7 +380,7 @@ export function createVariants(theme: Theme): Variants {
|
||||
|
||||
{
|
||||
function contentProperties() {
|
||||
return rule('@at-root', [
|
||||
return atRoot([
|
||||
rule('@property --tw-content', [
|
||||
decl('syntax', '"*"'),
|
||||
decl('initial-value', '""'),
|
||||
@ -933,16 +933,13 @@ export function substituteAtSlot(ast: AstNode[], nodes: AstNode[]) {
|
||||
replaceWith(nodes)
|
||||
}
|
||||
|
||||
// Wrap `@keyframes` and `@property` in `@at-root`
|
||||
// Wrap `@keyframes` and `@property` in `AtRoot` nodes
|
||||
else if (
|
||||
node.kind === 'rule' &&
|
||||
node.selector[0] === '@' &&
|
||||
(node.selector.startsWith('@keyframes ') || node.selector.startsWith('@property '))
|
||||
) {
|
||||
Object.assign(node, {
|
||||
selector: '@at-root',
|
||||
nodes: [rule(node.selector, node.nodes)],
|
||||
})
|
||||
Object.assign(node, atRoot([rule(node.selector, node.nodes)]))
|
||||
return WalkAction.Skip
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user