From b1e2c8fd5cb5dfa46bc440a12eafaf56cd844b1c Mon Sep 17 00:00:00 2001 From: Philipp Tanlak Date: Mon, 24 Nov 2025 20:54:57 +0100 Subject: Docs --- .../tailwindcss/src/lib/expandTailwindAtRules.js | 297 +++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 node_modules/tailwindcss/src/lib/expandTailwindAtRules.js (limited to 'node_modules/tailwindcss/src/lib/expandTailwindAtRules.js') diff --git a/node_modules/tailwindcss/src/lib/expandTailwindAtRules.js b/node_modules/tailwindcss/src/lib/expandTailwindAtRules.js new file mode 100644 index 0000000..2933d6f --- /dev/null +++ b/node_modules/tailwindcss/src/lib/expandTailwindAtRules.js @@ -0,0 +1,297 @@ +import fs from 'fs' +import LRU from '@alloc/quick-lru' +import * as sharedState from './sharedState' +import { generateRules } from './generateRules' +import log from '../util/log' +import cloneNodes from '../util/cloneNodes' +import { defaultExtractor } from './defaultExtractor' + +let env = sharedState.env + +const builtInExtractors = { + DEFAULT: defaultExtractor, +} + +const builtInTransformers = { + DEFAULT: (content) => content, + svelte: (content) => content.replace(/(?:^|\s)class:/g, ' '), +} + +function getExtractor(context, fileExtension) { + let extractors = context.tailwindConfig.content.extract + + return ( + extractors[fileExtension] || + extractors.DEFAULT || + builtInExtractors[fileExtension] || + builtInExtractors.DEFAULT(context) + ) +} + +function getTransformer(tailwindConfig, fileExtension) { + let transformers = tailwindConfig.content.transform + + return ( + transformers[fileExtension] || + transformers.DEFAULT || + builtInTransformers[fileExtension] || + builtInTransformers.DEFAULT + ) +} + +let extractorCache = new WeakMap() + +// Scans template contents for possible classes. This is a hot path on initial build but +// not too important for subsequent builds. The faster the better though — if we can speed +// up these regexes by 50% that could cut initial build time by like 20%. +function getClassCandidates(content, extractor, candidates, seen) { + if (!extractorCache.has(extractor)) { + extractorCache.set(extractor, new LRU({ maxSize: 25000 })) + } + + for (let line of content.split('\n')) { + line = line.trim() + + if (seen.has(line)) { + continue + } + seen.add(line) + + if (extractorCache.get(extractor).has(line)) { + for (let match of extractorCache.get(extractor).get(line)) { + candidates.add(match) + } + } else { + let extractorMatches = extractor(line).filter((s) => s !== '!*') + let lineMatchesSet = new Set(extractorMatches) + + for (let match of lineMatchesSet) { + candidates.add(match) + } + + extractorCache.get(extractor).set(line, lineMatchesSet) + } + } +} + +/** + * + * @param {[import('./offsets.js').RuleOffset, import('postcss').Node][]} rules + * @param {*} context + */ +function buildStylesheet(rules, context) { + let sortedRules = context.offsets.sort(rules) + + let returnValue = { + base: new Set(), + defaults: new Set(), + components: new Set(), + utilities: new Set(), + variants: new Set(), + } + + for (let [sort, rule] of sortedRules) { + returnValue[sort.layer].add(rule) + } + + return returnValue +} + +export default function expandTailwindAtRules(context) { + return async (root) => { + let layerNodes = { + base: null, + components: null, + utilities: null, + variants: null, + } + + root.walkAtRules((rule) => { + // Make sure this file contains Tailwind directives. If not, we can save + // a lot of work and bail early. Also we don't have to register our touch + // file as a dependency since the output of this CSS does not depend on + // the source of any templates. Think Vue