Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 uid=33(www-data) gid=33(www-data) groups=33(www-data) Safe-mode: OFF (not secure) /usr/local/share/.cache/yarn/v6/npm-tailwindcss-2.2.17-integrity/node_modules/tailwindcss/lib/lib/ drwxr-xr-x | |
| Viewing file: Select action/file-type: "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = substituteClassApplyAtRules;
var _lodash = _interopRequireDefault(require("lodash"));
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _postcss = _interopRequireDefault(require("postcss"));
var _didyoumean = _interopRequireDefault(require("didyoumean"));
var _substituteTailwindAtRules = _interopRequireDefault(require("./substituteTailwindAtRules"));
var _evaluateTailwindFunctions = _interopRequireDefault(require("./evaluateTailwindFunctions"));
var _substituteVariantsAtRules = _interopRequireDefault(require("./substituteVariantsAtRules"));
var _substituteResponsiveAtRules = _interopRequireDefault(require("./substituteResponsiveAtRules"));
var _convertLayerAtRulesToControlComments = _interopRequireDefault(require("./convertLayerAtRulesToControlComments"));
var _substituteScreenAtRules = _interopRequireDefault(require("./substituteScreenAtRules"));
var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
var _useMemo = require("../util/useMemo");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function hasAtRule(css, atRule, condition) {
let found = false;
css.walkAtRules(atRule, condition === undefined ? () => {
found = true;
return false;
} : node => {
if (condition(node)) {
found = true;
return false;
}
});
return found;
}
function cloneWithoutChildren(node) {
if (node.type === 'atrule') {
return _postcss.default.atRule({
name: node.name,
params: node.params
});
}
if (node.type === 'rule') {
return _postcss.default.rule({
name: node.name,
selectors: node.selectors
});
}
const clone = node.clone();
clone.removeAll();
return clone;
}
const tailwindApplyPlaceholder = _postcssSelectorParser.default.attribute({
attribute: '__TAILWIND-APPLY-PLACEHOLDER__'
});
function generateRulesFromApply({
rule,
utilityName: className,
classPosition
}, replaceWiths) {
const parser = (0, _postcssSelectorParser.default)(selectors => {
let i = 0;
selectors.walkClasses(c => {
if (classPosition === i++ && c.value === className) {
c.replaceWith(tailwindApplyPlaceholder);
}
});
});
const processedSelectors = _lodash.default.flatMap(rule.selectors, selector => {
// You could argue we should make this replacement at the AST level, but if we believe
// the placeholder string is safe from collisions then it is safe to do this is a simple
// string replacement, and much, much faster.
return replaceWiths.map(replaceWith => parser.processSync(selector).replace('[__TAILWIND-APPLY-PLACEHOLDER__]', replaceWith));
});
const cloned = rule.clone();
let current = cloned;
let parent = rule.parent;
while (parent && parent.type !== 'root') {
const parentClone = cloneWithoutChildren(parent);
parentClone.append(current);
current.parent = parentClone;
current = parentClone;
parent = parent.parent;
}
cloned.selectors = processedSelectors;
return current;
}
const extractUtilityNamesParser = (0, _postcssSelectorParser.default)(selectors => {
let classes = [];
selectors.walkClasses(c => classes.push(c.value));
return classes;
});
const extractUtilityNames = (0, _useMemo.useMemo)(selector => extractUtilityNamesParser.transformSync(selector), selector => selector);
const cloneRuleWithParent = (0, _useMemo.useMemo)(rule => rule.clone({
parent: rule.parent
}), rule => rule);
function buildCssUtilityMap(css, startIndex) {
let index = startIndex;
const utilityMap = {};
function handle(getRule, rule) {
const utilityNames = extractUtilityNames(rule.selector);
utilityNames.forEach((utilityName, i) => {
if (utilityMap[utilityName] === undefined) {
utilityMap[utilityName] = [];
}
utilityMap[utilityName].push({
index,
utilityName,
classPosition: i,
...getRule(rule)
});
index++;
});
} // This is the end user's css. This might contain rules that we want to
// apply. We want immediate copies of everything in case that we have user
// defined classes that are recursively applied. Down below we are modifying
// the rules directly. We could do a better solution where we keep track of a
// dependency tree, but that is a bit more complex. Might revisit later,
// we'll see how this turns out!
css.walkRules(handle.bind(null, rule => ({
rule: cloneRuleWithParent(rule)
})));
return utilityMap;
}
const buildLookupTreeUtilityMap = (0, _useMemo.useMemo)(lookupTree => {
let index = 0;
const utilityMap = {};
function handle(getRule, rule) {
const utilityNames = extractUtilityNames(rule.selector);
utilityNames.forEach((utilityName, i) => {
if (utilityMap[utilityName] === undefined) {
utilityMap[utilityName] = [];
}
utilityMap[utilityName].push({
index,
utilityName,
classPosition: i,
...getRule(rule)
});
index++;
});
} // Lookup tree is the big lookup tree, making the rule lazy allows us to save
// some memory because we don't need everything.
lookupTree.walkRules(handle.bind(null, rule => ({
get rule() {
return cloneRuleWithParent(rule);
}
})));
return utilityMap;
}, tree => tree);
function mergeAdjacentRules(initialRule, rulesToInsert) {
let previousRule = initialRule;
rulesToInsert.forEach(toInsert => {
if (toInsert.type === 'rule' && previousRule.type === 'rule' && toInsert.selector === previousRule.selector) {
previousRule.append(toInsert.nodes);
} else if (toInsert.type === 'atrule' && previousRule.type === 'atrule' && toInsert.params === previousRule.params) {
const merged = mergeAdjacentRules(previousRule.nodes[previousRule.nodes.length - 1], toInsert.nodes);
previousRule.append(merged);
} else {
previousRule = toInsert;
}
toInsert.walk(n => {
if (n.nodes && n.nodes.length === 0) {
n.remove();
}
});
});
return rulesToInsert.filter(r => r.nodes.length > 0);
}
function makeExtractUtilityRules(css, lookupTree, config) {
const lookupTreeUtilityMap = buildLookupTreeUtilityMap(lookupTree);
const lookupTreeUtilityMapKeys = Object.keys(lookupTreeUtilityMap);
const utilityMap = buildCssUtilityMap(css, lookupTreeUtilityMapKeys.length);
function getUtility(utilityName) {
const utility = [];
if (lookupTreeUtilityMap[utilityName]) {
utility.push(...lookupTreeUtilityMap[utilityName]);
}
if (utilityMap[utilityName]) {
utility.push(...utilityMap[utilityName]);
}
if (utility.length > 0) return utility;
}
return function extractUtilityRules(utilityNames, rule) {
const combined = [];
utilityNames.forEach(utilityName => {
const utility = getUtility(utilityName);
if (utility === undefined) {
// Look for prefixed utility in case the user has goofed
const prefixedUtilityName = (0, _prefixSelector.default)(config.prefix, `.${utilityName}`).slice(1);
const prefixedUtility = getUtility(prefixedUtilityName);
if (prefixedUtility !== undefined) {
throw rule.error(`The \`${utilityName}\` class does not exist, but \`${prefixedUtilityName}\` does. Did you forget the prefix?`);
}
const suggestedClass = (0, _didyoumean.default)(utilityName, Object.keys(utilityMap).concat(lookupTreeUtilityMapKeys));
const suggestionMessage = suggestedClass ? `, but \`${suggestedClass}\` does` : '';
throw rule.error(`The \`${utilityName}\` class does not exist${suggestionMessage}. If you're sure that \`${utilityName}\` exists, make sure that any \`@import\` statements are being properly processed before Tailwind CSS sees your CSS, as \`@apply\` can only be used for classes in the same CSS tree.`, {
word: utilityName
});
}
combined.push(...utility);
});
return combined.sort((a, b) => a.index - b.index);
};
}
function findParent(rule, predicate) {
let parent = rule.parent;
while (parent) {
if (predicate(parent)) {
return parent;
}
parent = parent.parent;
}
throw new Error('No parent could be found');
}
function processApplyAtRules(css, lookupTree, config) {
const extractUtilityRules = makeExtractUtilityRules(css, lookupTree, config);
do {
css.walkAtRules('apply', applyRule => {
const parent = applyRule.parent; // Direct parent
const nearestParentRule = findParent(applyRule, r => r.type === 'rule');
const currentUtilityNames = extractUtilityNames(nearestParentRule.selector);
const [importantEntries, applyUtilityNames, important = importantEntries.length > 0] = _lodash.default.partition(applyRule.params.split(/[\s\t\n]+/g), n => n === '!important');
if (_lodash.default.intersection(applyUtilityNames, currentUtilityNames).length > 0) {
const currentUtilityName = _lodash.default.intersection(applyUtilityNames, currentUtilityNames)[0];
throw parent.error(`You cannot \`@apply\` the \`${currentUtilityName}\` utility here because it creates a circular dependency.`);
} // Extract any post-apply declarations and re-insert them after apply rules
const afterRule = parent.clone({
raws: {}
});
afterRule.nodes = afterRule.nodes.slice(parent.index(applyRule) + 1);
parent.nodes = parent.nodes.slice(0, parent.index(applyRule) + 1); // Sort applys to match CSS source order
const applys = extractUtilityRules(applyUtilityNames, applyRule); // Get new rules with the utility portion of the selector replaced with the new selector
const rulesToInsert = [];
applys.forEach(nearestParentRule === parent ? util => rulesToInsert.push(generateRulesFromApply(util, parent.selectors)) : util => util.rule.nodes.forEach(n => afterRule.append(n.clone())));
rulesToInsert.forEach(rule => {
if (rule.type === 'atrule') {
rule.walkRules(rule => {
rule.__tailwind = { ...rule.__tailwind,
important
};
});
} else {
rule.__tailwind = { ...rule.__tailwind,
important
};
}
});
const {
nodes
} = _lodash.default.tap(_postcss.default.root({
nodes: rulesToInsert
}), root => {
root.walkDecls(d => {
d.important = important;
});
});
const mergedRules = mergeAdjacentRules(nearestParentRule, [...nodes, afterRule]);
applyRule.remove();
parent.after(mergedRules); // If the base rule has nothing in it (all applys were pseudo or responsive variants),
// remove the rule fuggit.
if (parent.nodes.length === 0) {
parent.remove();
}
}); // We already know that we have at least 1 @apply rule. Otherwise this
// function would not have been called. Therefore we can execute this code
// at least once. This also means that in the best case scenario we only
// call this 2 times, instead of 3 times.
// 1st time -> before we call this function
// 2nd time -> when we check if we have to do this loop again (because do {} while (check))
// .. instead of
// 1st time -> before we call this function
// 2nd time -> when we check the first time (because while (check) do {})
// 3rd time -> when we re-check to see if we should do this loop again
} while (hasAtRule(css, 'apply'));
return css;
}
let defaultTailwindTree = new Map();
function substituteClassApplyAtRules(config, getProcessedPlugins, configChanged) {
return function (css) {
// We can stop already when we don't have any @apply rules. Vue users: you're welcome!
if (!hasAtRule(css, 'apply')) {
return css;
}
let requiredTailwindAtRules = ['base', 'components', 'utilities'];
if (hasAtRule(css, 'tailwind', node => {
let idx = requiredTailwindAtRules.indexOf(node.params);
if (idx !== -1) requiredTailwindAtRules.splice(idx, 1);
if (requiredTailwindAtRules.length <= 0) return true;
return false;
})) {
// Tree already contains all the at rules (requiredTailwindAtRules)
return processApplyAtRules(css, _postcss.default.root(), config);
}
let lookupKey = requiredTailwindAtRules.join(','); // We mutated the `requiredTailwindAtRules`, but when we hit this point in
// time, it means that we don't have all the atrules. The missing atrules
// are listed inside the requiredTailwindAtRules, which we can use to fill
// in the missing pieces.
//
// Important for <style> blocks in Vue components.
const generateLookupTree = configChanged || !defaultTailwindTree.has(lookupKey) ? () => {
return (0, _postcss.default)([(0, _substituteTailwindAtRules.default)(config, getProcessedPlugins()), (0, _evaluateTailwindFunctions.default)({
tailwindConfig: config
}), (0, _substituteVariantsAtRules.default)(config, getProcessedPlugins()), (0, _substituteResponsiveAtRules.default)(config), (0, _convertLayerAtRulesToControlComments.default)(config), (0, _substituteScreenAtRules.default)({
tailwindConfig: config
})]).process(requiredTailwindAtRules.map(rule => `@tailwind ${rule};`).join('\n'), {
from: __filename
}).then(result => {
defaultTailwindTree.set(lookupKey, result);
return result;
});
} : () => Promise.resolve(defaultTailwindTree.get(lookupKey));
return generateLookupTree().then(result => {
return processApplyAtRules(css, result.root, config);
});
};
} |
:: Command execute :: | |
--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.005 ]-- |