Socket
Socket
Sign inDemoInstall

tailwindcss

Package Overview
Dependencies
Maintainers
4
Versions
1731
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tailwindcss - npm Package Compare versions

Comparing version 3.3.3 to 3.3.5

nesting/index.d.ts

2

lib/cli/build/watching.js

@@ -129,3 +129,3 @@ // @ts-check

watcher.on("raw", (evt, filePath, meta)=>{
if (evt !== "rename") {
if (evt !== "rename" || filePath === null) {
return;

@@ -132,0 +132,0 @@ }

@@ -11,3 +11,2 @@ "use strict";

});
const _featureFlags = require("../featureFlags");
const _regex = /*#__PURE__*/ _interop_require_wildcard(require("./regex"));

@@ -61,8 +60,7 @@ function _getRequireWildcardCache(nodeInterop) {

var _content_match;
results = [
...results,
...(_content_match = content.match(pattern)) !== null && _content_match !== void 0 ? _content_match : []
];
for (let result of (_content_match = content.match(pattern)) !== null && _content_match !== void 0 ? _content_match : []){
results.push(clipAtBalancedParens(result));
}
}
return results.filter((v)=>v !== undefined).map(clipAtBalancedParens);
return results;
};

@@ -72,3 +70,2 @@ }

let separator = context.tailwindConfig.separator;
let variantGroupingEnabled = (0, _featureFlags.flagEnabled)(context.tailwindConfig, "variantGrouping");
let prefix = context.tailwindConfig.prefix !== "" ? _regex.optional(_regex.pattern([

@@ -85,3 +82,3 @@ /-?/,

// while fixing a problem with the regex matching too much
/\[[^\s:'"`]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
// Utilities

@@ -122,3 +119,8 @@ _regex.pattern([

]),
// With variant modifier (e.g.: group-[..]/modifier)
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/\w+/,
separator
]),
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,

@@ -134,3 +136,8 @@ separator

_regex.any([
// With variant modifier (e.g.: group-[..]/modifier)
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/\w+/,
separator
]),
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s`]+\]/,

@@ -154,16 +161,3 @@ separator

prefix,
variantGroupingEnabled ? _regex.any([
// Or any of those things but grouped separated by commas
_regex.pattern([
/\(/,
utility,
_regex.zeroOrMore([
/,/,
utility
]),
/\)/
]),
// Arbitrary properties, constrained utilities, arbitrary values, etc…
utility
]) : utility
utility
]);

@@ -170,0 +164,0 @@ }

@@ -485,2 +485,8 @@ "use strict";

let parentSelector = isGenerated && importantSelector && parent.selector.indexOf(importantSelector) === 0 ? parent.selector.slice(importantSelector.length) : parent.selector;
// If the selector becomes empty after replacing the important selector
// This means that it's the same as the parent selector and we don't want to replace it
// Otherwise we'll crash
if (parentSelector === "") {
parentSelector = parent.selector;
}
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate);

@@ -487,0 +493,0 @@ // And then re-add it if it was removed

@@ -168,8 +168,22 @@ "use strict";

} else {
await Promise.all(context.changedContent.map(async ({ file , content , extension })=>{
let transformer = getTransformer(context.tailwindConfig, extension);
let extractor = getExtractor(context, extension);
content = file ? await _fs.default.promises.readFile(file, "utf8") : content;
getClassCandidates(transformer(content), extractor, candidates, seen);
}));
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */ let regexParserContent = [];
for (let item of context.changedContent){
let transformer = getTransformer(context.tailwindConfig, item.extension);
let extractor = getExtractor(context, item.extension);
regexParserContent.push([
item,
{
transformer,
extractor
}
]);
}
const BATCH_SIZE = 500;
for(let i = 0; i < regexParserContent.length; i += BATCH_SIZE){
let batch = regexParserContent.slice(i, i + BATCH_SIZE);
await Promise.all(batch.map(async ([{ file , content }, { transformer , extractor }])=>{
content = file ? await _fs.default.promises.readFile(file, "utf8") : content;
getClassCandidates(transformer(content), extractor, candidates, seen);
}));
}
}

@@ -176,0 +190,0 @@ env.DEBUG && console.timeEnd("Reading changed files");

@@ -503,3 +503,5 @@ "use strict";

}
let normalized = (0, _dataTypes.normalize)(value);
let normalized = (0, _dataTypes.normalize)(value, {
property
});
if (!isParsableCssValue(property, normalized)) {

@@ -582,3 +584,3 @@ return null;

}
function* resolveMatches(candidate, context, original = candidate) {
function* resolveMatches(candidate, context) {
let separator = context.tailwindConfig.separator;

@@ -591,10 +593,2 @@ let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse();

}
if ((0, _featureFlags.flagEnabled)(context.tailwindConfig, "variantGrouping")) {
if (classCandidate.startsWith("(") && classCandidate.endsWith(")")) {
let base = variants.slice().reverse().join(separator);
for (let part of (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(classCandidate.slice(1, -1), ",")){
yield* resolveMatches(base + separator + part, context, original);
}
}
}
// TODO: Reintroduce this in ways that doesn't break on false positives

@@ -759,4 +753,3 @@ // function sortAgainst(toSort, against) {

context,
candidate,
original
candidate
});

@@ -773,3 +766,3 @@ // Skip rules with invalid selectors

}
function applyFinalFormat(match, { context , candidate , original }) {
function applyFinalFormat(match, { context , candidate }) {
if (!match[0].collectedFormats) {

@@ -807,6 +800,13 @@ return match;

try {
rule.selector = (0, _formatVariantSelector.finalizeSelector)(rule.selector, finalFormat, {
candidate: original,
let selector = (0, _formatVariantSelector.finalizeSelector)(rule.selector, finalFormat, {
candidate,
context
});
// Finalize Selector determined that this candidate is irrelevant
// TODO: This elimination should happen earlier so this never happens
if (selector === null) {
rule.remove();
return;
}
rule.selector = selector;
} catch {

@@ -852,3 +852,3 @@ // If this selector is invalid we also want to skip it

}
function generateRules(candidates, context) {
function generateRules(candidates, context, isSorting = false) {
let allRules = [];

@@ -884,5 +884,7 @@ let strategy = getImportantStrategy(context.tailwindConfig.important);

}
// Note: We have to clone rules during sorting
// so we eliminate some shared mutable state
let newEntry = [
sort,
rule
isSorting ? rule.clone() : rule
];

@@ -889,0 +891,0 @@ rules.add(newEntry);

@@ -204,2 +204,16 @@ "use strict";

}
/**
* Ignore everything inside a :not(...). This allows you to write code like
* `div:not(.foo)`. If `.foo` is never found in your code, then we used to
* not generated it. But now we will ignore everything inside a `:not`, so
* that it still gets generated.
*
* @param {selectorParser.Root} selectors
*/ function ignoreNot(selectors) {
selectors.walkPseudos((pseudo)=>{
if (pseudo.value === ":not") {
pseudo.remove();
}
});
}
function extractCandidates(node, state = {

@@ -209,31 +223,19 @@ containsNonOnDemandable: false

let classes = [];
// Handle normal rules
let selectors = [];
if (node.type === "rule") {
// Ignore everything inside a :not(...). This allows you to write code like
// `div:not(.foo)`. If `.foo` is never found in your code, then we used to
// not generated it. But now we will ignore everything inside a `:not`, so
// that it still gets generated.
function ignoreNot(selectors) {
selectors.walkPseudos((pseudo)=>{
if (pseudo.value === ":not") {
pseudo.remove();
}
});
// Handle normal rules
selectors.push(...node.selectors);
} else if (node.type === "atrule") {
// Handle at-rules (which contains nested rules)
node.walkRules((rule)=>selectors.push(...rule.selectors));
}
for (let selector of selectors){
let classCandidates = getClasses(selector, ignoreNot);
// At least one of the selectors contains non-"on-demandable" candidates.
if (classCandidates.length === 0) {
state.containsNonOnDemandable = true;
}
for (let selector of node.selectors){
let classCandidates = getClasses(selector, ignoreNot);
// At least one of the selectors contains non-"on-demandable" candidates.
if (classCandidates.length === 0) {
state.containsNonOnDemandable = true;
}
for (let classCandidate of classCandidates){
classes.push(classCandidate);
}
for (let classCandidate of classCandidates){
classes.push(classCandidate);
}
} else if (node.type === "atrule") {
node.walkRules((rule)=>{
for (let classCandidate of rule.selectors.flatMap((selector)=>getClasses(selector))){
classes.push(classCandidate);
}
});
}

@@ -932,3 +934,3 @@ if (depth === 0) {

// Non-tailwind classes won't be generated and will be left as `null`
let rules = (0, _generateRules.generateRules)(new Set(sorted), context);
let rules = (0, _generateRules.generateRules)(new Set(sorted), context, true);
rules = context.offsets.sort(rules);

@@ -935,0 +937,0 @@ let idx = BigInt(parasiteUtilities.length);

@@ -247,5 +247,5 @@ "use strict";

postcssPlugin: "tailwindcss",
Once (root, { result }) {
async Once (root, { result }) {
_sharedState.env.DEBUG && console.time("Compiling CSS");
(0, _processTailwindFeatures.default)(({ createContext })=>{
await (0, _processTailwindFeatures.default)(({ createContext })=>{
console.error();

@@ -252,0 +252,0 @@ console.error("Rebuilding...");

@@ -30,3 +30,3 @@ "use strict";

let ALPHA_SEP = /\s*[,/]\s*/;
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/;
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/;
let RGB = new RegExp(`^(rgba?)\\(\\s*(${VALUE.source}|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`);

@@ -33,0 +33,0 @@ let HSL = new RegExp(`^(hsla?)\\(\\s*((?:${VALUE.source})(?:deg|rad|grad|turn)?|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`);

@@ -71,6 +71,26 @@ "use strict";

}
const placeholder = "--tw-placeholder";
const placeholderRe = new RegExp(placeholder, "g");
function normalize(value, isRoot = true) {
if (value.startsWith("--")) {
// These properties accept a `<dashed-ident>` as one of the values. This means that you can use them
// as: `timeline-scope: --tl;`
//
// Without the `var(--tl)`, in these cases we don't want to normalize the value, and you should add
// the `var()` yourself.
//
// More info:
// - https://drafts.csswg.org/scroll-animations/#propdef-timeline-scope
// - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident
//
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
// Concrete properties
"scroll-timeline-name",
"timeline-scope",
"view-timeline-name",
"font-palette",
// Shorthand properties
"scroll-timeline",
"animation-timeline",
"view-timeline"
]);
function normalize(value, context = null, isRoot = true) {
let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property);
if (value.startsWith("--") && !isVarException) {
return `var(${value})`;

@@ -84,3 +104,3 @@ }

}
return normalize(part, false);
return normalize(part, context, false);
}).join("");

@@ -104,8 +124,88 @@ }

*/ function normalizeMathOperatorSpacing(value) {
let preventFormattingInFunctions = [
"theme"
];
let preventFormattingKeywords = [
"min-content",
"max-content",
"fit-content",
// Env
"safe-area-inset-top",
"safe-area-inset-right",
"safe-area-inset-bottom",
"safe-area-inset-left",
"titlebar-area-x",
"titlebar-area-y",
"titlebar-area-width",
"titlebar-area-height",
"keyboard-inset-top",
"keyboard-inset-right",
"keyboard-inset-bottom",
"keyboard-inset-left",
"keyboard-inset-width",
"keyboard-inset-height"
];
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
let vars = [];
return match.replace(/var\((--.+?)[,)]/g, (match, g1)=>{
vars.push(g1);
return match.replace(g1, placeholder);
}).replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, "$1 $2 ").replace(placeholderRe, ()=>vars.shift());
let result = "";
function lastChar() {
let char = result.trimEnd();
return char[char.length - 1];
}
for(let i = 0; i < match.length; i++){
function peek(word) {
return word.split("").every((char, j)=>match[i + j] === char);
}
function consumeUntil(chars) {
let minIndex = Infinity;
for (let char of chars){
let index = match.indexOf(char, i);
if (index !== -1 && index < minIndex) {
minIndex = index;
}
}
let result = match.slice(i, minIndex);
i += result.length - 1;
return result;
}
let char = match[i];
// Handle `var(--variable)`
if (peek("var")) {
// When we consume until `)`, then we are dealing with this scenario:
// `var(--example)`
//
// When we consume until `,`, then we are dealing with this scenario:
// `var(--example, 1rem)`
//
// In this case we do want to "format", the default value as well
result += consumeUntil([
")",
","
]);
} else if (preventFormattingKeywords.some((keyword)=>peek(keyword))) {
let keyword = preventFormattingKeywords.find((keyword)=>peek(keyword));
result += keyword;
i += keyword.length - 1;
} else if (preventFormattingInFunctions.some((fn)=>peek(fn))) {
result += consumeUntil([
")"
]);
} else if ([
"+",
"-",
"*",
"/"
].includes(char) && ![
"(",
"+",
"-",
"*",
"/"
].includes(lastChar())) {
result += ` ${char} `;
} else {
result += char;
}
}
// Simplify multiple spaces
return result.replace(/\s+/g, " ");
});

@@ -112,0 +212,0 @@ }

@@ -30,2 +30,3 @@ "use strict";

const _pseudoElements = require("./pseudoElements");
const _splitAtTopLevelOnly = require("./splitAtTopLevelOnly");
function _interop_require_default(obj) {

@@ -142,3 +143,3 @@ return obj && obj.__esModule ? obj : {

//
base = base !== null && base !== void 0 ? base : candidate.split(new RegExp(`\\${separator}(?![^[]*\\])`)).pop();
base = base !== null && base !== void 0 ? base : (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(candidate, separator).pop();
// Parse the selector into an AST

@@ -164,2 +165,8 @@ let selector = (0, _postcssselectorparser.default)().astSync(current);

selector.each((sel)=>eliminateIrrelevantSelectors(sel, base));
// If ffter eliminating irrelevant selectors, we end up with nothing
// Then the whole "rule" this is associated with does not need to exist
// We use `null` as a marker value for that case
if (selector.length === 0) {
return null;
}
// If there are no formats that means there were no variants added to the candidate

@@ -166,0 +173,0 @@ // so we can just return the selector as-is

@@ -16,3 +16,3 @@ "use strict";

const prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
return prototype === null || Object.getPrototypeOf(prototype) === null;
}
{
"name": "tailwindcss",
"version": "3.3.3",
"version": "3.3.5",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",

@@ -61,4 +61,4 @@ "license": "MIT",

"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0",
"jest-diff": "^29.5.0",
"jest": "^29.6.0",
"jest-diff": "^29.6.0",
"lightningcss": "1.18.0",

@@ -76,6 +76,6 @@ "prettier": "^2.8.8",

"dlv": "^1.1.3",
"fast-glob": "^3.2.12",
"fast-glob": "^3.3.0",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.18.2",
"jiti": "^1.19.1",
"lilconfig": "^2.1.0",

@@ -82,0 +82,0 @@ "micromatch": "^4.0.5",

@@ -167,3 +167,3 @@ // @ts-check

watcher.on('raw', (evt, filePath, meta) => {
if (evt !== 'rename') {
if (evt !== 'rename' || filePath === null) {
return

@@ -170,0 +170,0 @@ }

@@ -25,3 +25,2 @@ import colors from 'picocolors'

'generalizedModifiers',
// 'variantGrouping',
],

@@ -28,0 +27,0 @@ }

@@ -15,6 +15,8 @@ import { flagEnabled } from '../featureFlags'

for (let pattern of patterns) {
results = [...results, ...(content.match(pattern) ?? [])]
for (let result of content.match(pattern) ?? []) {
results.push(clipAtBalancedParens(result))
}
}
return results.filter((v) => v !== undefined).map(clipAtBalancedParens)
return results
}

@@ -25,3 +27,2 @@ }

let separator = context.tailwindConfig.separator
let variantGroupingEnabled = flagEnabled(context.tailwindConfig, 'variantGrouping')
let prefix =

@@ -40,3 +41,3 @@ context.tailwindConfig.prefix !== ''

// while fixing a problem with the regex matching too much
/\[[^\s:'"`]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,

@@ -86,2 +87,5 @@ // Utilities

// With variant modifier (e.g.: group-[..]/modifier)
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/\w+/, separator]),
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),

@@ -93,2 +97,5 @@ regex.pattern([/[^\s"'`\[\\]+/, separator]),

regex.any([
// With variant modifier (e.g.: group-[..]/modifier)
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/\w+/, separator]),
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),

@@ -111,11 +118,3 @@ regex.pattern([/[^\s`\[\\]+/, separator]),

variantGroupingEnabled
? regex.any([
// Or any of those things but grouped separated by commas
regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]),
// Arbitrary properties, constrained utilities, arbitrary values, etc…
utility,
])
: utility,
utility,
])

@@ -122,0 +121,0 @@ }

@@ -556,2 +556,9 @@ import postcss from 'postcss'

// If the selector becomes empty after replacing the important selector
// This means that it's the same as the parent selector and we don't want to replace it
// Otherwise we'll crash
if (parentSelector === '') {
parentSelector = parent.selector
}
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate)

@@ -558,0 +565,0 @@

@@ -148,10 +148,22 @@ import fs from 'fs'

} else {
await Promise.all(
context.changedContent.map(async ({ file, content, extension }) => {
let transformer = getTransformer(context.tailwindConfig, extension)
let extractor = getExtractor(context, extension)
content = file ? await fs.promises.readFile(file, 'utf8') : content
getClassCandidates(transformer(content), extractor, candidates, seen)
})
)
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */
let regexParserContent = []
for (let item of context.changedContent) {
let transformer = getTransformer(context.tailwindConfig, item.extension)
let extractor = getExtractor(context, item.extension)
regexParserContent.push([item, { transformer, extractor }])
}
const BATCH_SIZE = 500
for (let i = 0; i < regexParserContent.length; i += BATCH_SIZE) {
let batch = regexParserContent.slice(i, i + BATCH_SIZE)
await Promise.all(
batch.map(async ([{ file, content }, { transformer, extractor }]) => {
content = file ? await fs.promises.readFile(file, 'utf8') : content
getClassCandidates(transformer(content), extractor, candidates, seen)
})
)
}
}

@@ -158,0 +170,0 @@

@@ -499,3 +499,3 @@ import postcss from 'postcss'

let normalized = normalize(value)
let normalized = normalize(value, { property })

@@ -577,3 +577,3 @@ if (!isParsableCssValue(property, normalized)) {

function* resolveMatches(candidate, context, original = candidate) {
function* resolveMatches(candidate, context) {
let separator = context.tailwindConfig.separator

@@ -588,11 +588,2 @@ let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse()

if (flagEnabled(context.tailwindConfig, 'variantGrouping')) {
if (classCandidate.startsWith('(') && classCandidate.endsWith(')')) {
let base = variants.slice().reverse().join(separator)
for (let part of splitAtTopLevelOnly(classCandidate.slice(1, -1), ',')) {
yield* resolveMatches(base + separator + part, context, original)
}
}
}
// TODO: Reintroduce this in ways that doesn't break on false positives

@@ -786,3 +777,3 @@ // function sortAgainst(toSort, against) {

// Apply final format selector
match = applyFinalFormat(match, { context, candidate, original })
match = applyFinalFormat(match, { context, candidate })

@@ -801,3 +792,3 @@ // Skip rules with invalid selectors

function applyFinalFormat(match, { context, candidate, original }) {
function applyFinalFormat(match, { context, candidate }) {
if (!match[0].collectedFormats) {

@@ -837,6 +828,15 @@ return match

try {
rule.selector = finalizeSelector(rule.selector, finalFormat, {
candidate: original,
let selector = finalizeSelector(rule.selector, finalFormat, {
candidate,
context,
})
// Finalize Selector determined that this candidate is irrelevant
// TODO: This elimination should happen earlier so this never happens
if (selector === null) {
rule.remove()
return
}
rule.selector = selector
} catch {

@@ -891,3 +891,3 @@ // If this selector is invalid we also want to skip it

function generateRules(candidates, context) {
function generateRules(candidates, context, isSorting = false) {
let allRules = []

@@ -927,3 +927,5 @@ let strategy = getImportantStrategy(context.tailwindConfig.important)

let newEntry = [sort, rule]
// Note: We have to clone rules during sorting
// so we eliminate some shared mutable state
let newEntry = [sort, isSorting ? rule.clone() : rule]
rules.add(newEntry)

@@ -930,0 +932,0 @@ context.ruleCache.add(newEntry)

@@ -151,39 +151,41 @@ import fs from 'fs'

/**
* Ignore everything inside a :not(...). This allows you to write code like
* `div:not(.foo)`. If `.foo` is never found in your code, then we used to
* not generated it. But now we will ignore everything inside a `:not`, so
* that it still gets generated.
*
* @param {selectorParser.Root} selectors
*/
function ignoreNot(selectors) {
selectors.walkPseudos((pseudo) => {
if (pseudo.value === ':not') {
pseudo.remove()
}
})
}
function extractCandidates(node, state = { containsNonOnDemandable: false }, depth = 0) {
let classes = []
let selectors = []
// Handle normal rules
if (node.type === 'rule') {
// Ignore everything inside a :not(...). This allows you to write code like
// `div:not(.foo)`. If `.foo` is never found in your code, then we used to
// not generated it. But now we will ignore everything inside a `:not`, so
// that it still gets generated.
function ignoreNot(selectors) {
selectors.walkPseudos((pseudo) => {
if (pseudo.value === ':not') {
pseudo.remove()
}
})
}
// Handle normal rules
selectors.push(...node.selectors)
} else if (node.type === 'atrule') {
// Handle at-rules (which contains nested rules)
node.walkRules((rule) => selectors.push(...rule.selectors))
}
for (let selector of node.selectors) {
let classCandidates = getClasses(selector, ignoreNot)
// At least one of the selectors contains non-"on-demandable" candidates.
if (classCandidates.length === 0) {
state.containsNonOnDemandable = true
}
for (let selector of selectors) {
let classCandidates = getClasses(selector, ignoreNot)
for (let classCandidate of classCandidates) {
classes.push(classCandidate)
}
// At least one of the selectors contains non-"on-demandable" candidates.
if (classCandidates.length === 0) {
state.containsNonOnDemandable = true
}
}
// Handle at-rules (which contains nested rules)
else if (node.type === 'atrule') {
node.walkRules((rule) => {
for (let classCandidate of rule.selectors.flatMap((selector) => getClasses(selector))) {
classes.push(classCandidate)
}
})
for (let classCandidate of classCandidates) {
classes.push(classCandidate)
}
}

@@ -949,3 +951,3 @@

// Non-tailwind classes won't be generated and will be left as `null`
let rules = generateRules(new Set(sorted), context)
let rules = generateRules(new Set(sorted), context, true)
rules = context.offsets.sort(rules)

@@ -952,0 +954,0 @@

@@ -280,5 +280,5 @@ import path from 'path'

postcssPlugin: 'tailwindcss',
Once(root, { result }) {
async Once(root, { result }) {
env.DEBUG && console.time('Compiling CSS')
tailwind(({ createContext }) => {
await tailwind(({ createContext }) => {
console.error()

@@ -285,0 +285,0 @@ console.error('Rebuilding...')

@@ -8,3 +8,3 @@ import namedColors from './colorNames'

let ALPHA_SEP = /\s*[,/]\s*/
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/

@@ -11,0 +11,0 @@ let RGB = new RegExp(

@@ -13,9 +13,30 @@ import { parseColor } from './color'

const placeholder = '--tw-placeholder'
const placeholderRe = new RegExp(placeholder, 'g')
// These properties accept a `<dashed-ident>` as one of the values. This means that you can use them
// as: `timeline-scope: --tl;`
//
// Without the `var(--tl)`, in these cases we don't want to normalize the value, and you should add
// the `var()` yourself.
//
// More info:
// - https://drafts.csswg.org/scroll-animations/#propdef-timeline-scope
// - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident
//
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
// Concrete properties
'scroll-timeline-name',
'timeline-scope',
'view-timeline-name',
'font-palette',
// Shorthand properties
'scroll-timeline',
'animation-timeline',
'view-timeline',
])
// This is not a data type, but rather a function that can normalize the
// correct values.
export function normalize(value, isRoot = true) {
if (value.startsWith('--')) {
export function normalize(value, context = null, isRoot = true) {
let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property)
if (value.startsWith('--') && !isVarException) {
return `var(${value})`

@@ -34,3 +55,3 @@ }

return normalize(part, false)
return normalize(part, context, false)
})

@@ -67,12 +88,93 @@ .join('')

function normalizeMathOperatorSpacing(value) {
let preventFormattingInFunctions = ['theme']
let preventFormattingKeywords = [
'min-content',
'max-content',
'fit-content',
// Env
'safe-area-inset-top',
'safe-area-inset-right',
'safe-area-inset-bottom',
'safe-area-inset-left',
'titlebar-area-x',
'titlebar-area-y',
'titlebar-area-width',
'titlebar-area-height',
'keyboard-inset-top',
'keyboard-inset-right',
'keyboard-inset-bottom',
'keyboard-inset-left',
'keyboard-inset-width',
'keyboard-inset-height',
]
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
let vars = []
let result = ''
return match
.replace(/var\((--.+?)[,)]/g, (match, g1) => {
vars.push(g1)
return match.replace(g1, placeholder)
})
.replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ')
.replace(placeholderRe, () => vars.shift())
function lastChar() {
let char = result.trimEnd()
return char[char.length - 1]
}
for (let i = 0; i < match.length; i++) {
function peek(word) {
return word.split('').every((char, j) => match[i + j] === char)
}
function consumeUntil(chars) {
let minIndex = Infinity
for (let char of chars) {
let index = match.indexOf(char, i)
if (index !== -1 && index < minIndex) {
minIndex = index
}
}
let result = match.slice(i, minIndex)
i += result.length - 1
return result
}
let char = match[i]
// Handle `var(--variable)`
if (peek('var')) {
// When we consume until `)`, then we are dealing with this scenario:
// `var(--example)`
//
// When we consume until `,`, then we are dealing with this scenario:
// `var(--example, 1rem)`
//
// In this case we do want to "format", the default value as well
result += consumeUntil([')', ','])
}
// Skip formatting of known keywords
else if (preventFormattingKeywords.some((keyword) => peek(keyword))) {
let keyword = preventFormattingKeywords.find((keyword) => peek(keyword))
result += keyword
i += keyword.length - 1
}
// Skip formatting inside known functions
else if (preventFormattingInFunctions.some((fn) => peek(fn))) {
result += consumeUntil([')'])
}
// Handle operators
else if (
['+', '-', '*', '/'].includes(char) &&
!['(', '+', '-', '*', '/'].includes(lastChar())
) {
result += ` ${char} `
} else {
result += char
}
}
// Simplify multiple spaces
return result.replace(/\s+/g, ' ')
})

@@ -79,0 +181,0 @@ }

@@ -6,2 +6,3 @@ import selectorParser from 'postcss-selector-parser'

import { movePseudos } from './pseudoElements'
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'

@@ -164,3 +165,3 @@ /** @typedef {import('postcss-selector-parser').Root} Root */

//
base = base ?? candidate.split(new RegExp(`\\${separator}(?![^[]*\\])`)).pop()
base = base ?? splitAtTopLevelOnly(candidate, separator).pop()

@@ -190,2 +191,9 @@ // Parse the selector into an AST

// If ffter eliminating irrelevant selectors, we end up with nothing
// Then the whole "rule" this is associated with does not need to exist
// We use `null` as a marker value for that case
if (selector.length === 0) {
return null
}
// If there are no formats that means there were no variants added to the candidate

@@ -192,0 +200,0 @@ // so we can just return the selector as-is

@@ -7,3 +7,3 @@ export default function isPlainObject(value) {

const prototype = Object.getPrototypeOf(value)
return prototype === null || prototype === Object.prototype
return prototype === null || Object.getPrototypeOf(prototype) === null
}

@@ -49,9 +49,9 @@ import type { CorePluginList } from './generated/corePluginList'

// Safelist related config
type SafelistConfig = (string | { pattern: RegExp; variants?: string[] })[]
type SafelistConfig = string | { pattern: RegExp; variants?: string[] }
// Blocklist related config
type BlocklistConfig = string[]
type BlocklistConfig = string
// Presets related config
type PresetsConfig = Config[]
type PresetsConfig = Partial<Config>

@@ -356,5 +356,5 @@ // Future related config

separator: Partial<SeparatorConfig>
safelist: Partial<SafelistConfig>
blocklist: Partial<BlocklistConfig>
presets: Partial<PresetsConfig>
safelist: Array<SafelistConfig>
blocklist: Array<BlocklistConfig>
presets: Array<PresetsConfig>
future: Partial<FutureConfig>

@@ -361,0 +361,0 @@ experimental: Partial<ExperimentalConfig>

@@ -1,2 +0,2 @@

import { PluginCreator } from 'postcss'
import type { PluginCreator } from 'postcss'
import type { Config } from './config.d'

@@ -6,3 +6,7 @@

export { Config }
export default plugin
declare type _Config = Config
declare namespace plugin {
export type { _Config as Config }
}
export = plugin

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc