MCPcopy
hub / github.com/tailwindlabs/tailwindcss / applyVariant

Function applyVariant

packages/tailwindcss/src/compile.ts:177–258  ·  view source on GitHub ↗
(
  node: Rule,
  variant: Variant,
  variants: Variants,
  depth: number = 0,
)

Source from the content-addressed store, hash-verified

175}
176
177export function applyVariant(
178 node: Rule,
179 variant: Variant,
180 variants: Variants,
181 depth: number = 0,
182): null | void {
183 if (variant.kind === 'arbitrary') {
184 // Relative selectors are not valid as an entire arbitrary variant, only as
185 // an arbitrary variant that is part of another compound variant.
186 //
187 // E.g. `[>img]:flex` is not valid, but `has-[>img]:flex` is
188 if (variant.relative && depth === 0) return null
189
190 node.nodes = [rule(variant.selector, node.nodes)]
191 return
192 }
193
194 // SAFETY: At this point it is safe to use TypeScript's non-null assertion
195 // operator because if the `candidate.root` didn't exist, `parseCandidate`
196 // would have returned `null` and we would have returned early resulting in
197 // not hitting this code path.
198 let { applyFn } = variants.get(variant.root)!
199
200 if (variant.kind === 'compound') {
201 // Some variants traverse the AST to mutate the nodes. E.g.: `group-*` wants
202 // to prefix every selector of the variant it's compounding with `.group`.
203 //
204 // E.g.:
205 // ```
206 // group-hover:[&_p]:flex
207 // ```
208 //
209 // Should only prefix the `group-hover` part with `.group`, and not the `&_p` part.
210 //
211 // To solve this, we provide an isolated placeholder node to the variant.
212 // The variant can now apply its logic to the isolated node without
213 // affecting the original node.
214 let isolatedNode = atRule('@slot')
215
216 let result = applyVariant(isolatedNode, variant.variant, variants, depth + 1)
217 if (result === null) return null
218
219 if (variant.root === 'not' && isolatedNode.nodes.length > 1) {
220 // The `not` variant cannot negate sibling rules / at-rules because these
221 // are an OR relationship. Doing so would require transforming sibling
222 // nodes into nesting while negating them. This isn't possible with the
223 // current implementation of the `not` variant or with how variants are
224 // applied in general (on a per-node basis).
225 return null
226 }
227
228 for (let child of isolatedNode.nodes) {
229 // Only some variants wrap children in rules. For example, the `force`
230 // variant is a noop on the AST. And the `has` variant modifies the
231 // selector rather than the children.
232 //
233 // This means `child` may be a declaration and we don't want to apply the
234 // variant to it. This also means the entire variant as a whole is not

Callers 3

selectorsFunction · 0.90
substituteAtVariantFunction · 0.90
compileAstNodesFunction · 0.85

Calls 4

ruleFunction · 0.90
atRuleFunction · 0.90
walkFunction · 0.90
getMethod · 0.45

Tested by

no test coverage detected