Socket
Socket
Sign inDemoInstall

tailwindcss

Package Overview
Dependencies
Maintainers
3
Versions
1738
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 0.0.0-insiders.23d3a31 to 0.0.0-insiders.245058c

lib/cli/build/deps.js

3

defaultTheme.d.ts
import type { Config } from './types/config'
declare const theme: Config['theme']
import { DefaultTheme } from './types/generated/default-theme'
declare const theme: Config['theme'] & DefaultTheme
export = theme

@@ -5,8 +5,28 @@ "use strict";

});
exports.lazyPostcss = lazyPostcss;
exports.lazyAutoprefixer = lazyAutoprefixer;
exports.lazyCssnano = lazyCssnano;
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
lazyPostcss: function() {
return lazyPostcss;
},
lazyPostcssImport: function() {
return lazyPostcssImport;
},
lazyAutoprefixer: function() {
return lazyAutoprefixer;
},
lazyCssnano: function() {
return lazyCssnano;
}
});
function lazyPostcss() {
return require("postcss");
}
function lazyPostcssImport() {
return require("postcss-import");
}
function lazyAutoprefixer() {

@@ -13,0 +33,0 @@ return require("autoprefixer");

#!/usr/bin/env node
"use strict";
var _indexJs = require("../peers/index.js");
var _chokidar = _interopRequireDefault(require("chokidar"));
var _path = _interopRequireDefault(require("path"));
var _arg = _interopRequireDefault(require("arg"));
var _fs = _interopRequireDefault(require("fs"));
var _postcssLoadConfig = _interopRequireDefault(require("postcss-load-config"));
var _lilconfig = require("lilconfig");
var _plugins // Little bit scary, looking at private/internal API
= _interopRequireDefault(require("postcss-load-config/src/plugins"));
var _options // Little bit scary, looking at private/internal API
= _interopRequireDefault(require("postcss-load-config/src/options"));
var _processTailwindFeatures = _interopRequireDefault(require("./processTailwindFeatures"));
var _resolveConfig = _interopRequireDefault(require("../resolveConfig"));
var _fastGlob = _interopRequireDefault(require("fast-glob"));
var _getModuleDependencies = _interopRequireDefault(require("./lib/getModuleDependencies"));
var _log = _interopRequireDefault(require("./util/log"));
var _packageJson = _interopRequireDefault(require("../package.json"));
var _normalizePath = _interopRequireDefault(require("normalize-path"));
var _validateConfigJs = require("./util/validateConfig.js");
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
let env = {
DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== "0"
};
function isESM() {
const pkgPath = _path.default.resolve("./package.json");
try {
let pkg = JSON.parse(_fs.default.readFileSync(pkgPath, "utf8"));
return pkg.type && pkg.type === "module";
} catch (err) {
return false;
}
}
let configs = isESM() ? {
tailwind: "tailwind.config.cjs",
postcss: "postcss.config.cjs"
} : {
tailwind: "tailwind.config.js",
postcss: "postcss.config.js"
};
// ---
function indentRecursive(node, indent = 0) {
node.each && node.each((child, i)=>{
if (!child.raws.before || !child.raws.before.trim() || child.raws.before.includes("\n")) {
child.raws.before = `\n${node.type !== "rule" && i > 0 ? "\n" : ""}${" ".repeat(indent)}`;
}
child.raws.after = `\n${" ".repeat(indent)}`;
indentRecursive(child, indent + 1);
});
}
function formatNodes(root) {
indentRecursive(root);
if (root.first) {
root.first.raws.before = "";
}
}
async function outputFile(file, contents) {
if (_fs.default.existsSync(file) && await _fs.default.promises.readFile(file, "utf8") === contents) {
return; // Skip writing the file
}
// Write the file
await _fs.default.promises.writeFile(file, contents, "utf8");
}
function drainStdin() {
return new Promise((resolve, reject)=>{
let result = "";
process.stdin.on("data", (chunk)=>{
result += chunk;
});
process.stdin.on("end", ()=>resolve(result)
);
process.stdin.on("error", (err)=>reject(err)
);
});
}
function help({ message , usage , commands: commands1 , options }) {
let indent = 2;
// Render header
console.log();
console.log(`${_packageJson.default.name} v${_packageJson.default.version}`);
// Render message
if (message) {
console.log();
for (let msg of message.split("\n")){
console.log(msg);
}
}
// Render usage
if (usage && usage.length > 0) {
console.log();
console.log("Usage:");
for (let example of usage){
console.log(" ".repeat(indent), example);
}
}
// Render commands
if (commands1 && commands1.length > 0) {
console.log();
console.log("Commands:");
for (let command1 of commands1){
console.log(" ".repeat(indent), command1);
}
}
// Render options
if (options) {
let groupedOptions = {};
for (let [key, value] of Object.entries(options)){
if (typeof value === "object") {
groupedOptions[key] = {
...value,
flags: [
key
]
};
} else {
groupedOptions[value].flags.push(key);
}
}
console.log();
console.log("Options:");
for (let { flags: flags1 , description , deprecated } of Object.values(groupedOptions)){
if (deprecated) continue;
if (flags1.length === 1) {
console.log(" ".repeat(indent + 4 /* 4 = "-i, ".length */ ), flags1.slice().reverse().join(", ").padEnd(20, " "), description);
} else {
console.log(" ".repeat(indent), flags1.slice().reverse().join(", ").padEnd(24, " "), description);
}
}
}
console.log();
}
function oneOf(...options) {
return Object.assign((value = true)=>{
for (let option of options){
let parsed = option(value);
if (parsed === value) {
return parsed;
}
}
throw new Error("...");
}, {
manualParsing: true
});
}
function loadPostcss() {
// Try to load a local `postcss` version first
try {
return require("postcss");
} catch {}
return (0, _indexJs).lazyPostcss();
}
let commands = {
init: {
run: init,
args: {
"--full": {
type: Boolean,
description: `Initialize a full \`${configs.tailwind}\` file`
},
"--postcss": {
type: Boolean,
description: `Initialize a \`${configs.postcss}\` file`
},
"--types": {
type: Boolean,
description: `Add TypeScript types for the \`${configs.tailwind}\` file`
},
"-f": "--full",
"-p": "--postcss"
}
},
build: {
run: build,
args: {
"--input": {
type: String,
description: "Input file"
},
"--output": {
type: String,
description: "Output file"
},
"--watch": {
type: Boolean,
description: "Watch for changes and rebuild as needed"
},
"--poll": {
type: Boolean,
description: "Use polling instead of filesystem events when watching"
},
"--content": {
type: String,
description: "Content paths to use for removing unused classes"
},
"--purge": {
type: String,
deprecated: true
},
"--postcss": {
type: oneOf(String, Boolean),
description: "Load custom PostCSS configuration"
},
"--minify": {
type: Boolean,
description: "Minify the output"
},
"--config": {
type: String,
description: "Path to a custom config file"
},
"--no-autoprefixer": {
type: Boolean,
description: "Disable autoprefixer"
},
"-c": "--config",
"-i": "--input",
"-o": "--output",
"-m": "--minify",
"-w": "--watch",
"-p": "--poll"
}
}
};
let sharedFlags = {
"--help": {
type: Boolean,
description: "Display usage information"
},
"-h": "--help"
};
if (process.stdout.isTTY /* Detect redirecting output to a file */ && (process.argv[2] === undefined || process.argv.slice(2).every((flag)=>sharedFlags[flag] !== undefined
))) {
help({
usage: [
"tailwindcss [--input input.css] [--output output.css] [--watch] [options...]",
"tailwindcss init [--full] [--postcss] [--types] [options...]",
],
commands: Object.keys(commands).filter((command2)=>command2 !== "build"
).map((command3)=>`${command3} [options]`
),
options: {
...commands.build.args,
...sharedFlags
}
});
process.exit(0);
}
let command = ((arg = "")=>arg.startsWith("-") ? undefined : arg
)(process.argv[2]) || "build";
if (commands[command] === undefined) {
if (_fs.default.existsSync(_path.default.resolve(command))) {
// TODO: Deprecate this in future versions
// Check if non-existing command, might be a file.
command = "build";
} else {
help({
message: `Invalid command: ${command}`,
usage: [
"tailwindcss <command> [options]"
],
commands: Object.keys(commands).filter((command4)=>command4 !== "build"
).map((command5)=>`${command5} [options]`
),
options: sharedFlags
});
process.exit(1);
}
}
// Execute command
let { args: flags , run } = commands[command];
let args = (()=>{
try {
let result = (0, _arg).default(Object.fromEntries(Object.entries({
...flags,
...sharedFlags
}).filter(([_key, value])=>{
var ref;
return !(value === null || value === void 0 ? void 0 : (ref = value.type) === null || ref === void 0 ? void 0 : ref.manualParsing);
}).map(([key, value])=>[
key,
typeof value === "object" ? value.type : value
]
)), {
permissive: true
});
// Manual parsing of flags to allow for special flags like oneOf(Boolean, String)
for(let i = result["_"].length - 1; i >= 0; --i){
let flag = result["_"][i];
if (!flag.startsWith("-")) continue;
let flagName = flag;
let handler = flags[flag];
// Resolve flagName & handler
while(typeof handler === "string"){
flagName = handler;
handler = flags[handler];
}
if (!handler) continue;
let args1 = [];
let offset = i + 1;
// Parse args for current flag
while(result["_"][offset] && !result["_"][offset].startsWith("-")){
args1.push(result["_"][offset++]);
}
// Cleanup manually parsed flags + args
result["_"].splice(i, 1 + args1.length);
// Set the resolved value in the `result` object
result[flagName] = handler.type(args1.length === 0 ? undefined : args1.length === 1 ? args1[0] : args1, flagName);
}
// Ensure that the `command` is always the first argument in the `args`.
// This is important so that we don't have to check if a default command
// (build) was used or not from within each plugin.
//
// E.g.: tailwindcss input.css -> _: ['build', 'input.css']
// E.g.: tailwindcss build input.css -> _: ['build', 'input.css']
if (result["_"][0] !== command) {
result["_"].unshift(command);
}
return result;
} catch (err) {
if (err.code === "ARG_UNKNOWN_OPTION") {
help({
message: err.message,
usage: [
"tailwindcss <command> [options]"
],
options: sharedFlags
});
process.exit(1);
}
throw err;
}
})();
if (args["--help"]) {
help({
options: {
...flags,
...sharedFlags
},
usage: [
`tailwindcss ${command} [options]`
]
});
process.exit(0);
}
run();
// ---
function init() {
let messages = [];
var ref;
let tailwindConfigLocation = _path.default.resolve((ref = args["_"][1]) !== null && ref !== void 0 ? ref : `./${configs.tailwind}`);
if (_fs.default.existsSync(tailwindConfigLocation)) {
messages.push(`${_path.default.basename(tailwindConfigLocation)} already exists.`);
} else {
let stubFile = _fs.default.readFileSync(args["--full"] ? _path.default.resolve(__dirname, "../stubs/defaultConfig.stub.js") : _path.default.resolve(__dirname, "../stubs/simpleConfig.stub.js"), "utf8");
if (args["--types"]) {
let typesHeading = "/** @type {import('tailwindcss/types').Config} */";
stubFile = stubFile.replace(`module.exports = `, `${typesHeading}\nconst config = `) + "\nmodule.exports = config";
}
// Change colors import
stubFile = stubFile.replace("../colors", "tailwindcss/colors");
_fs.default.writeFileSync(tailwindConfigLocation, stubFile, "utf8");
messages.push(`Created Tailwind CSS config file: ${_path.default.basename(tailwindConfigLocation)}`);
}
if (args["--postcss"]) {
let postcssConfigLocation = _path.default.resolve(`./${configs.postcss}`);
if (_fs.default.existsSync(postcssConfigLocation)) {
messages.push(`${_path.default.basename(postcssConfigLocation)} already exists.`);
} else {
let stubFile = _fs.default.readFileSync(_path.default.resolve(__dirname, "../stubs/defaultPostCssConfig.stub.js"), "utf8");
_fs.default.writeFileSync(postcssConfigLocation, stubFile, "utf8");
messages.push(`Created PostCSS config file: ${_path.default.basename(postcssConfigLocation)}`);
}
}
if (messages.length > 0) {
console.log();
for (let message of messages){
console.log(message);
}
}
}
async function build() {
let input = args["--input"];
let output = args["--output"];
let shouldWatch = args["--watch"];
let shouldPoll = args["--poll"];
let shouldCoalesceWriteEvents = shouldPoll || process.platform === "win32";
let includePostCss = args["--postcss"];
// Polling interval in milliseconds
// Used only when polling or coalescing add/change events on Windows
let pollInterval = 10;
// TODO: Deprecate this in future versions
if (!input && args["_"][1]) {
console.error("[deprecation] Running tailwindcss without -i, please provide an input file.");
input = args["--input"] = args["_"][1];
}
if (input && input !== "-" && !_fs.default.existsSync(input = _path.default.resolve(input))) {
console.error(`Specified input file ${args["--input"]} does not exist.`);
process.exit(9);
}
if (args["--config"] && !_fs.default.existsSync(args["--config"] = _path.default.resolve(args["--config"]))) {
console.error(`Specified config file ${args["--config"]} does not exist.`);
process.exit(9);
}
let configPath = args["--config"] ? args["--config"] : ((defaultPath)=>_fs.default.existsSync(defaultPath) ? defaultPath : null
)(_path.default.resolve(`./${configs.tailwind}`));
async function loadPostCssPlugins() {
let customPostCssPath = typeof args["--postcss"] === "string" ? args["--postcss"] : undefined;
let config1 = customPostCssPath ? await (async ()=>{
let file = _path.default.resolve(customPostCssPath);
// Implementation, see: https://unpkg.com/browse/postcss-load-config@3.1.0/src/index.js
let { config ={} } = await (0, _lilconfig).lilconfig("postcss").load(file);
if (typeof config === "function") {
config = config();
} else {
config = Object.assign({}, config);
}
if (!config.plugins) {
config.plugins = [];
}
return {
file,
plugins: (0, _plugins).default(config, file),
options: (0, _options).default(config, file)
};
})() : await (0, _postcssLoadConfig).default();
let configPlugins = config1.plugins;
let configPluginTailwindIdx = configPlugins.findIndex((plugin)=>{
if (typeof plugin === "function" && plugin.name === "tailwindcss") {
return true;
}
if (typeof plugin === "object" && plugin !== null && plugin.postcssPlugin === "tailwindcss") {
return true;
}
return false;
});
let beforePlugins = configPluginTailwindIdx === -1 ? [] : configPlugins.slice(0, configPluginTailwindIdx);
let afterPlugins = configPluginTailwindIdx === -1 ? configPlugins : configPlugins.slice(configPluginTailwindIdx + 1);
return [
beforePlugins,
afterPlugins,
config1.options
];
}
function resolveConfig() {
let config = configPath ? require(configPath) : {};
if (args["--purge"]) {
_log.default.warn("purge-flag-deprecated", [
"The `--purge` flag has been deprecated.",
"Please use `--content` instead.",
]);
if (!args["--content"]) {
args["--content"] = args["--purge"];
}
}
if (args["--content"]) {
let files = args["--content"].split(/(?<!{[^}]+),/);
let resolvedConfig = (0, _resolveConfig).default(config, {
content: {
files
}
});
resolvedConfig.content.files = files;
resolvedConfig = (0, _validateConfigJs).validateConfig(resolvedConfig);
return resolvedConfig;
}
let resolvedConfig = (0, _resolveConfig).default(config);
resolvedConfig = (0, _validateConfigJs).validateConfig(resolvedConfig);
return resolvedConfig;
}
function extractFileGlobs(config) {
return config.content.files.filter((file)=>{
// Strings in this case are files / globs. If it is something else,
// like an object it's probably a raw content object. But this object
// is not watchable, so let's remove it.
return typeof file === "string";
}).map((glob)=>(0, _normalizePath).default(glob)
);
}
function extractRawContent(config) {
return config.content.files.filter((file)=>{
return typeof file === "object" && file !== null;
});
}
function getChangedContent(config) {
let changedContent = [];
// Resolve globs from the content config
let globs = extractFileGlobs(config);
let files = _fastGlob.default.sync(globs);
for (let file of files){
changedContent.push({
content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
extension: _path.default.extname(file).slice(1)
});
}
// Resolve raw content in the tailwind config
for (let { raw: content , extension ="html" } of extractRawContent(config)){
changedContent.push({
content,
extension
});
}
return changedContent;
}
async function buildOnce() {
let config = resolveConfig();
let changedContent = getChangedContent(config);
let tailwindPlugin = ()=>{
return {
postcssPlugin: "tailwindcss",
Once (root, { result }) {
(0, _processTailwindFeatures).default(({ createContext })=>{
return ()=>{
return createContext(config, changedContent);
};
})(root, result);
}
};
};
tailwindPlugin.postcss = true;
let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins() : [
[],
[],
{}
];
let plugins = [
...beforePlugins,
tailwindPlugin,
!args["--minify"] && formatNodes,
...afterPlugins,
!args["--no-autoprefixer"] && (()=>{
// Try to load a local `autoprefixer` version first
try {
return require("autoprefixer");
} catch {}
return (0, _indexJs).lazyAutoprefixer();
})(),
args["--minify"] && (()=>{
let options = {
preset: [
"default",
{
cssDeclarationSorter: false
}
]
};
// Try to load a local `cssnano` version first
try {
return require("cssnano");
} catch {}
return (0, _indexJs).lazyCssnano()(options);
})(),
].filter(Boolean);
let postcss = loadPostcss();
let processor = postcss(plugins);
function processCSS(css) {
let start = process.hrtime.bigint();
return Promise.resolve().then(()=>output ? _fs.default.promises.mkdir(_path.default.dirname(output), {
recursive: true
}) : null
).then(()=>processor.process(css, {
...postcssOptions,
from: input,
to: output
})
).then((result)=>{
if (!output) {
return process.stdout.write(result.css);
}
return Promise.all([
outputFile(output, result.css),
result.map && outputFile(output + ".map", result.map.toString()),
].filter(Boolean));
}).then(()=>{
let end = process.hrtime.bigint();
console.error();
console.error("Done in", (end - start) / BigInt(1000000) + "ms.");
});
}
let css1 = await (()=>{
// Piping in data, let's drain the stdin
if (input === "-") {
return drainStdin();
}
// Input file has been provided
if (input) {
return _fs.default.readFileSync(_path.default.resolve(input), "utf8");
}
// No input file provided, fallback to default atrules
return "@tailwind base; @tailwind components; @tailwind utilities";
})();
return processCSS(css1);
}
let context = null;
async function startWatcher() {
let changedContent = [];
let configDependencies = [];
let contextDependencies = new Set();
let watcher = null;
function refreshConfig() {
env.DEBUG && console.time("Module dependencies");
for (let file1 of configDependencies){
delete require.cache[require.resolve(file1)];
}
if (configPath) {
configDependencies = (0, _getModuleDependencies).default(configPath).map(({ file })=>file
);
for (let dependency of configDependencies){
contextDependencies.add(dependency);
}
}
env.DEBUG && console.timeEnd("Module dependencies");
return resolveConfig();
}
let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [
[],
[]
];
let plugins = [
...beforePlugins,
"__TAILWIND_PLUGIN_POSITION__",
!args["--minify"] && formatNodes,
...afterPlugins,
!args["--no-autoprefixer"] && (()=>{
// Try to load a local `autoprefixer` version first
try {
return require("autoprefixer");
} catch {}
return (0, _indexJs).lazyAutoprefixer();
})(),
args["--minify"] && (()=>{
let options = {
preset: [
"default",
{
cssDeclarationSorter: false
}
]
};
// Try to load a local `cssnano` version first
try {
return require("cssnano");
} catch {}
return (0, _indexJs).lazyCssnano()(options);
})(),
].filter(Boolean);
async function rebuild(config) {
env.DEBUG && console.time("Finished in");
let tailwindPlugin = ()=>{
return {
postcssPlugin: "tailwindcss",
Once (root, { result }) {
env.DEBUG && console.time("Compiling CSS");
(0, _processTailwindFeatures).default(({ createContext })=>{
console.error();
console.error("Rebuilding...");
return ()=>{
if (context !== null) {
context.changedContent = changedContent.splice(0);
return context;
}
env.DEBUG && console.time("Creating context");
context = createContext(config, changedContent.splice(0));
env.DEBUG && console.timeEnd("Creating context");
return context;
};
})(root, result);
env.DEBUG && console.timeEnd("Compiling CSS");
}
};
};
tailwindPlugin.postcss = true;
let tailwindPluginIdx = plugins.indexOf("__TAILWIND_PLUGIN_POSITION__");
let copy = plugins.slice();
copy.splice(tailwindPluginIdx, 1, tailwindPlugin);
let postcss = loadPostcss();
let processor = postcss(copy);
function processCSS(css) {
let start = process.hrtime.bigint();
return Promise.resolve().then(()=>output ? _fs.default.promises.mkdir(_path.default.dirname(output), {
recursive: true
}) : null
).then(()=>processor.process(css, {
from: input,
to: output
})
).then(async (result)=>{
for (let message of result.messages){
if (message.type === "dependency") {
contextDependencies.add(message.file);
}
}
watcher.add([
...contextDependencies
]);
if (!output) {
return process.stdout.write(result.css);
}
return Promise.all([
outputFile(output, result.css),
result.map && outputFile(output + ".map", result.map.toString()),
].filter(Boolean));
}).then(()=>{
let end = process.hrtime.bigint();
console.error("Done in", (end - start) / BigInt(1000000) + "ms.");
}).catch((err)=>{
if (err.name === "CssSyntaxError") {
console.error(err.toString());
} else {
console.error(err);
}
});
}
let css2 = await (()=>{
// Piping in data, let's drain the stdin
if (input === "-") {
return drainStdin();
}
// Input file has been provided
if (input) {
return _fs.default.readFileSync(_path.default.resolve(input), "utf8");
}
// No input file provided, fallback to default atrules
return "@tailwind base; @tailwind components; @tailwind utilities";
})();
let result1 = await processCSS(css2);
env.DEBUG && console.timeEnd("Finished in");
return result1;
}
let config2 = refreshConfig(configPath);
if (input) {
contextDependencies.add(_path.default.resolve(input));
}
watcher = _chokidar.default.watch([
...contextDependencies,
...extractFileGlobs(config2)
], {
usePolling: shouldPoll,
interval: shouldPoll ? pollInterval : undefined,
ignoreInitial: true,
awaitWriteFinish: shouldCoalesceWriteEvents ? {
stabilityThreshold: 50,
pollInterval: pollInterval
} : false
});
let chain = Promise.resolve();
watcher.on("change", async (file)=>{
if (contextDependencies.has(file)) {
env.DEBUG && console.time("Resolve config");
context = null;
config2 = refreshConfig(configPath);
env.DEBUG && console.timeEnd("Resolve config");
env.DEBUG && console.time("Watch new files");
let globs = extractFileGlobs(config2);
watcher.add(configDependencies);
watcher.add(globs);
env.DEBUG && console.timeEnd("Watch new files");
chain = chain.then(async ()=>{
changedContent.push(...getChangedContent(config2));
await rebuild(config2);
});
} else {
chain = chain.then(async ()=>{
changedContent.push({
content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
extension: _path.default.extname(file).slice(1)
});
await rebuild(config2);
});
}
});
watcher.on("add", async (file)=>{
chain = chain.then(async ()=>{
changedContent.push({
content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
extension: _path.default.extname(file).slice(1)
});
await rebuild(config2);
});
});
chain = chain.then(()=>{
changedContent.push(...getChangedContent(config2));
return rebuild(config2);
});
}
if (shouldWatch) {
/* Abort the watcher if stdin is closed to avoid zombie processes */ process.stdin.on("end", ()=>process.exit(0)
);
process.stdin.resume();
startWatcher();
} else {
buildOnce();
}
}
module.exports = require("./cli/index");

@@ -5,4 +5,9 @@ "use strict";

});
exports.default = void 0;
var _default = [
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _default = [
"preflight",

@@ -28,4 +33,6 @@ "container",

"boxSizing",
"lineClamp",
"display",
"aspectRatio",
"size",
"height",

@@ -42,2 +49,3 @@ "maxHeight",

"tableLayout",
"captionSide",
"borderCollapse",

@@ -63,2 +71,3 @@ "borderSpacing",

"listStyleType",
"listStyleImage",
"appearance",

@@ -95,3 +104,5 @@ "columns",

"textOverflow",
"hyphens",
"whitespace",
"textWrap",
"wordBreak",

@@ -182,4 +193,5 @@ "borderRadius",

"willChange",
"content"
"contain",
"content",
"forcedColorAdjust"
];
exports.default = _default;

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

});
exports.flagEnabled = flagEnabled;
exports.issueFlagNotices = issueFlagNotices;
exports.default = void 0;
var _picocolors = _interopRequireDefault(require("picocolors"));
var _log = _interopRequireDefault(require("./util/log"));
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
flagEnabled: function() {
return flagEnabled;
},
issueFlagNotices: function() {
return issueFlagNotices;
},
default: function() {
return _default;
}
});
const _picocolors = /*#__PURE__*/ _interop_require_default(require("picocolors"));
const _log = /*#__PURE__*/ _interop_require_default(require("./util/log"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -17,8 +31,17 @@ default: obj

let defaults = {
optimizeUniversalDefaults: false
optimizeUniversalDefaults: false,
generalizedModifiers: true,
disableColorOpacityUtilitiesByDefault: false,
relativeContentPathsByDefault: false
};
let featureFlags = {
future: [],
future: [
"hoverOnlyWhenSupported",
"respectDefaultRingColorOpacity",
"disableColorOpacityUtilitiesByDefault",
"relativeContentPathsByDefault"
],
experimental: [
"optimizeUniversalDefaults"
"optimizeUniversalDefaults",
"generalizedModifiers"
]

@@ -28,10 +51,10 @@ };

if (featureFlags.future.includes(flag)) {
var ref;
var ref1, ref2;
return config.future === "all" || ((ref2 = (ref1 = config === null || config === void 0 ? void 0 : (ref = config.future) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref1 !== void 0 ? ref1 : defaults[flag]) !== null && ref2 !== void 0 ? ref2 : false);
var _config_future;
var _config_future_flag, _ref;
return config.future === "all" || ((_ref = (_config_future_flag = config === null || config === void 0 ? void 0 : (_config_future = config.future) === null || _config_future === void 0 ? void 0 : _config_future[flag]) !== null && _config_future_flag !== void 0 ? _config_future_flag : defaults[flag]) !== null && _ref !== void 0 ? _ref : false);
}
if (featureFlags.experimental.includes(flag)) {
var ref3;
var ref4, ref5;
return config.experimental === "all" || ((ref5 = (ref4 = config === null || config === void 0 ? void 0 : (ref3 = config.experimental) === null || ref3 === void 0 ? void 0 : ref3[flag]) !== null && ref4 !== void 0 ? ref4 : defaults[flag]) !== null && ref5 !== void 0 ? ref5 : false);
var _config_experimental;
var _config_experimental_flag, _ref1;
return config.experimental === "all" || ((_ref1 = (_config_experimental_flag = config === null || config === void 0 ? void 0 : (_config_experimental = config.experimental) === null || _config_experimental === void 0 ? void 0 : _config_experimental[flag]) !== null && _config_experimental_flag !== void 0 ? _config_experimental_flag : defaults[flag]) !== null && _ref1 !== void 0 ? _ref1 : false);
}

@@ -44,5 +67,4 @@ return false;

}
var ref;
return Object.keys((ref = config === null || config === void 0 ? void 0 : config.experimental) !== null && ref !== void 0 ? ref : {}).filter((flag)=>featureFlags.experimental.includes(flag) && config.experimental[flag]
);
var _config_experimental;
return Object.keys((_config_experimental = config === null || config === void 0 ? void 0 : config.experimental) !== null && _config_experimental !== void 0 ? _config_experimental : {}).filter((flag)=>featureFlags.experimental.includes(flag) && config.experimental[flag]);
}

@@ -54,11 +76,9 @@ function issueFlagNotices(config) {

if (experimentalFlagsEnabled(config).length > 0) {
let changes = experimentalFlagsEnabled(config).map((s)=>_picocolors.default.yellow(s)
).join(", ");
let changes = experimentalFlagsEnabled(config).map((s)=>_picocolors.default.yellow(s)).join(", ");
_log.default.warn("experimental-flags-enabled", [
`You have enabled experimental features: ${changes}`,
"Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time.",
"Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time."
]);
}
}
var _default = featureFlags;
exports.default = _default;
const _default = featureFlags;
"use strict";
var _setupTrackingContext = _interopRequireDefault(require("./lib/setupTrackingContext"));
var _processTailwindFeatures = _interopRequireDefault(require("./processTailwindFeatures"));
var _sharedState = require("./lib/sharedState");
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
module.exports = function tailwindcss(configOrPath) {
return {
postcssPlugin: "tailwindcss",
plugins: [
_sharedState.env.DEBUG && function(root) {
console.log("\n");
console.time("JIT TOTAL");
return root;
},
function(root, result) {
let context = (0, _setupTrackingContext).default(configOrPath);
if (root.type === "document") {
let roots = root.nodes.filter((node)=>node.type === "root"
);
for (const root1 of roots){
if (root1.type === "root") {
(0, _processTailwindFeatures).default(context)(root1, result);
}
}
return;
}
(0, _processTailwindFeatures).default(context)(root, result);
},
_sharedState.env.DEBUG && function(root) {
console.timeEnd("JIT TOTAL");
console.log("\n");
return root;
},
].filter(Boolean)
};
};
module.exports.postcss = true;
module.exports = require("./plugin");

@@ -5,6 +5,11 @@ "use strict";

});
exports.hasContentChanged = hasContentChanged;
var _crypto = _interopRequireDefault(require("crypto"));
var sharedState = _interopRequireWildcard(require("./sharedState"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "hasContentChanged", {
enumerable: true,
get: function() {
return hasContentChanged;
}
});
const _crypto = /*#__PURE__*/ _interop_require_default(require("crypto"));
const _sharedState = /*#__PURE__*/ _interop_require_wildcard(require("./sharedState"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -14,22 +19,40 @@ default: obj

}
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}

@@ -66,7 +89,7 @@ /**

}
let existingHash = sharedState.sourceHashMap.get(sourcePath);
let existingHash = _sharedState.sourceHashMap.get(sourcePath);
let rootHash = getHash(css);
let didChange = existingHash !== rootHash;
sharedState.sourceHashMap.set(sourcePath, rootHash);
_sharedState.sourceHashMap.set(sourcePath, rootHash);
return didChange;
}

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

});
exports.default = collapseAdjacentRules;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return collapseAdjacentRules;
}
});
let comparisonMap = {
atrule: [
"name",
"params"
],
rule: [
"selector"
]
};
let types = new Set(Object.keys(comparisonMap));
function collapseAdjacentRules() {

@@ -20,7 +35,6 @@ function collapseRulesIn(root) {

let properties = comparisonMap[node.type];
var _property, _property1;
var _node_property, _currentRule_property;
if (node.type === "atrule" && node.name === "font-face") {
currentRule = node;
} else if (properties.every((property)=>((_property = node[property]) !== null && _property !== void 0 ? _property : "").replace(/\s+/g, " ") === ((_property1 = currentRule[property]) !== null && _property1 !== void 0 ? _property1 : "").replace(/\s+/g, " ")
)) {
} else if (properties.every((property)=>((_node_property = node[property]) !== null && _node_property !== void 0 ? _node_property : "").replace(/\s+/g, " ") === ((_currentRule_property = currentRule[property]) !== null && _currentRule_property !== void 0 ? _currentRule_property : "").replace(/\s+/g, " "))) {
// An AtRule may not have children (for example if we encounter duplicate @import url(…) rules)

@@ -50,11 +64,1 @@ if (node.nodes) {

}
let comparisonMap = {
atrule: [
"name",
"params"
],
rule: [
"selector"
]
};
let types = new Set(Object.keys(comparisonMap));

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

});
exports.default = collapseDuplicateDeclarations;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return collapseDuplicateDeclarations;
}
});
function collapseDuplicateDeclarations() {

@@ -45,4 +50,4 @@ return (root)=>{

// already seen so far.
for (let decl1 of droppable){
decl1.remove();
for (let decl of droppable){
decl.remove();
}

@@ -63,5 +68,5 @@ // Analyze the declarations based on its unit, drop all the declarations

}
for (let declarations1 of byUnit.values()){
for (let declarations of byUnit.values()){
// Get all but the last one
let removableDeclarations = Array.from(declarations1).slice(0, -1);
let removableDeclarations = Array.from(declarations).slice(0, -1);
for (let decl of removableDeclarations){

@@ -79,6 +84,6 @@ decl.remove();

if (result) {
var ref;
return (ref = result[1]) !== null && ref !== void 0 ? ref : UNITLESS_NUMBER;
var _result_;
return (_result_ = result[1]) !== null && _result_ !== void 0 ? _result_ : UNITLESS_NUMBER;
}
return null;
}

@@ -5,24 +5,48 @@ "use strict";

});
exports.defaultExtractor = defaultExtractor;
var regex = _interopRequireWildcard(require("./regex"));
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
Object.defineProperty(exports, "defaultExtractor", {
enumerable: true,
get: function() {
return defaultExtractor;
}
});
const _regex = /*#__PURE__*/ _interop_require_wildcard(require("./regex"));
const _splitAtTopLevelOnly = require("../util/splitAtTopLevelOnly");
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}

@@ -36,7 +60,29 @@ function defaultExtractor(context) {

for (let pattern of patterns){
var ref;
results.push(...(ref = content.match(pattern)) !== null && ref !== void 0 ? ref : []);
var _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);
// Extract any subclasses from languages like Slim and Pug, eg:
// div.flex.px-5.underline
for (let result of results.slice()){
let segments = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(result, ".");
for(let idx = 0; idx < segments.length; idx++){
let segment = segments[idx];
if (idx >= segments.length - 1) {
results.push(segment);
continue;
}
// If the next segment is a number, discard both, for example seeing
// `px-1` and `5` means the real candidate was `px-1.5` which is already
// captured.
let next = Number(segments[idx + 1]);
if (isNaN(next)) {
results.push(segment);
} else {
idx++;
}
}
}
return results;
};

@@ -46,51 +92,108 @@ }

let separator = context.tailwindConfig.separator;
yield regex.pattern([
// Variants
"((?=((",
regex.any([
regex.pattern([
/([^\s"'\[\\]+-)?\[[^\s"'\\]+\]/,
separator
let prefix = context.tailwindConfig.prefix !== "" ? _regex.optional(_regex.pattern([
/-?/,
_regex.escape(context.tailwindConfig.prefix)
])) : "";
let utility = _regex.any([
// Arbitrary properties (without square brackets)
/\[[^\s:'"`]+:[^\s\[\]]+\]/,
// Arbitrary properties with balanced square brackets
// This is a targeted fix to continue to allow theme()
// with square brackets to work in arbitrary properties
// while fixing a problem with the regex matching too much
/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
// Utilities
_regex.pattern([
// Utility Name / Group Name
_regex.any([
/-?(?:\w+)/,
// This is here to make sure @container supports everything that other utilities do
/@(?:\w+)/
]),
regex.pattern([
/[^\s"'\[\\]+/,
separator
]),
], true),
")+))\\2)?",
// Important (optional)
/!?/,
regex.any([
// Arbitrary properties
/\[[^\s:'"]+:[^\s\]]+\]/,
// Utilities
regex.pattern([
// Utility Name / Group Name
/-?(?:\w+)/,
// Normal/Arbitrary values
regex.optional(regex.any([
regex.pattern([
// Arbitrary values
/-\[[^\s:]+\]/,
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"\\$]*)?/,
// Normal/Arbitrary values
_regex.optional(_regex.any([
_regex.pattern([
// Arbitrary values
_regex.any([
/-(?:\w+-)*\['[^\s]+'\]/,
/-(?:\w+-)*\["[^\s]+"\]/,
/-(?:\w+-)*\[`[^\s]+`\]/,
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/
]),
regex.pattern([
// Arbitrary values
/-\[[^\s]+\]/,
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"\\$]*)?/,
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"`\\><$]*)?/
]),
_regex.pattern([
// Arbitrary values
_regex.any([
/-(?:\w+-)*\['[^\s]+'\]/,
/-(?:\w+-)*\["[^\s]+"\]/,
/-(?:\w+-)*\[`[^\s]+`\]/,
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/
]),
// Normal values w/o quotes — may include an opacity modifier
/[-\/][^\s'"\\$={]*/,
])),
]),
]),
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"`\\$]*)?/
]),
// Normal values w/o quotes — may include an opacity modifier
/[-\/][^\s'"`\\$={><]*/
]))
])
]);
// 5. Inner matches
// yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
let variantPatterns = [
// Without quotes
_regex.any([
// This is here to provide special support for the `@` variant
_regex.pattern([
/@\[[^\s"'`]+\](\/[^\s"'`]+)?/,
separator
]),
// With variant modifier (e.g.: group-[..]/modifier)
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/,
separator
]),
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,
separator
]),
_regex.pattern([
/[^\s"'`\[\\]+/,
separator
])
]),
// With quotes allowed
_regex.any([
// With variant modifier (e.g.: group-[..]/modifier)
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/,
separator
]),
_regex.pattern([
/([^\s"'`\[\\]+-)?\[[^\s`]+\]/,
separator
]),
_regex.pattern([
/[^\s`\[\\]+/,
separator
])
])
];
for (const variantPattern of variantPatterns){
yield _regex.pattern([
// Variants
"((?=((",
variantPattern,
")+))\\2)?",
// Important (optional)
/!?/,
prefix,
utility
]);
}
// 5. Inner matches
yield /[^<>"'`\s.(){}[\]#=%$][^<>"'`\s(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
}

@@ -133,7 +236,6 @@ // We want to capture any "special" characters

0: group
})
);
}));
});
for (let match1 of matches){
let char = match1[0];
for (let match of matches){
let char = match[0];
let inStringType = openStringTypes[openStringTypes.length - 1];

@@ -158,3 +260,3 @@ if (char === inStringType) {

if (depth < 0) {
return input.substring(0, match1.index);
return input.substring(0, match.index - 1);
}

@@ -166,3 +268,3 @@ // We've finished balancing the brackets but there still may be characters that can be included

if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
return input.substring(0, match1.index);
return input.substring(0, match.index);
}

@@ -169,0 +271,0 @@ }

@@ -5,11 +5,19 @@ "use strict";

});
exports.default = _default;
var _dlv = _interopRequireDefault(require("dlv"));
var _didyoumean = _interopRequireDefault(require("didyoumean"));
var _transformThemeValue = _interopRequireDefault(require("../util/transformThemeValue"));
var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
var _normalizeScreens = require("../util/normalizeScreens");
var _buildMediaQuery = _interopRequireDefault(require("../util/buildMediaQuery"));
var _toPath = require("../util/toPath");
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _dlv = /*#__PURE__*/ _interop_require_default(require("dlv"));
const _didyoumean = /*#__PURE__*/ _interop_require_default(require("didyoumean"));
const _transformThemeValue = /*#__PURE__*/ _interop_require_default(require("../util/transformThemeValue"));
const _index = /*#__PURE__*/ _interop_require_default(require("../value-parser/index"));
const _normalizeScreens = require("../util/normalizeScreens");
const _buildMediaQuery = /*#__PURE__*/ _interop_require_default(require("../util/buildMediaQuery"));
const _toPath = require("../util/toPath");
const _withAlphaVariable = require("../util/withAlphaVariable");
const _pluginUtils = require("../util/pluginUtils");
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -23,6 +31,6 @@ default: obj

function findClosestExistingPath(theme, path) {
let parts = (0, _toPath).toPath(path);
let parts = (0, _toPath.toPath)(path);
do {
parts.pop();
if ((0, _dlv).default(theme, parts) !== undefined) break;
if ((0, _dlv.default)(theme, parts) !== undefined) break;
}while (parts.length);

@@ -39,4 +47,3 @@ return parts.length ? parts : undefined;

function list(items) {
return items.map((key)=>`'${key}'`
).join(", ");
return items.map((key)=>`'${key}'`).join(", ");
}

@@ -46,10 +53,10 @@ function listKeys(obj) {

}
function validatePath(config, path, defaultValue) {
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+/g, "").replace(/['"]+$/g, "");
const pathSegments = Array.isArray(path) ? path : (0, _toPath).toPath(pathString);
const value = (0, _dlv).default(config.theme, pathSegments, defaultValue);
function validatePath(config, path, defaultValue, themeOpts = {}) {
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, "");
const pathSegments = Array.isArray(path) ? path : (0, _toPath.toPath)(pathString);
const value = (0, _dlv.default)(config.theme, pathSegments, defaultValue);
if (value === undefined) {
let error = `'${pathString}' does not exist in your theme config.`;
const parentSegments = pathSegments.slice(0, -1);
const parentValue = (0, _dlv).default(config.theme, parentSegments);
const parentValue = (0, _dlv.default)(config.theme, parentSegments);
if (isObject(parentValue)) {

@@ -59,5 +66,4 @@ const validKeys = Object.keys(parentValue).filter((key)=>validatePath(config, [

key
]).isValid
);
const suggestion = (0, _didyoumean).default(pathSegments[pathSegments.length - 1], validKeys);
]).isValid);
const suggestion = (0, _didyoumean.default)(pathSegments[pathSegments.length - 1], validKeys);
if (suggestion) {

@@ -74,3 +80,3 @@ error += ` Did you mean '${pathToString([

if (closestPath) {
const closestValue = (0, _dlv).default(config.theme, closestPath);
const closestValue = (0, _dlv.default)(config.theme, closestPath);
if (isObject(closestValue)) {

@@ -96,4 +102,3 @@ error += ` '${pathToString(closestPath)}' has the following keys: ${listKeys(closestValue)}`;

key
]).isValid
);
]).isValid);
if (validKeys.length) {

@@ -114,16 +119,15 @@ error += ` Did you mean something like '${pathToString([

isValid: true,
value: (0, _transformThemeValue).default(themeSection)(value)
value: (0, _transformThemeValue.default)(themeSection)(value, themeOpts)
};
}
function extractArgs(node, vNodes, functions) {
vNodes = vNodes.map((vNode)=>resolveVNode(node, vNode, functions)
);
vNodes = vNodes.map((vNode)=>resolveVNode(node, vNode, functions));
let args = [
""
];
for (let vNode1 of vNodes){
if (vNode1.type === "div" && vNode1.value === ",") {
for (let vNode of vNodes){
if (vNode.type === "div" && vNode.value === ",") {
args.push("");
} else {
args[args.length - 1] += _postcssValueParser.default.stringify(vNode1);
args[args.length - 1] += _index.default.stringify(vNode);
}

@@ -142,3 +146,5 @@ }

function resolveFunctions(node, input, functions) {
return (0, _postcssValueParser).default(input).walk((vNode)=>{
let hasAnyFn = Object.keys(functions).some((fn)=>input.includes(`${fn}(`));
if (!hasAnyFn) return input;
return (0, _index.default)(input).walk((vNode)=>{
resolveVNode(node, vNode, functions);

@@ -151,9 +157,71 @@ }).toString();

};
function _default({ tailwindConfig: config }) {
/**
* @param {string} path
* @returns {Iterable<[path: string, alpha: string|undefined]>}
*/ function* toPaths(path) {
// Strip quotes from beginning and end of string
// This allows the alpha value to be present inside of quotes
path = path.replace(/^['"]+|['"]+$/g, "");
let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/);
let alpha = undefined;
yield [
path,
undefined
];
if (matches) {
path = matches[1];
alpha = matches[2];
yield [
path,
alpha
];
}
}
/**
*
* @param {any} config
* @param {string} path
* @param {any} defaultValue
*/ function resolvePath(config, path, defaultValue) {
const results = Array.from(toPaths(path)).map(([path, alpha])=>{
return Object.assign(validatePath(config, path, defaultValue, {
opacityValue: alpha
}), {
resolvedPath: path,
alpha
});
});
var _results_find;
return (_results_find = results.find((result)=>result.isValid)) !== null && _results_find !== void 0 ? _results_find : results[0];
}
function _default(context) {
let config = context.tailwindConfig;
let functions = {
theme: (node, path, ...defaultValue)=>{
const { isValid , value , error } = validatePath(config, path, defaultValue.length ? defaultValue : undefined);
let { isValid , value , error , alpha } = resolvePath(config, path, defaultValue.length ? defaultValue : undefined);
if (!isValid) {
var _parentNode_raws_tailwind;
let parentNode = node.parent;
let candidate = (_parentNode_raws_tailwind = parentNode === null || parentNode === void 0 ? void 0 : parentNode.raws.tailwind) === null || _parentNode_raws_tailwind === void 0 ? void 0 : _parentNode_raws_tailwind.candidate;
if (parentNode && candidate !== undefined) {
// Remove this utility from any caches
context.markInvalidUtilityNode(parentNode);
// Remove the CSS node from the markup
parentNode.remove();
// Show a warning
_log.default.warn("invalid-theme-key-in-class", [
`The utility \`${candidate}\` contains an invalid theme value and was not generated.`
]);
return;
}
throw node.error(error);
}
let maybeColor = (0, _pluginUtils.parseColorFormat)(value);
let isColorFunction = maybeColor !== undefined && typeof maybeColor === "function";
if (alpha !== undefined || isColorFunction) {
if (alpha === undefined) {
alpha = 1.0;
}
value = (0, _withAlphaVariable.withAlphaValue)(maybeColor, alpha, maybeColor);
}
return value;

@@ -163,9 +231,8 @@ },

screen = screen.replace(/^['"]+/g, "").replace(/['"]+$/g, "");
let screens = (0, _normalizeScreens).normalizeScreens(config.theme.screens);
let screenDefinition = screens.find(({ name })=>name === screen
);
let screens = (0, _normalizeScreens.normalizeScreens)(config.theme.screens);
let screenDefinition = screens.find(({ name })=>name === screen);
if (!screenDefinition) {
throw node.error(`The '${screen}' screen does not exist in your theme.`);
}
return (0, _buildMediaQuery).default(screenDefinition);
return (0, _buildMediaQuery.default)(screenDefinition);
}

@@ -172,0 +239,0 @@ };

@@ -5,17 +5,15 @@ "use strict";

});
exports.default = expandApplyAtRules;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _generateRules = require("./generateRules");
var _bigSign = _interopRequireDefault(require("../util/bigSign"));
var _escapeClassName = _interopRequireDefault(require("../util/escapeClassName"));
function expandApplyAtRules(context) {
return (root)=>{
// Build a cache of the user's CSS so we can use it to resolve classes used by @apply
let localCache = lazyCache(()=>buildLocalApplyCache(root, context)
);
processApply(root, context, localCache);
};
}
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return expandApplyAtRules;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
const _generateRules = require("./generateRules");
const _escapeClassName = /*#__PURE__*/ _interop_require_default(require("../util/escapeClassName"));
const _applyImportantSelector = require("../util/applyImportantSelector");
const _pseudoElements = require("../util/pseudoElements");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -33,3 +31,3 @@ default: obj

container.walkRules((rule)=>{
(0, _postcssSelectorParser).default((selectors)=>{
(0, _postcssselectorparser.default)((selectors)=>{
selectors.walkClasses((classSelector)=>{

@@ -45,16 +43,13 @@ let parentSelector = classSelector.parent.toString();

});
let normalizedGroups = Array.from(groups.values(), (classes)=>Array.from(classes)
);
let classes1 = normalizedGroups.flat();
return Object.assign(classes1, {
let normalizedGroups = Array.from(groups.values(), (classes)=>Array.from(classes));
let classes = normalizedGroups.flat();
return Object.assign(classes, {
groups: normalizedGroups
});
}
let selectorExtractor = (0, _postcssSelectorParser).default((root)=>root.nodes.map((node)=>node.toString()
)
);
let selectorExtractor = (0, _postcssselectorparser.default)();
/**
* @param {string} ruleSelectors
*/ function extractSelectors(ruleSelectors) {
return selectorExtractor.transformSync(ruleSelectors);
return selectorExtractor.astSync(ruleSelectors);
}

@@ -69,4 +64,4 @@ function extractBaseCandidates(candidates, separator) {

function prefix(context, selector) {
let prefix1 = context.tailwindConfig.prefix;
return typeof prefix1 === "function" ? prefix1(selector) : prefix1 + selector;
let prefix = context.tailwindConfig.prefix;
return typeof prefix === "function" ? prefix(selector) : prefix + selector;
}

@@ -152,8 +147,7 @@ function* pathToRoot(node) {

/** @type {ApplyCache} */ let cache = new Map();
let highestOffset = context.layerOrder.user >> 4n;
root.walkRules((rule, idx)=>{
root.walkRules((rule)=>{
// Ignore rules generated by Tailwind
for (let node of pathToRoot(rule)){
var ref;
if (((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.layer) !== undefined) {
var _node_raws_tailwind;
if (((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.layer) !== undefined) {
return;

@@ -164,2 +158,3 @@ }

let container = nestedClone(rule);
let sort = context.offsets.create("user");
for (let className of extractClasses(rule)){

@@ -171,6 +166,6 @@ let list = cache.get(className) || [];

layer: "user",
sort: BigInt(idx) + highestOffset,
sort,
important: false
},
container,
container
]);

@@ -192,7 +187,6 @@ }

rule.clone()
]
));
]));
continue;
}
let matches = Array.from((0, _generateRules).resolveMatches(candidate, context));
let matches = Array.from((0, _generateRules.resolveMatches)(candidate, context));
if (matches.length === 0) {

@@ -232,7 +226,4 @@ context.notClassCache.add(candidate);

return {
get: (name)=>caches.flatMap((cache)=>cache.get(name) || []
)
,
has: (name)=>caches.some((cache)=>cache.has(name)
)
get: (name)=>caches.flatMap((cache)=>cache.get(name) || []),
has: (name)=>caches.some((cache)=>cache.has(name))
};

@@ -292,26 +283,79 @@ }

* Which means that we can replace `.hover\:font-bold` with `.abc` in `.hover\:font-bold:hover` resulting in `.abc:hover`
*/ // TODO: Should we use postcss-selector-parser for this instead?
function replaceSelector(selector, utilitySelectors, candidate) {
let needle1 = `.${(0, _escapeClassName).default(candidate)}`;
let needles = [
...new Set([
needle1,
needle1.replace(/\\2c /g, "\\,")
])
];
*
* @param {string} selector
* @param {string} utilitySelectors
* @param {string} candidate
*/ function replaceSelector(selector, utilitySelectors, candidate) {
let selectorList = extractSelectors(selector);
let utilitySelectorsList = extractSelectors(utilitySelectors);
return extractSelectors(selector).map((s)=>{
let replaced = [];
for (let utilitySelector of utilitySelectorsList){
let replacedSelector = utilitySelector;
for (const needle of needles){
replacedSelector = replacedSelector.replace(needle, s);
let candidateList = extractSelectors(`.${(0, _escapeClassName.default)(candidate)}`);
let candidateClass = candidateList.nodes[0].nodes[0];
selectorList.each((sel)=>{
/** @type {Set<import('postcss-selector-parser').Selector>} */ let replaced = new Set();
utilitySelectorsList.each((utilitySelector)=>{
let hasReplaced = false;
utilitySelector = utilitySelector.clone();
utilitySelector.walkClasses((node)=>{
if (node.value !== candidateClass.value) {
return;
}
// Don't replace multiple instances of the same class
// This is theoretically correct but only partially
// We'd need to generate every possible permutation of the replacement
// For example with `.foo + .foo { … }` and `section { @apply foo; }`
// We'd need to generate all of these:
// - `.foo + .foo`
// - `.foo + section`
// - `section + .foo`
// - `section + section`
if (hasReplaced) {
return;
}
// Since you can only `@apply` class names this is sufficient
// We want to replace the matched class name with the selector the user is using
// Ex: Replace `.text-blue-500` with `.foo.bar:is(.something-cool)`
node.replaceWith(...sel.nodes.map((node)=>node.clone()));
// Record that we did something and we want to use this new selector
replaced.add(utilitySelector);
hasReplaced = true;
});
});
// Sort tag names before class names (but only sort each group (separated by a combinator)
// separately and not in total)
// This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
for (let sel of replaced){
let groups = [
[]
];
for (let node of sel.nodes){
if (node.type === "combinator") {
groups.push(node);
groups.push([]);
} else {
let last = groups[groups.length - 1];
last.push(node);
}
}
if (replacedSelector === utilitySelector) {
continue;
sel.nodes = [];
for (let group of groups){
if (Array.isArray(group)) {
group.sort((a, b)=>{
if (a.type === "tag" && b.type === "class") {
return -1;
} else if (a.type === "class" && b.type === "tag") {
return 1;
} else if (a.type === "class" && b.type === "pseudo" && b.value.startsWith("::")) {
return -1;
} else if (a.type === "pseudo" && a.value.startsWith("::") && b.type === "class") {
return 1;
}
return 0;
});
}
sel.nodes = sel.nodes.concat(group);
}
replaced.push(replacedSelector);
}
return replaced.join(", ");
}).join(", ");
sel.replaceWith(...replaced);
});
return selectorList.toString();
}

@@ -332,5 +376,4 @@ let perParentApplies = new Map();

if (apply.parent.name === "screen") {
const screenType = apply.parent.params;
throw apply.error(`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates.map((c)=>`${screenType}:${c}`
).join(" ")} instead.`);
let screenType = apply.parent.params;
throw apply.error(`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates.map((c)=>`${screenType}:${c}`).join(" ")} instead.`);
}

@@ -351,2 +394,15 @@ throw apply.error(`@apply is not supported within nested at-rules like @${apply.parent.name}. You can fix this by un-nesting @${apply.parent.name}.`);

let rules = applyClassCache.get(applyCandidate);
// Verify that we can apply the class
for (let [, rule] of rules){
if (rule.type === "atrule") {
continue;
}
rule.walkRules(()=>{
throw apply.error([
`The \`${applyCandidate}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`,
"Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:",
"https://tailwindcss.com/docs/using-with-preprocessors#nesting"
].join("\n"));
});
}
candidates.push([

@@ -359,5 +415,5 @@ applyCandidate,

}
for (const [parent, [candidates1, atApplySource]] of perParentApplies){
for (let [parent, [candidates, atApplySource]] of perParentApplies){
let siblings = [];
for (let [applyCandidate, important, rules] of candidates1){
for (let [applyCandidate, important, rules] of candidates){
let potentialApplyCandidates = [

@@ -367,12 +423,10 @@ applyCandidate,

applyCandidate
], context.tailwindConfig.separator),
], context.tailwindConfig.separator)
];
for (let [meta, node1] of rules){
for (let [meta, node] of rules){
let parentClasses = extractClasses(parent);
let nodeClasses = extractClasses(node1);
let nodeClasses = extractClasses(node);
// When we encounter a rule like `.dark .a, .b { … }` we only want to be left with `[.dark, .a]` if the base applyCandidate is `.a` or with `[.b]` if the base applyCandidate is `.b`
// So we've split them into groups
nodeClasses = nodeClasses.groups.filter((classList)=>classList.some((className)=>potentialApplyCandidates.includes(className)
)
).flat();
nodeClasses = nodeClasses.groups.filter((classList)=>classList.some((className)=>potentialApplyCandidates.includes(className))).flat();
// Add base utility classes from the @apply node to the list of

@@ -401,10 +455,9 @@ // classes to check whether it intersects and therefore results in a

nodeClasses = nodeClasses.concat(extractBaseCandidates(nodeClasses, context.tailwindConfig.separator));
let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector)
);
let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector));
if (intersects) {
throw node1.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
throw node.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
}
let root = _postcss.default.root({
nodes: [
node1.clone()
node.clone()
]

@@ -416,3 +469,3 @@ });

});
let canRewriteSelector = node1.type !== "atrule" || node1.type === "atrule" && node1.name !== "keyframes";
let canRewriteSelector = node.type !== "atrule" || node.type === "atrule" && node.name !== "keyframes";
if (canRewriteSelector) {

@@ -451,4 +504,3 @@ root.walkRules((rule)=>{

// case it would result in `{}` instead of `.something-unrelated {}`
if (!extractClasses(rule).some((candidate)=>candidate === applyCandidate
)) {
if (!extractClasses(rule).some((candidate)=>candidate === applyCandidate)) {
rule.remove();

@@ -463,6 +515,12 @@ return;

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);
// And then re-add it if it was removed
if (importantSelector && parentSelector !== parent.selector) {
rule.selector = `${importantSelector} ${rule.selector}`;
rule.selector = (0, _applyImportantSelector.applyImportantSelector)(rule.selector, importantSelector);
}

@@ -472,12 +530,17 @@ rule.walkDecls((d)=>{

});
// Move pseudo elements to the end of the selector (if necessary)
let selector = (0, _postcssselectorparser.default)().astSync(rule.selector);
selector.each((sel)=>(0, _pseudoElements.movePseudos)(sel));
rule.selector = selector.toString();
});
}
// It could be that the node we were inserted was removed because the class didn't match
// If that was the *only* rule in the parent, then we have nothing add so we skip it
if (!root.nodes[0]) {
continue;
}
// Insert it
siblings.push([
// Ensure that when we are sorting, that we take the layer order into account
{
...meta,
sort: meta.sort | context.layerOrder[meta.layer]
},
root.nodes[0],
meta.sort,
root.nodes[0]
]);

@@ -487,15 +550,13 @@ }

// Inject the rules, sorted, correctly
let nodes = siblings.sort(([a], [z])=>(0, _bigSign).default(a.sort - z.sort)
).map((s)=>s[1]
);
let nodes = context.offsets.sort(siblings).map((s)=>s[1]);
// `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
parent.after(nodes);
}
for (let apply1 of applies){
for (let apply of applies){
// If there are left-over declarations, just remove the @apply
if (apply1.parent.nodes.length > 1) {
apply1.remove();
if (apply.parent.nodes.length > 1) {
apply.remove();
} else {
// The node is empty, drop the full node
apply1.parent.remove();
apply.parent.remove();
}

@@ -506,1 +567,8 @@ }

}
function expandApplyAtRules(context) {
return (root)=>{
// Build a cache of the user's CSS so we can use it to resolve classes used by @apply
let localCache = lazyCache(()=>buildLocalApplyCache(root, context));
processApply(root, context, localCache);
};
}

@@ -5,12 +5,125 @@ "use strict";

});
exports.default = expandTailwindAtRules;
var _quickLru = _interopRequireDefault(require("quick-lru"));
var sharedState = _interopRequireWildcard(require("./sharedState"));
var _generateRules = require("./generateRules");
var _bigSign = _interopRequireDefault(require("../util/bigSign"));
var _log = _interopRequireDefault(require("../util/log"));
var _cloneNodes = _interopRequireDefault(require("../util/cloneNodes"));
var _defaultExtractor = require("./defaultExtractor");
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return expandTailwindAtRules;
}
});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _quicklru = /*#__PURE__*/ _interop_require_default(require("@alloc/quick-lru"));
const _sharedState = /*#__PURE__*/ _interop_require_wildcard(require("./sharedState"));
const _generateRules = require("./generateRules");
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log"));
const _cloneNodes = /*#__PURE__*/ _interop_require_default(require("../util/cloneNodes"));
const _defaultExtractor = require("./defaultExtractor");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
let env = _sharedState.env;
const builtInExtractors = {
DEFAULT: _defaultExtractor.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 _quicklru.default({
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;
}
function expandTailwindAtRules(context) {
return (root)=>{
return async (root)=>{
let layerNodes = {

@@ -33,18 +146,34 @@ base: null,

});
if (Object.values(layerNodes).every((n)=>n === null
)) {
if (Object.values(layerNodes).every((n)=>n === null)) {
return root;
}
var _context_candidates;
// ---
// Find potential rules in changed files
let candidates = new Set([
sharedState.NOT_ON_DEMAND
...(_context_candidates = context.candidates) !== null && _context_candidates !== void 0 ? _context_candidates : [],
_sharedState.NOT_ON_DEMAND
]);
let seen = new Set();
env.DEBUG && console.time("Reading changed files");
for (let { content , extension } of context.changedContent){
let transformer = getTransformer(context.tailwindConfig, extension);
let extractor = getExtractor(context, extension);
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);
}));
}
env.DEBUG && console.timeEnd("Reading changed files");

@@ -55,3 +184,12 @@ // ---

env.DEBUG && console.time("Generate rules");
let rules = (0, _generateRules).generateRules(candidates, context);
env.DEBUG && console.time("Sorting candidates");
let sortedCandidates = new Set([
...candidates
].sort((a, z)=>{
if (a === z) return 0;
if (a < z) return -1;
return 1;
}));
env.DEBUG && console.timeEnd("Sorting candidates");
(0, _generateRules.generateRules)(sortedCandidates, context);
env.DEBUG && console.timeEnd("Generate rules");

@@ -61,5 +199,2 @@ // We only ever add to the classCache, so if it didn't grow, there is nothing new.

if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
for (let rule of rules){
context.ruleCache.add(rule);
}
context.stylesheetCache = buildStylesheet([

@@ -70,7 +205,7 @@ ...context.ruleCache

env.DEBUG && console.timeEnd("Build stylesheet");
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes } = context.stylesheetCache;
// ---
// Replace any Tailwind directives with generated CSS
if (layerNodes.base) {
layerNodes.base.before((0, _cloneNodes).default([
layerNodes.base.before((0, _cloneNodes.default)([
...baseNodes,

@@ -84,3 +219,3 @@ ...defaultNodes

if (layerNodes.components) {
layerNodes.components.before((0, _cloneNodes).default([
layerNodes.components.before((0, _cloneNodes.default)([
...componentNodes

@@ -93,3 +228,3 @@ ], layerNodes.components.source, {

if (layerNodes.utilities) {
layerNodes.utilities.before((0, _cloneNodes).default([
layerNodes.utilities.before((0, _cloneNodes.default)([
...utilityNodes

@@ -103,4 +238,4 @@ ], layerNodes.utilities.source, {

const variantNodes = Array.from(screenNodes).filter((node)=>{
var ref;
const parentLayer = (ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer;
var _node_raws_tailwind;
const parentLayer = (_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer;
if (parentLayer === "components") {

@@ -115,3 +250,3 @@ return layerNodes.components !== null;

if (layerNodes.variants) {
layerNodes.variants.before((0, _cloneNodes).default(variantNodes, layerNodes.variants.source, {
layerNodes.variants.before((0, _cloneNodes.default)(variantNodes, layerNodes.variants.source, {
layer: "variants"

@@ -121,10 +256,13 @@ }));

} else if (variantNodes.length > 0) {
root.append((0, _cloneNodes).default(variantNodes, root.source, {
root.append((0, _cloneNodes.default)(variantNodes, root.source, {
layer: "variants"
}));
}
var _root_source_end;
// TODO: Why is the root node having no source location for `end` possible?
root.source.end = (_root_source_end = root.source.end) !== null && _root_source_end !== void 0 ? _root_source_end : root.source.start;
// If we've got a utility layer and no utilities are generated there's likely something wrong
const hasUtilityVariants = variantNodes.some((node)=>{
var ref;
return ((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer) === "utilities";
var _node_raws_tailwind;
return ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer) === "utilities";
});

@@ -134,3 +272,3 @@ if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {

"No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.",
"https://tailwindcss.com/docs/content-configuration",
"https://tailwindcss.com/docs/content-configuration"
]);

@@ -141,3 +279,3 @@ }

console.log("Potential classes: ", candidates.size);
console.log("Active contexts: ", sharedState.contextSourcesMap.size);
console.log("Active contexts: ", _sharedState.contextSourcesMap.size);
}

@@ -154,122 +292,1 @@ // Clear the cache for the changed files

}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
}
newObj.default = obj;
return newObj;
}
}
let env = sharedState.env;
const builtInExtractors = {
DEFAULT: _defaultExtractor.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 _quickLru.default({
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);
}
}
}
function buildStylesheet(rules, context) {
let sortedRules = rules.sort(([a], [z])=>(0, _bigSign).default(a - z)
);
let returnValue = {
base: new Set(),
defaults: new Set(),
components: new Set(),
utilities: new Set(),
variants: new Set(),
// All the CSS that is not Tailwind related can be put in this bucket. This
// will make it easier to later use this information when we want to
// `@apply` for example. The main reason we do this here is because we
// still need to make sure the order is correct. Last but not least, we
// will make sure to always re-inject this section into the css, even if
// certain rules were not used. This means that it will look like a no-op
// from the user's perspective, but we gathered all the useful information
// we need.
user: new Set()
};
for (let [sort, rule] of sortedRules){
if (sort >= context.minimumScreen) {
returnValue.variants.add(rule);
continue;
}
if (sort & context.layerOrder.base) {
returnValue.base.add(rule);
continue;
}
if (sort & context.layerOrder.defaults) {
returnValue.defaults.add(rule);
continue;
}
if (sort & context.layerOrder.components) {
returnValue.components.add(rule);
continue;
}
if (sort & context.layerOrder.utilities) {
returnValue.utilities.add(rule);
continue;
}
if (sort & context.layerOrder.user) {
returnValue.user.add(rule);
continue;
}
}
return returnValue;
}

@@ -5,18 +5,36 @@ "use strict";

});
exports.generateRules = exports.resolveMatches = void 0;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _parseObjectStyles = _interopRequireDefault(require("../util/parseObjectStyles"));
var _isPlainObject = _interopRequireDefault(require("../util/isPlainObject"));
var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
var _pluginUtils = require("../util/pluginUtils");
var _log = _interopRequireDefault(require("../util/log"));
var sharedState = _interopRequireWildcard(require("./sharedState"));
var _formatVariantSelector = require("../util/formatVariantSelector");
var _nameClass = require("../util/nameClass");
var _dataTypes = require("../util/dataTypes");
var _setupContextUtils = require("./setupContextUtils");
var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
var _splitAtTopLevelOnlyJs = require("../util/splitAtTopLevelOnly.js");
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
getClassNameFromSelector: function() {
return getClassNameFromSelector;
},
resolveMatches: function() {
return resolveMatches;
},
generateRules: function() {
return generateRules;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
const _parseObjectStyles = /*#__PURE__*/ _interop_require_default(require("../util/parseObjectStyles"));
const _isPlainObject = /*#__PURE__*/ _interop_require_default(require("../util/isPlainObject"));
const _prefixSelector = /*#__PURE__*/ _interop_require_default(require("../util/prefixSelector"));
const _pluginUtils = require("../util/pluginUtils");
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log"));
const _sharedState = /*#__PURE__*/ _interop_require_wildcard(require("./sharedState"));
const _formatVariantSelector = require("../util/formatVariantSelector");
const _nameClass = require("../util/nameClass");
const _dataTypes = require("../util/dataTypes");
const _setupContextUtils = require("./setupContextUtils");
const _isSyntacticallyValidPropertyValue = /*#__PURE__*/ _interop_require_default(require("../util/isSyntacticallyValidPropertyValue"));
const _splitAtTopLevelOnly = require("../util/splitAtTopLevelOnly.js");
const _featureFlags = require("../featureFlags");
const _applyImportantSelector = require("../util/applyImportantSelector");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -26,26 +44,43 @@ default: obj

}
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
let classNameParser = (0, _postcssSelectorParser).default((selectors)=>{
return selectors.first.filter(({ type })=>type === "class"
).pop().value;
let classNameParser = (0, _postcssselectorparser.default)((selectors)=>{
return selectors.first.filter(({ type })=>type === "class").pop().value;
});

@@ -66,2 +101,3 @@ function getClassNameFromSelector(selector) {

let dashIdx;
let wasSlash = false;
if (lastIndex === Infinity && candidate.endsWith("]")) {

@@ -71,6 +107,13 @@ let bracketIdx = candidate.indexOf("[");

// eg. string[]
dashIdx = [
"-",
"/"
].includes(candidate[bracketIdx - 1]) ? bracketIdx - 1 : -1;
if (candidate[bracketIdx - 1] === "-") {
dashIdx = bracketIdx - 1;
} else if (candidate[bracketIdx - 1] === "/") {
dashIdx = bracketIdx - 1;
wasSlash = true;
} else {
dashIdx = -1;
}
} else if (lastIndex === Infinity && candidate.includes("/")) {
dashIdx = candidate.lastIndexOf("/");
wasSlash = true;
} else {

@@ -83,3 +126,8 @@ dashIdx = candidate.lastIndexOf("-", lastIndex);

let prefix = candidate.slice(0, dashIdx);
let modifier = candidate.slice(dashIdx + 1);
let modifier = candidate.slice(wasSlash ? dashIdx : dashIdx + 1);
lastIndex = dashIdx - 1;
// TODO: This feels a bit hacky
if (prefix === "" || modifier === "/") {
continue;
}
yield [

@@ -89,3 +137,2 @@ prefix,

];
lastIndex = dashIdx - 1;
}

@@ -112,3 +159,3 @@ }

let shouldPrependNegative = classCandidate.startsWith("-");
r.selector = (0, _prefixSelector).default(context.tailwindConfig.prefix, r.selector, shouldPrependNegative);
r.selector = (0, _prefixSelector.default)(context.tailwindConfig.prefix, r.selector, shouldPrependNegative);
});

@@ -125,2 +172,5 @@ match[1] = container.nodes[0];

let result = [];
function isInKeyframes(rule) {
return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes";
}
for (let [meta, rule] of matches){

@@ -133,10 +183,14 @@ let container = _postcss.default.root({

container.walkRules((r)=>{
r.selector = (0, _pluginUtils).updateAllClasses(r.selector, (className)=>{
if (className === classCandidate) {
return `!${className}`;
}
return className;
});
r.walkDecls((d)=>d.important = true
);
// Declarations inside keyframes cannot be marked as important
// They will be ignored by the browser
if (isInKeyframes(r)) {
return;
}
let ast = (0, _postcssselectorparser.default)().astSync(r.selector);
// Remove extraneous selectors that do not include the base candidate
ast.each((sel)=>(0, _formatVariantSelector.eliminateIrrelevantSelectors)(sel, classCandidate));
// Update all instances of the base candidate to include the important marker
(0, _pluginUtils.updateAllClasses)(ast, (className)=>className === classCandidate ? `!${className}` : className);
r.selector = ast.toString();
r.walkDecls((d)=>d.important = true);
});

@@ -165,28 +219,74 @@ result.push([

}
let args;
// Find partial arbitrary variants
/** @type {{modifier: string | null, value: string | null}} */ let args = {
modifier: null,
value: _sharedState.NONE
};
// Retrieve "modifier"
{
let [baseVariant, ...modifiers] = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(variant, "/");
// This is a hack to support variants with `/` in them, like `ar-1/10/20:text-red-500`
// In this case 1/10 is a value but /20 is a modifier
if (modifiers.length > 1) {
baseVariant = baseVariant + "/" + modifiers.slice(0, -1).join("/");
modifiers = modifiers.slice(-1);
}
if (modifiers.length && !context.variantMap.has(variant)) {
variant = baseVariant;
args.modifier = modifiers[0];
if (!(0, _featureFlags.flagEnabled)(context.tailwindConfig, "generalizedModifiers")) {
return [];
}
}
}
// Retrieve "arbitrary value"
if (variant.endsWith("]") && !variant.startsWith("[")) {
args = variant.slice(variant.lastIndexOf("[") + 1, -1);
variant = variant.slice(0, variant.indexOf(args) - 1 /* - */ - 1 /* [ */ );
// We either have:
// @[200px]
// group-[:hover]
//
// But we don't want:
// @-[200px] (`-` is incorrect)
// group[:hover] (`-` is missing)
let match = /(.)(-?)\[(.*)\]/g.exec(variant);
if (match) {
let [, char, separator, value] = match;
// @-[200px] case
if (char === "@" && separator === "-") return [];
// group[:hover] case
if (char !== "@" && separator === "") return [];
variant = variant.replace(`${separator}[${value}]`, "");
args.value = value;
}
}
// Register arbitrary variants
if (isArbitraryValue(variant) && !context.variantMap.has(variant)) {
let selector = (0, _dataTypes).normalize(variant.slice(1, -1));
if (!(0, _setupContextUtils).isValidVariantFormatString(selector)) {
let sort = context.offsets.recordVariant(variant);
let selector = (0, _dataTypes.normalize)(variant.slice(1, -1));
let selectors = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(selector, ",");
// We do not support multiple selectors for arbitrary variants
if (selectors.length > 1) {
return [];
}
let fn = (0, _setupContextUtils).parseVariant(selector);
let sort = Array.from(context.variantOrder.values()).pop() << 1n;
context.variantMap.set(variant, [
[
sort,
fn
]
]);
context.variantOrder.set(variant, sort);
if (!selectors.every(_setupContextUtils.isValidVariantFormatString)) {
return [];
}
let records = selectors.map((sel, idx)=>[
context.offsets.applyParallelOffset(sort, idx),
(0, _setupContextUtils.parseVariant)(sel.trim())
]);
context.variantMap.set(variant, records);
}
if (context.variantMap.has(variant)) {
let variantFunctionTuples = context.variantMap.get(variant);
var _context_variantOptions_get;
let isArbitraryVariant = isArbitraryValue(variant);
var _context_variantOptions_get_INTERNAL_FEATURES;
let internalFeatures = (_context_variantOptions_get_INTERNAL_FEATURES = (_context_variantOptions_get = context.variantOptions.get(variant)) === null || _context_variantOptions_get === void 0 ? void 0 : _context_variantOptions_get[_setupContextUtils.INTERNAL_FEATURES]) !== null && _context_variantOptions_get_INTERNAL_FEATURES !== void 0 ? _context_variantOptions_get_INTERNAL_FEATURES : {};
let variantFunctionTuples = context.variantMap.get(variant).slice();
let result = [];
for (let [meta, rule1] of matches){
let respectPrefix = (()=>{
if (isArbitraryVariant) return false;
if (internalFeatures.respectPrefix === false) return false;
return true;
})();
for (let [meta, rule] of matches){
// Don't generate variants for user css

@@ -198,13 +298,15 @@ if (meta.layer === "user") {

nodes: [
rule1.clone()
rule.clone()
]
});
for (let [variantSort, variantFunction] of variantFunctionTuples){
let clone = container.clone();
for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples){
let clone = (containerFromArray !== null && containerFromArray !== void 0 ? containerFromArray : container).clone();
let collectedFormats = [];
let originals = new Map();
function prepareBackup() {
if (originals.size > 0) return; // Already prepared, chicken out
clone.walkRules((rule)=>originals.set(rule, rule.selector)
);
// Already prepared, chicken out
if (clone.raws.neededBackup) {
return;
}
clone.raws.neededBackup = true;
clone.walkRules((rule)=>rule.raws.originalSelector = rule.selector);
}

@@ -244,8 +346,32 @@ function modifySelectors(modifierFunction) {

format (selectorFormat) {
collectedFormats.push(selectorFormat);
collectedFormats.push({
format: selectorFormat,
respectPrefix
});
},
args
});
// It can happen that a list of format strings is returned from within the function. In that
// case, we have to process them as well. We can use the existing `variantSort`.
if (Array.isArray(ruleWithVariant)) {
for (let [idx, variantFunction] of ruleWithVariant.entries()){
// This is a little bit scary since we are pushing to an array of items that we are
// currently looping over. However, you can also think of it like a processing queue
// where you keep handling jobs until everything is done and each job can queue more
// jobs if needed.
variantFunctionTuples.push([
context.offsets.applyParallelOffset(variantSort, idx),
variantFunction,
// If the clone has been modified we have to pass that back
// though so each rule can use the modified container
clone.clone()
]);
}
continue;
}
if (typeof ruleWithVariant === "string") {
collectedFormats.push(ruleWithVariant);
collectedFormats.push({
format: ruleWithVariant,
respectPrefix
});
}

@@ -255,9 +381,11 @@ if (ruleWithVariant === null) {

}
// We filled the `originals`, therefore we assume that somebody touched
// We had to backup selectors, therefore we assume that somebody touched
// `container` or `modifySelectors`. Let's see if they did, so that we
// can restore the selectors, and collect the format strings.
if (originals.size > 0) {
if (clone.raws.neededBackup) {
delete clone.raws.neededBackup;
clone.walkRules((rule)=>{
if (!originals.has(rule)) return;
let before = originals.get(rule);
let before = rule.raws.originalSelector;
if (!before) return;
delete rule.raws.originalSelector;
if (before === rule.selector) return; // No mutation happened

@@ -269,3 +397,3 @@ let modified = rule.selector;

// classes, pseudos, ids, ...
let rebuiltBase = (0, _postcssSelectorParser).default((selectors)=>{
let rebuiltBase = (0, _postcssselectorparser.default)((selectors)=>{
selectors.walkClasses((classNode)=>{

@@ -286,3 +414,6 @@ classNode.value = `${variant}${context.tailwindConfig.separator}${classNode.value}`;

// format: .foo &
collectedFormats.push(modified.replace(rebuiltBase, "&"));
collectedFormats.push({
format: modified.replace(rebuiltBase, "&"),
respectPrefix
});
rule.selector = before;

@@ -299,10 +430,10 @@ });

};
var _collectedFormats;
var _meta_collectedFormats;
let withOffset = [
{
...meta,
sort: variantSort | meta.sort,
collectedFormats: ((_collectedFormats = meta.collectedFormats) !== null && _collectedFormats !== void 0 ? _collectedFormats : []).concat(collectedFormats)
sort: context.offsets.applyVariantOffset(meta.sort, variantSort, Object.assign(args, context.variantOptions.get(variant))),
collectedFormats: ((_meta_collectedFormats = meta.collectedFormats) !== null && _meta_collectedFormats !== void 0 ? _meta_collectedFormats : []).concat(collectedFormats)
},
clone.nodes[0],
clone.nodes[0]
];

@@ -318,3 +449,3 @@ result.push(withOffset);

// PostCSS node
if (!(0, _isPlainObject).default(rule) && !Array.isArray(rule)) {
if (!(0, _isPlainObject.default)(rule) && !Array.isArray(rule)) {
return [

@@ -333,3 +464,3 @@ [

if (!cache.has(rule)) {
cache.set(rule, (0, _parseObjectStyles).default(rule));
cache.set(rule, (0, _parseObjectStyles.default)(rule));
}

@@ -365,3 +496,3 @@ return [

node.walkDecls((decl)=>{
if (!isParsableCssValue(decl.name, decl.value)) {
if (!isParsableCssValue(decl.prop, decl.value)) {
isParsable = false;

@@ -388,4 +519,4 @@ return false;

function extractArbitraryProperty(classCandidate, context) {
var ref;
let [, property, value] = (ref = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)) !== null && ref !== void 0 ? ref : [];
var _classCandidate_match;
let [, property, value] = (_classCandidate_match = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)) !== null && _classCandidate_match !== void 0 ? _classCandidate_match : [];
if (value === undefined) {

@@ -397,22 +528,27 @@ return null;

}
if (!(0, _isValidArbitraryValue).default(value)) {
if (!(0, _isSyntacticallyValidPropertyValue.default)(value)) {
return null;
}
let normalized = (0, _dataTypes).normalize(value);
let normalized = (0, _dataTypes.normalize)(value, {
property
});
if (!isParsableCssValue(property, normalized)) {
return null;
}
let sort = context.offsets.arbitraryProperty(classCandidate);
return [
[
{
sort: context.arbitraryPropertiesSort,
layer: "utilities"
sort,
layer: "utilities",
options: {
respectImportant: true
}
},
()=>({
[(0, _nameClass).asClass(classCandidate)]: {
[(0, _nameClass.asClass)(classCandidate)]: {
[property]: normalized
}
})
,
],
]
];

@@ -460,14 +596,17 @@ }

function splitWithSeparator(input, separator) {
if (input === sharedState.NOT_ON_DEMAND) {
if (input === _sharedState.NOT_ON_DEMAND) {
return [
sharedState.NOT_ON_DEMAND
_sharedState.NOT_ON_DEMAND
];
}
return Array.from((0, _splitAtTopLevelOnlyJs).splitAtTopLevelOnly(input, separator));
return (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(input, separator);
}
function* recordCandidates(matches, classCandidate) {
for (const match of matches){
var _match__options;
var _match__options_preserveSource;
match[1].raws.tailwind = {
...match[1].raws.tailwind,
classCandidate
classCandidate,
preserveSource: (_match__options_preserveSource = (_match__options = match[0].options) === null || _match__options === void 0 ? void 0 : _match__options.preserveSource) !== null && _match__options_preserveSource !== void 0 ? _match__options_preserveSource : false
};

@@ -538,4 +677,8 @@ yield match;

if (matchesPerPlugin.length > 0) {
var ref;
typesByMatches.set(matchesPerPlugin, (ref = sort.options) === null || ref === void 0 ? void 0 : ref.type);
var _sort_options;
var _sort_options_types, _sort_options1;
let matchingTypes = Array.from((0, _pluginUtils.getMatchingTypes)((_sort_options_types = (_sort_options = sort.options) === null || _sort_options === void 0 ? void 0 : _sort_options.types) !== null && _sort_options_types !== void 0 ? _sort_options_types : [], modifier, (_sort_options1 = sort.options) !== null && _sort_options1 !== void 0 ? _sort_options1 : {}, context.tailwindConfig)).map(([_, type])=>type);
if (matchingTypes.length > 0) {
typesByMatches.set(matchesPerPlugin, matchingTypes);
}
matches.push(matchesPerPlugin);

@@ -545,48 +688,80 @@ }

if (isArbitraryValue(modifier)) {
// When generated arbitrary values are ambiguous, we can't know
// which to pick so don't generate any utilities for them
if (matches.length > 1) {
var ref1;
let typesPerPlugin = matches.map((match)=>new Set([
...(ref1 = typesByMatches.get(match)) !== null && ref1 !== void 0 ? ref1 : []
])
);
// Remove duplicates, so that we can detect proper unique types for each plugin.
for (let pluginTypes of typesPerPlugin){
for (let type of pluginTypes){
let removeFromOwnGroup = false;
for (let otherGroup of typesPerPlugin){
if (pluginTypes === otherGroup) continue;
if (otherGroup.has(type)) {
otherGroup.delete(type);
removeFromOwnGroup = true;
// Partition plugins in 2 categories so that we can start searching in the plugins that
// don't have `any` as a type first.
let [withAny, withoutAny] = matches.reduce((group, plugin)=>{
let hasAnyType = plugin.some(([{ options }])=>options.types.some(({ type })=>type === "any"));
if (hasAnyType) {
group[0].push(plugin);
} else {
group[1].push(plugin);
}
return group;
}, [
[],
[]
]);
function findFallback(matches) {
// If only a single plugin matches, let's take that one
if (matches.length === 1) {
return matches[0];
}
// Otherwise, find the plugin that creates a valid rule given the arbitrary value, and
// also has the correct type which preferOnConflicts the plugin in case of clashes.
return matches.find((rules)=>{
let matchingTypes = typesByMatches.get(rules);
return rules.some(([{ options }, rule])=>{
if (!isParsableNode(rule)) {
return false;
}
return options.types.some(({ type , preferOnConflict })=>matchingTypes.includes(type) && preferOnConflict);
});
});
}
var _findFallback;
// Try to find a fallback plugin, because we already know that multiple plugins matched for
// the given arbitrary value.
let fallback = (_findFallback = findFallback(withoutAny)) !== null && _findFallback !== void 0 ? _findFallback : findFallback(withAny);
if (fallback) {
matches = [
fallback
];
} else {
var _typesByMatches_get;
let typesPerPlugin = matches.map((match)=>new Set([
...(_typesByMatches_get = typesByMatches.get(match)) !== null && _typesByMatches_get !== void 0 ? _typesByMatches_get : []
]));
// Remove duplicates, so that we can detect proper unique types for each plugin.
for (let pluginTypes of typesPerPlugin){
for (let type of pluginTypes){
let removeFromOwnGroup = false;
for (let otherGroup of typesPerPlugin){
if (pluginTypes === otherGroup) continue;
if (otherGroup.has(type)) {
otherGroup.delete(type);
removeFromOwnGroup = true;
}
}
if (removeFromOwnGroup) pluginTypes.delete(type);
}
if (removeFromOwnGroup) pluginTypes.delete(type);
}
}
let messages = [];
for (let [idx, group] of typesPerPlugin.entries()){
for (let type of group){
let rules = matches[idx].map(([, rule])=>rule
).flat().map((rule)=>rule.toString().split("\n").slice(1, -1) // Remove selector and closing '}'
.map((line)=>line.trim()
).map((x)=>` ${x}`
) // Re-indent
.join("\n")
).join("\n\n");
messages.push(` Use \`${candidate.replace("[", `[${type}:`)}\` for \`${rules.trim()}\``);
break;
let messages = [];
for (let [idx, group] of typesPerPlugin.entries()){
for (let type of group){
let rules = matches[idx].map(([, rule])=>rule).flat().map((rule)=>rule.toString().split("\n").slice(1, -1) // Remove selector and closing '}'
.map((line)=>line.trim()).map((x)=>` ${x}`) // Re-indent
.join("\n")).join("\n\n");
messages.push(` Use \`${candidate.replace("[", `[${type}:`)}\` for \`${rules.trim()}\``);
break;
}
}
_log.default.warn([
`The class \`${candidate}\` is ambiguous and matches multiple utilities.`,
...messages,
`If this is content and not a class, replace it with \`${candidate.replace("[", "&lsqb;").replace("]", "&rsqb;")}\` to silence this warning.`
]);
continue;
}
_log.default.warn([
`The class \`${candidate}\` is ambiguous and matches multiple utilities.`,
...messages,
`If this is content and not a class, replace it with \`${candidate.replace("[", "&lsqb;").replace("]", "&rsqb;")}\` to silence this warning.`,
]);
continue;
}
matches = matches.map((list)=>list.filter((match)=>isParsableNode(match[1])
)
);
matches = matches.map((list)=>list.filter((match)=>isParsableNode(match[1])));
}

@@ -602,35 +777,113 @@ matches = matches.flat();

}
for (let match1 of matches){
match1[1].raws.tailwind = {
...match1[1].raws.tailwind,
for (let match of matches){
match[1].raws.tailwind = {
...match[1].raws.tailwind,
candidate
};
// Apply final format selector
if (match1[0].collectedFormats) {
let finalFormat = (0, _formatVariantSelector).formatVariantSelector("&", ...match1[0].collectedFormats);
let container = _postcss.default.root({
nodes: [
match1[1].clone()
]
});
container.walkRules((rule)=>{
if (inKeyframes(rule)) return;
rule.selector = (0, _formatVariantSelector).finalizeSelector(finalFormat, {
selector: rule.selector,
candidate,
context
});
});
match1[1] = container.nodes[0];
match = applyFinalFormat(match, {
context,
candidate
});
// Skip rules with invalid selectors
// This will cause the candidate to be added to the "not class"
// cache skipping it entirely for future builds
if (match === null) {
continue;
}
yield match1;
yield match;
}
}
}
exports.resolveMatches = resolveMatches;
function applyFinalFormat(match, { context , candidate }) {
if (!match[0].collectedFormats) {
return match;
}
let isValid = true;
let finalFormat;
try {
finalFormat = (0, _formatVariantSelector.formatVariantSelector)(match[0].collectedFormats, {
context,
candidate
});
} catch {
// The format selector we produced is invalid
// This could be because:
// - A bug exists
// - A plugin introduced an invalid variant selector (ex: `addVariant('foo', '&;foo')`)
// - The user used an invalid arbitrary variant (ex: `[&;foo]:underline`)
// Either way the build will fail because of this
// We would rather that the build pass "silently" given that this could
// happen because of picking up invalid things when scanning content
// So we'll throw out the candidate instead
return null;
}
let container = _postcss.default.root({
nodes: [
match[1].clone()
]
});
container.walkRules((rule)=>{
if (inKeyframes(rule)) {
return;
}
try {
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 {
// If this selector is invalid we also want to skip it
// But it's likely that being invalid here means there's a bug in a plugin rather than too loosely matching content
isValid = false;
return false;
}
});
if (!isValid) {
return null;
}
// If all rules have been eliminated we can skip this candidate entirely
if (container.nodes.length === 0) {
return null;
}
match[1] = container.nodes[0];
return match;
}
function inKeyframes(rule) {
return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes";
}
function generateRules(candidates, context) {
function getImportantStrategy(important) {
if (important === true) {
return (rule)=>{
if (inKeyframes(rule)) {
return;
}
rule.walkDecls((d)=>{
if (d.parent.type === "rule" && !inKeyframes(d.parent)) {
d.important = true;
}
});
};
}
if (typeof important === "string") {
return (rule)=>{
if (inKeyframes(rule)) {
return;
}
rule.selectors = rule.selectors.map((selector)=>{
return (0, _applyImportantSelector.applyImportantSelector)(selector, important);
});
};
}
}
function generateRules(candidates, context, isSorting = false) {
let allRules = [];
let strategy = getImportantStrategy(context.tailwindConfig.important);
for (let candidate of candidates){

@@ -640,4 +893,4 @@ if (context.notClassCache.has(candidate)) {

}
if (context.classCache.has(candidate)) {
allRules.push(context.classCache.get(candidate));
if (context.candidateRuleCache.has(candidate)) {
allRules = allRules.concat(Array.from(context.candidateRuleCache.get(candidate)));
continue;

@@ -651,26 +904,8 @@ }

context.classCache.set(candidate, matches);
allRules.push(matches);
}
// Strategy based on `tailwindConfig.important`
let strategy = ((important)=>{
if (important === true) {
return (rule)=>{
rule.walkDecls((d)=>{
if (d.parent.type === "rule" && !inKeyframes(d.parent)) {
d.important = true;
}
});
};
}
if (typeof important === "string") {
return (rule)=>{
rule.selectors = rule.selectors.map((selector)=>{
return `${important} ${selector}`;
});
};
}
})(context.tailwindConfig.important);
return allRules.flat(1).map(([{ sort , layer , options }, rule])=>{
if (options.respectImportant) {
if (strategy) {
var _context_candidateRuleCache_get;
let rules = (_context_candidateRuleCache_get = context.candidateRuleCache.get(candidate)) !== null && _context_candidateRuleCache_get !== void 0 ? _context_candidateRuleCache_get : new Set();
context.candidateRuleCache.set(candidate, rules);
for (const match of matches){
let [{ sort , options }, rule] = match;
if (options.respectImportant && strategy) {
let container = _postcss.default.root({

@@ -681,20 +916,20 @@ nodes: [

});
container.walkRules((r)=>{
if (inKeyframes(r)) {
return;
}
strategy(r);
});
container.walkRules(strategy);
rule = container.nodes[0];
}
// 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);
context.ruleCache.add(newEntry);
allRules.push(newEntry);
}
return [
sort | context.layerOrder[layer],
rule
];
});
}
return allRules;
}
exports.generateRules = generateRules;
function isArbitraryValue(input) {
return input.startsWith("[") && input.endsWith("]");
}

@@ -5,34 +5,11 @@ "use strict";

});
exports.default = getModuleDependencies;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _resolve = _interopRequireDefault(require("resolve"));
var _detective = _interopRequireDefault(require("detective"));
function getModuleDependencies(entryFile) {
const rootModule = createModule(entryFile);
const modules = [
rootModule
];
// Iterate over the modules, even when new
// ones are being added
for (const mdl of modules){
mdl.requires.filter((dep)=>{
// Only track local modules, not node_modules
return dep.startsWith("./") || dep.startsWith("../");
}).forEach((dep)=>{
try {
const basedir = _path.default.dirname(mdl.file);
const depPath = _resolve.default.sync(dep, {
basedir
});
const depModule = createModule(depPath);
modules.push(depModule);
} catch (_err) {
// eslint-disable-next-line no-empty
}
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return getModuleDependencies;
}
return modules;
}
function _interopRequireDefault(obj) {
});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -42,9 +19,83 @@ default: obj

}
function createModule(file) {
const source = _fs.default.readFileSync(file, "utf-8");
const requires = (0, _detective).default(source);
return {
file,
requires
};
let jsExtensions = [
".js",
".cjs",
".mjs"
];
// Given the current file `a.ts`, we want to make sure that when importing `b` that we resolve
// `b.ts` before `b.js`
//
// E.g.:
//
// a.ts
// b // .ts
// c // .ts
// a.js
// b // .js or .ts
let jsResolutionOrder = [
"",
".js",
".cjs",
".mjs",
".ts",
".cts",
".mts",
".jsx",
".tsx"
];
let tsResolutionOrder = [
"",
".ts",
".cts",
".mts",
".tsx",
".js",
".cjs",
".mjs",
".jsx"
];
function resolveWithExtension(file, extensions) {
// Try to find `./a.ts`, `./a.ts`, ... from `./a`
for (let ext of extensions){
let full = `${file}${ext}`;
if (_fs.default.existsSync(full) && _fs.default.statSync(full).isFile()) {
return full;
}
}
// Try to find `./a/index.js` from `./a`
for (let ext of extensions){
let full = `${file}/index${ext}`;
if (_fs.default.existsSync(full)) {
return full;
}
}
return null;
}
function* _getModuleDependencies(filename, base, seen, ext = _path.default.extname(filename)) {
// Try to find the file
let absoluteFile = resolveWithExtension(_path.default.resolve(base, filename), jsExtensions.includes(ext) ? jsResolutionOrder : tsResolutionOrder);
if (absoluteFile === null) return; // File doesn't exist
// Prevent infinite loops when there are circular dependencies
if (seen.has(absoluteFile)) return; // Already seen
seen.add(absoluteFile);
// Mark the file as a dependency
yield absoluteFile;
// Resolve new base for new imports/requires
base = _path.default.dirname(absoluteFile);
ext = _path.default.extname(absoluteFile);
let contents = _fs.default.readFileSync(absoluteFile, "utf-8");
// Find imports/requires
for (let match of [
...contents.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi),
...contents.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi),
...contents.matchAll(/require\(['"`](.+)['"`]\)/gi)
]){
// Bail out if it's not a relative file
if (!match[1].startsWith(".")) continue;
yield* _getModuleDependencies(match[1], base, seen, ext);
}
}
function getModuleDependencies(absoluteFilePath) {
if (absoluteFilePath === null) return new Set();
return new Set(_getModuleDependencies(absoluteFilePath, _path.default.dirname(absoluteFilePath), new Set()));
}

@@ -5,4 +5,14 @@ "use strict";

});
exports.default = normalizeTailwindDirectives;
var _log = _interopRequireDefault(require("../util/log"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return normalizeTailwindDirectives;
}
});
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function normalizeTailwindDirectives(root) {

@@ -49,3 +59,3 @@ let tailwindDirectives = new Set();

`Use \`@layer utilities\` or \`@layer components\` instead.`,
"https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer",
"https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer"
]);

@@ -82,6 +92,1 @@ }

}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

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

});
exports.default = expandApplyAtRules;
function expandApplyAtRules() {
return (root)=>{
partitionRules(root);
};
}
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return expandApplyAtRules;
}
});
function partitionRules(root) {

@@ -21,6 +21,6 @@ if (!root.walkAtRules) return;

}
for (let rule1 of applyParents){
for (let rule of applyParents){
let nodeGroups = [];
let lastGroup = [];
for (let node of rule1.nodes){
for (let node of rule.nodes){
if (node.type === "atrule" && node.name === "apply") {

@@ -47,10 +47,15 @@ if (lastGroup.length > 0) {

].reverse()){
let clone = rule1.clone({
let clone = rule.clone({
nodes: []
});
clone.append(group);
rule1.after(clone);
rule.after(clone);
}
rule1.remove();
rule.remove();
}
}
function expandApplyAtRules() {
return (root)=>{
partitionRules(root);
};
}

@@ -5,9 +5,31 @@ "use strict";

});
exports.pattern = pattern;
exports.withoutCapturing = withoutCapturing;
exports.any = any;
exports.optional = optional;
exports.zeroOrMore = zeroOrMore;
exports.nestedBrackets = nestedBrackets;
exports.escape = escape;
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
pattern: function() {
return pattern;
},
withoutCapturing: function() {
return withoutCapturing;
},
any: function() {
return any;
},
optional: function() {
return optional;
},
zeroOrMore: function() {
return zeroOrMore;
},
nestedBrackets: function() {
return nestedBrackets;
},
escape: function() {
return escape;
}
});
const REGEX_SPECIAL = /[\\^$.*+?()[\]{}|]/g;

@@ -21,4 +43,3 @@ const REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source);

];
source = source.map((item)=>item instanceof RegExp ? item.source : item
);
source = source.map((item)=>item instanceof RegExp ? item.source : item);
return source.join("");

@@ -50,3 +71,3 @@ }

/[^\s]*/,
escape(close),
escape(close)
]);

@@ -53,0 +74,0 @@ }

@@ -5,73 +5,20 @@ "use strict";

});
exports.default = resolveDefaultsAtRules;
exports.elementSelectorParser = void 0;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _featureFlags = require("../featureFlags");
function resolveDefaultsAtRules({ tailwindConfig }) {
return (root)=>{
let variableNodeMap = new Map();
/** @type {Set<import('postcss').AtRule>} */ let universals = new Set();
root.walkAtRules("defaults", (rule)=>{
if (rule.nodes && rule.nodes.length > 0) {
universals.add(rule);
return;
}
let variable = rule.params;
if (!variableNodeMap.has(variable)) {
variableNodeMap.set(variable, new Set());
}
variableNodeMap.get(variable).add(rule.parent);
rule.remove();
});
for (let universal of universals){
/** @type {Map<string, Set<string>>} */ let selectorGroups = new Map();
var ref;
let rules = (ref = variableNodeMap.get(universal.params)) !== null && ref !== void 0 ? ref : [];
for (let rule of rules){
for (let selector of extractElementSelector(rule.selector)){
// If selector contains a vendor prefix after a pseudo element or class,
// we consider them separately because merging the declarations into
// a single rule will cause browsers that do not understand the
// vendor prefix to throw out the whole rule
let selectorGroupName = selector.includes(":-") || selector.includes("::-") ? selector : "__DEFAULT__";
var ref1;
let selectors = (ref1 = selectorGroups.get(selectorGroupName)) !== null && ref1 !== void 0 ? ref1 : new Set();
selectorGroups.set(selectorGroupName, selectors);
selectors.add(selector);
}
}
if ((0, _featureFlags).flagEnabled(tailwindConfig, "optimizeUniversalDefaults")) {
if (selectorGroups.size === 0) {
universal.remove();
continue;
}
for (let [, selectors] of selectorGroups){
let universalRule = _postcss.default.rule({
source: universal.source
});
universalRule.selectors = [
...selectors
];
universalRule.append(universal.nodes.map((node)=>node.clone()
));
universal.before(universalRule);
}
} else {
let universalRule = _postcss.default.rule({
source: universal.source
});
universalRule.selectors = [
"*",
"::before",
"::after"
];
universalRule.append(universal.nodes);
universal.before(universalRule);
}
universal.remove();
}
};
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
function _interopRequireDefault(obj) {
_export(exports, {
elementSelectorParser: function() {
return elementSelectorParser;
},
default: function() {
return resolveDefaultsAtRules;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
const _featureFlags = require("../featureFlags");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -83,3 +30,3 @@ default: obj

id (node) {
return _postcssSelectorParser.default.attribute({
return _postcssselectorparser.default.attribute({
attribute: "id",

@@ -114,13 +61,11 @@ operator: "=",

]);
let splitPointIdx = rest.findIndex((n)=>searchFor.has(n.type)
);
let splitPointIdx = rest.findIndex((n)=>searchFor.has(n.type));
if (splitPointIdx === -1) return rest.reverse().join("").trim();
let node1 = rest[splitPointIdx];
let bestNode = getNode[node1.type] ? getNode[node1.type](node1) : node1;
let node = rest[splitPointIdx];
let bestNode = getNode[node.type] ? getNode[node.type](node) : node;
rest = rest.slice(0, splitPointIdx);
let combinatorIdx = rest.findIndex((n)=>n.type === "combinator" && n.value === ">"
);
let combinatorIdx = rest.findIndex((n)=>n.type === "combinator" && n.value === ">");
if (combinatorIdx !== -1) {
rest.splice(0, combinatorIdx);
rest.unshift(_postcssSelectorParser.default.universal());
rest.unshift(_postcssselectorparser.default.universal());
}

@@ -132,10 +77,8 @@ return [

}
let elementSelectorParser = (0, _postcssSelectorParser).default((selectors)=>{
let elementSelectorParser = (0, _postcssselectorparser.default)((selectors)=>{
return selectors.map((s)=>{
let nodes = s.split((n)=>n.type === "combinator" && n.value === " "
).pop();
let nodes = s.split((n)=>n.type === "combinator" && n.value === " ").pop();
return minimumImpactSelector(nodes);
});
});
exports.elementSelectorParser = elementSelectorParser;
let cache = new Map();

@@ -148,1 +91,82 @@ function extractElementSelector(selector) {

}
function resolveDefaultsAtRules({ tailwindConfig }) {
return (root)=>{
let variableNodeMap = new Map();
/** @type {Set<import('postcss').AtRule>} */ let universals = new Set();
root.walkAtRules("defaults", (rule)=>{
if (rule.nodes && rule.nodes.length > 0) {
universals.add(rule);
return;
}
let variable = rule.params;
if (!variableNodeMap.has(variable)) {
variableNodeMap.set(variable, new Set());
}
variableNodeMap.get(variable).add(rule.parent);
rule.remove();
});
if ((0, _featureFlags.flagEnabled)(tailwindConfig, "optimizeUniversalDefaults")) {
for (let universal of universals){
/** @type {Map<string, Set<string>>} */ let selectorGroups = new Map();
var _variableNodeMap_get;
let rules = (_variableNodeMap_get = variableNodeMap.get(universal.params)) !== null && _variableNodeMap_get !== void 0 ? _variableNodeMap_get : [];
for (let rule of rules){
for (let selector of extractElementSelector(rule.selector)){
// If selector contains a vendor prefix after a pseudo element or class,
// we consider them separately because merging the declarations into
// a single rule will cause browsers that do not understand the
// vendor prefix to throw out the whole rule
// Additionally if a selector contains `:has` we also consider
// it separately because FF only recently gained support for it
let selectorGroupName = selector.includes(":-") || selector.includes("::-") || selector.includes(":has") ? selector : "__DEFAULT__";
var _selectorGroups_get;
let selectors = (_selectorGroups_get = selectorGroups.get(selectorGroupName)) !== null && _selectorGroups_get !== void 0 ? _selectorGroups_get : new Set();
selectorGroups.set(selectorGroupName, selectors);
selectors.add(selector);
}
}
if ((0, _featureFlags.flagEnabled)(tailwindConfig, "optimizeUniversalDefaults")) {
if (selectorGroups.size === 0) {
universal.remove();
continue;
}
for (let [, selectors] of selectorGroups){
let universalRule = _postcss.default.rule({
source: universal.source
});
universalRule.selectors = [
...selectors
];
universalRule.append(universal.nodes.map((node)=>node.clone()));
universal.before(universalRule);
}
}
universal.remove();
}
} else if (universals.size) {
let universalRule = _postcss.default.rule({
selectors: [
"*",
"::before",
"::after"
]
});
for (let universal of universals){
universalRule.append(universal.nodes);
if (!universalRule.parent) {
universal.before(universalRule);
}
if (!universalRule.source) {
universalRule.source = universal.source;
}
universal.remove();
}
let backdropRule = universalRule.clone({
selectors: [
"::backdrop"
]
});
universalRule.after(backdropRule);
}
};
}

@@ -5,29 +5,52 @@ "use strict";

});
exports.isValidVariantFormatString = isValidVariantFormatString;
exports.parseVariant = parseVariant;
exports.getFileModifiedMap = getFileModifiedMap;
exports.createContext = createContext;
exports.getContext = getContext;
var _fs = _interopRequireDefault(require("fs"));
var _url = _interopRequireDefault(require("url"));
var _postcss = _interopRequireDefault(require("postcss"));
var _dlv = _interopRequireDefault(require("dlv"));
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _transformThemeValue = _interopRequireDefault(require("../util/transformThemeValue"));
var _parseObjectStyles = _interopRequireDefault(require("../util/parseObjectStyles"));
var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
var _isPlainObject = _interopRequireDefault(require("../util/isPlainObject"));
var _escapeClassName = _interopRequireDefault(require("../util/escapeClassName"));
var _nameClass = _interopRequireWildcard(require("../util/nameClass"));
var _pluginUtils = require("../util/pluginUtils");
var _bigSign = _interopRequireDefault(require("../util/bigSign"));
var _corePlugins = require("../corePlugins");
var sharedState = _interopRequireWildcard(require("./sharedState"));
var _toPath = require("../util/toPath");
var _log = _interopRequireDefault(require("../util/log"));
var _negateValue = _interopRequireDefault(require("../util/negateValue"));
var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
var _generateRules = require("./generateRules");
var _cacheInvalidationJs = require("./cacheInvalidation.js");
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
INTERNAL_FEATURES: function() {
return INTERNAL_FEATURES;
},
isValidVariantFormatString: function() {
return isValidVariantFormatString;
},
parseVariant: function() {
return parseVariant;
},
getFileModifiedMap: function() {
return getFileModifiedMap;
},
createContext: function() {
return createContext;
},
getContext: function() {
return getContext;
}
});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _url = /*#__PURE__*/ _interop_require_default(require("url"));
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _dlv = /*#__PURE__*/ _interop_require_default(require("dlv"));
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
const _transformThemeValue = /*#__PURE__*/ _interop_require_default(require("../util/transformThemeValue"));
const _parseObjectStyles = /*#__PURE__*/ _interop_require_default(require("../util/parseObjectStyles"));
const _prefixSelector = /*#__PURE__*/ _interop_require_default(require("../util/prefixSelector"));
const _isPlainObject = /*#__PURE__*/ _interop_require_default(require("../util/isPlainObject"));
const _escapeClassName = /*#__PURE__*/ _interop_require_default(require("../util/escapeClassName"));
const _nameClass = /*#__PURE__*/ _interop_require_wildcard(require("../util/nameClass"));
const _pluginUtils = require("../util/pluginUtils");
const _corePlugins = require("../corePlugins");
const _sharedState = /*#__PURE__*/ _interop_require_wildcard(require("./sharedState"));
const _toPath = require("../util/toPath");
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log"));
const _negateValue = /*#__PURE__*/ _interop_require_default(require("../util/negateValue"));
const _isSyntacticallyValidPropertyValue = /*#__PURE__*/ _interop_require_default(require("../util/isSyntacticallyValidPropertyValue"));
const _generateRules = require("./generateRules");
const _cacheInvalidation = require("./cacheInvalidation.js");
const _offsets = require("./offsets.js");
const _featureFlags = require("../featureFlags.js");
const _formatVariantSelector = require("../util/formatVariantSelector");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -37,51 +60,108 @@ default: obj

}
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
let MATCH_VARIANT = Symbol();
const INTERNAL_FEATURES = Symbol();
const VARIANT_TYPES = {
AddVariant: Symbol.for("ADD_VARIANT"),
MatchVariant: Symbol.for("MATCH_VARIANT")
};
const VARIANT_INFO = {
Base: 1 << 0,
Dynamic: 1 << 1
};
function prefix(context, selector) {
let prefix1 = context.tailwindConfig.prefix;
return typeof prefix1 === "function" ? prefix1(selector) : prefix1 + selector;
let prefix = context.tailwindConfig.prefix;
return typeof prefix === "function" ? prefix(selector) : prefix + selector;
}
function normalizeOptionTypes({ type ="any" , ...options }) {
let types = [].concat(type);
return {
...options,
types: types.map((type)=>{
if (Array.isArray(type)) {
return {
type: type[0],
...type[1]
};
}
return {
type,
preferOnConflict: false
};
})
};
}
function parseVariantFormatString(input) {
if (input.includes("{")) {
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`);
return input.split(/{(.*)}/gim).flatMap((line)=>parseVariantFormatString(line)
).filter(Boolean);
}
return [
input.trim()
];
}
function isBalanced(input) {
let count = 0;
for (let char of input){
if (char === "{") {
count++;
/** @type {string[]} */ let parts = [];
// When parsing whitespace around special characters are insignificant
// However, _inside_ of a variant they could be
// Because the selector could look like this
// @media { &[data-name="foo bar"] }
// This is why we do not skip whitespace
let current = "";
let depth = 0;
for(let idx = 0; idx < input.length; idx++){
let char = input[idx];
if (char === "\\") {
// Escaped characters are not special
current += "\\" + input[++idx];
} else if (char === "{") {
// Nested rule: start
++depth;
parts.push(current.trim());
current = "";
} else if (char === "}") {
if (--count < 0) {
return false // unbalanced
;
// Nested rule: end
if (--depth < 0) {
throw new Error(`Your { and } are unbalanced.`);
}
parts.push(current.trim());
current = "";
} else {
// Normal character
current += char;
}
}
return count === 0;
if (current.length > 0) {
parts.push(current.trim());
}
parts = parts.filter((part)=>part !== "");
return parts;
}

@@ -109,8 +189,8 @@ function insertInto(list, value, { before =[] } = {}) {

return styles.flatMap((style)=>{
let isNode = !Array.isArray(style) && !(0, _isPlainObject).default(style);
return isNode ? style : (0, _parseObjectStyles).default(style);
let isNode = !Array.isArray(style) && !(0, _isPlainObject.default)(style);
return isNode ? style : (0, _parseObjectStyles.default)(style);
});
}
function getClasses(selector, mutate) {
let parser = (0, _postcssSelectorParser).default((selectors)=>{
let parser = (0, _postcssselectorparser.default)((selectors)=>{
let allClasses = [];

@@ -127,2 +207,16 @@ if (mutate) {

}
/**
* 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 = {

@@ -132,32 +226,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);
}
});
}

@@ -178,3 +259,3 @@ if (depth === 0) {

if (containsNonOnDemandableSelectors) {
candidates.unshift(sharedState.NOT_ON_DEMAND);
candidates.unshift(_sharedState.NOT_ON_DEMAND);
}

@@ -202,11 +283,12 @@ // However, it could be that it also contains "on-demandable" candidates.

if (!str.startsWith("@")) {
return ({ format })=>format(str)
;
return ({ format })=>format(str);
}
let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(str);
return ({ wrap })=>wrap(_postcss.default.atRule({
let [, name, params] = /@(\S*)( .+|[({].*)?/g.exec(str);
var _params_trim;
return ({ wrap })=>{
return wrap(_postcss.default.atRule({
name,
params: params.trim()
}))
;
params: (_params_trim = params === null || params === void 0 ? void 0 : params.trim()) !== null && _params_trim !== void 0 ? _params_trim : ""
}));
};
}).reverse();

@@ -219,12 +301,18 @@ return (api)=>{

}
function buildPluginApi(tailwindConfig, context, { variantList , variantMap , offsets , classList }) {
/**
*
* @param {any} tailwindConfig
* @param {any} context
* @param {object} param2
* @param {Offsets} param2.offsets
*/ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , offsets , classList }) {
function getConfigValue(path, defaultValue) {
return path ? (0, _dlv).default(tailwindConfig, path, defaultValue) : tailwindConfig;
return path ? (0, _dlv.default)(tailwindConfig, path, defaultValue) : tailwindConfig;
}
function applyConfiguredPrefix(selector) {
return (0, _prefixSelector).default(tailwindConfig.prefix, selector);
return (0, _prefixSelector.default)(tailwindConfig.prefix, selector);
}
function prefixIdentifier(identifier, options) {
if (identifier === sharedState.NOT_ON_DEMAND) {
return sharedState.NOT_ON_DEMAND;
if (identifier === _sharedState.NOT_ON_DEMAND) {
return _sharedState.NOT_ON_DEMAND;
}

@@ -236,31 +324,12 @@ if (!options.respectPrefix) {

}
function resolveThemeValue(path, defaultValue, opts = {}) {
let parts = (0, _toPath.toPath)(path);
let value = getConfigValue([
"theme",
...parts
], defaultValue);
return (0, _transformThemeValue.default)(parts[0])(value, opts);
}
let variantIdentifier = 0;
let api = {
addVariant (variantName, variantFunctions, options = {}) {
variantFunctions = [].concat(variantFunctions).map((variantFunction)=>{
if (typeof variantFunction !== "string") {
// Safelist public API functions
return ({ args , modifySelectors , container , separator , wrap , format })=>{
let result = variantFunction(Object.assign({
modifySelectors,
container,
separator
}, variantFunction[MATCH_VARIANT] && {
args,
wrap,
format
}));
if (typeof result === "string" && !isValidVariantFormatString(result)) {
throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
}
return result;
};
}
if (!isValidVariantFormatString(variantFunction)) {
throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
}
return parseVariant(variantFunction);
});
insertInto(variantList, variantName, options);
variantMap.set(variantName, variantFunctions);
},
postcss: _postcss.default,

@@ -270,11 +339,3 @@ prefix: applyConfiguredPrefix,

config: getConfigValue,
theme (path, defaultValue) {
const [pathRoot, ...subPaths] = (0, _toPath).toPath(path);
const value = getConfigValue([
"theme",
pathRoot,
...subPaths
], defaultValue);
return (0, _transformThemeValue).default(pathRoot)(value);
},
theme: resolveThemeValue,
corePlugins: (path)=>{

@@ -296,3 +357,3 @@ if (Array.isArray(tailwindConfig.corePlugins)) {

let prefixedIdentifier = prefixIdentifier(identifier, {});
let offset = offsets.base++;
let offset = offsets.create("base");
if (!context.candidateRuleMap.has(prefixedIdentifier)) {

@@ -324,3 +385,3 @@ context.candidateRuleMap.set(prefixedIdentifier, []);

{
sort: offsets.base++,
sort: offsets.create("defaults"),
layer: "defaults"

@@ -334,2 +395,3 @@ },

let defaultOptions = {
preserveSource: false,
respectPrefix: true,

@@ -347,3 +409,3 @@ respectImportant: false

{
sort: offsets.components++,
sort: offsets.create("components"),
layer: "components",

@@ -358,2 +420,3 @@ options

let defaultOptions = {
preserveSource: false,
respectPrefix: true,

@@ -371,3 +434,3 @@ respectImportant: true

{
sort: offsets.utilities++,
sort: offsets.create("utilities"),
layer: "utilities",

@@ -383,9 +446,10 @@ options

respectPrefix: true,
respectImportant: true
respectImportant: true,
modifiers: false
};
options = {
options = normalizeOptionTypes({
...defaultOptions,
...options
};
let offset = offsets.utilities++;
});
let offset = offsets.create("utilities");
for(let identifier in utilities){

@@ -399,18 +463,33 @@ let prefixedIdentifier = prefixIdentifier(identifier, options);

function wrapped(modifier, { isOnlyPlugin }) {
let { type ="any" } = options;
type = [].concat(type);
let [value, coercedType] = (0, _pluginUtils).coerceValue(type, modifier, options, tailwindConfig);
let [value, coercedType, utilityModifier] = (0, _pluginUtils.coerceValue)(options.types, modifier, options, tailwindConfig);
if (value === undefined) {
return [];
}
if (!type.includes(coercedType) && !isOnlyPlugin) {
return [];
if (!options.types.some(({ type })=>type === coercedType)) {
if (isOnlyPlugin) {
_log.default.warn([
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
`You can safely update it to \`${identifier}-${modifier.replace(coercedType + ":", "")}\`.`
]);
} else {
return [];
}
}
if (!(0, _isValidArbitraryValue).default(value)) {
if (!(0, _isSyntacticallyValidPropertyValue.default)(value)) {
return [];
}
let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
[(0, _nameClass).default(identifier, modifier)]: declaration
})
);
let extras = {
get modifier () {
if (!options.modifiers) {
_log.default.warn(`modifier-used-without-options-for-${identifier}`, [
"Your plugin must set `modifiers: true` in its options to support modifiers."
]);
}
return utilityModifier;
}
};
let modifiersEnabled = (0, _featureFlags.flagEnabled)(tailwindConfig, "generalizedModifiers");
let ruleSets = [].concat(modifiersEnabled ? rule(value, extras) : rule(value)).filter(Boolean).map((declaration)=>({
[(0, _nameClass.default)(identifier, modifier)]: declaration
}));
return ruleSets;

@@ -435,9 +514,10 @@ }

respectPrefix: true,
respectImportant: false
respectImportant: false,
modifiers: false
};
options = {
options = normalizeOptionTypes({
...defaultOptions,
...options
};
let offset = offsets.components++;
});
let offset = offsets.create("components");
for(let identifier in components){

@@ -451,13 +531,11 @@ let prefixedIdentifier = prefixIdentifier(identifier, options);

function wrapped(modifier, { isOnlyPlugin }) {
let { type ="any" } = options;
type = [].concat(type);
let [value, coercedType] = (0, _pluginUtils).coerceValue(type, modifier, options, tailwindConfig);
let [value, coercedType, utilityModifier] = (0, _pluginUtils.coerceValue)(options.types, modifier, options, tailwindConfig);
if (value === undefined) {
return [];
}
if (!type.includes(coercedType)) {
if (!options.types.some(({ type })=>type === coercedType)) {
if (isOnlyPlugin) {
_log.default.warn([
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
`You can safely update it to \`${identifier}-${modifier.replace(coercedType + ":", "")}\`.`,
`You can safely update it to \`${identifier}-${modifier.replace(coercedType + ":", "")}\`.`
]);

@@ -468,9 +546,19 @@ } else {

}
if (!(0, _isValidArbitraryValue).default(value)) {
if (!(0, _isSyntacticallyValidPropertyValue.default)(value)) {
return [];
}
let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
[(0, _nameClass).default(identifier, modifier)]: declaration
})
);
let extras = {
get modifier () {
if (!options.modifiers) {
_log.default.warn(`modifier-used-without-options-for-${identifier}`, [
"Your plugin must set `modifiers: true` in its options to support modifiers."
]);
}
return utilityModifier;
}
};
let modifiersEnabled = (0, _featureFlags.flagEnabled)(tailwindConfig, "generalizedModifiers");
let ruleSets = [].concat(modifiersEnabled ? rule(value, extras) : rule(value)).filter(Boolean).map((declaration)=>({
[(0, _nameClass.default)(identifier, modifier)]: declaration
}));
return ruleSets;

@@ -492,23 +580,82 @@ }

},
matchVariant: function(variants, options) {
for(let variant in variants){
var ref;
for (let [k, v] of Object.entries((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {})){
api.addVariant(`${variant}-${k}`, variants[variant](v));
addVariant (variantName, variantFunctions, options = {}) {
variantFunctions = [].concat(variantFunctions).map((variantFunction)=>{
if (typeof variantFunction !== "string") {
// Safelist public API functions
return (api = {})=>{
let { args , modifySelectors , container , separator , wrap , format } = api;
let result = variantFunction(Object.assign({
modifySelectors,
container,
separator
}, options.type === VARIANT_TYPES.MatchVariant && {
args,
wrap,
format
}));
if (typeof result === "string" && !isValidVariantFormatString(result)) {
throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
}
if (Array.isArray(result)) {
return result.filter((variant)=>typeof variant === "string").map((variant)=>parseVariant(variant));
}
// result may be undefined with legacy variants that use APIs like `modifySelectors`
// result may also be a postcss node if someone was returning the result from `modifySelectors`
return result && typeof result === "string" && parseVariant(result)(api);
};
}
api.addVariant(variant, Object.assign(({ args , wrap })=>{
let formatString = variants[variant](args);
if (!formatString) return null;
if (!formatString.startsWith("@")) {
return formatString;
}
let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(formatString);
return wrap(_postcss.default.atRule({
name,
params: params.trim()
}));
if (!isValidVariantFormatString(variantFunction)) {
throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
}
return parseVariant(variantFunction);
});
insertInto(variantList, variantName, options);
variantMap.set(variantName, variantFunctions);
context.variantOptions.set(variantName, options);
},
matchVariant (variant, variantFn, options) {
var _options_id;
// A unique identifier that "groups" these variants together.
// This is for internal use only which is why it is not present in the types
let id = (_options_id = options === null || options === void 0 ? void 0 : options.id) !== null && _options_id !== void 0 ? _options_id : ++variantIdentifier;
let isSpecial = variant === "@";
let modifiersEnabled = (0, _featureFlags.flagEnabled)(tailwindConfig, "generalizedModifiers");
var _options_values;
for (let [key, value] of Object.entries((_options_values = options === null || options === void 0 ? void 0 : options.values) !== null && _options_values !== void 0 ? _options_values : {})){
if (key === "DEFAULT") continue;
api.addVariant(isSpecial ? `${variant}${key}` : `${variant}-${key}`, ({ args , container })=>{
return variantFn(value, modifiersEnabled ? {
modifier: args === null || args === void 0 ? void 0 : args.modifier,
container
} : {
container
});
}, {
[MATCH_VARIANT]: true
}), options);
...options,
value,
id,
type: VARIANT_TYPES.MatchVariant,
variantInfo: VARIANT_INFO.Base
});
}
var _options_values1;
let hasDefault = "DEFAULT" in ((_options_values1 = options === null || options === void 0 ? void 0 : options.values) !== null && _options_values1 !== void 0 ? _options_values1 : {});
api.addVariant(variant, ({ args , container })=>{
if ((args === null || args === void 0 ? void 0 : args.value) === _sharedState.NONE && !hasDefault) {
return null;
}
var // (JetBrains) plugins.
_args_value;
return variantFn((args === null || args === void 0 ? void 0 : args.value) === _sharedState.NONE ? options.values.DEFAULT : (_args_value = args === null || args === void 0 ? void 0 : args.value) !== null && _args_value !== void 0 ? _args_value : typeof args === "string" ? args : "", modifiersEnabled ? {
modifier: args === null || args === void 0 ? void 0 : args.modifier,
container
} : {
container
});
}, {
...options,
id,
type: VARIANT_TYPES.MatchVariant,
variantInfo: VARIANT_INFO.Dynamic
});
}

@@ -527,4 +674,5 @@ };

let changed = false;
let mtimesToCommit = new Map();
for (let file of files){
var ref;
var _fs_statSync;
if (!file) continue;

@@ -534,5 +682,5 @@ let parsed = _url.default.parse(file);

pathname = parsed.search ? pathname.replace(parsed.search, "") : pathname;
let newModified = (ref = _fs.default.statSync(decodeURIComponent(pathname), {
let newModified = (_fs_statSync = _fs.default.statSync(decodeURIComponent(pathname), {
throwIfNoEntry: false
})) === null || ref === void 0 ? void 0 : ref.mtimeMs;
})) === null || _fs_statSync === void 0 ? void 0 : _fs_statSync.mtimeMs;
if (!newModified) {

@@ -544,5 +692,8 @@ continue;

}
fileModifiedMap.set(file, newModified);
mtimesToCommit.set(file, newModified);
}
return changed;
return [
changed,
mtimesToCommit
];
}

@@ -588,3 +739,4 @@ function extractVariantAtRules(node) {

addComponents(node, {
respectPrefix: false
respectPrefix: false,
preserveSource: true
});

@@ -598,3 +750,4 @@ });

addUtilities(node, {
respectPrefix: false
respectPrefix: false,
preserveSource: true
});

@@ -628,13 +781,36 @@ });

let beforeVariants = [
_corePlugins.variantPlugins["childVariant"],
_corePlugins.variantPlugins["pseudoElementVariants"],
_corePlugins.variantPlugins["pseudoClassVariants"],
_corePlugins.variantPlugins["pseudoClassVariants"],
_corePlugins.variantPlugins["hasVariants"],
_corePlugins.variantPlugins["ariaVariants"],
_corePlugins.variantPlugins["dataVariants"]
];
let afterVariants = [
_corePlugins.variantPlugins["supportsVariants"],
_corePlugins.variantPlugins["reducedMotionVariants"],
_corePlugins.variantPlugins["prefersContrastVariants"],
_corePlugins.variantPlugins["screenVariants"],
_corePlugins.variantPlugins["orientationVariants"],
_corePlugins.variantPlugins["directionVariants"],
_corePlugins.variantPlugins["reducedMotionVariants"],
_corePlugins.variantPlugins["darkVariants"],
_corePlugins.variantPlugins["printVariant"],
_corePlugins.variantPlugins["screenVariants"],
_corePlugins.variantPlugins["orientationVariants"],
_corePlugins.variantPlugins["forcedColorsVariants"],
_corePlugins.variantPlugins["printVariant"]
];
// This is a compatibility fix for the pre 3.4 dark mode behavior
// `class` retains the old behavior, but `selector` keeps the new behavior
let isLegacyDarkMode = context.tailwindConfig.darkMode === "class" || Array.isArray(context.tailwindConfig.darkMode) && context.tailwindConfig.darkMode[0] === "class";
if (isLegacyDarkMode) {
afterVariants = [
_corePlugins.variantPlugins["supportsVariants"],
_corePlugins.variantPlugins["reducedMotionVariants"],
_corePlugins.variantPlugins["prefersContrastVariants"],
_corePlugins.variantPlugins["darkVariants"],
_corePlugins.variantPlugins["screenVariants"],
_corePlugins.variantPlugins["orientationVariants"],
_corePlugins.variantPlugins["directionVariants"],
_corePlugins.variantPlugins["forcedColorsVariants"],
_corePlugins.variantPlugins["printVariant"]
];
}
return [

@@ -651,9 +827,5 @@ ...corePluginList,

let variantMap = new Map();
let offsets = {
defaults: 0n,
base: 0n,
components: 0n,
utilities: 0n,
user: 0n
};
context.variantMap = variantMap;
let offsets = new _offsets.Offsets();
context.offsets = offsets;
let classList = new Set();

@@ -675,54 +847,19 @@ let pluginApi = buildPluginApi(context.tailwindConfig, context, {

}
let highestOffset = ((args)=>args.reduce((m, e)=>e > m ? e : m
)
)([
offsets.base,
offsets.defaults,
offsets.components,
offsets.utilities,
offsets.user,
]);
let reservedBits = BigInt(highestOffset.toString(2).length);
// A number one less than the top range of the highest offset area
// so arbitrary properties are always sorted at the end.
context.arbitraryPropertiesSort = (1n << reservedBits << 0n) - 1n;
context.layerOrder = {
defaults: 1n << reservedBits << 0n,
base: 1n << reservedBits << 1n,
components: 1n << reservedBits << 2n,
utilities: 1n << reservedBits << 3n,
user: 1n << reservedBits << 4n
};
reservedBits += 5n;
let offset = 0;
context.variantOrder = new Map(variantList.map((variant, i)=>{
let variantFunctions = variantMap.get(variant).length;
let bits = 1n << BigInt(i + offset) << reservedBits;
offset += variantFunctions - 1;
return [
variant,
bits
];
}).sort(([, a], [, z])=>(0, _bigSign).default(a - z)
));
context.minimumScreen = [
...context.variantOrder.values()
].shift();
// Make sure to record bit masks for every variant
offsets.recordVariants(variantList, (variant)=>variantMap.get(variant).length);
// Build variantMap
for (let [variantName, variantFunctions1] of variantMap.entries()){
let sort = context.variantOrder.get(variantName);
context.variantMap.set(variantName, variantFunctions1.map((variantFunction, idx)=>[
sort << BigInt(idx),
for (let [variantName, variantFunctions] of variantMap.entries()){
context.variantMap.set(variantName, variantFunctions.map((variantFunction, idx)=>[
offsets.forVariant(variantName, idx),
variantFunction
]
));
]));
}
var _safelist;
let safelist = ((_safelist = context.tailwindConfig.safelist) !== null && _safelist !== void 0 ? _safelist : []).filter(Boolean);
var _context_tailwindConfig_safelist;
let safelist = ((_context_tailwindConfig_safelist = context.tailwindConfig.safelist) !== null && _context_tailwindConfig_safelist !== void 0 ? _context_tailwindConfig_safelist : []).filter(Boolean);
if (safelist.length > 0) {
let checks = [];
for (let value1 of safelist){
if (typeof value1 === "string") {
for (let value of safelist){
if (typeof value === "string") {
context.changedContent.push({
content: value1,
content: value,
extension: "html"

@@ -732,11 +869,11 @@ });

}
if (value1 instanceof RegExp) {
if (value instanceof RegExp) {
_log.default.warn("root-regex", [
"Regular expressions in `safelist` work differently in Tailwind CSS v3.0.",
"Update your `safelist` configuration to eliminate this warning.",
"https://tailwindcss.com/docs/content-configuration#safelisting-classes",
"https://tailwindcss.com/docs/content-configuration#safelisting-classes"
]);
continue;
}
checks.push(value1);
checks.push(value);
}

@@ -746,9 +883,9 @@ if (checks.length > 0) {

let prefixLength = context.tailwindConfig.prefix.length;
let checkImportantUtils = checks.some((check)=>check.pattern.source.includes("!"));
for (let util of classList){
let utils = Array.isArray(util) ? (()=>{
let [utilName, options] = util;
var ref;
let values = Object.keys((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {});
let classes = values.map((value)=>(0, _nameClass).formatClass(utilName, value)
);
var _options_values;
let values = Object.keys((_options_values = options === null || options === void 0 ? void 0 : options.values) !== null && _options_values !== void 0 ? _options_values : {});
let classes = values.map((value)=>(0, _nameClass.formatClass)(utilName, value));
if (options === null || options === void 0 ? void 0 : options.supportsNegativeValues) {

@@ -759,4 +896,3 @@ // This is the normal negated version

...classes,
...classes.map((cls)=>"-" + cls
)
...classes.map((cls)=>"-" + cls)
];

@@ -769,6 +905,17 @@ // This is the negated version *after* the prefix

...classes,
...classes.map((cls)=>cls.slice(0, prefixLength) + "-" + cls.slice(prefixLength)
),
...classes.map((cls)=>cls.slice(0, prefixLength) + "-" + cls.slice(prefixLength))
];
}
if (options.types.some(({ type })=>type === "color")) {
classes = [
...classes,
...classes.flatMap((cls)=>Object.keys(context.tailwindConfig.theme.opacity).map((opacity)=>`${cls}/${opacity}`))
];
}
if (checkImportantUtils && (options === null || options === void 0 ? void 0 : options.respectImportant)) {
classes = [
...classes,
...classes.map((cls)=>"!" + cls)
];
}
return classes;

@@ -778,3 +925,3 @@ })() : [

];
for (let util1 of utils){
for (let util of utils){
for (let { pattern , variants =[] } of checks){

@@ -787,6 +934,6 @@ // RegExp with the /g flag are stateful, so let's reset the last

}
if (!pattern.test(util1)) continue;
if (!pattern.test(util)) continue;
patternMatchingCount.set(pattern, patternMatchingCount.get(pattern) + 1);
context.changedContent.push({
content: util1,
content: util,
extension: "html"

@@ -796,3 +943,3 @@ });

context.changedContent.push({
content: variant + context.tailwindConfig.separator + util1,
content: variant + context.tailwindConfig.separator + util,
extension: "html"

@@ -809,3 +956,3 @@ });

"Fix this pattern or remove it from your `safelist` configuration.",
"https://tailwindcss.com/docs/content-configuration#safelisting-classes",
"https://tailwindcss.com/docs/content-configuration#safelisting-classes"
]);

@@ -815,24 +962,48 @@ }

}
var _context_tailwindConfig_darkMode, _concat_;
let darkClassName = (_concat_ = [].concat((_context_tailwindConfig_darkMode = context.tailwindConfig.darkMode) !== null && _context_tailwindConfig_darkMode !== void 0 ? _context_tailwindConfig_darkMode : "media")[1]) !== null && _concat_ !== void 0 ? _concat_ : "dark";
// A list of utilities that are used by certain Tailwind CSS utilities but
// that don't exist on their own. This will result in them "not existing" and
// sorting could be weird since you still require them in order to make the
// host utitlies work properly. (Thanks Biology)
let parasiteUtilities = new Set([
// host utilities work properly. (Thanks Biology)
let parasiteUtilities = [
prefix(context, darkClassName),
prefix(context, "group"),
prefix(context, "peer")
]);
];
context.getClassOrder = function getClassOrder(classes) {
let sortedClassNames = new Map();
for (let [sort, rule] of (0, _generateRules).generateRules(new Set(classes), context)){
if (sortedClassNames.has(rule.raws.tailwind.candidate)) continue;
sortedClassNames.set(rule.raws.tailwind.candidate, sort);
// Sort classes so they're ordered in a deterministic manner
let sorted = [
...classes
].sort((a, z)=>{
if (a === z) return 0;
if (a < z) return -1;
return 1;
});
// Non-util classes won't be generated, so we default them to null
let sortedClassNames = new Map(sorted.map((className)=>[
className,
null
]));
// Sort all classes in order
// Non-tailwind classes won't be generated and will be left as `null`
let rules = (0, _generateRules.generateRules)(new Set(sorted), context, true);
rules = context.offsets.sort(rules);
let idx = BigInt(parasiteUtilities.length);
for (const [, rule] of rules){
let candidate = rule.raws.tailwind.candidate;
var _sortedClassNames_get;
// When multiple rules match a candidate
// always take the position of the first one
sortedClassNames.set(candidate, (_sortedClassNames_get = sortedClassNames.get(candidate)) !== null && _sortedClassNames_get !== void 0 ? _sortedClassNames_get : idx++);
}
return classes.map((className)=>{
var ref;
let order = (ref = sortedClassNames.get(className)) !== null && ref !== void 0 ? ref : null;
if (order === null && parasiteUtilities.has(className)) {
var _sortedClassNames_get;
let order = (_sortedClassNames_get = sortedClassNames.get(className)) !== null && _sortedClassNames_get !== void 0 ? _sortedClassNames_get : null;
let parasiteIndex = parasiteUtilities.indexOf(className);
if (order === null && parasiteIndex !== -1) {
// This will make sure that it is at the very beginning of the
// `components` layer which technically means 'before any
// components'.
order = context.layerOrder.components;
order = BigInt(parasiteIndex);
}

@@ -847,14 +1018,37 @@ return [

// ['uppercase', 'lowercase', ...]
context.getClassList = function getClassList() {
context.getClassList = function getClassList(options = {}) {
let output = [];
for (let util of classList){
if (Array.isArray(util)) {
let [utilName, options] = util;
var _utilOptions_types;
let [utilName, utilOptions] = util;
let negativeClasses = [];
var ref;
for (let [key, value] of Object.entries((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {})){
output.push((0, _nameClass).formatClass(utilName, key));
if ((options === null || options === void 0 ? void 0 : options.supportsNegativeValues) && (0, _negateValue).default(value)) {
negativeClasses.push((0, _nameClass).formatClass(utilName, `-${key}`));
var _utilOptions_modifiers;
let modifiers = Object.keys((_utilOptions_modifiers = utilOptions === null || utilOptions === void 0 ? void 0 : utilOptions.modifiers) !== null && _utilOptions_modifiers !== void 0 ? _utilOptions_modifiers : {});
if (utilOptions === null || utilOptions === void 0 ? void 0 : (_utilOptions_types = utilOptions.types) === null || _utilOptions_types === void 0 ? void 0 : _utilOptions_types.some(({ type })=>type === "color")) {
var _context_tailwindConfig_theme_opacity;
modifiers.push(...Object.keys((_context_tailwindConfig_theme_opacity = context.tailwindConfig.theme.opacity) !== null && _context_tailwindConfig_theme_opacity !== void 0 ? _context_tailwindConfig_theme_opacity : {}));
}
let metadata = {
modifiers
};
let includeMetadata = options.includeMetadata && modifiers.length > 0;
var _utilOptions_values;
for (let [key, value] of Object.entries((_utilOptions_values = utilOptions === null || utilOptions === void 0 ? void 0 : utilOptions.values) !== null && _utilOptions_values !== void 0 ? _utilOptions_values : {})){
// Ignore undefined and null values
if (value == null) {
continue;
}
let cls = (0, _nameClass.formatClass)(utilName, key);
output.push(includeMetadata ? [
cls,
metadata
] : cls);
if ((utilOptions === null || utilOptions === void 0 ? void 0 : utilOptions.supportsNegativeValues) && (0, _negateValue.default)(value)) {
let cls = (0, _nameClass.formatClass)(utilName, `-${key}`);
negativeClasses.push(includeMetadata ? [
cls,
metadata
] : cls);
}
}

@@ -868,10 +1062,190 @@ output.push(...negativeClasses);

};
// Generate a list of available variants with meta information of the type of variant.
context.getVariants = function getVariants() {
// We use a unique, random ID for candidate names to avoid conflicts
// We can't use characters like `_`, `:`, `@` or `.` because they might
// be used as a separator
let id = Math.random().toString(36).substring(7).toUpperCase();
let result = [];
for (let [name, options] of context.variantOptions.entries()){
if (options.variantInfo === VARIANT_INFO.Base) continue;
var _options_values;
result.push({
name,
isArbitrary: options.type === Symbol.for("MATCH_VARIANT"),
values: Object.keys((_options_values = options.values) !== null && _options_values !== void 0 ? _options_values : {}),
hasDash: name !== "@",
selectors ({ modifier , value } = {}) {
let candidate = `TAILWINDPLACEHOLDER${id}`;
let rule = _postcss.default.rule({
selector: `.${candidate}`
});
let container = _postcss.default.root({
nodes: [
rule.clone()
]
});
let before = container.toString();
var _context_variantMap_get;
let fns = ((_context_variantMap_get = context.variantMap.get(name)) !== null && _context_variantMap_get !== void 0 ? _context_variantMap_get : []).flatMap(([_, fn])=>fn);
let formatStrings = [];
for (let fn of fns){
var _options_values;
let localFormatStrings = [];
var _options_values_value;
let api = {
args: {
modifier,
value: (_options_values_value = (_options_values = options.values) === null || _options_values === void 0 ? void 0 : _options_values[value]) !== null && _options_values_value !== void 0 ? _options_values_value : value
},
separator: context.tailwindConfig.separator,
modifySelectors (modifierFunction) {
// Run the modifierFunction over each rule
container.each((rule)=>{
if (rule.type !== "rule") {
return;
}
rule.selectors = rule.selectors.map((selector)=>{
return modifierFunction({
get className () {
return (0, _generateRules.getClassNameFromSelector)(selector);
},
selector
});
});
});
return container;
},
format (str) {
localFormatStrings.push(str);
},
wrap (wrapper) {
localFormatStrings.push(`@${wrapper.name} ${wrapper.params} { & }`);
},
container
};
let ruleWithVariant = fn(api);
if (localFormatStrings.length > 0) {
formatStrings.push(localFormatStrings);
}
if (Array.isArray(ruleWithVariant)) {
for (let variantFunction of ruleWithVariant){
localFormatStrings = [];
variantFunction(api);
formatStrings.push(localFormatStrings);
}
}
}
// Reverse engineer the result of the `container`
let manualFormatStrings = [];
let after = container.toString();
if (before !== after) {
// Figure out all selectors
container.walkRules((rule)=>{
let modified = rule.selector;
// Rebuild the base selector, this is what plugin authors would do
// as well. E.g.: `${variant}${separator}${className}`.
// However, plugin authors probably also prepend or append certain
// classes, pseudos, ids, ...
let rebuiltBase = (0, _postcssselectorparser.default)((selectors)=>{
selectors.walkClasses((classNode)=>{
classNode.value = `${name}${context.tailwindConfig.separator}${classNode.value}`;
});
}).processSync(modified);
// Now that we know the original selector, the new selector, and
// the rebuild part in between, we can replace the part that plugin
// authors need to rebuild with `&`, and eventually store it in the
// collectedFormats. Similar to what `format('...')` would do.
//
// E.g.:
// variant: foo
// selector: .markdown > p
// modified (by plugin): .foo .foo\\:markdown > p
// rebuiltBase (internal): .foo\\:markdown > p
// format: .foo &
manualFormatStrings.push(modified.replace(rebuiltBase, "&").replace(candidate, "&"));
});
// Figure out all atrules
container.walkAtRules((atrule)=>{
manualFormatStrings.push(`@${atrule.name} (${atrule.params}) { & }`);
});
}
var _options_values1;
let isArbitraryVariant = !(value in ((_options_values1 = options.values) !== null && _options_values1 !== void 0 ? _options_values1 : {}));
var _options_INTERNAL_FEATURES;
let internalFeatures = (_options_INTERNAL_FEATURES = options[INTERNAL_FEATURES]) !== null && _options_INTERNAL_FEATURES !== void 0 ? _options_INTERNAL_FEATURES : {};
let respectPrefix = (()=>{
if (isArbitraryVariant) return false;
if (internalFeatures.respectPrefix === false) return false;
return true;
})();
formatStrings = formatStrings.map((format)=>format.map((str)=>({
format: str,
respectPrefix
})));
manualFormatStrings = manualFormatStrings.map((format)=>({
format,
respectPrefix
}));
let opts = {
candidate,
context
};
let result = formatStrings.map((formats)=>(0, _formatVariantSelector.finalizeSelector)(`.${candidate}`, (0, _formatVariantSelector.formatVariantSelector)(formats, opts), opts).replace(`.${candidate}`, "&").replace("{ & }", "").trim());
if (manualFormatStrings.length > 0) {
result.push((0, _formatVariantSelector.formatVariantSelector)(manualFormatStrings, opts).toString().replace(`.${candidate}`, "&"));
}
return result;
}
});
}
return result;
};
}
/**
* Mark as class as retroactively invalid
*
*
* @param {string} candidate
*/ function markInvalidUtilityCandidate(context, candidate) {
if (!context.classCache.has(candidate)) {
return;
}
// Mark this as not being a real utility
context.notClassCache.add(candidate);
// Remove it from any candidate-specific caches
context.classCache.delete(candidate);
context.applyClassCache.delete(candidate);
context.candidateRuleMap.delete(candidate);
context.candidateRuleCache.delete(candidate);
// Ensure the stylesheet gets rebuilt
context.stylesheetCache = null;
}
/**
* Mark as class as retroactively invalid
*
* @param {import('postcss').Node} node
*/ function markInvalidUtilityNode(context, node) {
let candidate = node.raws.tailwind.candidate;
if (!candidate) {
return;
}
for (const entry of context.ruleCache){
if (entry[1].raws.tailwind.candidate === candidate) {
context.ruleCache.delete(entry);
// context.postCssNodeCache.delete(node)
}
}
markInvalidUtilityCandidate(context, candidate);
}
function createContext(tailwindConfig, changedContent = [], root = _postcss.default.root()) {
var _tailwindConfig_blocklist;
let context = {
disposables: [],
ruleCache: new Set(),
candidateRuleCache: new Map(),
classCache: new Map(),
applyClassCache: new Map(),
notClassCache: new Set(),
// Seed the not class cache with the blocklist (which is only strings)
notClassCache: new Set((_tailwindConfig_blocklist = tailwindConfig.blocklist) !== null && _tailwindConfig_blocklist !== void 0 ? _tailwindConfig_blocklist : []),
postCssNodeCache: new Map(),

@@ -882,3 +1256,6 @@ candidateRuleMap: new Map(),

variantMap: new Map(),
stylesheetCache: null
stylesheetCache: null,
variantOptions: new Map(),
markInvalidUtilityCandidate: (candidate)=>markInvalidUtilityCandidate(context, candidate),
markInvalidUtilityNode: (node)=>markInvalidUtilityNode(context, node)
};

@@ -889,9 +1266,9 @@ let resolvedPlugins = resolvePlugins(context, root);

}
let contextMap = sharedState.contextMap;
let configContextMap = sharedState.configContextMap;
let contextSourcesMap = sharedState.contextSourcesMap;
let contextMap = _sharedState.contextMap;
let configContextMap = _sharedState.configContextMap;
let contextSourcesMap = _sharedState.contextSourcesMap;
function getContext(root, result, tailwindConfig, userConfigPath, tailwindConfigHash, contextDependencies) {
let sourcePath = result.opts.from;
let isConfigFile = userConfigPath !== null;
sharedState.env.DEBUG && console.log("Source path:", sourcePath);
_sharedState.env.DEBUG && console.log("Source path:", sourcePath);
let existingContext;

@@ -906,7 +1283,7 @@ if (isConfigFile && contextMap.has(sourcePath)) {

}
let cssDidChange = (0, _cacheInvalidationJs).hasContentChanged(sourcePath, root);
let cssDidChange = (0, _cacheInvalidation.hasContentChanged)(sourcePath, root);
// If there's already a context in the cache and we don't need to
// reset the context, return the cached context.
if (existingContext) {
let contextDependenciesChanged = trackModified([
let [contextDependenciesChanged, mtimesToCommit] = trackModified([
...contextDependencies

@@ -917,3 +1294,4 @@ ], getFileModifiedMap(existingContext));

existingContext,
false
false,
mtimesToCommit
];

@@ -944,5 +1322,8 @@ }

}
sharedState.env.DEBUG && console.log("Setting up new context...");
_sharedState.env.DEBUG && console.log("Setting up new context...");
let context = createContext(tailwindConfig, [], root);
trackModified([
Object.assign(context, {
userConfigPath
});
let [, mtimesToCommit] = trackModified([
...contextDependencies

@@ -960,4 +1341,5 @@ ], getFileModifiedMap(context));

context,
true
true,
mtimesToCommit
];
}

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

// @ts-check
"use strict";

@@ -5,68 +6,24 @@ Object.defineProperty(exports, "__esModule", {

});
exports.default = setupTrackingContext;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _fastGlob = _interopRequireDefault(require("fast-glob"));
var _quickLru = _interopRequireDefault(require("quick-lru"));
var _normalizePath = _interopRequireDefault(require("normalize-path"));
var _hashConfig = _interopRequireDefault(require("../util/hashConfig"));
var _getModuleDependencies = _interopRequireDefault(require("../lib/getModuleDependencies"));
var _resolveConfig = _interopRequireDefault(require("../public/resolve-config"));
var _resolveConfigPath = _interopRequireDefault(require("../util/resolveConfigPath"));
var _sharedState = require("./sharedState");
var _setupContextUtils = require("./setupContextUtils");
var _parseDependency = _interopRequireDefault(require("../util/parseDependency"));
var _validateConfigJs = require("../util/validateConfig.js");
function setupTrackingContext(configOrPath) {
return ({ tailwindDirectives , registerDependency })=>{
return (root, result)=>{
let [tailwindConfig, userConfigPath, tailwindConfigHash, configDependencies] = getTailwindConfig(configOrPath);
let contextDependencies = new Set(configDependencies);
// If there are no @tailwind or @apply rules, we don't consider this CSS
// file or its dependencies to be dependencies of the context. Can reuse
// the context even if they change. We may want to think about `@layer`
// being part of this trigger too, but it's tough because it's impossible
// for a layer in one file to end up in the actual @tailwind rule in
// another file since independent sources are effectively isolated.
if (tailwindDirectives.size > 0) {
// Add current css file as a context dependencies.
contextDependencies.add(result.opts.from);
// Add all css @import dependencies as context dependencies.
for (let message of result.messages){
if (message.type === "dependency") {
contextDependencies.add(message.file);
}
}
}
let [context] = (0, _setupContextUtils).getContext(root, result, tailwindConfig, userConfigPath, tailwindConfigHash, contextDependencies);
let candidateFiles = getCandidateFiles(context, tailwindConfig);
// If there are no @tailwind or @apply rules, we don't consider this CSS file or it's
// dependencies to be dependencies of the context. Can reuse the context even if they change.
// We may want to think about `@layer` being part of this trigger too, but it's tough
// because it's impossible for a layer in one file to end up in the actual @tailwind rule
// in another file since independent sources are effectively isolated.
if (tailwindDirectives.size > 0) {
let fileModifiedMap = (0, _setupContextUtils).getFileModifiedMap(context);
// Add template paths as postcss dependencies.
for (let fileOrGlob of candidateFiles){
let dependency = (0, _parseDependency).default(fileOrGlob);
if (dependency) {
registerDependency(dependency);
}
}
for (let changedContent of resolvedChangedContent(context, candidateFiles, fileModifiedMap)){
context.changedContent.push(changedContent);
}
}
for (let file of configDependencies){
registerDependency({
type: "dependency",
file
});
}
return context;
};
};
}
function _interopRequireDefault(obj) {
Object.defineProperty(exports, // DISABLE_TOUCH = TRUE
// Retrieve an existing context from cache if possible (since contexts are unique per
// source path), or set up a new one (including setting up watchers and registering
// plugins) then return it
"default", {
enumerable: true,
get: function() {
return setupTrackingContext;
}
});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _quicklru = /*#__PURE__*/ _interop_require_default(require("@alloc/quick-lru"));
const _hashConfig = /*#__PURE__*/ _interop_require_default(require("../util/hashConfig"));
const _resolveconfig = /*#__PURE__*/ _interop_require_default(require("../public/resolve-config"));
const _resolveConfigPath = /*#__PURE__*/ _interop_require_default(require("../util/resolveConfigPath"));
const _setupContextUtils = require("./setupContextUtils");
const _parseDependency = /*#__PURE__*/ _interop_require_default(require("../util/parseDependency"));
const _validateConfig = require("../util/validateConfig.js");
const _content = require("./content.js");
const _loadconfig = require("../lib/load-config");
const _getModuleDependencies = /*#__PURE__*/ _interop_require_default(require("./getModuleDependencies"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -76,3 +33,3 @@ default: obj

}
let configPathCache = new _quickLru.default({
let configPathCache = new _quicklru.default({
maxSize: 100

@@ -85,5 +42,3 @@ });

}
let candidateFiles = tailwindConfig.content.files.filter((item)=>typeof item === "string"
).map((contentPath)=>(0, _normalizePath).default(contentPath)
);
let candidateFiles = (0, _content.parseCandidateFiles)(context, tailwindConfig);
return candidateFilesCache.set(context, candidateFiles).get(context);

@@ -93,7 +48,6 @@ }

function getTailwindConfig(configOrPath) {
let userConfigPath = (0, _resolveConfigPath).default(configOrPath);
let userConfigPath = (0, _resolveConfigPath.default)(configOrPath);
if (userConfigPath !== null) {
let [prevConfig, prevConfigHash, prevDeps, prevModified] = configPathCache.get(userConfigPath) || [];
let newDeps = (0, _getModuleDependencies).default(userConfigPath).map((dep)=>dep.file
);
let newDeps = (0, _getModuleDependencies.default)(userConfigPath);
let modified = false;

@@ -118,8 +72,7 @@ let newModified = new Map();

// It has changed (based on timestamps), or first run
for (let file1 of newDeps){
delete require.cache[file1];
for (let file of newDeps){
delete require.cache[file];
}
let newConfig = (0, _resolveConfig).default(require(userConfigPath));
newConfig = (0, _validateConfigJs).validateConfig(newConfig);
let newHash = (0, _hashConfig).default(newConfig);
let newConfig = (0, _validateConfig.validateConfig)((0, _resolveconfig.default)((0, _loadconfig.loadConfig)(userConfigPath)));
let newHash = (0, _hashConfig.default)(newConfig);
configPathCache.set(userConfigPath, [

@@ -138,43 +91,82 @@ newConfig,

}
var _configOrPath_config, _ref;
// It's a plain object, not a path
let newConfig = (0, _resolveConfig).default(configOrPath.config === undefined ? configOrPath : configOrPath.config);
newConfig = (0, _validateConfigJs).validateConfig(newConfig);
let newConfig = (0, _resolveconfig.default)((_ref = (_configOrPath_config = configOrPath === null || configOrPath === void 0 ? void 0 : configOrPath.config) !== null && _configOrPath_config !== void 0 ? _configOrPath_config : configOrPath) !== null && _ref !== void 0 ? _ref : {});
newConfig = (0, _validateConfig.validateConfig)(newConfig);
return [
newConfig,
null,
(0, _hashConfig).default(newConfig),
(0, _hashConfig.default)(newConfig),
[]
];
}
function resolvedChangedContent(context, candidateFiles, fileModifiedMap) {
let changedContent = context.tailwindConfig.content.files.filter((item)=>typeof item.raw === "string"
).map(({ raw , extension ="html" })=>({
content: raw,
extension
})
);
for (let changedFile of resolveChangedFiles(candidateFiles, fileModifiedMap)){
let content = _fs.default.readFileSync(changedFile, "utf8");
let extension = _path.default.extname(changedFile).slice(1);
changedContent.push({
content,
extension
});
}
return changedContent;
function setupTrackingContext(configOrPath) {
return ({ tailwindDirectives , registerDependency })=>{
return (root, result)=>{
let [tailwindConfig, userConfigPath, tailwindConfigHash, configDependencies] = getTailwindConfig(configOrPath);
let contextDependencies = new Set(configDependencies);
// If there are no @tailwind or @apply rules, we don't consider this CSS
// file or its dependencies to be dependencies of the context. Can reuse
// the context even if they change. We may want to think about `@layer`
// being part of this trigger too, but it's tough because it's impossible
// for a layer in one file to end up in the actual @tailwind rule in
// another file since independent sources are effectively isolated.
if (tailwindDirectives.size > 0) {
// Add current css file as a context dependencies.
contextDependencies.add(result.opts.from);
// Add all css @import dependencies as context dependencies.
for (let message of result.messages){
if (message.type === "dependency") {
contextDependencies.add(message.file);
}
}
}
let [context, , mTimesToCommit] = (0, _setupContextUtils.getContext)(root, result, tailwindConfig, userConfigPath, tailwindConfigHash, contextDependencies);
let fileModifiedMap = (0, _setupContextUtils.getFileModifiedMap)(context);
let candidateFiles = getCandidateFiles(context, tailwindConfig);
// If there are no @tailwind or @apply rules, we don't consider this CSS file or it's
// dependencies to be dependencies of the context. Can reuse the context even if they change.
// We may want to think about `@layer` being part of this trigger too, but it's tough
// because it's impossible for a layer in one file to end up in the actual @tailwind rule
// in another file since independent sources are effectively isolated.
if (tailwindDirectives.size > 0) {
// Add template paths as postcss dependencies.
for (let contentPath of candidateFiles){
for (let dependency of (0, _parseDependency.default)(contentPath)){
registerDependency(dependency);
}
}
let [changedContent, contentMTimesToCommit] = (0, _content.resolvedChangedContent)(context, candidateFiles, fileModifiedMap);
for (let content of changedContent){
context.changedContent.push(content);
}
// Add the mtimes of the content files to the commit list
// We can overwrite the existing values because unconditionally
// This is because:
// 1. Most of the files here won't be in the map yet
// 2. If they are that means it's a context dependency
// and we're reading this after the context. This means
// that the mtime we just read is strictly >= the context
// mtime. Unless the user / os is doing something weird
// in which the mtime would be going backwards. If that
// happens there's already going to be problems.
for (let [path, mtime] of contentMTimesToCommit.entries()){
mTimesToCommit.set(path, mtime);
}
}
for (let file of configDependencies){
registerDependency({
type: "dependency",
file
});
}
// "commit" the new modified time for all context deps
// We do this here because we want content tracking to
// read the "old" mtime even when it's a context dependency.
for (let [path, mtime] of mTimesToCommit.entries()){
fileModifiedMap.set(path, mtime);
}
return context;
};
};
}
function resolveChangedFiles(candidateFiles, fileModifiedMap) {
let changedFiles = new Set();
_sharedState.env.DEBUG && console.time("Finding changed files");
let files = _fastGlob.default.sync(candidateFiles);
for (let file of files){
let prevModified = fileModifiedMap.has(file) ? fileModifiedMap.get(file) : -Infinity;
let modified = _fs.default.statSync(file).mtimeMs;
if (modified > prevModified) {
changedFiles.add(file);
fileModifiedMap.set(file, modified);
}
}
_sharedState.env.DEBUG && console.timeEnd("Finding changed files");
return changedFiles;
}

@@ -5,19 +5,47 @@ "use strict";

});
exports.resolveDebug = resolveDebug;
exports.NOT_ON_DEMAND = exports.sourceHashMap = exports.contextSourcesMap = exports.configContextMap = exports.contextMap = exports.env = void 0;
const env = {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
env: function() {
return env;
},
contextMap: function() {
return contextMap;
},
configContextMap: function() {
return configContextMap;
},
contextSourcesMap: function() {
return contextSourcesMap;
},
sourceHashMap: function() {
return sourceHashMap;
},
NOT_ON_DEMAND: function() {
return NOT_ON_DEMAND;
},
NONE: function() {
return NONE;
},
resolveDebug: function() {
return resolveDebug;
}
});
const env = typeof process !== "undefined" ? {
NODE_ENV: process.env.NODE_ENV,
DEBUG: resolveDebug(process.env.DEBUG)
} : {
NODE_ENV: "production",
DEBUG: false
};
exports.env = env;
const contextMap = new Map();
exports.contextMap = contextMap;
const configContextMap = new Map();
exports.configContextMap = configContextMap;
const contextSourcesMap = new Map();
exports.contextSourcesMap = contextSourcesMap;
const sourceHashMap = new Map();
exports.sourceHashMap = sourceHashMap;
const NOT_ON_DEMAND = new String("*");
exports.NOT_ON_DEMAND = NOT_ON_DEMAND;
const NONE = Symbol("__NONE__");
function resolveDebug(debug) {

@@ -42,4 +70,3 @@ if (debug === undefined) {

}
let debuggers = debug.split(",").map((d)=>d.split(":")[0]
);
let debuggers = debug.split(",").map((d)=>d.split(":")[0]);
// Ignoring tailwindcss

@@ -46,0 +73,0 @@ if (debuggers.includes("-tailwindcss")) {

@@ -5,6 +5,11 @@ "use strict";

});
exports.default = _default;
var _normalizeScreens = require("../util/normalizeScreens");
var _buildMediaQuery = _interopRequireDefault(require("../util/buildMediaQuery"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _normalizeScreens = require("../util/normalizeScreens");
const _buildMediaQuery = /*#__PURE__*/ _interop_require_default(require("../util/buildMediaQuery"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -18,5 +23,4 @@ default: obj

let screen = atRule.params;
let screens = (0, _normalizeScreens).normalizeScreens(theme.screens);
let screenDefinition = screens.find(({ name })=>name === screen
);
let screens = (0, _normalizeScreens.normalizeScreens)(theme.screens);
let screenDefinition = screens.find(({ name })=>name === screen);
if (!screenDefinition) {

@@ -26,5 +30,5 @@ throw atRule.error(`No \`${screen}\` screen found.`);

atRule.name = "media";
atRule.params = (0, _buildMediaQuery).default(screenDefinition);
atRule.params = (0, _buildMediaQuery.default)(screenDefinition);
});
};
}

@@ -5,9 +5,14 @@ "use strict";

});
exports.default = void 0;
var _plugin = require("./plugin");
var _default = Object.assign(function(opts) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _plugin = require("./plugin");
const _default = Object.assign(function(opts) {
return {
postcssPlugin: "tailwindcss/nesting",
Once (root, { result }) {
return (0, _plugin).nesting(opts)(root, result);
return (0, _plugin.nesting)(opts)(root, result);
}

@@ -18,2 +23,1 @@ };

});
exports.default = _default;

@@ -5,6 +5,11 @@ "use strict";

});
exports.nesting = nesting;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcssNested = _interopRequireDefault(require("postcss-nested"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "nesting", {
enumerable: true,
get: function() {
return nesting;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _postcssnested = /*#__PURE__*/ _interop_require_default(require("postcss-nested"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -14,3 +19,3 @@ default: obj

}
function nesting(opts = _postcssNested.default) {
function nesting(opts = _postcssnested.default) {
return (root, result)=>{

@@ -30,4 +35,4 @@ root.walkAtRules("screen", (rule)=>{

let plugin = (()=>{
var ref;
if (typeof opts === "function" || typeof opts === "object" && (opts === null || opts === void 0 ? void 0 : (ref = opts.hasOwnProperty) === null || ref === void 0 ? void 0 : ref.call(opts, "postcssPlugin"))) {
var _opts_hasOwnProperty;
if (typeof opts === "function" || typeof opts === "object" && (opts === null || opts === void 0 ? void 0 : (_opts_hasOwnProperty = opts.hasOwnProperty) === null || _opts_hasOwnProperty === void 0 ? void 0 : _opts_hasOwnProperty.call(opts, "postcssPlugin"))) {
return opts;

@@ -39,7 +44,7 @@ }

if (Object.keys(opts).length <= 0) {
return _postcssNested.default;
return _postcssnested.default;
}
throw new Error("tailwindcss/nesting should be loaded with a nesting plugin.");
})();
(0, _postcss).default([
(0, _postcss.default)([
plugin

@@ -74,4 +79,3 @@ ]).process(root, result.opts).sync();

if (node.nodes) {
node.nodes.forEach((n)=>markDirty(n)
);
node.nodes.forEach((n)=>markDirty(n));
}

@@ -78,0 +82,0 @@ // If it's a leaf node mark it as dirty

@@ -5,22 +5,30 @@ "use strict";

});
exports.default = processTailwindFeatures;
var _normalizeTailwindDirectives = _interopRequireDefault(require("./lib/normalizeTailwindDirectives"));
var _expandTailwindAtRules = _interopRequireDefault(require("./lib/expandTailwindAtRules"));
var _expandApplyAtRules = _interopRequireDefault(require("./lib/expandApplyAtRules"));
var _evaluateTailwindFunctions = _interopRequireDefault(require("./lib/evaluateTailwindFunctions"));
var _substituteScreenAtRules = _interopRequireDefault(require("./lib/substituteScreenAtRules"));
var _resolveDefaultsAtRules = _interopRequireDefault(require("./lib/resolveDefaultsAtRules"));
var _collapseAdjacentRules = _interopRequireDefault(require("./lib/collapseAdjacentRules"));
var _collapseDuplicateDeclarations = _interopRequireDefault(require("./lib/collapseDuplicateDeclarations"));
var _partitionApplyAtRules = _interopRequireDefault(require("./lib/partitionApplyAtRules"));
var _detectNesting = _interopRequireDefault(require("./lib/detectNesting"));
var _setupContextUtils = require("./lib/setupContextUtils");
var _featureFlags = require("./featureFlags");
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return processTailwindFeatures;
}
});
const _normalizeTailwindDirectives = /*#__PURE__*/ _interop_require_default(require("./lib/normalizeTailwindDirectives"));
const _expandTailwindAtRules = /*#__PURE__*/ _interop_require_default(require("./lib/expandTailwindAtRules"));
const _expandApplyAtRules = /*#__PURE__*/ _interop_require_default(require("./lib/expandApplyAtRules"));
const _evaluateTailwindFunctions = /*#__PURE__*/ _interop_require_default(require("./lib/evaluateTailwindFunctions"));
const _substituteScreenAtRules = /*#__PURE__*/ _interop_require_default(require("./lib/substituteScreenAtRules"));
const _resolveDefaultsAtRules = /*#__PURE__*/ _interop_require_default(require("./lib/resolveDefaultsAtRules"));
const _collapseAdjacentRules = /*#__PURE__*/ _interop_require_default(require("./lib/collapseAdjacentRules"));
const _collapseDuplicateDeclarations = /*#__PURE__*/ _interop_require_default(require("./lib/collapseDuplicateDeclarations"));
const _partitionApplyAtRules = /*#__PURE__*/ _interop_require_default(require("./lib/partitionApplyAtRules"));
const _setupContextUtils = require("./lib/setupContextUtils");
const _featureFlags = require("./featureFlags");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function processTailwindFeatures(setupContext) {
return function(root, result) {
let { tailwindDirectives , applyDirectives } = (0, _normalizeTailwindDirectives).default(root);
(0, _detectNesting).default()(root, result);
return async function(root, result) {
let { tailwindDirectives , applyDirectives } = (0, _normalizeTailwindDirectives.default)(root);
// Partition apply rules that are found in the css
// itself.
(0, _partitionApplyAtRules).default()(root, result);
(0, _partitionApplyAtRules.default)()(root, result);
let context = setupContext({

@@ -37,3 +45,3 @@ tailwindDirectives,

createContext (tailwindConfig, changedContent) {
return (0, _setupContextUtils).createContext(tailwindConfig, changedContent, root);
return (0, _setupContextUtils.createContext)(tailwindConfig, changedContent, root);
}

@@ -44,19 +52,14 @@ })(root, result);

}
(0, _featureFlags).issueFlagNotices(context.tailwindConfig);
(0, _expandTailwindAtRules).default(context)(root, result);
(0, _featureFlags.issueFlagNotices)(context.tailwindConfig);
await (0, _expandTailwindAtRules.default)(context)(root, result);
// Partition apply rules that are generated by
// addComponents, addUtilities and so on.
(0, _partitionApplyAtRules).default()(root, result);
(0, _expandApplyAtRules).default(context)(root, result);
(0, _evaluateTailwindFunctions).default(context)(root, result);
(0, _substituteScreenAtRules).default(context)(root, result);
(0, _resolveDefaultsAtRules).default(context)(root, result);
(0, _collapseAdjacentRules).default(context)(root, result);
(0, _collapseDuplicateDeclarations).default(context)(root, result);
(0, _partitionApplyAtRules.default)()(root, result);
(0, _expandApplyAtRules.default)(context)(root, result);
(0, _evaluateTailwindFunctions.default)(context)(root, result);
(0, _substituteScreenAtRules.default)(context)(root, result);
(0, _resolveDefaultsAtRules.default)(context)(root, result);
(0, _collapseAdjacentRules.default)(context)(root, result);
(0, _collapseDuplicateDeclarations.default)(context)(root, result);
};
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

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

});
exports.default = void 0;
var _log = _interopRequireDefault(require("../util/log"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -16,6 +21,6 @@ default: obj

`As of Tailwind CSS ${version}, \`${from}\` has been renamed to \`${to}\`.`,
"Update your configuration file to silence this warning.",
"Update your configuration file to silence this warning."
]);
}
var _default = {
const _default = {
inherit: "inherit",

@@ -36,3 +41,4 @@ current: "currentColor",

800: "#1e293b",
900: "#0f172a"
900: "#0f172a",
950: "#020617"
},

@@ -49,3 +55,4 @@ gray: {

800: "#1f2937",
900: "#111827"
900: "#111827",
950: "#030712"
},

@@ -62,3 +69,4 @@ zinc: {

800: "#27272a",
900: "#18181b"
900: "#18181b",
950: "#09090b"
},

@@ -75,3 +83,4 @@ neutral: {

800: "#262626",
900: "#171717"
900: "#171717",
950: "#0a0a0a"
},

@@ -88,3 +97,4 @@ stone: {

800: "#292524",
900: "#1c1917"
900: "#1c1917",
950: "#0c0a09"
},

@@ -101,3 +111,4 @@ red: {

800: "#991b1b",
900: "#7f1d1d"
900: "#7f1d1d",
950: "#450a0a"
},

@@ -114,3 +125,4 @@ orange: {

800: "#9a3412",
900: "#7c2d12"
900: "#7c2d12",
950: "#431407"
},

@@ -127,3 +139,4 @@ amber: {

800: "#92400e",
900: "#78350f"
900: "#78350f",
950: "#451a03"
},

@@ -140,3 +153,4 @@ yellow: {

800: "#854d0e",
900: "#713f12"
900: "#713f12",
950: "#422006"
},

@@ -153,3 +167,4 @@ lime: {

800: "#3f6212",
900: "#365314"
900: "#365314",
950: "#1a2e05"
},

@@ -166,3 +181,4 @@ green: {

800: "#166534",
900: "#14532d"
900: "#14532d",
950: "#052e16"
},

@@ -179,3 +195,4 @@ emerald: {

800: "#065f46",
900: "#064e3b"
900: "#064e3b",
950: "#022c22"
},

@@ -192,3 +209,4 @@ teal: {

800: "#115e59",
900: "#134e4a"
900: "#134e4a",
950: "#042f2e"
},

@@ -205,3 +223,4 @@ cyan: {

800: "#155e75",
900: "#164e63"
900: "#164e63",
950: "#083344"
},

@@ -218,3 +237,4 @@ sky: {

800: "#075985",
900: "#0c4a6e"
900: "#0c4a6e",
950: "#082f49"
},

@@ -231,3 +251,4 @@ blue: {

800: "#1e40af",
900: "#1e3a8a"
900: "#1e3a8a",
950: "#172554"
},

@@ -244,3 +265,4 @@ indigo: {

800: "#3730a3",
900: "#312e81"
900: "#312e81",
950: "#1e1b4b"
},

@@ -257,3 +279,4 @@ violet: {

800: "#5b21b6",
900: "#4c1d95"
900: "#4c1d95",
950: "#2e1065"
},

@@ -270,3 +293,4 @@ purple: {

800: "#6b21a8",
900: "#581c87"
900: "#581c87",
950: "#3b0764"
},

@@ -283,3 +307,4 @@ fuchsia: {

800: "#86198f",
900: "#701a75"
900: "#701a75",
950: "#4a044e"
},

@@ -296,3 +321,4 @@ pink: {

800: "#9d174d",
900: "#831843"
900: "#831843",
950: "#500724"
},

@@ -309,3 +335,4 @@ rose: {

800: "#9f1239",
900: "#881337"
900: "#881337",
950: "#4c0519"
},

@@ -353,2 +380,1 @@ get lightBlue () {

};
exports.default = _default;

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

});
exports.default = void 0;
var _createPlugin = _interopRequireDefault(require("../util/createPlugin"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _createPlugin = /*#__PURE__*/ _interop_require_default(require("../util/createPlugin"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -13,3 +18,2 @@ default: obj

}
var _default = _createPlugin.default;
exports.default = _default;
const _default = _createPlugin.default;

@@ -5,6 +5,11 @@ "use strict";

});
exports.default = void 0;
var _cloneDeep = require("../util/cloneDeep");
var _defaultConfigStub = _interopRequireDefault(require("../../stubs/defaultConfig.stub"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _cloneDeep = require("../util/cloneDeep");
const _configfull = /*#__PURE__*/ _interop_require_default(require("../../stubs/config.full"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -14,3 +19,2 @@ default: obj

}
var _default = (0, _cloneDeep).cloneDeep(_defaultConfigStub.default);
exports.default = _default;
const _default = (0, _cloneDeep.cloneDeep)(_configfull.default);

@@ -5,6 +5,11 @@ "use strict";

});
exports.default = void 0;
var _cloneDeep = require("../util/cloneDeep");
var _defaultConfigStub = _interopRequireDefault(require("../../stubs/defaultConfig.stub"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _cloneDeep = require("../util/cloneDeep");
const _configfull = /*#__PURE__*/ _interop_require_default(require("../../stubs/config.full"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -14,3 +19,2 @@ default: obj

}
var _default = (0, _cloneDeep).cloneDeep(_defaultConfigStub.default.theme);
exports.default = _default;
const _default = (0, _cloneDeep.cloneDeep)(_configfull.default.theme);

@@ -5,8 +5,18 @@ "use strict";

});
exports.default = resolveConfig;
var _resolveConfig = _interopRequireDefault(require("../util/resolveConfig"));
var _getAllConfigs = _interopRequireDefault(require("../util/getAllConfigs"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return resolveConfig;
}
});
const _resolveConfig = /*#__PURE__*/ _interop_require_default(require("../util/resolveConfig"));
const _getAllConfigs = /*#__PURE__*/ _interop_require_default(require("../util/getAllConfigs"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function resolveConfig(...configs) {
let [, ...defaultConfigs] = (0, _getAllConfigs).default(configs[0]);
return (0, _resolveConfig).default([
let [, ...defaultConfigs] = (0, _getAllConfigs.default)(configs[0]);
return (0, _resolveConfig.default)([
...configs,

@@ -16,6 +26,1 @@ ...defaultConfigs

}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

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

});
exports.default = bigSign;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return bigSign;
}
});
function bigSign(bigIntValue) {
return (bigIntValue > 0n) - (bigIntValue < 0n);
}

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

});
exports.default = buildMediaQuery;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return buildMediaQuery;
}
});
function buildMediaQuery(screens) {

@@ -11,3 +16,4 @@ screens = Array.isArray(screens) ? screens : [

];
return screens.map((screen1)=>screen1.values.map((screen)=>{
return screens.map((screen)=>{
let values = screen.values.map((screen)=>{
if (screen.raw !== undefined) {

@@ -18,6 +24,7 @@ return screen.raw;

screen.min && `(min-width: ${screen.min})`,
screen.max && `(max-width: ${screen.max})`,
screen.max && `(max-width: ${screen.max})`
].filter(Boolean).join(" and ");
})
).join(", ");
});
return screen.not ? `not all and ${values}` : values;
}).join(", ");
}

@@ -5,7 +5,11 @@ "use strict";

});
exports.cloneDeep = cloneDeep;
Object.defineProperty(exports, "cloneDeep", {
enumerable: true,
get: function() {
return cloneDeep;
}
});
function cloneDeep(value) {
if (Array.isArray(value)) {
return value.map((child)=>cloneDeep(child)
);
return value.map((child)=>cloneDeep(child));
}

@@ -16,6 +20,5 @@ if (typeof value === "object" && value !== null) {

cloneDeep(v)
]
));
]));
}
return value;
}

@@ -1,17 +0,19 @@

"use strict";
/**
* @param {import('postcss').Container[]} nodes
* @param {any} source
* @param {any} raws
* @returns {import('postcss').Container[]}
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = cloneNodes;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return cloneNodes;
}
});
function cloneNodes(nodes, source = undefined, raws = undefined) {
return nodes.map((node)=>{
let cloned = node.clone();
if (source !== undefined) {
cloned.source = source;
if ("walk" in cloned) {
cloned.walk((child)=>{
child.source = source;
});
}
}
if (raws !== undefined) {

@@ -23,4 +25,31 @@ cloned.raws.tailwind = {

}
if (source !== undefined) {
traverse(cloned, (node)=>{
var _node_raws_tailwind;
// Do not traverse nodes that have opted
// to preserve their original source
let shouldPreserveSource = ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.preserveSource) === true && node.source;
if (shouldPreserveSource) {
return false;
}
// Otherwise we can safely replace the source
// And continue traversing
node.source = source;
});
}
return cloned;
});
}
/**
* Traverse a tree of nodes and don't traverse children if the callback
* returns false. Ideally we'd use Container#walk instead of this
* function but it stops traversing siblings too.
*
* @param {import('postcss').Container} node
* @param {(node: import('postcss').Container) => boolean} onNode
*/ function traverse(node, onNode) {
if (onNode(node) !== false) {
var _node_each;
(_node_each = node.each) === null || _node_each === void 0 ? void 0 : _node_each.call(node, (child)=>traverse(child, onNode));
}
}

@@ -5,6 +5,18 @@ "use strict";

});
exports.parseColor = parseColor;
exports.formatColor = formatColor;
var _colorName = _interopRequireDefault(require("color-name"));
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
parseColor: function() {
return parseColor;
},
formatColor: function() {
return formatColor;
}
});
const _colorNames = /*#__PURE__*/ _interop_require_default(require("./colorNames"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -19,7 +31,7 @@ default: obj

let ALPHA_SEP = /\s*[,/]\s*/;
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/;
let RGB = new RegExp(`^(rgb)a?\\(\\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*\\)$`);
let HSL = new RegExp(`^(hsl)a?\\(\\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*\\)$`);
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*\\)$`);
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*\\)$`);
function parseColor(value, { loose =false } = {}) {
var ref, ref1;
var _match_, _match__toString;
if (typeof value !== "string") {

@@ -40,7 +52,6 @@ return null;

}
if (value in _colorName.default) {
if (value in _colorNames.default) {
return {
mode: "rgb",
color: _colorName.default[value].map((v)=>v.toString()
)
color: _colorNames.default[value].map((v)=>v.toString())
};

@@ -57,4 +68,3 @@ }

a ? a + a : ""
].join("")
).match(HEX);
].join("")).match(HEX);
if (hex !== null) {

@@ -67,9 +77,8 @@ return {

parseInt(hex[3], 16)
].map((v)=>v.toString()
),
].map((v)=>v.toString()),
alpha: hex[4] ? (parseInt(hex[4], 16) / 255).toString() : undefined
};
}
var ref2;
let match = (ref2 = value.match(RGB)) !== null && ref2 !== void 0 ? ref2 : value.match(HSL);
var _value_match;
let match = (_value_match = value.match(RGB)) !== null && _value_match !== void 0 ? _value_match : value.match(HSL);
if (match === null) {

@@ -82,9 +91,18 @@ return null;

match[4]
].filter(Boolean).map((v)=>v.toString()
);
].filter(Boolean).map((v)=>v.toString());
// rgba(var(--my-color), 0.1)
// hsla(var(--my-color), 0.1)
if (color.length === 2 && color[0].startsWith("var(")) {
return {
mode: match[1],
color: [
color[0]
],
alpha: color[1]
};
}
if (!loose && color.length !== 3) {
return null;
}
if (color.length < 3 && !color.some((part)=>/^var\(.*?\)$/.test(part)
)) {
if (color.length < 3 && !color.some((part)=>/^var\(.*?\)$/.test(part))) {
return null;

@@ -95,3 +113,3 @@ }

color,
alpha: (ref = match[5]) === null || ref === void 0 ? void 0 : (ref1 = ref.toString) === null || ref1 === void 0 ? void 0 : ref1.call(ref)
alpha: (_match_ = match[5]) === null || _match_ === void 0 ? void 0 : (_match__toString = _match_.toString) === null || _match__toString === void 0 ? void 0 : _match__toString.call(_match_)
};

@@ -101,3 +119,6 @@ }

let hasAlpha = alpha !== undefined;
if (mode === "rgba" || mode === "hsla") {
return `${mode}(${color.join(", ")}${hasAlpha ? `, ${alpha}` : ""})`;
}
return `${mode}(${color.join(" ")}${hasAlpha ? ` / ${alpha}` : ""})`;
}

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

});
exports.default = _default;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
function _default(pluginConfig, plugins) {

@@ -16,5 +21,5 @@ if (pluginConfig === undefined) {

return pluginConfig[pluginName] !== false;
}))),
})))
];
return pluginNames;
}

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

});
exports.default = void 0;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
function createPlugin(plugin, config) {

@@ -13,4 +18,3 @@ return {

}
createPlugin.withOptions = function(pluginFunction, configFunction = ()=>({})
) {
createPlugin.withOptions = function(pluginFunction, configFunction = ()=>({})) {
const optionsFunction = function(options) {

@@ -30,3 +34,2 @@ return {

};
var _default = createPlugin;
exports.default = _default;
const _default = createPlugin;

@@ -5,4 +5,14 @@ "use strict";

});
exports.default = createUtilityPlugin;
var _transformThemeValue = _interopRequireDefault(require("./transformThemeValue"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return createUtilityPlugin;
}
});
const _transformThemeValue = /*#__PURE__*/ _interop_require_default(require("./transformThemeValue"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function createUtilityPlugin(themeKey, utilityVariations = [

@@ -16,3 +26,3 @@ [

], { filterDefault =false , ...options } = {}) {
let transformValue = (0, _transformThemeValue).default(themeKey);
let transformValue = (0, _transformThemeValue.default)(themeKey);
return function({ matchUtilities , theme }) {

@@ -23,5 +33,5 @@ for (let utilityVariation of utilityVariations){

];
var ref;
matchUtilities(group.reduce((obj1, [classPrefix, properties])=>{
return Object.assign(obj1, {
var _theme;
matchUtilities(group.reduce((obj, [classPrefix, properties])=>{
return Object.assign(obj, {
[classPrefix]: (value)=>{

@@ -42,4 +52,3 @@ return properties.reduce((obj, name)=>{

...options,
values: filterDefault ? Object.fromEntries(Object.entries((ref = theme(themeKey)) !== null && ref !== void 0 ? ref : {}).filter(([modifier])=>modifier !== "DEFAULT"
)) : theme(themeKey)
values: filterDefault ? Object.fromEntries(Object.entries((_theme = theme(themeKey)) !== null && _theme !== void 0 ? _theme : {}).filter(([modifier])=>modifier !== "DEFAULT")) : theme(themeKey)
});

@@ -49,6 +58,1 @@ }

}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

@@ -5,19 +5,61 @@ "use strict";

});
exports.normalize = normalize;
exports.url = url;
exports.number = number;
exports.percentage = percentage;
exports.length = length;
exports.lineWidth = lineWidth;
exports.shadow = shadow;
exports.color = color;
exports.image = image;
exports.gradient = gradient;
exports.position = position;
exports.familyName = familyName;
exports.genericName = genericName;
exports.absoluteSize = absoluteSize;
exports.relativeSize = relativeSize;
var _color = require("./color");
var _parseBoxShadowValue = require("./parseBoxShadowValue");
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
normalize: function() {
return normalize;
},
normalizeAttributeSelectors: function() {
return normalizeAttributeSelectors;
},
url: function() {
return url;
},
number: function() {
return number;
},
percentage: function() {
return percentage;
},
length: function() {
return length;
},
lineWidth: function() {
return lineWidth;
},
shadow: function() {
return shadow;
},
color: function() {
return color;
},
image: function() {
return image;
},
gradient: function() {
return gradient;
},
position: function() {
return position;
},
familyName: function() {
return familyName;
},
genericName: function() {
return genericName;
},
absoluteSize: function() {
return absoluteSize;
},
relativeSize: function() {
return relativeSize;
}
});
const _color = require("./color");
const _parseBoxShadowValue = require("./parseBoxShadowValue");
const _splitAtTopLevelOnly = require("./splitAtTopLevelOnly");
let cssFunctions = [

@@ -30,7 +72,37 @@ "min",

// Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types
let COMMA = /,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
;
let UNDERSCORE = /_(?![^(]*\))/g // Underscore separator that is not located between brackets. E.g.: `rgba(255,_255,_255)_black` these don't count.
;
function normalize(value, isRoot = true) {
function isCSSFunction(value) {
return cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.*\\)`).test(value));
}
// 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
// - https://www.w3.org/TR/css-anchor-position-1
//
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
// Concrete properties
"scroll-timeline-name",
"timeline-scope",
"view-timeline-name",
"font-palette",
"anchor-name",
"anchor-scope",
"position-anchor",
"position-try-options",
// Shorthand properties
"scroll-timeline",
"animation-timeline",
"view-timeline",
"position-try"
]);
function normalize(value, context = null, isRoot = true) {
let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property);
if (value.startsWith("--") && !isVarException) {
return `var(${value})`;
}
// Keep raw strings if it starts with `url(`

@@ -42,8 +114,7 @@ if (value.includes("url(")) {

}
return normalize(part, false);
return normalize(part, context, false);
}).join("");
}
// Convert `_` to ` `, except for escaped underscores `\_`
value = value.replace(/([^\\])_+/g, (fullMatch, characterBefore)=>characterBefore + " ".repeat(fullMatch.length - 1)
).replace(/^_/g, " ").replace(/\\_/g, "_");
value = value.replace(/([^\\])_+/g, (fullMatch, characterBefore)=>characterBefore + " ".repeat(fullMatch.length - 1)).replace(/^_/g, " ").replace(/\\_/g, "_");
// Remove leftover whitespace

@@ -53,10 +124,129 @@ if (isRoot) {

}
// Add spaces around operators inside calc() that do not follow an operator
// or '('.
value = value.replace(/calc\(.+\)/g, (match)=>{
return match.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, "$1 $2 ");
value = normalizeMathOperatorSpacing(value);
return value;
}
function normalizeAttributeSelectors(value) {
// Wrap values in attribute selectors with quotes
if (value.includes("=")) {
value = value.replace(/(=.*)/g, (_fullMatch, match)=>{
if (match[1] === "'" || match[1] === '"') {
return match;
}
// Handle regex flags on unescaped values
if (match.length > 2) {
let trailingCharacter = match[match.length - 1];
if (match[match.length - 2] === " " && (trailingCharacter === "i" || trailingCharacter === "I" || trailingCharacter === "s" || trailingCharacter === "S")) {
return `="${match.slice(1, -2)}" ${match[match.length - 1]}`;
}
}
return `="${match.slice(1)}"`;
});
}
return value;
}
/**
* Add spaces around operators inside math functions
* like calc() that do not follow an operator, '(', or `,`.
*
* @param {string} value
* @returns {string}
*/ 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",
"radial-gradient",
"linear-gradient",
"conic-gradient",
"repeating-radial-gradient",
"repeating-linear-gradient",
"repeating-conic-gradient"
];
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
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 (peek("[")) {
result += consumeUntil([
"]"
]);
} else if ([
"+",
"-",
"*",
"/"
].includes(char) && ![
"(",
"+",
"-",
"*",
"/",
","
].includes(lastChar())) {
result += ` ${char} `;
} else {
result += char;
}
}
// Simplify multiple spaces
return result.replace(/\s+/g, " ");
});
// Add spaces around some operators not inside calc() that do not follow an operator
// or '('.
return value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([\/])/g, "$1 $2 ");
}

@@ -67,11 +257,10 @@ function url(value) {

function number(value) {
return !isNaN(Number(value)) || cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.+?`).test(value)
);
return !isNaN(Number(value)) || isCSSFunction(value);
}
function percentage(value) {
return value.split(UNDERSCORE).every((part)=>{
return /%$/g.test(part) || cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.+?%`).test(part)
);
});
return value.endsWith("%") && number(value.slice(0, -1)) || isCSSFunction(value);
}
// Please refer to MDN when updating this list:
// https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries#container_query_length_units
let lengthUnits = [

@@ -90,13 +279,25 @@ "cm",

"lh",
"rlh",
"vw",
"vh",
"vmin",
"vmax",
"vmax",
"vb",
"vi",
"svw",
"svh",
"lvw",
"lvh",
"dvw",
"dvh",
"cqw",
"cqh",
"cqi",
"cqb",
"cqmin",
"cqmax"
];
let lengthUnitsPattern = `(?:${lengthUnits.join("|")})`;
function length(value) {
return value.split(UNDERSCORE).every((part)=>{
return part === "0" || new RegExp(`${lengthUnitsPattern}$`).test(part) || cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.+?${lengthUnitsPattern}`).test(part)
);
});
return value === "0" || new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`).test(value) || isCSSFunction(value);
}

@@ -112,3 +313,3 @@ let lineWidths = new Set([

function shadow(value) {
let parsedShadows = (0, _parseBoxShadowValue).parseBoxShadowValue(normalize(value));
let parsedShadows = (0, _parseBoxShadowValue.parseBoxShadowValue)(normalize(value));
for (let parsedShadow of parsedShadows){

@@ -123,6 +324,6 @@ if (!parsedShadow.valid) {

let colors = 0;
let result = value.split(UNDERSCORE).every((part)=>{
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, "_").every((part)=>{
part = normalize(part);
if (part.startsWith("var(")) return true;
if ((0, _color).parseColor(part, {
if ((0, _color.parseColor)(part, {
loose: true

@@ -137,3 +338,3 @@ }) !== null) return colors++, true;

let images = 0;
let result = value.split(COMMA).every((part)=>{
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ",").every((part)=>{
part = normalize(part);

@@ -146,4 +347,3 @@ if (part.startsWith("var(")) return true;

"image-set("
].some((fn)=>part.startsWith(fn)
)) {
].some((fn)=>part.startsWith(fn))) {
images++;

@@ -158,7 +358,8 @@ return true;

let gradientTypes = new Set([
"conic-gradient",
"linear-gradient",
"radial-gradient",
"repeating-conic-gradient",
"repeating-linear-gradient",
"repeating-radial-gradient",
"conic-gradient",
"repeating-radial-gradient"
]);

@@ -183,3 +384,3 @@ function gradient(value) {

let positions = 0;
let result = value.split(UNDERSCORE).every((part)=>{
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, "_").every((part)=>{
part = normalize(part);

@@ -198,3 +399,3 @@ if (part.startsWith("var(")) return true;

let fonts = 0;
let result = value.split(COMMA).every((part)=>{
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ",").every((part)=>{
part = normalize(part);

@@ -231,3 +432,3 @@ if (part.startsWith("var(")) return true;

"emoji",
"fangsong",
"fangsong"
]);

@@ -244,4 +445,4 @@ function genericName(value) {

"x-large",
"x-large",
"xxx-large",
"xx-large",
"xxx-large"
]);

@@ -248,0 +449,0 @@ function absoluteSize(value) {

@@ -5,15 +5,20 @@ "use strict";

});
exports.defaults = defaults;
Object.defineProperty(exports, "defaults", {
enumerable: true,
get: function() {
return defaults;
}
});
function defaults(target, ...sources) {
for (let source of sources){
for(let k in source){
var ref;
if (!(target === null || target === void 0 ? void 0 : (ref = target.hasOwnProperty) === null || ref === void 0 ? void 0 : ref.call(target, k))) {
var _target_hasOwnProperty;
if (!(target === null || target === void 0 ? void 0 : (_target_hasOwnProperty = target.hasOwnProperty) === null || _target_hasOwnProperty === void 0 ? void 0 : _target_hasOwnProperty.call(target, k))) {
target[k] = source[k];
}
}
for (let k1 of Object.getOwnPropertySymbols(source)){
var ref1;
if (!(target === null || target === void 0 ? void 0 : (ref1 = target.hasOwnProperty) === null || ref1 === void 0 ? void 0 : ref1.call(target, k1))) {
target[k1] = source[k1];
for (let k of Object.getOwnPropertySymbols(source)){
var _target_hasOwnProperty1;
if (!(target === null || target === void 0 ? void 0 : (_target_hasOwnProperty1 = target.hasOwnProperty) === null || _target_hasOwnProperty1 === void 0 ? void 0 : _target_hasOwnProperty1.call(target, k))) {
target[k] = source[k];
}

@@ -20,0 +25,0 @@ }

@@ -5,13 +5,11 @@ "use strict";

});
exports.default = escapeClassName;
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _escapeCommas = _interopRequireDefault(require("./escapeCommas"));
function escapeClassName(className) {
var ref;
let node = _postcssSelectorParser.default.className();
node.value = className;
var ref1;
return (0, _escapeCommas).default((ref1 = node === null || node === void 0 ? void 0 : (ref = node.raws) === null || ref === void 0 ? void 0 : ref.value) !== null && ref1 !== void 0 ? ref1 : node.value);
}
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return escapeClassName;
}
});
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
const _escapeCommas = /*#__PURE__*/ _interop_require_default(require("./escapeCommas"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -21,1 +19,8 @@ default: obj

}
function escapeClassName(className) {
var _node_raws;
let node = _postcssselectorparser.default.className();
node.value = className;
var _node_raws_value;
return (0, _escapeCommas.default)((_node_raws_value = node === null || node === void 0 ? void 0 : (_node_raws = node.raws) === null || _node_raws === void 0 ? void 0 : _node_raws.value) !== null && _node_raws_value !== void 0 ? _node_raws_value : node.value);
}

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

});
exports.default = escapeCommas;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return escapeCommas;
}
});
function escapeCommas(className) {
return className.replace(/\\,/g, "\\2c ");
}

@@ -5,14 +5,15 @@ "use strict";

});
exports.default = void 0;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return _default;
}
});
const flattenColorPalette = (colors)=>Object.assign({}, ...Object.entries(colors !== null && colors !== void 0 ? colors : {}).flatMap(([color, values])=>typeof values == "object" ? Object.entries(flattenColorPalette(values)).map(([number, hex])=>({
[color + (number === "DEFAULT" ? "" : `-${number}`)]: hex
})
) : [
})) : [
{
[`${color}`]: values
}
]
))
;
var _default = flattenColorPalette;
exports.default = _default;
]));
const _default = flattenColorPalette;

@@ -5,10 +5,29 @@ "use strict";

});
exports.formatVariantSelector = formatVariantSelector;
exports.finalizeSelector = finalizeSelector;
exports.selectorFunctions = void 0;
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _unesc = _interopRequireDefault(require("postcss-selector-parser/dist/util/unesc"));
var _escapeClassName = _interopRequireDefault(require("../util/escapeClassName"));
var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
formatVariantSelector: function() {
return formatVariantSelector;
},
eliminateIrrelevantSelectors: function() {
return eliminateIrrelevantSelectors;
},
finalizeSelector: function() {
return finalizeSelector;
},
handleMergePseudo: function() {
return handleMergePseudo;
}
});
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
const _unesc = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser/dist/util/unesc"));
const _escapeClassName = /*#__PURE__*/ _interop_require_default(require("../util/escapeClassName"));
const _prefixSelector = /*#__PURE__*/ _interop_require_default(require("../util/prefixSelector"));
const _pseudoElements = require("./pseudoElements");
const _splitAtTopLevelOnly = require("./splitAtTopLevelOnly");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -18,30 +37,101 @@ default: obj

}
let MERGE = ":merge";
let PARENT = "&";
let selectorFunctions = new Set([
MERGE
]);
exports.selectorFunctions = selectorFunctions;
function formatVariantSelector(current, ...others) {
for (let other of others){
let incomingValue = resolveFunctionArgument(other, MERGE);
if (incomingValue !== null) {
let existingValue = resolveFunctionArgument(current, MERGE, incomingValue);
if (existingValue !== null) {
let existingTarget = `${MERGE}(${incomingValue})`;
let splitIdx = other.indexOf(existingTarget);
let addition = other.slice(splitIdx + existingTarget.length).split(" ")[0];
current = current.replace(existingTarget, existingTarget + addition);
continue;
}
/** @typedef {import('postcss-selector-parser').Root} Root */ /** @typedef {import('postcss-selector-parser').Selector} Selector */ /** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */ /** @typedef {import('postcss-selector-parser').Node} Node */ /** @typedef {{format: string, respectPrefix: boolean}[]} RawFormats */ /** @typedef {import('postcss-selector-parser').Root} ParsedFormats */ /** @typedef {RawFormats | ParsedFormats} AcceptedFormats */ let MERGE = ":merge";
function formatVariantSelector(formats, { context , candidate }) {
var _context_tailwindConfig_prefix;
let prefix = (_context_tailwindConfig_prefix = context === null || context === void 0 ? void 0 : context.tailwindConfig.prefix) !== null && _context_tailwindConfig_prefix !== void 0 ? _context_tailwindConfig_prefix : "";
// Parse the format selector into an AST
let parsedFormats = formats.map((format)=>{
let ast = (0, _postcssselectorparser.default)().astSync(format.format);
return {
...format,
ast: format.respectPrefix ? (0, _prefixSelector.default)(prefix, ast) : ast
};
});
// We start with the candidate selector
let formatAst = _postcssselectorparser.default.root({
nodes: [
_postcssselectorparser.default.selector({
nodes: [
_postcssselectorparser.default.className({
value: (0, _escapeClassName.default)(candidate)
})
]
})
]
});
// And iteratively merge each format selector into the candidate selector
for (let { ast } of parsedFormats){
[formatAst, ast] = handleMergePseudo(formatAst, ast);
// 2. Merge the format selector into the current selector AST
ast.walkNesting((nesting)=>nesting.replaceWith(...formatAst.nodes[0].nodes));
// 3. Keep going!
formatAst = ast;
}
return formatAst;
}
/**
* Given any node in a selector this gets the "simple" selector it's a part of
* A simple selector is just a list of nodes without any combinators
* Technically :is(), :not(), :has(), etc… can have combinators but those are nested
* inside the relevant node and won't be picked up so they're fine to ignore
*
* @param {Node} node
* @returns {Node[]}
**/ function simpleSelectorForNode(node) {
/** @type {Node[]} */ let nodes = [];
// Walk backwards until we hit a combinator node (or the start)
while(node.prev() && node.prev().type !== "combinator"){
node = node.prev();
}
// Now record all non-combinator nodes until we hit one (or the end)
while(node && node.type !== "combinator"){
nodes.push(node);
node = node.next();
}
return nodes;
}
/**
* Resorts the nodes in a selector to ensure they're in the correct order
* Tags go before classes, and pseudo classes go after classes
*
* @param {Selector} sel
* @returns {Selector}
**/ function resortSelector(sel) {
sel.sort((a, b)=>{
if (a.type === "tag" && b.type === "class") {
return -1;
} else if (a.type === "class" && b.type === "tag") {
return 1;
} else if (a.type === "class" && b.type === "pseudo" && b.value.startsWith("::")) {
return -1;
} else if (a.type === "pseudo" && a.value.startsWith("::") && b.type === "class") {
return 1;
}
current = other.replace(PARENT, current);
return sel.index(a) - sel.index(b);
});
return sel;
}
function eliminateIrrelevantSelectors(sel, base) {
let hasClassesMatchingCandidate = false;
sel.walk((child)=>{
if (child.type === "class" && child.value === base) {
hasClassesMatchingCandidate = true;
return false // Stop walking
;
}
});
if (!hasClassesMatchingCandidate) {
sel.remove();
}
return current;
// We do NOT recursively eliminate sub selectors that don't have the base class
// as this is NOT a safe operation. For example, if we have:
// `.space-x-2 > :not([hidden]) ~ :not([hidden])`
// We cannot remove the [hidden] from the :not() because it would change the
// meaning of the selector.
// TODO: Can we do this for :matches, :is, and :where?
}
function finalizeSelector(format, { selector: selector1 , candidate , context }) {
var ref, ref1;
let ast = (0, _postcssSelectorParser).default().astSync(selector1);
var ref2;
let separator = (ref2 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref2 !== void 0 ? ref2 : ":";
function finalizeSelector(current, formats, { context , candidate , base }) {
var _context_tailwindConfig;
var _context_tailwindConfig_separator;
let separator = (_context_tailwindConfig_separator = context === null || context === void 0 ? void 0 : (_context_tailwindConfig = context.tailwindConfig) === null || _context_tailwindConfig === void 0 ? void 0 : _context_tailwindConfig.separator) !== null && _context_tailwindConfig_separator !== void 0 ? _context_tailwindConfig_separator : ":";
// Split by the separator, but ignore the separator inside square brackets:

@@ -54,19 +144,5 @@ //

//
let splitter = new RegExp(`\\${separator}(?![^[]*\\])`);
let base = candidate.split(splitter).pop();
if (context === null || context === void 0 ? void 0 : (ref1 = context.tailwindConfig) === null || ref1 === void 0 ? void 0 : ref1.prefix) {
format = (0, _prefixSelector).default(context.tailwindConfig.prefix, format);
}
format = format.replace(PARENT, `.${(0, _escapeClassName).default(candidate)}`);
let formatAst = (0, _postcssSelectorParser).default().astSync(format);
// Remove extraneous selectors that do not include the base class/candidate being matched against
// For example if we have a utility defined `.a, .b { color: red}`
// And the formatted variant is sm:b then we want the final selector to be `.sm\:b` and not `.a, .sm\:b`
ast.each((node)=>{
let hasClassesMatchingCandidate = node.some((n)=>n.type === "class" && n.value === base
);
if (!hasClassesMatchingCandidate) {
node.remove();
}
});
base = base !== null && base !== void 0 ? base : (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(candidate, separator).pop();
// Parse the selector into an AST
let selector = (0, _postcssselectorparser.default)().astSync(current);
// Normalize escaped classes, e.g.:

@@ -83,118 +159,116 @@ //

//
ast.walkClasses((node)=>{
selector.walkClasses((node)=>{
if (node.raws && node.value.includes(base)) {
node.raws.value = (0, _escapeClassName).default((0, _unesc).default(node.raws.value));
node.raws.value = (0, _escapeClassName.default)((0, _unesc.default)(node.raws.value));
}
});
// Remove extraneous selectors that do not include the base candidate
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
// so we can just return the selector as-is
let formatAst = Array.isArray(formats) ? formatVariantSelector(formats, {
context,
candidate
}) : formats;
if (formatAst === null) {
return selector.toString();
}
let simpleStart = _postcssselectorparser.default.comment({
value: "/*__simple__*/"
});
let simpleEnd = _postcssselectorparser.default.comment({
value: "/*__simple__*/"
});
// We can safely replace the escaped base now, since the `base` section is
// now in a normalized escaped value.
ast.walkClasses((node)=>{
if (node.value === base) {
node.replaceWith(...formatAst.nodes);
selector.walkClasses((node)=>{
if (node.value !== base) {
return;
}
let parent = node.parent;
let formatNodes = formatAst.nodes[0].nodes;
// Perf optimization: if the parent is a single class we can just replace it and be done
if (parent.nodes.length === 1) {
node.replaceWith(...formatNodes);
return;
}
let simpleSelector = simpleSelectorForNode(node);
parent.insertBefore(simpleSelector[0], simpleStart);
parent.insertAfter(simpleSelector[simpleSelector.length - 1], simpleEnd);
for (let child of formatNodes){
parent.insertBefore(simpleSelector[0], child.clone());
}
node.remove();
// Re-sort the simple selector to ensure it's in the correct order
simpleSelector = simpleSelectorForNode(simpleStart);
let firstNode = parent.index(simpleStart);
parent.nodes.splice(firstNode, simpleSelector.length, ...resortSelector(_postcssselectorparser.default.selector({
nodes: simpleSelector
})).nodes);
simpleStart.remove();
simpleEnd.remove();
});
// This will make sure to move pseudo's to the correct spot (the end for
// pseudo elements) because otherwise the selector will never work
// anyway.
//
// E.g.:
// - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
// - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
//
// `::before:hover` doesn't work, which means that we can make it work for you by flipping the order.
function collectPseudoElements(selector) {
let nodes = [];
for (let node of selector.nodes){
if (isPseudoElement(node)) {
nodes.push(node);
selector.removeChild(node);
}
if (node === null || node === void 0 ? void 0 : node.nodes) {
nodes.push(...collectPseudoElements(node));
}
}
return nodes;
}
// Remove unnecessary pseudo selectors that we used as placeholders
ast.each((selector)=>{
selector.walkPseudos((p)=>{
if (selectorFunctions.has(p.value)) {
p.replaceWith(p.nodes);
}
});
let pseudoElements = collectPseudoElements(selector);
if (pseudoElements.length > 0) {
selector.nodes.push(pseudoElements.sort(sortSelector));
selector.walkPseudos((p)=>{
if (p.value === MERGE) {
p.replaceWith(p.nodes);
}
});
return ast.toString();
// Move pseudo elements to the end of the selector (if necessary)
selector.each((sel)=>(0, _pseudoElements.movePseudos)(sel));
return selector.toString();
}
// Note: As a rule, double colons (::) should be used instead of a single colon
// (:). This distinguishes pseudo-classes from pseudo-elements. However, since
// this distinction was not present in older versions of the W3C spec, most
// browsers support both syntaxes for the original pseudo-elements.
let pseudoElementsBC = [
":before",
":after",
":first-line",
":first-letter"
];
// These pseudo-elements _can_ be combined with other pseudo selectors AND the order does matter.
let pseudoElementExceptions = [
"::file-selector-button"
];
// This will make sure to move pseudo's to the correct spot (the end for
// pseudo elements) because otherwise the selector will never work
// anyway.
//
// E.g.:
// - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
// - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
//
// `::before:hover` doesn't work, which means that we can make it work
// for you by flipping the order.
function sortSelector(a, z) {
// Both nodes are non-pseudo's so we can safely ignore them and keep
// them in the same order.
if (a.type !== "pseudo" && z.type !== "pseudo") {
return 0;
}
// If one of them is a combinator, we need to keep it in the same order
// because that means it will start a new "section" in the selector.
if (a.type === "combinator" ^ z.type === "combinator") {
return 0;
}
// One of the items is a pseudo and the other one isn't. Let's move
// the pseudo to the right.
if (a.type === "pseudo" ^ z.type === "pseudo") {
return (a.type === "pseudo") - (z.type === "pseudo");
}
// Both are pseudo's, move the pseudo elements (except for
// ::file-selector-button) to the right.
return isPseudoElement(a) - isPseudoElement(z);
}
function isPseudoElement(node) {
if (node.type !== "pseudo") return false;
if (pseudoElementExceptions.includes(node.value)) return false;
return node.value.startsWith("::") || pseudoElementsBC.includes(node.value);
}
function resolveFunctionArgument(haystack, needle, arg) {
let startIdx = haystack.indexOf(arg ? `${needle}(${arg})` : needle);
if (startIdx === -1) return null;
// Start inside the `(`
startIdx += needle.length + 1;
let target = "";
let count = 0;
for (let char of haystack.slice(startIdx)){
if (char !== "(" && char !== ")") {
target += char;
} else if (char === "(") {
target += char;
count++;
} else if (char === ")") {
if (--count < 0) break; // unbalanced
target += char;
function handleMergePseudo(selector, format) {
/** @type {{pseudo: Pseudo, value: string}[]} */ let merges = [];
// Find all :merge() pseudo-classes in `selector`
selector.walkPseudos((pseudo)=>{
if (pseudo.value === MERGE) {
merges.push({
pseudo,
value: pseudo.nodes[0].toString()
});
}
}
return target;
});
// Find all :merge() "attachments" in `format` and attach them to the matching selector in `selector`
format.walkPseudos((pseudo)=>{
if (pseudo.value !== MERGE) {
return;
}
let value = pseudo.nodes[0].toString();
// Does `selector` contain a :merge() pseudo-class with the same value?
let existing = merges.find((merge)=>merge.value === value);
// Nope so there's nothing to do
if (!existing) {
return;
}
// Everything after `:merge()` up to the next combinator is what is attached to the merged selector
let attachments = [];
let next = pseudo.next();
while(next && next.type !== "combinator"){
attachments.push(next);
next = next.next();
}
let combinator = next;
existing.pseudo.parent.insertAfter(existing.pseudo, _postcssselectorparser.default.selector({
nodes: attachments.map((node)=>node.clone())
}));
pseudo.remove();
attachments.forEach((node)=>node.remove());
// What about this case:
// :merge(.group):focus > &
// :merge(.group):hover &
if (combinator && combinator.type === "combinator") {
combinator.remove();
}
});
return [
selector,
format
];
}

@@ -5,16 +5,42 @@ "use strict";

});
exports.default = getAllConfigs;
var _defaultConfigStubJs = _interopRequireDefault(require("../../stubs/defaultConfig.stub.js"));
var _featureFlags = require("../featureFlags");
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return getAllConfigs;
}
});
const _configfull = /*#__PURE__*/ _interop_require_default(require("../../stubs/config.full.js"));
const _featureFlags = require("../featureFlags");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function getAllConfigs(config) {
var ref;
const configs = ((ref = config === null || config === void 0 ? void 0 : config.presets) !== null && ref !== void 0 ? ref : [
_defaultConfigStubJs.default
]).slice().reverse().flatMap((preset)=>getAllConfigs(preset instanceof Function ? preset() : preset)
);
var _config_presets;
const configs = ((_config_presets = config === null || config === void 0 ? void 0 : config.presets) !== null && _config_presets !== void 0 ? _config_presets : [
_configfull.default
]).slice().reverse().flatMap((preset)=>getAllConfigs(preset instanceof Function ? preset() : preset));
const features = {
// Add experimental configs here...
respectDefaultRingColorOpacity: {
theme: {
ringColor: ({ theme })=>({
DEFAULT: "#3b82f67f",
...theme("colors")
})
}
},
disableColorOpacityUtilitiesByDefault: {
corePlugins: {
backgroundOpacity: false,
borderOpacity: false,
divideOpacity: false,
placeholderOpacity: false,
ringOpacity: false,
textOpacity: false
}
}
};
const experimentals = Object.keys(features).filter((feature)=>(0, _featureFlags).flagEnabled(config, feature)
).map((feature)=>features[feature]
);
const experimentals = Object.keys(features).filter((feature)=>(0, _featureFlags.flagEnabled)(config, feature)).map((feature)=>features[feature]);
return [

@@ -26,6 +52,1 @@ config,

}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

@@ -5,13 +5,18 @@ "use strict";

});
exports.default = hashConfig;
var _objectHash = _interopRequireDefault(require("object-hash"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return hashConfig;
}
});
const _objecthash = /*#__PURE__*/ _interop_require_default(require("object-hash"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function hashConfig(config) {
return (0, _objectHash).default(config, {
return (0, _objecthash.default)(config, {
ignoreUnknown: true
});
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

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

});
exports.default = isKeyframeRule;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return isKeyframeRule;
}
});
function isKeyframeRule(rule) {
return rule.parent && rule.parent.type === "atrule" && /keyframes$/.test(rule.parent.name);
}

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

});
exports.default = isPlainObject;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return isPlainObject;
}
});
function isPlainObject(value) {

@@ -12,3 +17,3 @@ if (Object.prototype.toString.call(value) !== "[object Object]") {

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

@@ -5,6 +5,18 @@ "use strict";

});
exports.dim = dim;
exports.default = void 0;
var _picocolors = _interopRequireDefault(require("picocolors"));
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
dim: function() {
return dim;
},
default: function() {
return _default;
}
});
const _picocolors = /*#__PURE__*/ _interop_require_default(require("picocolors"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -16,8 +28,7 @@ default: obj

function log(type, messages, key) {
if (process.env.JEST_WORKER_ID !== undefined) return;
if (typeof process !== "undefined" && process.env.JEST_WORKER_ID) return;
if (key && alreadyShown.has(key)) return;
if (key) alreadyShown.add(key);
console.warn("");
messages.forEach((message)=>console.warn(type, "-", message)
);
messages.forEach((message)=>console.warn(type, "-", message));
}

@@ -27,3 +38,3 @@ function dim(input) {

}
var _default = {
const _default = {
info (key, messages) {

@@ -54,2 +65,1 @@ log(_picocolors.default.bold(_picocolors.default.cyan("info")), ...Array.isArray(key) ? [

};
exports.default = _default;

@@ -5,11 +5,22 @@ "use strict";

});
exports.default = nameClass;
exports.asClass = asClass;
exports.formatClass = formatClass;
var _escapeClassName = _interopRequireDefault(require("./escapeClassName"));
var _escapeCommas = _interopRequireDefault(require("./escapeCommas"));
function nameClass(classPrefix, key) {
return asClass(formatClass(classPrefix, key));
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
function _interopRequireDefault(obj) {
_export(exports, {
asClass: function() {
return asClass;
},
default: function() {
return nameClass;
},
formatClass: function() {
return formatClass;
}
});
const _escapeClassName = /*#__PURE__*/ _interop_require_default(require("./escapeClassName"));
const _escapeCommas = /*#__PURE__*/ _interop_require_default(require("./escapeCommas"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -20,4 +31,7 @@ default: obj

function asClass(name) {
return (0, _escapeCommas).default(`.${(0, _escapeClassName).default(name)}`);
return (0, _escapeCommas.default)(`.${(0, _escapeClassName.default)(name)}`);
}
function nameClass(classPrefix, key) {
return asClass(formatClass(classPrefix, key));
}
function formatClass(classPrefix, key) {

@@ -33,3 +47,6 @@ if (key === "DEFAULT") {

}
if (key.startsWith("/")) {
return `${classPrefix}${key}`;
}
return `${classPrefix}-${key}`;
}

@@ -5,4 +5,9 @@ "use strict";

});
exports.default = _default;
function _default(value) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return negateValue;
}
});
function negateValue(value) {
value = `${value}`;

@@ -14,8 +19,20 @@ if (value === "0") {

if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(value)) {
return value.replace(/^[+-]?/, (sign)=>sign === "-" ? "" : "-"
);
return value.replace(/^[+-]?/, (sign)=>sign === "-" ? "" : "-");
}
if (value.includes("var(") || value.includes("calc(")) {
return `calc(${value} * -1)`;
// What functions we support negating numeric values for
// var() isn't inherently a numeric function but we support it anyway
// The trigonometric functions are omitted because you'll need to use calc(…) with them _anyway_
// to produce generally useful results and that will be covered already
let numericFunctions = [
"var",
"calc",
"min",
"max",
"clamp"
];
for (const fn of numericFunctions){
if (value.includes(`${fn}(`)) {
return `calc(${value} * -1)`;
}
}
}

@@ -5,24 +5,48 @@ "use strict";

});
exports.normalizeConfig = normalizeConfig;
var _log = _interopRequireWildcard(require("./log"));
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
Object.defineProperty(exports, "normalizeConfig", {
enumerable: true,
get: function() {
return normalizeConfig;
}
});
const _featureFlags = require("../featureFlags");
const _log = /*#__PURE__*/ _interop_require_wildcard(require("./log"));
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}

@@ -74,9 +98,9 @@ function normalizeConfig(config) {

if (typeof config.content === "object" && config.content !== null) {
// Only `files`, `extract` and `transform` can exist in `config.content`
// Only `files`, `relative`, `extract`, and `transform` can exist in `config.content`
if (Object.keys(config.content).some((key)=>![
"files",
"relative",
"extract",
"transform"
].includes(key)
)) {
].includes(key))) {
return false;

@@ -120,2 +144,6 @@ }

}
// `config.content.relative` is optional and can be a boolean
if (typeof config.content.relative !== "boolean" && typeof config.content.relative !== "undefined") {
return false;
}
}

@@ -130,3 +158,3 @@ return true;

"Update your configuration file to eliminate this warning.",
"https://tailwindcss.com/docs/upgrade-guide#configure-content-sources",
"https://tailwindcss.com/docs/upgrade-guide#configure-content-sources"
]);

@@ -136,3 +164,3 @@ }

config.safelist = (()=>{
var ref;
var _purge_options;
let { content , purge , safelist } = config;

@@ -142,5 +170,19 @@ if (Array.isArray(safelist)) return safelist;

if (Array.isArray(purge === null || purge === void 0 ? void 0 : purge.safelist)) return purge.safelist;
if (Array.isArray(purge === null || purge === void 0 ? void 0 : (ref = purge.options) === null || ref === void 0 ? void 0 : ref.safelist)) return purge.options.safelist;
if (Array.isArray(purge === null || purge === void 0 ? void 0 : (_purge_options = purge.options) === null || _purge_options === void 0 ? void 0 : _purge_options.safelist)) return purge.options.safelist;
return [];
})();
// Normalize the `blocklist`
config.blocklist = (()=>{
let { blocklist } = config;
if (Array.isArray(blocklist)) {
if (blocklist.every((item)=>typeof item === "string")) {
return blocklist;
}
_log.default.warn("blocklist-invalid", [
"The `blocklist` option must be an array of strings.",
"https://tailwindcss.com/docs/content-configuration#discarding-classes"
]);
}
return [];
})();
// Normalize prefix option

@@ -151,11 +193,18 @@ if (typeof config.prefix === "function") {

"Update `prefix` in your configuration to be a string to eliminate this warning.",
"https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function",
"https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function"
]);
config.prefix = "";
} else {
var _prefix;
config.prefix = (_prefix = config.prefix) !== null && _prefix !== void 0 ? _prefix : "";
var _config_prefix;
config.prefix = (_config_prefix = config.prefix) !== null && _config_prefix !== void 0 ? _config_prefix : "";
}
// Normalize the `content`
config.content = {
relative: (()=>{
let { content } = config;
if (content === null || content === void 0 ? void 0 : content.relative) {
return content.relative;
}
return (0, _featureFlags.flagEnabled)(config, "relativeContentPathsByDefault");
})(),
files: (()=>{

@@ -172,9 +221,9 @@ let { content , purge } = config;

let extract = (()=>{
var ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9;
if ((ref = config.purge) === null || ref === void 0 ? void 0 : ref.extract) return config.purge.extract;
if ((ref1 = config.content) === null || ref1 === void 0 ? void 0 : ref1.extract) return config.content.extract;
if ((ref2 = config.purge) === null || ref2 === void 0 ? void 0 : (ref3 = ref2.extract) === null || ref3 === void 0 ? void 0 : ref3.DEFAULT) return config.purge.extract.DEFAULT;
if ((ref4 = config.content) === null || ref4 === void 0 ? void 0 : (ref5 = ref4.extract) === null || ref5 === void 0 ? void 0 : ref5.DEFAULT) return config.content.extract.DEFAULT;
if ((ref6 = config.purge) === null || ref6 === void 0 ? void 0 : (ref7 = ref6.options) === null || ref7 === void 0 ? void 0 : ref7.extractors) return config.purge.options.extractors;
if ((ref8 = config.content) === null || ref8 === void 0 ? void 0 : (ref9 = ref8.options) === null || ref9 === void 0 ? void 0 : ref9.extractors) return config.content.options.extractors;
var _config_purge, _config_content, _config_purge1, _config_purge_extract, _config_content1, _config_content_extract, _config_purge2, _config_purge_options, _config_content2, _config_content_options;
if ((_config_purge = config.purge) === null || _config_purge === void 0 ? void 0 : _config_purge.extract) return config.purge.extract;
if ((_config_content = config.content) === null || _config_content === void 0 ? void 0 : _config_content.extract) return config.content.extract;
if ((_config_purge1 = config.purge) === null || _config_purge1 === void 0 ? void 0 : (_config_purge_extract = _config_purge1.extract) === null || _config_purge_extract === void 0 ? void 0 : _config_purge_extract.DEFAULT) return config.purge.extract.DEFAULT;
if ((_config_content1 = config.content) === null || _config_content1 === void 0 ? void 0 : (_config_content_extract = _config_content1.extract) === null || _config_content_extract === void 0 ? void 0 : _config_content_extract.DEFAULT) return config.content.extract.DEFAULT;
if ((_config_purge2 = config.purge) === null || _config_purge2 === void 0 ? void 0 : (_config_purge_options = _config_purge2.options) === null || _config_purge_options === void 0 ? void 0 : _config_purge_options.extractors) return config.purge.options.extractors;
if ((_config_content2 = config.content) === null || _config_content2 === void 0 ? void 0 : (_config_content_options = _config_content2.options) === null || _config_content_options === void 0 ? void 0 : _config_content_options.extractors) return config.content.options.extractors;
return {};

@@ -184,7 +233,7 @@ })();

let defaultExtractor = (()=>{
var ref, ref10, ref11, ref12;
if ((ref = config.purge) === null || ref === void 0 ? void 0 : (ref10 = ref.options) === null || ref10 === void 0 ? void 0 : ref10.defaultExtractor) {
var _config_purge, _config_purge_options, _config_content, _config_content_options;
if ((_config_purge = config.purge) === null || _config_purge === void 0 ? void 0 : (_config_purge_options = _config_purge.options) === null || _config_purge_options === void 0 ? void 0 : _config_purge_options.defaultExtractor) {
return config.purge.options.defaultExtractor;
}
if ((ref11 = config.content) === null || ref11 === void 0 ? void 0 : (ref12 = ref11.options) === null || ref12 === void 0 ? void 0 : ref12.defaultExtractor) {
if ((_config_content = config.content) === null || _config_content === void 0 ? void 0 : (_config_content_options = _config_content.options) === null || _config_content_options === void 0 ? void 0 : _config_content_options.defaultExtractor) {
return config.content.options.defaultExtractor;

@@ -213,7 +262,7 @@ }

let transform = (()=>{
var ref, ref13, ref14, ref15, ref16, ref17;
if ((ref = config.purge) === null || ref === void 0 ? void 0 : ref.transform) return config.purge.transform;
if ((ref13 = config.content) === null || ref13 === void 0 ? void 0 : ref13.transform) return config.content.transform;
if ((ref14 = config.purge) === null || ref14 === void 0 ? void 0 : (ref15 = ref14.transform) === null || ref15 === void 0 ? void 0 : ref15.DEFAULT) return config.purge.transform.DEFAULT;
if ((ref16 = config.content) === null || ref16 === void 0 ? void 0 : (ref17 = ref16.transform) === null || ref17 === void 0 ? void 0 : ref17.DEFAULT) return config.content.transform.DEFAULT;
var _config_purge, _config_content, _config_purge1, _config_purge_transform, _config_content1, _config_content_transform;
if ((_config_purge = config.purge) === null || _config_purge === void 0 ? void 0 : _config_purge.transform) return config.purge.transform;
if ((_config_content = config.content) === null || _config_content === void 0 ? void 0 : _config_content.transform) return config.content.transform;
if ((_config_purge1 = config.purge) === null || _config_purge1 === void 0 ? void 0 : (_config_purge_transform = _config_purge1.transform) === null || _config_purge_transform === void 0 ? void 0 : _config_purge_transform.DEFAULT) return config.purge.transform.DEFAULT;
if ((_config_content1 = config.content) === null || _config_content1 === void 0 ? void 0 : (_config_content_transform = _config_content1.transform) === null || _config_content_transform === void 0 ? void 0 : _config_content_transform.DEFAULT) return config.content.transform.DEFAULT;
return {};

@@ -224,4 +273,3 @@ })();

transformers.DEFAULT = transform;
}
if (typeof transform === "object" && transform !== null) {
} else if (typeof transform === "object" && transform !== null) {
Object.assign(transformers, transform);

@@ -237,4 +285,4 @@ }

_log.default.warn("invalid-glob-braces", [
`The glob pattern ${(0, _log).dim(file)} in your Tailwind CSS configuration is invalid.`,
`Update it to ${(0, _log).dim(file.replace(/{([^,]*?)}/g, "$1"))} to silence this warning.`
`The glob pattern ${(0, _log.dim)(file)} in your Tailwind CSS configuration is invalid.`,
`Update it to ${(0, _log.dim)(file.replace(/{([^,]*?)}/g, "$1"))} to silence this warning.`
]);

@@ -241,0 +289,0 @@ break;

@@ -1,6 +0,49 @@

"use strict";
/**
* @typedef {object} ScreenValue
* @property {number|undefined} min
* @property {number|undefined} max
* @property {string|undefined} raw
*/ /**
* @typedef {object} Screen
* @property {string} name
* @property {boolean} not
* @property {ScreenValue[]} values
*/ /**
* A function that normalizes the various forms that the screens object can be
* provided in.
*
* Input(s):
* - ['100px', '200px'] // Raw strings
* - { sm: '100px', md: '200px' } // Object with string values
* - { sm: { min: '100px' }, md: { max: '100px' } } // Object with object values
* - { sm: [{ min: '100px' }, { max: '200px' }] } // Object with object array (multiple values)
*
* Output(s):
* - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
*
* @returns {Screen[]}
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.normalizeScreens = normalizeScreens;
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
normalizeScreens: function() {
return normalizeScreens;
},
isScreenSortable: function() {
return isScreenSortable;
},
compareScreens: function() {
return compareScreens;
},
toScreen: function() {
return toScreen;
}
});
function normalizeScreens(screens, root = true) {

@@ -15,2 +58,3 @@ if (Array.isArray(screens)) {

name: screen.toString(),
not: false,
values: [

@@ -29,2 +73,3 @@ {

name,
not: false,
values: [

@@ -41,4 +86,4 @@ {

name,
values: options.map((option)=>resolveValue(option)
)
not: false,
values: options.map((option)=>resolveValue(option))
};

@@ -48,2 +93,3 @@ }

name,
not: false,
values: [

@@ -57,2 +103,75 @@ resolveValue(options)

}
function isScreenSortable(screen) {
if (screen.values.length !== 1) {
return {
result: false,
reason: "multiple-values"
};
} else if (screen.values[0].raw !== undefined) {
return {
result: false,
reason: "raw-values"
};
} else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) {
return {
result: false,
reason: "min-and-max"
};
}
return {
result: true,
reason: null
};
}
function compareScreens(type, a, z) {
let aScreen = toScreen(a, type);
let zScreen = toScreen(z, type);
let aSorting = isScreenSortable(aScreen);
let bSorting = isScreenSortable(zScreen);
// These cases should never happen and indicate a bug in Tailwind CSS itself
if (aSorting.reason === "multiple-values" || bSorting.reason === "multiple-values") {
throw new Error("Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.");
} else if (aSorting.reason === "raw-values" || bSorting.reason === "raw-values") {
throw new Error("Attempted to sort a screen with raw values. This should never happen. Please open a bug report.");
} else if (aSorting.reason === "min-and-max" || bSorting.reason === "min-and-max") {
throw new Error("Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.");
}
// Let the sorting begin
let { min: aMin , max: aMax } = aScreen.values[0];
let { min: zMin , max: zMax } = zScreen.values[0];
// Negating screens flip their behavior. Basically `not min-width` is `max-width`
if (a.not) [aMin, aMax] = [
aMax,
aMin
];
if (z.not) [zMin, zMax] = [
zMax,
zMin
];
aMin = aMin === undefined ? aMin : parseFloat(aMin);
aMax = aMax === undefined ? aMax : parseFloat(aMax);
zMin = zMin === undefined ? zMin : parseFloat(zMin);
zMax = zMax === undefined ? zMax : parseFloat(zMax);
let [aValue, zValue] = type === "min" ? [
aMin,
zMin
] : [
zMax,
aMax
];
return aValue - zValue;
}
function toScreen(value, type) {
if (typeof value === "object") {
return value;
}
return {
name: "arbitrary-screen",
values: [
{
[type]: value
}
]
};
}
function resolveValue({ "min-width": _minWidth , min =_minWidth , max , raw } = {}) {

@@ -59,0 +178,0 @@ return {

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

});
exports.default = parseAnimationValue;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return parseAnimationValue;
}
});
const DIRECTIONS = new Set([
"normal",
"reverse",
"alternate",
"alternate-reverse"
]);
const PLAY_STATES = new Set([
"running",
"paused"
]);
const FILL_MODES = new Set([
"none",
"forwards",
"backwards",
"both"
]);
const ITERATION_COUNTS = new Set([
"infinite"
]);
const TIMINGS = new Set([
"linear",
"ease",
"ease-in",
"ease-out",
"ease-in-out",
"step-start",
"step-end"
]);
const TIMING_FNS = [
"cubic-bezier",
"steps"
];
const COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubic-bezier(a, b, c)` these don't count.
;
const SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
;
const TIME = /^(-?[\d.]+m?s)$/;
const DIGIT = /^(\d+)$/;
function parseAnimationValue(input) {

@@ -32,4 +75,3 @@ let animations = input.split(COMMA);

seen.add("TIMING_FUNCTION");
} else if (!seen.has("TIMING_FUNCTION") && TIMING_FNS.some((f)=>part.startsWith(`${f}(`)
)) {
} else if (!seen.has("TIMING_FUNCTION") && TIMING_FNS.some((f)=>part.startsWith(`${f}(`))) {
result.timingFunction = part;

@@ -54,39 +96,1 @@ seen.add("TIMING_FUNCTION");

}
const DIRECTIONS = new Set([
"normal",
"reverse",
"alternate",
"alternate-reverse"
]);
const PLAY_STATES = new Set([
"running",
"paused"
]);
const FILL_MODES = new Set([
"none",
"forwards",
"backwards",
"both"
]);
const ITERATION_COUNTS = new Set([
"infinite"
]);
const TIMINGS = new Set([
"linear",
"ease",
"ease-in",
"ease-out",
"ease-in-out",
"step-start",
"step-end",
]);
const TIMING_FNS = [
"cubic-bezier",
"steps"
];
const COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
;
const SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
;
const TIME = /^(-?[\d.]+m?s)$/;
const DIGIT = /^(\d+)$/;

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

});
exports.parseBoxShadowValue = parseBoxShadowValue;
exports.formatBoxShadowValue = formatBoxShadowValue;
var _splitAtTopLevelOnly = require("./splitAtTopLevelOnly");
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
parseBoxShadowValue: function() {
return parseBoxShadowValue;
},
formatBoxShadowValue: function() {
return formatBoxShadowValue;
}
});
const _splitAtTopLevelOnly = require("./splitAtTopLevelOnly");
let KEYWORDS = new Set([

@@ -20,3 +32,3 @@ "inset",

function parseBoxShadowValue(input) {
let shadows = Array.from((0, _splitAtTopLevelOnly).splitAtTopLevelOnly(input, ","));
let shadows = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(input, ",");
return shadows.map((shadow)=>{

@@ -23,0 +35,0 @@ let value = shadow.trim();

@@ -1,63 +0,47 @@

"use strict";
// @ts-check
/**
* @typedef {{type: 'dependency', file: string} | {type: 'dir-dependency', dir: string, glob: string}} Dependency
*/ /**
*
* @param {import('../lib/content.js').ContentPath} contentPath
* @returns {Dependency[]}
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = parseDependency;
var _isGlob = _interopRequireDefault(require("is-glob"));
var _globParent = _interopRequireDefault(require("glob-parent"));
var _path = _interopRequireDefault(require("path"));
function parseDependency(normalizedFileOrGlob) {
if (normalizedFileOrGlob.startsWith("!")) {
return null;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return parseDependency;
}
let message;
if ((0, _isGlob).default(normalizedFileOrGlob)) {
let { base , glob } = parseGlob(normalizedFileOrGlob);
message = {
type: "dir-dependency",
dir: _path.default.resolve(base),
glob
};
} else {
message = {
type: "dependency",
file: _path.default.resolve(normalizedFileOrGlob)
};
});
function parseDependency(contentPath) {
if (contentPath.ignore) {
return [];
}
// rollup-plugin-postcss does not support dir-dependency messages
// but directories can be watched in the same way as files
if (message.type === "dir-dependency" && process.env.ROLLUP_WATCH === "true") {
message = {
type: "dependency",
file: message.dir
};
if (!contentPath.glob) {
return [
{
type: "dependency",
file: contentPath.base
}
];
}
return message;
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
// Based on `glob-base`
// https://github.com/micromatch/glob-base/blob/master/index.js
function parseGlob(pattern) {
let glob = pattern;
let base = (0, _globParent).default(pattern);
if (base !== ".") {
glob = pattern.substr(base.length);
if (glob.charAt(0) === "/") {
glob = glob.substr(1);
if (process.env.ROLLUP_WATCH === "true") {
// rollup-plugin-postcss does not support dir-dependency messages
// but directories can be watched in the same way as files
return [
{
type: "dependency",
file: contentPath.base
}
];
}
return [
{
type: "dir-dependency",
dir: contentPath.base,
glob: contentPath.glob
}
}
if (glob.substr(0, 2) === "./") {
glob = glob.substr(2);
}
if (glob.charAt(0) === "/") {
glob = glob.substr(1);
}
return {
base,
glob
};
];
}

@@ -5,6 +5,16 @@ "use strict";

});
exports.default = parseObjectStyles;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcssNested = _interopRequireDefault(require("postcss-nested"));
var _postcssJs = _interopRequireDefault(require("postcss-js"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return parseObjectStyles;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _postcssnested = /*#__PURE__*/ _interop_require_default(require("postcss-nested"));
const _postcssjs = /*#__PURE__*/ _interop_require_default(require("postcss-js"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function parseObjectStyles(styles) {

@@ -17,17 +27,12 @@ if (!Array.isArray(styles)) {

return styles.flatMap((style)=>{
return (0, _postcss).default([
(0, _postcssNested).default({
return (0, _postcss.default)([
(0, _postcssnested.default)({
bubble: [
"screen"
]
}),
})
]).process(style, {
parser: _postcssJs.default
parser: _postcssjs.default
}).root.nodes;
});
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

@@ -5,13 +5,41 @@ "use strict";

});
exports.updateAllClasses = updateAllClasses;
exports.asValue = asValue;
exports.asColor = asColor;
exports.asLookupValue = asLookupValue;
exports.coerceValue = coerceValue;
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
var _escapeCommas = _interopRequireDefault(require("./escapeCommas"));
var _withAlphaVariable = require("./withAlphaVariable");
var _dataTypes = require("./dataTypes");
var _negateValue = _interopRequireDefault(require("./negateValue"));
function _interopRequireDefault(obj) {
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
updateAllClasses: function() {
return updateAllClasses;
},
asValue: function() {
return asValue;
},
parseColorFormat: function() {
return parseColorFormat;
},
asColor: function() {
return asColor;
},
asLookupValue: function() {
return asLookupValue;
},
typeMap: function() {
return typeMap;
},
coerceValue: function() {
return coerceValue;
},
getMatchingTypes: function() {
return getMatchingTypes;
}
});
const _escapeCommas = /*#__PURE__*/ _interop_require_default(require("./escapeCommas"));
const _withAlphaVariable = require("./withAlphaVariable");
const _dataTypes = require("./dataTypes");
const _negateValue = /*#__PURE__*/ _interop_require_default(require("./negateValue"));
const _validateFormalSyntax = require("./validateFormalSyntax");
const _featureFlags = require("../featureFlags.js");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -21,14 +49,9 @@ default: obj

}
function updateAllClasses(selectors1, updateClass) {
let parser = (0, _postcssSelectorParser).default((selectors)=>{
selectors.walkClasses((sel)=>{
let updatedClass = updateClass(sel.value);
sel.value = updatedClass;
if (sel.raws && sel.raws.value) {
sel.raws.value = (0, _escapeCommas).default(sel.raws.value);
}
});
function updateAllClasses(selectors, updateClass) {
selectors.walkClasses((sel)=>{
sel.value = updateClass(sel.value);
if (sel.raws && sel.raws.value) {
sel.raws.value = (0, _escapeCommas.default)(sel.raws.value);
}
});
let result = parser.processSync(selectors1);
return result;
}

@@ -43,3 +66,3 @@ function resolveArbitraryValue(modifier, validate) {

}
return (0, _dataTypes).normalize(value);
return (0, _dataTypes.normalize)(value);
}

@@ -49,3 +72,3 @@ function asNegativeValue(modifier, lookup = {}, validate) {

if (positiveValue !== undefined) {
return (0, _negateValue).default(positiveValue);
return (0, _negateValue.default)(positiveValue);
}

@@ -57,9 +80,8 @@ if (isArbitraryValue(modifier)) {

}
return (0, _negateValue).default(resolved);
return (0, _negateValue.default)(resolved);
}
}
function asValue(modifier, options = {}, { validate =()=>true
} = {}) {
var ref;
let value = (ref = options.values) === null || ref === void 0 ? void 0 : ref[modifier];
function asValue(modifier, options = {}, { validate =()=>true } = {}) {
var _options_values;
let value = (_options_values = options.values) === null || _options_values === void 0 ? void 0 : _options_values[modifier];
if (value !== undefined) {

@@ -76,9 +98,33 @@ return value;

}
function splitAlpha(modifier) {
function splitUtilityModifier(modifier) {
let slashIdx = modifier.lastIndexOf("/");
// If the `/` is inside an arbitrary, we want to find the previous one if any
// This logic probably isn't perfect but it should work for most cases
let arbitraryStartIdx = modifier.lastIndexOf("[", slashIdx);
let arbitraryEndIdx = modifier.indexOf("]", slashIdx);
let isNextToArbitrary = modifier[slashIdx - 1] === "]" || modifier[slashIdx + 1] === "[";
// Backtrack to the previous `/` if the one we found was inside an arbitrary
if (!isNextToArbitrary) {
if (arbitraryStartIdx !== -1 && arbitraryEndIdx !== -1) {
if (arbitraryStartIdx < slashIdx && slashIdx < arbitraryEndIdx) {
slashIdx = modifier.lastIndexOf("/", arbitraryStartIdx);
}
}
}
if (slashIdx === -1 || slashIdx === modifier.length - 1) {
return [
modifier
modifier,
undefined
];
}
let arbitrary = isArbitraryValue(modifier);
// The modifier could be of the form `[foo]/[bar]`
// We want to handle this case properly
// without affecting `[foo/bar]`
if (arbitrary && !modifier.includes("]/[")) {
return [
modifier,
undefined
];
}
return [

@@ -89,23 +135,36 @@ modifier.slice(0, slashIdx),

}
function parseColorFormat(value) {
if (typeof value === "string" && value.includes("<alpha-value>")) {
let oldValue = value;
return ({ opacityValue =1 })=>oldValue.replace(/<alpha-value>/g, opacityValue);
}
return value;
}
function unwrapArbitraryModifier(modifier) {
return (0, _dataTypes.normalize)(modifier.slice(1, -1));
}
function asColor(modifier, options = {}, { tailwindConfig ={} } = {}) {
var ref;
if (((ref = options.values) === null || ref === void 0 ? void 0 : ref[modifier]) !== undefined) {
var ref1;
return (ref1 = options.values) === null || ref1 === void 0 ? void 0 : ref1[modifier];
var _options_values;
if (((_options_values = options.values) === null || _options_values === void 0 ? void 0 : _options_values[modifier]) !== undefined) {
var _options_values1;
return parseColorFormat((_options_values1 = options.values) === null || _options_values1 === void 0 ? void 0 : _options_values1[modifier]);
}
let [color, alpha] = splitAlpha(modifier);
// TODO: Hoist this up to getMatchingTypes or something
// We do this here because we need the alpha value (if any)
let [color, alpha] = splitUtilityModifier(modifier);
if (alpha !== undefined) {
var ref2, ref3, ref4;
var ref5;
let normalizedColor = (ref5 = (ref2 = options.values) === null || ref2 === void 0 ? void 0 : ref2[color]) !== null && ref5 !== void 0 ? ref5 : isArbitraryValue(color) ? color.slice(1, -1) : undefined;
var _options_values2, _tailwindConfig_theme, _tailwindConfig_theme_opacity;
var _options_values_color;
let normalizedColor = (_options_values_color = (_options_values2 = options.values) === null || _options_values2 === void 0 ? void 0 : _options_values2[color]) !== null && _options_values_color !== void 0 ? _options_values_color : isArbitraryValue(color) ? color.slice(1, -1) : undefined;
if (normalizedColor === undefined) {
return undefined;
}
normalizedColor = parseColorFormat(normalizedColor);
if (isArbitraryValue(alpha)) {
return (0, _withAlphaVariable).withAlphaValue(normalizedColor, alpha.slice(1, -1));
return (0, _withAlphaVariable.withAlphaValue)(normalizedColor, unwrapArbitraryModifier(alpha));
}
if (((ref3 = tailwindConfig.theme) === null || ref3 === void 0 ? void 0 : (ref4 = ref3.opacity) === null || ref4 === void 0 ? void 0 : ref4[alpha]) === undefined) {
if (((_tailwindConfig_theme = tailwindConfig.theme) === null || _tailwindConfig_theme === void 0 ? void 0 : (_tailwindConfig_theme_opacity = _tailwindConfig_theme.opacity) === null || _tailwindConfig_theme_opacity === void 0 ? void 0 : _tailwindConfig_theme_opacity[alpha]) === undefined) {
return undefined;
}
return (0, _withAlphaVariable).withAlphaValue(normalizedColor, tailwindConfig.theme.opacity[alpha]);
return (0, _withAlphaVariable.withAlphaValue)(normalizedColor, tailwindConfig.theme.opacity[alpha]);
}

@@ -117,4 +176,4 @@ return asValue(modifier, options, {

function asLookupValue(modifier, options = {}) {
var ref;
return (ref = options.values) === null || ref === void 0 ? void 0 : ref[modifier];
var _options_values;
return (_options_values = options.values) === null || _options_values === void 0 ? void 0 : _options_values[modifier];
}

@@ -143,3 +202,4 @@ function guess(validate) {

"relative-size": guess(_dataTypes.relativeSize),
shadow: guess(_dataTypes.shadow)
shadow: guess(_dataTypes.shadow),
size: guess(_validateFormalSyntax.backgroundSize)
};

@@ -159,2 +219,17 @@ let supportedTypes = Object.keys(typeMap);

function coerceValue(types, modifier, options, tailwindConfig) {
if (options.values && modifier in options.values) {
for (let { type } of types !== null && types !== void 0 ? types : []){
let result = typeMap[type](modifier, options, {
tailwindConfig
});
if (result === undefined) {
continue;
}
return [
result,
type,
null
];
}
}
if (isArbitraryValue(modifier)) {

@@ -174,17 +249,52 @@ let arbitraryValue = modifier.slice(1, -1);

asValue(`[${value}]`, options),
explicitType
explicitType,
null
];
}
}
let matches = getMatchingTypes(types, modifier, options, tailwindConfig);
// Find first matching type
for (let type of [].concat(types)){
for (let match of matches){
return match;
}
return [];
}
function* getMatchingTypes(types, rawModifier, options, tailwindConfig) {
let modifiersEnabled = (0, _featureFlags.flagEnabled)(tailwindConfig, "generalizedModifiers");
let [modifier, utilityModifier] = splitUtilityModifier(rawModifier);
let canUseUtilityModifier = modifiersEnabled && options.modifiers != null && (options.modifiers === "any" || typeof options.modifiers === "object" && (utilityModifier && isArbitraryValue(utilityModifier) || utilityModifier in options.modifiers));
if (!canUseUtilityModifier) {
modifier = rawModifier;
utilityModifier = undefined;
}
if (utilityModifier !== undefined && modifier === "") {
modifier = "DEFAULT";
}
// Check the full value first
// TODO: Move to asValue… somehow
if (utilityModifier !== undefined) {
if (typeof options.modifiers === "object") {
var _options_modifiers;
var _options_modifiers_utilityModifier;
let configValue = (_options_modifiers_utilityModifier = (_options_modifiers = options.modifiers) === null || _options_modifiers === void 0 ? void 0 : _options_modifiers[utilityModifier]) !== null && _options_modifiers_utilityModifier !== void 0 ? _options_modifiers_utilityModifier : null;
if (configValue !== null) {
utilityModifier = configValue;
} else if (isArbitraryValue(utilityModifier)) {
utilityModifier = unwrapArbitraryModifier(utilityModifier);
}
}
}
for (let { type } of types !== null && types !== void 0 ? types : []){
let result = typeMap[type](modifier, options, {
tailwindConfig
});
if (result !== undefined) return [
if (result === undefined) {
continue;
}
yield [
result,
type
type,
utilityModifier !== null && utilityModifier !== void 0 ? utilityModifier : null
];
}
return [];
}

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

});
exports.default = _default;
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, /**
* @template {string | import('postcss-selector-parser').Root} T
*
* Prefix all classes in the selector with the given prefix
*
* It can take either a string or a selector AST and will return the same type
*
* @param {string} prefix
* @param {T} selector
* @param {boolean} prependNegative
* @returns {T}
*/ "default", {
enumerable: true,
get: function() {
return _default;
}
});
const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -14,9 +30,12 @@ default: obj

function _default(prefix, selector, prependNegative = false) {
return (0, _postcssSelectorParser).default((selectors)=>{
selectors.walkClasses((classSelector)=>{
let baseClass = classSelector.value;
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith("-");
classSelector.value = shouldPlaceNegativeBeforePrefix ? `-${prefix}${baseClass.slice(1)}` : `${prefix}${baseClass}`;
});
}).processSync(selector);
if (prefix === "") {
return selector;
}
/** @type {import('postcss-selector-parser').Root} */ let ast = typeof selector === "string" ? (0, _postcssselectorparser.default)().astSync(selector) : selector;
ast.walkClasses((classSelector)=>{
let baseClass = classSelector.value;
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith("-");
classSelector.value = shouldPlaceNegativeBeforePrefix ? `-${prefix}${baseClass.slice(1)}` : `${prefix}${baseClass}`;
});
return typeof selector === "string" ? ast.toString() : ast;
}

@@ -5,36 +5,21 @@ "use strict";

});
exports.default = resolveConfig;
var _negateValue = _interopRequireDefault(require("./negateValue"));
var _corePluginList = _interopRequireDefault(require("../corePluginList"));
var _configurePlugins = _interopRequireDefault(require("./configurePlugins"));
var _defaultConfigStub = _interopRequireDefault(require("../../stubs/defaultConfig.stub"));
var _colors = _interopRequireDefault(require("../public/colors"));
var _defaults = require("./defaults");
var _toPath = require("./toPath");
var _normalizeConfig = require("./normalizeConfig");
var _isPlainObject = _interopRequireDefault(require("./isPlainObject"));
var _cloneDeep = require("./cloneDeep");
function resolveConfig(configs) {
let allConfigs = [
...extractPluginConfigs(configs),
{
prefix: "",
important: false,
separator: ":",
variantOrder: _defaultConfigStub.default.variantOrder
},
];
var ref, ref1;
return (0, _normalizeConfig).normalizeConfig((0, _defaults).defaults({
theme: resolveFunctionKeys(mergeExtensions(mergeThemes(allConfigs.map((t)=>{
return (ref = t === null || t === void 0 ? void 0 : t.theme) !== null && ref !== void 0 ? ref : {};
})))),
corePlugins: resolveCorePlugins(allConfigs.map((c)=>c.corePlugins
)),
plugins: resolvePluginLists(configs.map((c)=>{
return (ref1 = c === null || c === void 0 ? void 0 : c.plugins) !== null && ref1 !== void 0 ? ref1 : [];
}))
}, ...allConfigs));
}
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return resolveConfig;
}
});
const _negateValue = /*#__PURE__*/ _interop_require_default(require("./negateValue"));
const _corePluginList = /*#__PURE__*/ _interop_require_default(require("../corePluginList"));
const _configurePlugins = /*#__PURE__*/ _interop_require_default(require("./configurePlugins"));
const _colors = /*#__PURE__*/ _interop_require_default(require("../public/colors"));
const _defaults = require("./defaults");
const _toPath = require("./toPath");
const _normalizeConfig = require("./normalizeConfig");
const _isPlainObject = /*#__PURE__*/ _interop_require_default(require("./isPlainObject"));
const _cloneDeep = require("./cloneDeep");
const _pluginUtils = require("./pluginUtils");
const _withAlphaVariable = require("./withAlphaVariable");
const _toColorValue = /*#__PURE__*/ _interop_require_default(require("./toColorValue"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -47,5 +32,2 @@ default: obj

}
function isObject(input) {
return typeof input === "object" && input !== null;
}
function mergeWith(target, ...sources) {

@@ -57,4 +39,4 @@ let customizer = sources.pop();

if (merged === undefined) {
if (isObject(target[k]) && isObject(source[k])) {
target[k] = mergeWith(target[k], source[k], customizer);
if ((0, _isPlainObject.default)(target[k]) && (0, _isPlainObject.default)(source[k])) {
target[k] = mergeWith({}, target[k], source[k], customizer);
} else {

@@ -74,5 +56,4 @@ target[k] = source[k];

// TODO: Log that this function isn't really needed anymore?
return Object.keys(scale).filter((key)=>scale[key] !== "0"
).reduce((negativeScale, key)=>{
let negativeValue = (0, _negateValue).default(scale[key]);
return Object.keys(scale).filter((key)=>scale[key] !== "0").reduce((negativeScale, key)=>{
let negativeValue = (0, _negateValue.default)(scale[key]);
if (negativeValue !== undefined) {

@@ -85,30 +66,6 @@ negativeScale[`-${key}`] = negativeValue;

breakpoints (screens) {
return Object.keys(screens).filter((key)=>typeof screens[key] === "string"
).reduce((breakpoints, key)=>({
return Object.keys(screens).filter((key)=>typeof screens[key] === "string").reduce((breakpoints, key)=>({
...breakpoints,
[`screen-${key}`]: screens[key]
})
, {});
},
rgb (property) {
if (!property.startsWith("--")) {
throw new Error("The rgb() helper requires a custom property name to be passed as the first argument.");
}
return ({ opacityValue })=>{
if (opacityValue === undefined || opacityValue === 1) {
return `rgb(var(${property}) / 1.0)`;
}
return `rgb(var(${property}) / ${opacityValue})`;
};
},
hsl (property) {
if (!property.startsWith("--")) {
throw new Error("The hsl() helper requires a custom property name to be passed as the first argument.");
}
return ({ opacityValue })=>{
if (opacityValue === undefined || opacityValue === 1) {
return `hsl(var(${property}) / 1)`;
}
return `hsl(var(${property}) / ${opacityValue})`;
};
}), {});
}

@@ -142,4 +99,3 @@ };

return {
...themes.reduce((merged, theme)=>(0, _defaults).defaults(merged, theme)
, {}),
...themes.reduce((merged, theme)=>(0, _defaults.defaults)(merged, theme), {}),
// In order to resolve n config objects, we combine all of their `extend` properties

@@ -150,17 +106,17 @@ // into arrays instead of objects so they aren't overridden.

}
function mergeExtensionCustomizer(merged, value1) {
function mergeExtensionCustomizer(merged, value) {
// When we have an array of objects, we do want to merge it
if (Array.isArray(merged) && isObject(merged[0])) {
return merged.concat(value1);
if (Array.isArray(merged) && (0, _isPlainObject.default)(merged[0])) {
return merged.concat(value);
}
// When the incoming value is an array, and the existing config is an object, prepend the existing object
if (Array.isArray(value1) && isObject(value1[0]) && isObject(merged)) {
if (Array.isArray(value) && (0, _isPlainObject.default)(value[0]) && (0, _isPlainObject.default)(merged)) {
return [
merged,
...value1
...value
];
}
// Override arrays (for example for font-families, box-shadows, ...)
if (Array.isArray(value1)) {
return value1;
if (Array.isArray(value)) {
return value;
}

@@ -179,33 +135,58 @@ // Execute default behaviour

...extensions
].map((e)=>value(e, resolveThemePath, utils)
), mergeExtensionCustomizer)
;
].map((e)=>value(e, resolveThemePath, utils)), mergeExtensionCustomizer);
});
}
/**
*
* @param {string} key
* @return {Iterable<string[] & {alpha: string | undefined}>}
*/ function* toPaths(key) {
let path = (0, _toPath.toPath)(key);
if (path.length === 0) {
return;
}
yield path;
if (Array.isArray(key)) {
return;
}
let pattern = /^(.*?)\s*\/\s*([^/]+)$/;
let matches = key.match(pattern);
if (matches !== null) {
let [, prefix, alpha] = matches;
let newPath = (0, _toPath.toPath)(prefix);
newPath.alpha = alpha;
yield newPath;
}
}
function resolveFunctionKeys(object) {
// theme('colors.red.500 / 0.5') -> ['colors', 'red', '500 / 0', '5]
const resolvePath = (key, defaultValue)=>{
const path = (0, _toPath).toPath(key);
let index = 0;
let val = object;
while(val !== undefined && val !== null && index < path.length){
val = val[path[index++]];
val = isFunction(val) ? val(resolvePath, configUtils) : val;
for (const path of toPaths(key)){
let index = 0;
let val = object;
while(val !== undefined && val !== null && index < path.length){
val = val[path[index++]];
let shouldResolveAsFn = isFunction(val) && (path.alpha === undefined || index <= path.length - 1);
val = shouldResolveAsFn ? val(resolvePath, configUtils) : val;
}
if (val !== undefined) {
if (path.alpha !== undefined) {
let normalized = (0, _pluginUtils.parseColorFormat)(val);
return (0, _withAlphaVariable.withAlphaValue)(normalized, path.alpha, (0, _toColorValue.default)(normalized));
}
if ((0, _isPlainObject.default)(val)) {
return (0, _cloneDeep.cloneDeep)(val);
}
return val;
}
}
if (val === undefined) {
return defaultValue;
}
if ((0, _isPlainObject).default(val)) {
return (0, _cloneDeep).cloneDeep(val);
}
return val;
return defaultValue;
};
resolvePath.theme = resolvePath;
for(let key1 in configUtils){
resolvePath[key1] = configUtils[key1];
}
Object.assign(resolvePath, {
theme: resolvePath,
...configUtils
});
return Object.keys(object).reduce((resolved, key)=>{
return {
...resolved,
[key]: isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key]
};
resolved[key] = isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key];
return resolved;
}, {});

@@ -220,4 +201,4 @@ }

];
var ref2;
const plugins = (ref2 = config === null || config === void 0 ? void 0 : config.plugins) !== null && ref2 !== void 0 ? ref2 : [];
var _config_plugins;
const plugins = (_config_plugins = config === null || config === void 0 ? void 0 : config.plugins) !== null && _config_plugins !== void 0 ? _config_plugins : [];
if (plugins.length === 0) {

@@ -230,7 +211,7 @@ return;

}
var ref;
var _plugin_config;
allConfigs = [
...allConfigs,
...extractPluginConfigs([
(ref = plugin === null || plugin === void 0 ? void 0 : plugin.config) !== null && ref !== void 0 ? ref : {}
(_plugin_config = plugin === null || plugin === void 0 ? void 0 : plugin.config) !== null && _plugin_config !== void 0 ? _plugin_config : {}
])

@@ -251,3 +232,3 @@ ];

}
return (0, _configurePlugins).default(corePluginConfig, resolved);
return (0, _configurePlugins.default)(corePluginConfig, resolved);
}, _corePluginList.default);

@@ -267,1 +248,21 @@ return result;

}
function resolveConfig(configs) {
let allConfigs = [
...extractPluginConfigs(configs),
{
prefix: "",
important: false,
separator: ":"
}
];
var _t_theme, _c_plugins;
return (0, _normalizeConfig.normalizeConfig)((0, _defaults.defaults)({
theme: resolveFunctionKeys(mergeExtensions(mergeThemes(allConfigs.map((t)=>{
return (_t_theme = t === null || t === void 0 ? void 0 : t.theme) !== null && _t_theme !== void 0 ? _t_theme : {};
})))),
corePlugins: resolveCorePlugins(allConfigs.map((c)=>c.corePlugins)),
plugins: resolvePluginLists(configs.map((c)=>{
return (_c_plugins = c === null || c === void 0 ? void 0 : c.plugins) !== null && _c_plugins !== void 0 ? _c_plugins : [];
}))
}, ...allConfigs));
}

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

});
exports.default = resolveConfigPath;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
default: function() {
return resolveConfigPath;
},
resolveDefaultConfigPath: function() {
return resolveDefaultConfigPath;
}
});
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const defaultConfigFiles = [
"./tailwind.config.js",
"./tailwind.config.cjs",
"./tailwind.config.mjs",
"./tailwind.config.ts",
"./tailwind.config.cts",
"./tailwind.config.mts"
];
function isObject(value) {
return typeof value === "object" && value !== null;
}
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
function isString(value) {
return typeof value === "string" || value instanceof String;
}
function resolveConfigPath(pathOrConfig) {

@@ -27,6 +62,6 @@ // require('tailwindcss')({ theme: ..., variants: ... })

// require('tailwindcss')
for (const configFile of [
"./tailwind.config.js",
"./tailwind.config.cjs"
]){
return resolveDefaultConfigPath();
}
function resolveDefaultConfigPath() {
for (const configFile of defaultConfigFiles){
try {

@@ -40,15 +75,1 @@ const configPath = _path.default.resolve(configFile);

}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function isObject(value) {
return typeof value === "object" && value !== null;
}
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
function isString(value) {
return typeof value === "string" || value instanceof String;
}

@@ -5,16 +5,21 @@ "use strict";

});
exports.default = responsive;
var _postcss = _interopRequireDefault(require("postcss"));
var _cloneNodes = _interopRequireDefault(require("./cloneNodes"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return responsive;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _cloneNodes = /*#__PURE__*/ _interop_require_default(require("./cloneNodes"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function responsive(rules) {
return _postcss.default.atRule({
name: "responsive"
}).append((0, _cloneNodes).default(Array.isArray(rules) ? rules : [
}).append((0, _cloneNodes.default)(Array.isArray(rules) ? rules : [
rules
]));
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

@@ -1,72 +0,47 @@

"use strict";
/**
* This splits a string on a top-level character.
*
* Regex doesn't support recursion (at least not the JS-flavored version).
* So we have to use a tiny state machine to keep track of paren placement.
*
* Expected behavior using commas:
* var(--a, 0 0 1px rgb(0, 0, 0)), 0 0 1px rgb(0, 0, 0)
* ─┬─ ┬ ┬ ┬
* x x x ╰──────── Split because top-level
* ╰──────────────┴──┴───────────── Ignored b/c inside >= 1 levels of parens
*
* @param {string} input
* @param {string} separator
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.splitAtTopLevelOnly = splitAtTopLevelOnly;
var regex = _interopRequireWildcard(require("../lib/regex"));
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for(var key in obj){
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
}
newObj.default = obj;
return newObj;
Object.defineProperty(exports, "splitAtTopLevelOnly", {
enumerable: true,
get: function() {
return splitAtTopLevelOnly;
}
}
function* splitAtTopLevelOnly(input, separator) {
let SPECIALS = new RegExp(`[(){}\\[\\]${regex.escape(separator)}]`, "g");
let depth = 0;
let lastIndex = 0;
let found = false;
let separatorIndex = 0;
let separatorStart = 0;
let separatorLength = separator.length;
// Find all paren-like things & character
// And only split on commas if they're top-level
for (let match of input.matchAll(SPECIALS)){
let matchesSeparator = match[0] === separator[separatorIndex];
let atEndOfSeparator = separatorIndex === separatorLength - 1;
let matchesFullSeparator = matchesSeparator && atEndOfSeparator;
if (match[0] === "(") depth++;
if (match[0] === ")") depth--;
if (match[0] === "[") depth++;
if (match[0] === "]") depth--;
if (match[0] === "{") depth++;
if (match[0] === "}") depth--;
if (matchesSeparator && depth === 0) {
if (separatorStart === 0) {
separatorStart = match.index;
});
function splitAtTopLevelOnly(input, separator) {
let stack = [];
let parts = [];
let lastPos = 0;
let isEscaped = false;
for(let idx = 0; idx < input.length; idx++){
let char = input[idx];
if (stack.length === 0 && char === separator[0] && !isEscaped) {
if (separator.length === 1 || input.slice(idx, idx + separator.length) === separator) {
parts.push(input.slice(lastPos, idx));
lastPos = idx + separator.length;
}
separatorIndex++;
}
if (matchesFullSeparator && depth === 0) {
found = true;
yield input.substring(lastIndex, separatorStart);
lastIndex = separatorStart + separatorLength;
isEscaped = isEscaped ? false : char === "\\";
if (char === "(" || char === "[" || char === "{") {
stack.push(char);
} else if (char === ")" && stack[stack.length - 1] === "(" || char === "]" && stack[stack.length - 1] === "[" || char === "}" && stack[stack.length - 1] === "{") {
stack.pop();
}
if (separatorIndex === separatorLength) {
separatorIndex = 0;
separatorStart = 0;
}
}
// Provide the last segment of the string if available
// Otherwise the whole string since no `char`s were found
// This mirrors the behavior of string.split()
if (found) {
yield input.substring(lastIndex);
} else {
yield input;
}
parts.push(input.slice(lastPos));
return parts;
}

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

});
exports.tap = tap;
Object.defineProperty(exports, "tap", {
enumerable: true,
get: function() {
return tap;
}
});
function tap(value, mutator) {

@@ -8,0 +13,0 @@ mutator(value);

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

});
exports.default = toColorValue;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return toColorValue;
}
});
function toColorValue(maybeFunction) {
return typeof maybeFunction === "function" ? maybeFunction({}) : maybeFunction;
}

@@ -1,6 +0,24 @@

"use strict";
/**
* Parse a path string into an array of path segments.
*
* Square bracket notation `a[b]` may be used to "escape" dots that would otherwise be interpreted as path separators.
*
* Example:
* a -> ['a']
* a.b.c -> ['a', 'b', 'c']
* a[b].c -> ['a', 'b', 'c']
* a[b.c].e.f -> ['a', 'b.c', 'e', 'f']
* a[b][c][d] -> ['a', 'b', 'c', 'd']
*
* @param {string|string[]} path
**/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toPath = toPath;
Object.defineProperty(exports, "toPath", {
enumerable: true,
get: function() {
return toPath;
}
});
function toPath(path) {

@@ -7,0 +25,0 @@ if (Array.isArray(path)) return path;

@@ -5,4 +5,15 @@ "use strict";

});
exports.default = transformThemeValue;
var _postcss = _interopRequireDefault(require("postcss"));
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return transformThemeValue;
}
});
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss"));
const _isPlainObject = /*#__PURE__*/ _interop_require_default(require("./isPlainObject"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function transformThemeValue(themeSection) {

@@ -19,4 +30,10 @@ if ([

}
if (themeSection === "fontFamily") {
return (value)=>{
if (typeof value === "function") value = value({});
let families = Array.isArray(value) && (0, _isPlainObject.default)(value[1]) ? value[0] : value;
return Array.isArray(families) ? families.join(", ") : families;
};
}
if ([
"fontFamily",
"boxShadow",

@@ -31,3 +48,3 @@ "transitionProperty",

"cursor",
"animation",
"animation"
].includes(themeSection)) {

@@ -53,11 +70,8 @@ return (value)=>{

}
return (value)=>{
if (typeof value === "function") value = value({});
return (value, opts = {})=>{
if (typeof value === "function") {
value = value(opts);
}
return value;
};
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}

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

});
exports.validateConfig = validateConfig;
var _log = _interopRequireDefault(require("./log"));
function _interopRequireDefault(obj) {
Object.defineProperty(exports, "validateConfig", {
enumerable: true,
get: function() {
return validateConfig;
}
});
const _log = /*#__PURE__*/ _interop_require_default(require("./log"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {

@@ -18,6 +23,17 @@ default: obj

"Configure your content sources or your generated CSS will be missing styles.",
"https://tailwindcss.com/docs/content-configuration",
"https://tailwindcss.com/docs/content-configuration"
]);
}
// Warn if the line-clamp plugin is installed
try {
let plugin = require("@tailwindcss/line-clamp");
if (config.plugins.includes(plugin)) {
_log.default.warn("line-clamp-in-core", [
"As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.",
"Remove it from the `plugins` array in your configuration to eliminate this warning."
]);
config.plugins = config.plugins.filter((p)=>p !== plugin);
}
} catch {}
return config;
}

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

});
exports.default = withAlphaVariable;
exports.withAlphaValue = withAlphaValue;
var _color = require("./color");
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
withAlphaValue: function() {
return withAlphaValue;
},
default: function() {
return withAlphaVariable;
}
});
const _color = require("./color");
function withAlphaValue(color, alphaValue, defaultValue) {
if (typeof color === "function") {
return color({
opacityValue: alphaValue
});
}
let parsed = (0, _color.parseColor)(color, {
loose: true
});
if (parsed === null) {
return defaultValue;
}
return (0, _color.formatColor)({
...parsed,
alpha: alphaValue
});
}
function withAlphaVariable({ color , property , variable }) {

@@ -25,3 +54,3 @@ let properties = [].concat(property);

}
const parsed = (0, _color).parseColor(color);
const parsed = (0, _color.parseColor)(color);
if (parsed === null) {

@@ -31,4 +60,3 @@ return Object.fromEntries(properties.map((p)=>[

color
]
));
]));
}

@@ -40,4 +68,3 @@ if (parsed.alpha !== undefined) {

color
]
));
]));
}

@@ -49,3 +76,3 @@ return {

p,
(0, _color).formatColor({
(0, _color.formatColor)({
...parsed,

@@ -58,16 +85,1 @@ alpha: `var(${variable})`

}
function withAlphaValue(color, alphaValue, defaultValue) {
if (typeof color === "function") {
return color({
opacityValue: alphaValue
});
}
let parsed = (0, _color).parseColor(color);
if (parsed === null) {
return defaultValue;
}
return (0, _color).formatColor({
...parsed,
alpha: alphaValue
});
}
{
"name": "tailwindcss",
"version": "0.0.0-insiders.23d3a31",
"version": "0.0.0-insiders.245058c",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",

@@ -16,7 +16,6 @@ "license": "MIT",

"scripts": {
"preswcify": "npm run generate && rimraf lib",
"swcify": "swc src --out-dir lib --copy-files",
"postswcify": "esbuild lib/cli-peer-dependencies.js --bundle --platform=node --outfile=peers/index.js",
"rebuild-fixtures": "npm run swcify && node -r @swc/register scripts/rebuildFixtures.js",
"prepublishOnly": "npm install --force && npm run swcify",
"prebuild": "npm run generate && rimraf lib",
"build": "swc src --out-dir lib --copy-files",
"postbuild": "esbuild lib/cli-peer-dependencies.js --bundle --platform=node --outfile=peers/index.js --define:process.env.CSS_TRANSFORMER_WASM=false",
"rebuild-fixtures": "npm run build && node -r @swc/register scripts/rebuildFixtures.js",
"style": "eslint .",

@@ -27,6 +26,8 @@ "pretest": "npm run generate",

"install:integrations": "node scripts/install-integrations.js",
"posttest": "npm run style",
"generate:plugin-list": "node -r @swc/register scripts/create-plugin-list.js",
"generate:types": "node -r @swc/register scripts/generate-types.js",
"generate": "npm run generate:plugin-list && npm run generate:types"
"generate": "npm run generate:plugin-list && npm run generate:types",
"release-channel": "node ./scripts/release-channel.js",
"release-notes": "node ./scripts/release-notes.js",
"prepublishOnly": "npm install --force && npm run build"
},

@@ -39,3 +40,3 @@ "files": [

"scripts/*.js",
"stubs/*.stub.js",
"stubs/*",
"nesting/*",

@@ -48,44 +49,45 @@ "types/**/*",

"devDependencies": {
"@swc/cli": "^0.1.57",
"@swc/core": "^1.2.160",
"@swc/jest": "^0.2.21",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.55",
"@swc/jest": "^0.2.26",
"@swc/register": "^0.1.10",
"autoprefixer": "^10.4.5",
"cssnano": "^5.1.7",
"esbuild": "^0.14.39",
"eslint": "^8.15.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^28.0.3",
"jest-diff": "^28.0.2",
"prettier": "^2.6.2",
"prettier-plugin-tailwindcss": "^0.1.10",
"rimraf": "^3.0.0",
"source-map-js": "^1.0.2"
"autoprefixer": "^10.4.14",
"browserslist": "^4.21.5",
"concurrently": "^8.0.1",
"cssnano": "^6.0.0",
"esbuild": "^0.20.2",
"eslint": "^8.39.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.6.0",
"jest-diff": "^29.6.0",
"lightningcss": "1.24.1",
"prettier": "^2.8.8",
"rimraf": "^5.0.0",
"source-map-js": "^1.0.2",
"turbo": "^1.9.3"
},
"peerDependencies": {
"postcss": "^8.0.9"
},
"dependencies": {
"arg": "^5.0.1",
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
"chokidar": "^3.5.3",
"color-name": "^1.1.4",
"detective": "^5.2.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.2.11",
"fast-glob": "^3.3.0",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"lilconfig": "^2.0.5",
"jiti": "^1.21.0",
"lilconfig": "^2.1.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
"picocolors": "^1.0.0",
"postcss": "^8.4.13",
"postcss-js": "^4.0.0",
"postcss-load-config": "^3.1.4",
"postcss-nested": "5.0.6",
"postcss-selector-parser": "^6.0.10",
"postcss-value-parser": "^4.2.0",
"quick-lru": "^5.1.1",
"resolve": "^1.22.0"
"postcss": "^8.4.23",
"postcss-import": "^15.1.0",
"postcss-js": "^4.0.1",
"postcss-load-config": "^4.0.1",
"postcss-nested": "^6.0.1",
"postcss-selector-parser": "^6.0.11",
"resolve": "^1.22.2",
"sucrase": "^3.32.0"
},

@@ -106,11 +108,16 @@ "browserslist": [

"/integrations/",
"/standalone-cli/"
"/standalone-cli/",
"\\.test\\.skip\\.js$"
],
"transformIgnorePatterns": [
"node_modules/(?!lightningcss)"
],
"transform": {
"\\.js$": "@swc/jest"
"\\.js$": "@swc/jest",
"\\.ts$": "@swc/jest"
}
},
"engines": {
"node": ">=12.13.0"
"node": ">=14.0.0"
}
}
import type { Config, PluginCreator } from './types/config'
declare function createPlugin(
plugin: PluginCreator,
config?: Config
): { handler: PluginCreator; config?: Config }
export = createPlugin
type Plugin = {
withOptions<T>(
plugin: (options: T) => PluginCreator,
config?: (options: T) => Partial<Config>
): { (options: T): { handler: PluginCreator; config?: Partial<Config> }; __isOptionsFunction: true }
(plugin: PluginCreator, config?: Partial<Config>): { handler: PluginCreator; config?: Partial<Config> }
}
declare const plugin: Plugin
export = plugin

@@ -1,14 +0,17 @@

<p>
<a href="https://tailwindcss.com/#gh-light-mode-only" target="_blank">
<img src="./.github/logo-light.svg" alt="Tailwind CSS" width="350" height="70">
<p align="center">
<a href="https://tailwindcss.com" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/tailwindlabs/tailwindcss/HEAD/.github/logo-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/tailwindlabs/tailwindcss/HEAD/.github/logo-light.svg">
<img alt="Tailwind CSS" src="https://raw.githubusercontent.com/tailwindlabs/tailwindcss/HEAD/.github/logo-light.svg" width="350" height="70" style="max-width: 100%;">
</picture>
</a>
<a href="https://tailwindcss.com/#gh-dark-mode-only" target="_blank">
<img src="./.github/logo-dark.svg" alt="Tailwind CSS" width="350" height="70">
</a>
</p>
A utility-first CSS framework for rapidly building custom user interfaces.
<p align="center">
A utility-first CSS framework for rapidly building custom user interfaces.
</p>
<p>
<a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/workflow/status/tailwindlabs/tailwindcss/Node.js%20CI" alt="Build Status"></a>
<p align="center">
<a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/actions/workflow/status/tailwindlabs/tailwindcss/ci.yml?branch=master" alt="Build Status"></a>
<a href="https://www.npmjs.com/package/tailwindcss"><img src="https://img.shields.io/npm/dt/tailwindcss.svg" alt="Total Downloads"></a>

@@ -19,3 +22,3 @@ <a href="https://github.com/tailwindcss/tailwindcss/releases"><img src="https://img.shields.io/npm/v/tailwindcss.svg" alt="Latest Release"></a>

------
---

@@ -22,0 +25,0 @@ ## Documentation

import prettier from 'prettier'
import { corePlugins } from '../src/corePlugins'
import colors from '../src/public/colors'
import defaultTheme from '../src/public/default-theme'
import fs from 'fs'
import path from 'path'
import * as types from './type-utils'

@@ -53,1 +55,51 @@ fs.writeFileSync(

)
const defaultThemeTypes = Object.entries(defaultTheme)
.map(([name, value]) => {
// Special cases for slightly more accurate types
if (name === 'keyframes') {
return [name, `Record<${types.forKeys(value)}, Record<string, CSSDeclarationList>>`]
}
if (name === 'fontSize') {
return [name, `Record<${types.forKeys(value)}, [string, { lineHeight: string }]>`]
}
// General cases
if (typeof value === 'string') {
return [name, `string`]
}
if (typeof value === 'function') {
return [name, null]
}
if (typeof value === 'object') {
if (Object.keys(value).length === 0) {
return [name, null]
}
return [name, types.forValue(value)]
}
return [name, `unknown`]
})
.filter(([, type]) => type !== null)
.map(([name, type]) => `${name}: ${type}`)
.join('\n')
fs.writeFileSync(
path.join(process.cwd(), 'types', 'generated', 'default-theme.d.ts'),
prettier.format(
`
type CSSDeclarationList = Record<string, string>
export type DefaultTheme = { ${defaultThemeTypes} }
`,
{
semi: false,
singleQuote: true,
printWidth: 100,
parser: 'typescript',
}
)
)

@@ -5,2 +5,6 @@ export function lazyPostcss() {

export function lazyPostcssImport() {
return require('postcss-import')
}
export function lazyAutoprefixer() {

@@ -7,0 +11,0 @@ return require('autoprefixer')

#!/usr/bin/env node
import { lazyPostcss, lazyCssnano, lazyAutoprefixer } from '../peers/index.js'
import chokidar from 'chokidar'
import path from 'path'
import arg from 'arg'
import fs from 'fs'
import postcssrc from 'postcss-load-config'
import { lilconfig } from 'lilconfig'
import loadPlugins from 'postcss-load-config/src/plugins' // Little bit scary, looking at private/internal API
import loadOptions from 'postcss-load-config/src/options' // Little bit scary, looking at private/internal API
import tailwind from './processTailwindFeatures'
import resolveConfigInternal from '../resolveConfig'
import fastGlob from 'fast-glob'
import getModuleDependencies from './lib/getModuleDependencies'
import log from './util/log'
import packageJson from '../package.json'
import normalizePath from 'normalize-path'
import { validateConfig } from './util/validateConfig.js'
let env = {
DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== '0',
}
function isESM() {
const pkgPath = path.resolve('./package.json')
try {
let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
return pkg.type && pkg.type === 'module'
} catch (err) {
return false
}
}
let configs = isESM()
? {
tailwind: 'tailwind.config.cjs',
postcss: 'postcss.config.cjs',
}
: {
tailwind: 'tailwind.config.js',
postcss: 'postcss.config.js',
}
// ---
function indentRecursive(node, indent = 0) {
node.each &&
node.each((child, i) => {
if (!child.raws.before || !child.raws.before.trim() || child.raws.before.includes('\n')) {
child.raws.before = `\n${node.type !== 'rule' && i > 0 ? '\n' : ''}${' '.repeat(indent)}`
}
child.raws.after = `\n${' '.repeat(indent)}`
indentRecursive(child, indent + 1)
})
}
function formatNodes(root) {
indentRecursive(root)
if (root.first) {
root.first.raws.before = ''
}
}
async function outputFile(file, contents) {
if (fs.existsSync(file) && (await fs.promises.readFile(file, 'utf8')) === contents) {
return // Skip writing the file
}
// Write the file
await fs.promises.writeFile(file, contents, 'utf8')
}
function drainStdin() {
return new Promise((resolve, reject) => {
let result = ''
process.stdin.on('data', (chunk) => {
result += chunk
})
process.stdin.on('end', () => resolve(result))
process.stdin.on('error', (err) => reject(err))
})
}
function help({ message, usage, commands, options }) {
let indent = 2
// Render header
console.log()
console.log(`${packageJson.name} v${packageJson.version}`)
// Render message
if (message) {
console.log()
for (let msg of message.split('\n')) {
console.log(msg)
}
}
// Render usage
if (usage && usage.length > 0) {
console.log()
console.log('Usage:')
for (let example of usage) {
console.log(' '.repeat(indent), example)
}
}
// Render commands
if (commands && commands.length > 0) {
console.log()
console.log('Commands:')
for (let command of commands) {
console.log(' '.repeat(indent), command)
}
}
// Render options
if (options) {
let groupedOptions = {}
for (let [key, value] of Object.entries(options)) {
if (typeof value === 'object') {
groupedOptions[key] = { ...value, flags: [key] }
} else {
groupedOptions[value].flags.push(key)
}
}
console.log()
console.log('Options:')
for (let { flags, description, deprecated } of Object.values(groupedOptions)) {
if (deprecated) continue
if (flags.length === 1) {
console.log(
' '.repeat(indent + 4 /* 4 = "-i, ".length */),
flags.slice().reverse().join(', ').padEnd(20, ' '),
description
)
} else {
console.log(
' '.repeat(indent),
flags.slice().reverse().join(', ').padEnd(24, ' '),
description
)
}
}
}
console.log()
}
function oneOf(...options) {
return Object.assign(
(value = true) => {
for (let option of options) {
let parsed = option(value)
if (parsed === value) {
return parsed
}
}
throw new Error('...')
},
{ manualParsing: true }
)
}
function loadPostcss() {
// Try to load a local `postcss` version first
try {
return require('postcss')
} catch {}
return lazyPostcss()
}
let commands = {
init: {
run: init,
args: {
'--full': { type: Boolean, description: `Initialize a full \`${configs.tailwind}\` file` },
'--postcss': { type: Boolean, description: `Initialize a \`${configs.postcss}\` file` },
'--types': {
type: Boolean,
description: `Add TypeScript types for the \`${configs.tailwind}\` file`,
},
'-f': '--full',
'-p': '--postcss',
},
},
build: {
run: build,
args: {
'--input': { type: String, description: 'Input file' },
'--output': { type: String, description: 'Output file' },
'--watch': { type: Boolean, description: 'Watch for changes and rebuild as needed' },
'--poll': {
type: Boolean,
description: 'Use polling instead of filesystem events when watching',
},
'--content': {
type: String,
description: 'Content paths to use for removing unused classes',
},
'--purge': {
type: String,
deprecated: true,
},
'--postcss': {
type: oneOf(String, Boolean),
description: 'Load custom PostCSS configuration',
},
'--minify': { type: Boolean, description: 'Minify the output' },
'--config': {
type: String,
description: 'Path to a custom config file',
},
'--no-autoprefixer': {
type: Boolean,
description: 'Disable autoprefixer',
},
'-c': '--config',
'-i': '--input',
'-o': '--output',
'-m': '--minify',
'-w': '--watch',
'-p': '--poll',
},
},
}
let sharedFlags = {
'--help': { type: Boolean, description: 'Display usage information' },
'-h': '--help',
}
if (
process.stdout.isTTY /* Detect redirecting output to a file */ &&
(process.argv[2] === undefined ||
process.argv.slice(2).every((flag) => sharedFlags[flag] !== undefined))
) {
help({
usage: [
'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
'tailwindcss init [--full] [--postcss] [--types] [options...]',
],
commands: Object.keys(commands)
.filter((command) => command !== 'build')
.map((command) => `${command} [options]`),
options: { ...commands.build.args, ...sharedFlags },
})
process.exit(0)
}
let command = ((arg = '') => (arg.startsWith('-') ? undefined : arg))(process.argv[2]) || 'build'
if (commands[command] === undefined) {
if (fs.existsSync(path.resolve(command))) {
// TODO: Deprecate this in future versions
// Check if non-existing command, might be a file.
command = 'build'
} else {
help({
message: `Invalid command: ${command}`,
usage: ['tailwindcss <command> [options]'],
commands: Object.keys(commands)
.filter((command) => command !== 'build')
.map((command) => `${command} [options]`),
options: sharedFlags,
})
process.exit(1)
}
}
// Execute command
let { args: flags, run } = commands[command]
let args = (() => {
try {
let result = arg(
Object.fromEntries(
Object.entries({ ...flags, ...sharedFlags })
.filter(([_key, value]) => !value?.type?.manualParsing)
.map(([key, value]) => [key, typeof value === 'object' ? value.type : value])
),
{ permissive: true }
)
// Manual parsing of flags to allow for special flags like oneOf(Boolean, String)
for (let i = result['_'].length - 1; i >= 0; --i) {
let flag = result['_'][i]
if (!flag.startsWith('-')) continue
let flagName = flag
let handler = flags[flag]
// Resolve flagName & handler
while (typeof handler === 'string') {
flagName = handler
handler = flags[handler]
}
if (!handler) continue
let args = []
let offset = i + 1
// Parse args for current flag
while (result['_'][offset] && !result['_'][offset].startsWith('-')) {
args.push(result['_'][offset++])
}
// Cleanup manually parsed flags + args
result['_'].splice(i, 1 + args.length)
// Set the resolved value in the `result` object
result[flagName] = handler.type(
args.length === 0 ? undefined : args.length === 1 ? args[0] : args,
flagName
)
}
// Ensure that the `command` is always the first argument in the `args`.
// This is important so that we don't have to check if a default command
// (build) was used or not from within each plugin.
//
// E.g.: tailwindcss input.css -> _: ['build', 'input.css']
// E.g.: tailwindcss build input.css -> _: ['build', 'input.css']
if (result['_'][0] !== command) {
result['_'].unshift(command)
}
return result
} catch (err) {
if (err.code === 'ARG_UNKNOWN_OPTION') {
help({
message: err.message,
usage: ['tailwindcss <command> [options]'],
options: sharedFlags,
})
process.exit(1)
}
throw err
}
})()
if (args['--help']) {
help({
options: { ...flags, ...sharedFlags },
usage: [`tailwindcss ${command} [options]`],
})
process.exit(0)
}
run()
// ---
function init() {
let messages = []
let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./${configs.tailwind}`)
if (fs.existsSync(tailwindConfigLocation)) {
messages.push(`${path.basename(tailwindConfigLocation)} already exists.`)
} else {
let stubFile = fs.readFileSync(
args['--full']
? path.resolve(__dirname, '../stubs/defaultConfig.stub.js')
: path.resolve(__dirname, '../stubs/simpleConfig.stub.js'),
'utf8'
)
if (args['--types']) {
let typesHeading = "/** @type {import('tailwindcss/types').Config} */"
stubFile =
stubFile.replace(`module.exports = `, `${typesHeading}\nconst config = `) +
'\nmodule.exports = config'
}
// Change colors import
stubFile = stubFile.replace('../colors', 'tailwindcss/colors')
fs.writeFileSync(tailwindConfigLocation, stubFile, 'utf8')
messages.push(`Created Tailwind CSS config file: ${path.basename(tailwindConfigLocation)}`)
}
if (args['--postcss']) {
let postcssConfigLocation = path.resolve(`./${configs.postcss}`)
if (fs.existsSync(postcssConfigLocation)) {
messages.push(`${path.basename(postcssConfigLocation)} already exists.`)
} else {
let stubFile = fs.readFileSync(
path.resolve(__dirname, '../stubs/defaultPostCssConfig.stub.js'),
'utf8'
)
fs.writeFileSync(postcssConfigLocation, stubFile, 'utf8')
messages.push(`Created PostCSS config file: ${path.basename(postcssConfigLocation)}`)
}
}
if (messages.length > 0) {
console.log()
for (let message of messages) {
console.log(message)
}
}
}
async function build() {
let input = args['--input']
let output = args['--output']
let shouldWatch = args['--watch']
let shouldPoll = args['--poll']
let shouldCoalesceWriteEvents = shouldPoll || process.platform === 'win32'
let includePostCss = args['--postcss']
// Polling interval in milliseconds
// Used only when polling or coalescing add/change events on Windows
let pollInterval = 10
// TODO: Deprecate this in future versions
if (!input && args['_'][1]) {
console.error('[deprecation] Running tailwindcss without -i, please provide an input file.')
input = args['--input'] = args['_'][1]
}
if (input && input !== '-' && !fs.existsSync((input = path.resolve(input)))) {
console.error(`Specified input file ${args['--input']} does not exist.`)
process.exit(9)
}
if (args['--config'] && !fs.existsSync((args['--config'] = path.resolve(args['--config'])))) {
console.error(`Specified config file ${args['--config']} does not exist.`)
process.exit(9)
}
let configPath = args['--config']
? args['--config']
: ((defaultPath) => (fs.existsSync(defaultPath) ? defaultPath : null))(
path.resolve(`./${configs.tailwind}`)
)
async function loadPostCssPlugins() {
let customPostCssPath = typeof args['--postcss'] === 'string' ? args['--postcss'] : undefined
let config = customPostCssPath
? await (async () => {
let file = path.resolve(customPostCssPath)
// Implementation, see: https://unpkg.com/browse/postcss-load-config@3.1.0/src/index.js
let { config = {} } = await lilconfig('postcss').load(file)
if (typeof config === 'function') {
config = config()
} else {
config = Object.assign({}, config)
}
if (!config.plugins) {
config.plugins = []
}
return {
file,
plugins: loadPlugins(config, file),
options: loadOptions(config, file),
}
})()
: await postcssrc()
let configPlugins = config.plugins
let configPluginTailwindIdx = configPlugins.findIndex((plugin) => {
if (typeof plugin === 'function' && plugin.name === 'tailwindcss') {
return true
}
if (typeof plugin === 'object' && plugin !== null && plugin.postcssPlugin === 'tailwindcss') {
return true
}
return false
})
let beforePlugins =
configPluginTailwindIdx === -1 ? [] : configPlugins.slice(0, configPluginTailwindIdx)
let afterPlugins =
configPluginTailwindIdx === -1
? configPlugins
: configPlugins.slice(configPluginTailwindIdx + 1)
return [beforePlugins, afterPlugins, config.options]
}
function resolveConfig() {
let config = configPath ? require(configPath) : {}
if (args['--purge']) {
log.warn('purge-flag-deprecated', [
'The `--purge` flag has been deprecated.',
'Please use `--content` instead.',
])
if (!args['--content']) {
args['--content'] = args['--purge']
}
}
if (args['--content']) {
let files = args['--content'].split(/(?<!{[^}]+),/)
let resolvedConfig = resolveConfigInternal(config, { content: { files } })
resolvedConfig.content.files = files
resolvedConfig = validateConfig(resolvedConfig)
return resolvedConfig
}
let resolvedConfig = resolveConfigInternal(config)
resolvedConfig = validateConfig(resolvedConfig)
return resolvedConfig
}
function extractFileGlobs(config) {
return config.content.files
.filter((file) => {
// Strings in this case are files / globs. If it is something else,
// like an object it's probably a raw content object. But this object
// is not watchable, so let's remove it.
return typeof file === 'string'
})
.map((glob) => normalizePath(glob))
}
function extractRawContent(config) {
return config.content.files.filter((file) => {
return typeof file === 'object' && file !== null
})
}
function getChangedContent(config) {
let changedContent = []
// Resolve globs from the content config
let globs = extractFileGlobs(config)
let files = fastGlob.sync(globs)
for (let file of files) {
changedContent.push({
content: fs.readFileSync(path.resolve(file), 'utf8'),
extension: path.extname(file).slice(1),
})
}
// Resolve raw content in the tailwind config
for (let { raw: content, extension = 'html' } of extractRawContent(config)) {
changedContent.push({ content, extension })
}
return changedContent
}
async function buildOnce() {
let config = resolveConfig()
let changedContent = getChangedContent(config)
let tailwindPlugin = () => {
return {
postcssPlugin: 'tailwindcss',
Once(root, { result }) {
tailwind(({ createContext }) => {
return () => {
return createContext(config, changedContent)
}
})(root, result)
},
}
}
tailwindPlugin.postcss = true
let [beforePlugins, afterPlugins, postcssOptions] = includePostCss
? await loadPostCssPlugins()
: [[], [], {}]
let plugins = [
...beforePlugins,
tailwindPlugin,
!args['--minify'] && formatNodes,
...afterPlugins,
!args['--no-autoprefixer'] &&
(() => {
// Try to load a local `autoprefixer` version first
try {
return require('autoprefixer')
} catch {}
return lazyAutoprefixer()
})(),
args['--minify'] &&
(() => {
let options = { preset: ['default', { cssDeclarationSorter: false }] }
// Try to load a local `cssnano` version first
try {
return require('cssnano')
} catch {}
return lazyCssnano()(options)
})(),
].filter(Boolean)
let postcss = loadPostcss()
let processor = postcss(plugins)
function processCSS(css) {
let start = process.hrtime.bigint()
return Promise.resolve()
.then(() => (output ? fs.promises.mkdir(path.dirname(output), { recursive: true }) : null))
.then(() => processor.process(css, { ...postcssOptions, from: input, to: output }))
.then((result) => {
if (!output) {
return process.stdout.write(result.css)
}
return Promise.all(
[
outputFile(output, result.css),
result.map && outputFile(output + '.map', result.map.toString()),
].filter(Boolean)
)
})
.then(() => {
let end = process.hrtime.bigint()
console.error()
console.error('Done in', (end - start) / BigInt(1e6) + 'ms.')
})
}
let css = await (() => {
// Piping in data, let's drain the stdin
if (input === '-') {
return drainStdin()
}
// Input file has been provided
if (input) {
return fs.readFileSync(path.resolve(input), 'utf8')
}
// No input file provided, fallback to default atrules
return '@tailwind base; @tailwind components; @tailwind utilities'
})()
return processCSS(css)
}
let context = null
async function startWatcher() {
let changedContent = []
let configDependencies = []
let contextDependencies = new Set()
let watcher = null
function refreshConfig() {
env.DEBUG && console.time('Module dependencies')
for (let file of configDependencies) {
delete require.cache[require.resolve(file)]
}
if (configPath) {
configDependencies = getModuleDependencies(configPath).map(({ file }) => file)
for (let dependency of configDependencies) {
contextDependencies.add(dependency)
}
}
env.DEBUG && console.timeEnd('Module dependencies')
return resolveConfig()
}
let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [[], []]
let plugins = [
...beforePlugins,
'__TAILWIND_PLUGIN_POSITION__',
!args['--minify'] && formatNodes,
...afterPlugins,
!args['--no-autoprefixer'] &&
(() => {
// Try to load a local `autoprefixer` version first
try {
return require('autoprefixer')
} catch {}
return lazyAutoprefixer()
})(),
args['--minify'] &&
(() => {
let options = { preset: ['default', { cssDeclarationSorter: false }] }
// Try to load a local `cssnano` version first
try {
return require('cssnano')
} catch {}
return lazyCssnano()(options)
})(),
].filter(Boolean)
async function rebuild(config) {
env.DEBUG && console.time('Finished in')
let tailwindPlugin = () => {
return {
postcssPlugin: 'tailwindcss',
Once(root, { result }) {
env.DEBUG && console.time('Compiling CSS')
tailwind(({ createContext }) => {
console.error()
console.error('Rebuilding...')
return () => {
if (context !== null) {
context.changedContent = changedContent.splice(0)
return context
}
env.DEBUG && console.time('Creating context')
context = createContext(config, changedContent.splice(0))
env.DEBUG && console.timeEnd('Creating context')
return context
}
})(root, result)
env.DEBUG && console.timeEnd('Compiling CSS')
},
}
}
tailwindPlugin.postcss = true
let tailwindPluginIdx = plugins.indexOf('__TAILWIND_PLUGIN_POSITION__')
let copy = plugins.slice()
copy.splice(tailwindPluginIdx, 1, tailwindPlugin)
let postcss = loadPostcss()
let processor = postcss(copy)
function processCSS(css) {
let start = process.hrtime.bigint()
return Promise.resolve()
.then(() =>
output ? fs.promises.mkdir(path.dirname(output), { recursive: true }) : null
)
.then(() => processor.process(css, { from: input, to: output }))
.then(async (result) => {
for (let message of result.messages) {
if (message.type === 'dependency') {
contextDependencies.add(message.file)
}
}
watcher.add([...contextDependencies])
if (!output) {
return process.stdout.write(result.css)
}
return Promise.all(
[
outputFile(output, result.css),
result.map && outputFile(output + '.map', result.map.toString()),
].filter(Boolean)
)
})
.then(() => {
let end = process.hrtime.bigint()
console.error('Done in', (end - start) / BigInt(1e6) + 'ms.')
})
.catch((err) => {
if (err.name === 'CssSyntaxError') {
console.error(err.toString())
} else {
console.error(err)
}
})
}
let css = await (() => {
// Piping in data, let's drain the stdin
if (input === '-') {
return drainStdin()
}
// Input file has been provided
if (input) {
return fs.readFileSync(path.resolve(input), 'utf8')
}
// No input file provided, fallback to default atrules
return '@tailwind base; @tailwind components; @tailwind utilities'
})()
let result = await processCSS(css)
env.DEBUG && console.timeEnd('Finished in')
return result
}
let config = refreshConfig(configPath)
if (input) {
contextDependencies.add(path.resolve(input))
}
watcher = chokidar.watch([...contextDependencies, ...extractFileGlobs(config)], {
usePolling: shouldPoll,
interval: shouldPoll ? pollInterval : undefined,
ignoreInitial: true,
awaitWriteFinish: shouldCoalesceWriteEvents
? {
stabilityThreshold: 50,
pollInterval: pollInterval,
}
: false,
})
let chain = Promise.resolve()
watcher.on('change', async (file) => {
if (contextDependencies.has(file)) {
env.DEBUG && console.time('Resolve config')
context = null
config = refreshConfig(configPath)
env.DEBUG && console.timeEnd('Resolve config')
env.DEBUG && console.time('Watch new files')
let globs = extractFileGlobs(config)
watcher.add(configDependencies)
watcher.add(globs)
env.DEBUG && console.timeEnd('Watch new files')
chain = chain.then(async () => {
changedContent.push(...getChangedContent(config))
await rebuild(config)
})
} else {
chain = chain.then(async () => {
changedContent.push({
content: fs.readFileSync(path.resolve(file), 'utf8'),
extension: path.extname(file).slice(1),
})
await rebuild(config)
})
}
})
watcher.on('add', async (file) => {
chain = chain.then(async () => {
changedContent.push({
content: fs.readFileSync(path.resolve(file), 'utf8'),
extension: path.extname(file).slice(1),
})
await rebuild(config)
})
})
chain = chain.then(() => {
changedContent.push(...getChangedContent(config))
return rebuild(config)
})
}
if (shouldWatch) {
/* Abort the watcher if stdin is closed to avoid zombie processes */
process.stdin.on('end', () => process.exit(0))
process.stdin.resume()
startWatcher()
} else {
buildOnce()
}
}
module.exports = require('./cli/index')

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

export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","lineClamp","display","aspectRatio","size","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","captionSide","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","listStyleImage","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","hyphens","whitespace","textWrap","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","contain","content","forcedColorAdjust"]

@@ -6,7 +6,15 @@ import colors from 'picocolors'

optimizeUniversalDefaults: false,
generalizedModifiers: true,
disableColorOpacityUtilitiesByDefault: false,
relativeContentPathsByDefault: false,
}
let featureFlags = {
future: [],
experimental: ['optimizeUniversalDefaults'],
future: [
'hoverOnlyWhenSupported',
'respectDefaultRingColorOpacity',
'disableColorOpacityUtilitiesByDefault',
'relativeContentPathsByDefault',
],
experimental: ['optimizeUniversalDefaults', 'generalizedModifiers'],
}

@@ -13,0 +21,0 @@

@@ -1,42 +0,1 @@

import setupTrackingContext from './lib/setupTrackingContext'
import processTailwindFeatures from './processTailwindFeatures'
import { env } from './lib/sharedState'
module.exports = function tailwindcss(configOrPath) {
return {
postcssPlugin: 'tailwindcss',
plugins: [
env.DEBUG &&
function (root) {
console.log('\n')
console.time('JIT TOTAL')
return root
},
function (root, result) {
let context = setupTrackingContext(configOrPath)
if (root.type === 'document') {
let roots = root.nodes.filter((node) => node.type === 'root')
for (const root of roots) {
if (root.type === 'root') {
processTailwindFeatures(context)(root, result)
}
}
return
}
processTailwindFeatures(context)(root, result)
},
env.DEBUG &&
function (root) {
console.timeEnd('JIT TOTAL')
console.log('\n')
return root
},
].filter(Boolean),
}
}
module.exports.postcss = true
module.exports = require('./plugin')
import * as regex from './regex'
import { splitAtTopLevelOnly } from '../util/splitAtTopLevelOnly'

@@ -14,6 +15,32 @@ export function defaultExtractor(context) {

for (let pattern of patterns) {
results.push(...(content.match(pattern) ?? []))
for (let result of content.match(pattern) ?? []) {
results.push(clipAtBalancedParens(result))
}
}
return results.filter((v) => v !== undefined).map(clipAtBalancedParens)
// Extract any subclasses from languages like Slim and Pug, eg:
// div.flex.px-5.underline
for (let result of results.slice()) {
let segments = splitAtTopLevelOnly(result, '.')
for (let idx = 0; idx < segments.length; idx++) {
let segment = segments[idx]
if (idx >= segments.length - 1) {
results.push(segment)
continue
}
// If the next segment is a number, discard both, for example seeing
// `px-1` and `5` means the real candidate was `px-1.5` which is already
// captured.
let next = Number(segments[idx + 1])
if (isNaN(next)) {
results.push(segment)
} else {
idx++
}
}
}
return results
}

@@ -24,62 +51,110 @@ }

let separator = context.tailwindConfig.separator
let prefix =
context.tailwindConfig.prefix !== ''
? regex.optional(regex.pattern([/-?/, regex.escape(context.tailwindConfig.prefix)]))
: ''
yield regex.pattern([
// Variants
'((?=((',
regex.any(
[
regex.pattern([/([^\s"'\[\\]+-)?\[[^\s"'\\]+\]/, separator]),
regex.pattern([/[^\s"'\[\\]+/, separator]),
],
true
),
')+))\\2)?',
let utility = regex.any([
// Arbitrary properties (without square brackets)
/\[[^\s:'"`]+:[^\s\[\]]+\]/,
// Important (optional)
/!?/,
// Arbitrary properties with balanced square brackets
// This is a targeted fix to continue to allow theme()
// with square brackets to work in arbitrary properties
// while fixing a problem with the regex matching too much
/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
regex.any([
// Arbitrary properties
/\[[^\s:'"]+:[^\s\]]+\]/,
// Utilities
regex.pattern([
// Utility Name / Group Name
// Utilities
regex.pattern([
// Utility Name / Group Name
regex.any([
/-?(?:\w+)/,
// Normal/Arbitrary values
regex.optional(
regex.any([
regex.pattern([
// Arbitrary values
/-\[[^\s:]+\]/,
// This is here to make sure @container supports everything that other utilities do
/@(?:\w+)/,
]),
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"\\$]*)?/,
// Normal/Arbitrary values
regex.optional(
regex.any([
regex.pattern([
// Arbitrary values
regex.any([
/-(?:\w+-)*\['[^\s]+'\]/,
/-(?:\w+-)*\["[^\s]+"\]/,
/-(?:\w+-)*\[`[^\s]+`\]/,
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/,
]),
regex.pattern([
// Arbitrary values
/-\[[^\s]+\]/,
// Not immediately followed by an `{[(`
/(?![{([]])/,
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"`\\><$]*)?/,
]),
// optionally followed by an opacity modifier
/(?:\/[^\s'"\\$]*)?/,
regex.pattern([
// Arbitrary values
regex.any([
/-(?:\w+-)*\['[^\s]+'\]/,
/-(?:\w+-)*\["[^\s]+"\]/,
/-(?:\w+-)*\[`[^\s]+`\]/,
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/,
]),
// Normal values w/o quotes — may include an opacity modifier
/[-\/][^\s'"\\$={]*/,
])
),
]),
// Not immediately followed by an `{[(`
/(?![{([]])/,
// optionally followed by an opacity modifier
/(?:\/[^\s'"`\\$]*)?/,
]),
// Normal values w/o quotes — may include an opacity modifier
/[-\/][^\s'"`\\$={><]*/,
])
),
]),
])
let variantPatterns = [
// Without quotes
regex.any([
// This is here to provide special support for the `@` variant
regex.pattern([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, separator]),
// With variant modifier (e.g.: group-[..]/modifier)
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/, separator]),
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
regex.pattern([/[^\s"'`\[\\]+/, separator]),
]),
// With quotes allowed
regex.any([
// With variant modifier (e.g.: group-[..]/modifier)
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/, separator]),
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
regex.pattern([/[^\s`\[\\]+/, separator]),
]),
]
for (const variantPattern of variantPatterns) {
yield regex.pattern([
// Variants
'((?=((',
variantPattern,
')+))\\2)?',
// Important (optional)
/!?/,
prefix,
utility,
])
}
// 5. Inner matches
// yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
yield /[^<>"'`\s.(){}[\]#=%$][^<>"'`\s(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
}

@@ -158,3 +233,3 @@

if (depth < 0) {
return input.substring(0, match.index)
return input.substring(0, match.index - 1)
}

@@ -161,0 +236,0 @@

import dlv from 'dlv'
import didYouMean from 'didyoumean'
import transformThemeValue from '../util/transformThemeValue'
import parseValue from 'postcss-value-parser'
import parseValue from '../value-parser/index'
import { normalizeScreens } from '../util/normalizeScreens'
import buildMediaQuery from '../util/buildMediaQuery'
import { toPath } from '../util/toPath'
import { withAlphaValue } from '../util/withAlphaVariable'
import { parseColorFormat } from '../util/pluginUtils'
import log from '../util/log'

@@ -40,6 +43,4 @@ function isObject(input) {

function validatePath(config, path, defaultValue) {
const pathString = Array.isArray(path)
? pathToString(path)
: path.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
function validatePath(config, path, defaultValue, themeOpts = {}) {
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, '')
const pathSegments = Array.isArray(path) ? path : toPath(pathString)

@@ -118,3 +119,3 @@ const value = dlv(config.theme, pathSegments, defaultValue)

isValid: true,
value: transformThemeValue(themeSection)(value),
value: transformThemeValue(themeSection)(value, themeOpts),
}

@@ -150,2 +151,5 @@ }

function resolveFunctions(node, input, functions) {
let hasAnyFn = Object.keys(functions).some((fn) => input.includes(`${fn}(`))
if (!hasAnyFn) return input
return parseValue(input)

@@ -163,6 +167,47 @@ .walk((vNode) => {

export default function ({ tailwindConfig: config }) {
/**
* @param {string} path
* @returns {Iterable<[path: string, alpha: string|undefined]>}
*/
function* toPaths(path) {
// Strip quotes from beginning and end of string
// This allows the alpha value to be present inside of quotes
path = path.replace(/^['"]+|['"]+$/g, '')
let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/)
let alpha = undefined
yield [path, undefined]
if (matches) {
path = matches[1]
alpha = matches[2]
yield [path, alpha]
}
}
/**
*
* @param {any} config
* @param {string} path
* @param {any} defaultValue
*/
function resolvePath(config, path, defaultValue) {
const results = Array.from(toPaths(path)).map(([path, alpha]) => {
return Object.assign(validatePath(config, path, defaultValue, { opacityValue: alpha }), {
resolvedPath: path,
alpha,
})
})
return results.find((result) => result.isValid) ?? results[0]
}
export default function (context) {
let config = context.tailwindConfig
let functions = {
theme: (node, path, ...defaultValue) => {
const { isValid, value, error } = validatePath(
let { isValid, value, error, alpha } = resolvePath(
config,

@@ -174,5 +219,34 @@ path,

if (!isValid) {
let parentNode = node.parent
let candidate = parentNode?.raws.tailwind?.candidate
if (parentNode && candidate !== undefined) {
// Remove this utility from any caches
context.markInvalidUtilityNode(parentNode)
// Remove the CSS node from the markup
parentNode.remove()
// Show a warning
log.warn('invalid-theme-key-in-class', [
`The utility \`${candidate}\` contains an invalid theme value and was not generated.`,
])
return
}
throw node.error(error)
}
let maybeColor = parseColorFormat(value)
let isColorFunction = maybeColor !== undefined && typeof maybeColor === 'function'
if (alpha !== undefined || isColorFunction) {
if (alpha === undefined) {
alpha = 1.0
}
value = withAlphaValue(maybeColor, alpha, maybeColor)
}
return value

@@ -179,0 +253,0 @@ },

@@ -5,4 +5,5 @@ import postcss from 'postcss'

import { resolveMatches } from './generateRules'
import bigSign from '../util/bigSign'
import escapeClassName from '../util/escapeClassName'
import { applyImportantSelector } from '../util/applyImportantSelector'
import { movePseudos } from '../util/pseudoElements'

@@ -38,3 +39,3 @@ /** @typedef {Map<string, [any, import('postcss').Rule[]]>} ApplyCache */

let selectorExtractor = parser((root) => root.nodes.map((node) => node.toString()))
let selectorExtractor = parser()

@@ -45,3 +46,3 @@ /**

function extractSelectors(ruleSelectors) {
return selectorExtractor.transformSync(ruleSelectors)
return selectorExtractor.astSync(ruleSelectors)
}

@@ -155,5 +156,3 @@

let highestOffset = context.layerOrder.user >> 4n
root.walkRules((rule, idx) => {
root.walkRules((rule) => {
// Ignore rules generated by Tailwind

@@ -168,2 +167,3 @@ for (let node of pathToRoot(rule)) {

let container = nestedClone(rule)
let sort = context.offsets.create('user')

@@ -177,3 +177,3 @@ for (let className of extractClasses(rule)) {

layer: 'user',
sort: BigInt(idx) + highestOffset,
sort,
important: false,

@@ -308,26 +308,93 @@ },

* Which means that we can replace `.hover\:font-bold` with `.abc` in `.hover\:font-bold:hover` resulting in `.abc:hover`
*
* @param {string} selector
* @param {string} utilitySelectors
* @param {string} candidate
*/
// TODO: Should we use postcss-selector-parser for this instead?
function replaceSelector(selector, utilitySelectors, candidate) {
let needle = `.${escapeClassName(candidate)}`
let needles = [...new Set([needle, needle.replace(/\\2c /g, '\\,')])]
let selectorList = extractSelectors(selector)
let utilitySelectorsList = extractSelectors(utilitySelectors)
let candidateList = extractSelectors(`.${escapeClassName(candidate)}`)
let candidateClass = candidateList.nodes[0].nodes[0]
return extractSelectors(selector)
.map((s) => {
let replaced = []
selectorList.each((sel) => {
/** @type {Set<import('postcss-selector-parser').Selector>} */
let replaced = new Set()
for (let utilitySelector of utilitySelectorsList) {
let replacedSelector = utilitySelector
for (const needle of needles) {
replacedSelector = replacedSelector.replace(needle, s)
utilitySelectorsList.each((utilitySelector) => {
let hasReplaced = false
utilitySelector = utilitySelector.clone()
utilitySelector.walkClasses((node) => {
if (node.value !== candidateClass.value) {
return
}
if (replacedSelector === utilitySelector) {
continue
// Don't replace multiple instances of the same class
// This is theoretically correct but only partially
// We'd need to generate every possible permutation of the replacement
// For example with `.foo + .foo { … }` and `section { @apply foo; }`
// We'd need to generate all of these:
// - `.foo + .foo`
// - `.foo + section`
// - `section + .foo`
// - `section + section`
if (hasReplaced) {
return
}
replaced.push(replacedSelector)
// Since you can only `@apply` class names this is sufficient
// We want to replace the matched class name with the selector the user is using
// Ex: Replace `.text-blue-500` with `.foo.bar:is(.something-cool)`
node.replaceWith(...sel.nodes.map((node) => node.clone()))
// Record that we did something and we want to use this new selector
replaced.add(utilitySelector)
hasReplaced = true
})
})
// Sort tag names before class names (but only sort each group (separated by a combinator)
// separately and not in total)
// This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
for (let sel of replaced) {
let groups = [[]]
for (let node of sel.nodes) {
if (node.type === 'combinator') {
groups.push(node)
groups.push([])
} else {
let last = groups[groups.length - 1]
last.push(node)
}
}
return replaced.join(', ')
})
.join(', ')
sel.nodes = []
for (let group of groups) {
if (Array.isArray(group)) {
group.sort((a, b) => {
if (a.type === 'tag' && b.type === 'class') {
return -1
} else if (a.type === 'class' && b.type === 'tag') {
return 1
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) {
return -1
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') {
return 1
}
return 0
})
}
sel.nodes = sel.nodes.concat(group)
}
}
sel.replaceWith(...replaced)
})
return selectorList.toString()
}

@@ -347,3 +414,3 @@

if (apply.parent.name === 'screen') {
const screenType = apply.parent.params
let screenType = apply.parent.params

@@ -376,2 +443,19 @@ throw apply.error(

// Verify that we can apply the class
for (let [, rule] of rules) {
if (rule.type === 'atrule') {
continue
}
rule.walkRules(() => {
throw apply.error(
[
`The \`${applyCandidate}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`,
'Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:',
'https://tailwindcss.com/docs/using-with-preprocessors#nesting',
].join('\n')
)
})
}
candidates.push([applyCandidate, important, rules])

@@ -381,3 +465,3 @@ }

for (const [parent, [candidates, atApplySource]] of perParentApplies) {
for (let [parent, [candidates, atApplySource]] of perParentApplies) {
let siblings = []

@@ -499,2 +583,9 @@

// 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)

@@ -504,3 +595,3 @@

if (importantSelector && parentSelector !== parent.selector) {
rule.selector = `${importantSelector} ${rule.selector}`
rule.selector = applyImportantSelector(rule.selector, importantSelector)
}

@@ -511,11 +602,18 @@

})
// Move pseudo elements to the end of the selector (if necessary)
let selector = parser().astSync(rule.selector)
selector.each((sel) => movePseudos(sel))
rule.selector = selector.toString()
})
}
// It could be that the node we were inserted was removed because the class didn't match
// If that was the *only* rule in the parent, then we have nothing add so we skip it
if (!root.nodes[0]) {
continue
}
// Insert it
siblings.push([
// Ensure that when we are sorting, that we take the layer order into account
{ ...meta, sort: meta.sort | context.layerOrder[meta.layer] },
root.nodes[0],
])
siblings.push([meta.sort, root.nodes[0]])
}

@@ -525,3 +623,3 @@ }

// Inject the rules, sorted, correctly
let nodes = siblings.sort(([a], [z]) => bigSign(a.sort - z.sort)).map((s) => s[1])
let nodes = context.offsets.sort(siblings).map((s) => s[1])

@@ -528,0 +626,0 @@ // `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }

@@ -1,5 +0,5 @@

import LRU from 'quick-lru'
import fs from 'fs'
import LRU from '@alloc/quick-lru'
import * as sharedState from './sharedState'
import { generateRules } from './generateRules'
import bigSign from '../util/bigSign'
import log from '../util/log'

@@ -77,4 +77,9 @@ import cloneNodes from '../util/cloneNodes'

/**
*
* @param {[import('./offsets.js').RuleOffset, import('postcss').Node][]} rules
* @param {*} context
*/
function buildStylesheet(rules, context) {
let sortedRules = rules.sort(([a], [z]) => bigSign(a - z))
let sortedRules = context.offsets.sort(rules)

@@ -87,44 +92,6 @@ let returnValue = {

variants: new Set(),
// All the CSS that is not Tailwind related can be put in this bucket. This
// will make it easier to later use this information when we want to
// `@apply` for example. The main reason we do this here is because we
// still need to make sure the order is correct. Last but not least, we
// will make sure to always re-inject this section into the css, even if
// certain rules were not used. This means that it will look like a no-op
// from the user's perspective, but we gathered all the useful information
// we need.
user: new Set(),
}
for (let [sort, rule] of sortedRules) {
if (sort >= context.minimumScreen) {
returnValue.variants.add(rule)
continue
}
if (sort & context.layerOrder.base) {
returnValue.base.add(rule)
continue
}
if (sort & context.layerOrder.defaults) {
returnValue.defaults.add(rule)
continue
}
if (sort & context.layerOrder.components) {
returnValue.components.add(rule)
continue
}
if (sort & context.layerOrder.utilities) {
returnValue.utilities.add(rule)
continue
}
if (sort & context.layerOrder.user) {
returnValue.user.add(rule)
continue
}
returnValue[sort.layer].add(rule)
}

@@ -136,3 +103,3 @@

export default function expandTailwindAtRules(context) {
return (root) => {
return async (root) => {
let layerNodes = {

@@ -164,3 +131,3 @@ base: null,

// Find potential rules in changed files
let candidates = new Set([sharedState.NOT_ON_DEMAND])
let candidates = new Set([...(context.candidates ?? []), sharedState.NOT_ON_DEMAND])
let seen = new Set()

@@ -170,8 +137,23 @@

for (let { content, extension } of context.changedContent) {
let transformer = getTransformer(context.tailwindConfig, extension)
let extractor = getExtractor(context, extension)
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)
})
)
}
env.DEBUG && console.timeEnd('Reading changed files')

@@ -185,3 +167,12 @@

env.DEBUG && console.time('Generate rules')
let rules = generateRules(candidates, context)
env.DEBUG && console.time('Sorting candidates')
let sortedCandidates = new Set(
[...candidates].sort((a, z) => {
if (a === z) return 0
if (a < z) return -1
return 1
})
)
env.DEBUG && console.timeEnd('Sorting candidates')
generateRules(sortedCandidates, context)
env.DEBUG && console.timeEnd('Generate rules')

@@ -192,6 +183,2 @@

if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
for (let rule of rules) {
context.ruleCache.add(rule)
}
context.stylesheetCache = buildStylesheet([...context.ruleCache], context)

@@ -270,2 +257,5 @@ }

// TODO: Why is the root node having no source location for `end` possible?
root.source.end = root.source.end ?? root.source.start
// If we've got a utility layer and no utilities are generated there's likely something wrong

@@ -272,0 +262,0 @@ const hasUtilityVariants = variantNodes.some(

@@ -6,11 +6,17 @@ import postcss from 'postcss'

import prefixSelector from '../util/prefixSelector'
import { updateAllClasses } from '../util/pluginUtils'
import { updateAllClasses, getMatchingTypes } from '../util/pluginUtils'
import log from '../util/log'
import * as sharedState from './sharedState'
import { formatVariantSelector, finalizeSelector } from '../util/formatVariantSelector'
import {
formatVariantSelector,
finalizeSelector,
eliminateIrrelevantSelectors,
} from '../util/formatVariantSelector'
import { asClass } from '../util/nameClass'
import { normalize } from '../util/dataTypes'
import { isValidVariantFormatString, parseVariant } from './setupContextUtils'
import isValidArbitraryValue from '../util/isValidArbitraryValue'
import { isValidVariantFormatString, parseVariant, INTERNAL_FEATURES } from './setupContextUtils'
import isValidArbitraryValue from '../util/isSyntacticallyValidPropertyValue'
import { splitAtTopLevelOnly } from '../util/splitAtTopLevelOnly.js'
import { flagEnabled } from '../featureFlags'
import { applyImportantSelector } from '../util/applyImportantSelector'

@@ -21,3 +27,3 @@ let classNameParser = selectorParser((selectors) => {

function getClassNameFromSelector(selector) {
export function getClassNameFromSelector(selector) {
return classNameParser.transformSync(selector)

@@ -38,2 +44,3 @@ }

let dashIdx
let wasSlash = false

@@ -45,3 +52,13 @@ if (lastIndex === Infinity && candidate.endsWith(']')) {

// eg. string[]
dashIdx = ['-', '/'].includes(candidate[bracketIdx - 1]) ? bracketIdx - 1 : -1
if (candidate[bracketIdx - 1] === '-') {
dashIdx = bracketIdx - 1
} else if (candidate[bracketIdx - 1] === '/') {
dashIdx = bracketIdx - 1
wasSlash = true
} else {
dashIdx = -1
}
} else if (lastIndex === Infinity && candidate.includes('/')) {
dashIdx = candidate.lastIndexOf('/')
wasSlash = true
} else {

@@ -56,7 +73,12 @@ dashIdx = candidate.lastIndexOf('-', lastIndex)

let prefix = candidate.slice(0, dashIdx)
let modifier = candidate.slice(dashIdx + 1)
let modifier = candidate.slice(wasSlash ? dashIdx : dashIdx + 1)
lastIndex = dashIdx - 1
// TODO: This feels a bit hacky
if (prefix === '' || modifier === '/') {
continue
}
yield [prefix, modifier]
lastIndex = dashIdx - 1
}

@@ -102,15 +124,34 @@ }

}
let result = []
function isInKeyframes(rule) {
return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes'
}
for (let [meta, rule] of matches) {
let container = postcss.root({ nodes: [rule.clone()] })
container.walkRules((r) => {
r.selector = updateAllClasses(r.selector, (className) => {
if (className === classCandidate) {
return `!${className}`
}
return className
})
// Declarations inside keyframes cannot be marked as important
// They will be ignored by the browser
if (isInKeyframes(r)) {
return
}
let ast = selectorParser().astSync(r.selector)
// Remove extraneous selectors that do not include the base candidate
ast.each((sel) => eliminateIrrelevantSelectors(sel, classCandidate))
// Update all instances of the base candidate to include the important marker
updateAllClasses(ast, (className) =>
className === classCandidate ? `!${className}` : className
)
r.selector = ast.toString()
r.walkDecls((d) => (d.important = true))
})
result.push([{ ...meta, important: true }, container.nodes[0]])

@@ -136,8 +177,46 @@ }

let args
/** @type {{modifier: string | null, value: string | null}} */
let args = { modifier: null, value: sharedState.NONE }
// Find partial arbitrary variants
// Retrieve "modifier"
{
let [baseVariant, ...modifiers] = splitAtTopLevelOnly(variant, '/')
// This is a hack to support variants with `/` in them, like `ar-1/10/20:text-red-500`
// In this case 1/10 is a value but /20 is a modifier
if (modifiers.length > 1) {
baseVariant = baseVariant + '/' + modifiers.slice(0, -1).join('/')
modifiers = modifiers.slice(-1)
}
if (modifiers.length && !context.variantMap.has(variant)) {
variant = baseVariant
args.modifier = modifiers[0]
if (!flagEnabled(context.tailwindConfig, 'generalizedModifiers')) {
return []
}
}
}
// Retrieve "arbitrary value"
if (variant.endsWith(']') && !variant.startsWith('[')) {
args = variant.slice(variant.lastIndexOf('[') + 1, -1)
variant = variant.slice(0, variant.indexOf(args) - 1 /* - */ - 1 /* [ */)
// We either have:
// @[200px]
// group-[:hover]
//
// But we don't want:
// @-[200px] (`-` is incorrect)
// group[:hover] (`-` is missing)
let match = /(.)(-?)\[(.*)\]/g.exec(variant)
if (match) {
let [, char, separator, value] = match
// @-[200px] case
if (char === '@' && separator === '-') return []
// group[:hover] case
if (char !== '@' && separator === '') return []
variant = variant.replace(`${separator}[${value}]`, '')
args.value = value
}
}

@@ -147,19 +226,36 @@

if (isArbitraryValue(variant) && !context.variantMap.has(variant)) {
let sort = context.offsets.recordVariant(variant)
let selector = normalize(variant.slice(1, -1))
let selectors = splitAtTopLevelOnly(selector, ',')
if (!isValidVariantFormatString(selector)) {
// We do not support multiple selectors for arbitrary variants
if (selectors.length > 1) {
return []
}
let fn = parseVariant(selector)
if (!selectors.every(isValidVariantFormatString)) {
return []
}
let sort = Array.from(context.variantOrder.values()).pop() << 1n
context.variantMap.set(variant, [[sort, fn]])
context.variantOrder.set(variant, sort)
let records = selectors.map((sel, idx) => [
context.offsets.applyParallelOffset(sort, idx),
parseVariant(sel.trim()),
])
context.variantMap.set(variant, records)
}
if (context.variantMap.has(variant)) {
let variantFunctionTuples = context.variantMap.get(variant)
let isArbitraryVariant = isArbitraryValue(variant)
let internalFeatures = context.variantOptions.get(variant)?.[INTERNAL_FEATURES] ?? {}
let variantFunctionTuples = context.variantMap.get(variant).slice()
let result = []
let respectPrefix = (() => {
if (isArbitraryVariant) return false
if (internalFeatures.respectPrefix === false) return false
return true
})()
for (let [meta, rule] of matches) {

@@ -173,11 +269,13 @@ // Don't generate variants for user css

for (let [variantSort, variantFunction] of variantFunctionTuples) {
let clone = container.clone()
for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples) {
let clone = (containerFromArray ?? container).clone()
let collectedFormats = []
let originals = new Map()
function prepareBackup() {
if (originals.size > 0) return // Already prepared, chicken out
clone.walkRules((rule) => originals.set(rule, rule.selector))
// Already prepared, chicken out
if (clone.raws.neededBackup) {
return
}
clone.raws.neededBackup = true
clone.walkRules((rule) => (rule.raws.originalSelector = rule.selector))
}

@@ -222,3 +320,6 @@

format(selectorFormat) {
collectedFormats.push(selectorFormat)
collectedFormats.push({
format: selectorFormat,
respectPrefix,
})
},

@@ -228,4 +329,27 @@ args,

// It can happen that a list of format strings is returned from within the function. In that
// case, we have to process them as well. We can use the existing `variantSort`.
if (Array.isArray(ruleWithVariant)) {
for (let [idx, variantFunction] of ruleWithVariant.entries()) {
// This is a little bit scary since we are pushing to an array of items that we are
// currently looping over. However, you can also think of it like a processing queue
// where you keep handling jobs until everything is done and each job can queue more
// jobs if needed.
variantFunctionTuples.push([
context.offsets.applyParallelOffset(variantSort, idx),
variantFunction,
// If the clone has been modified we have to pass that back
// though so each rule can use the modified container
clone.clone(),
])
}
continue
}
if (typeof ruleWithVariant === 'string') {
collectedFormats.push(ruleWithVariant)
collectedFormats.push({
format: ruleWithVariant,
respectPrefix,
})
}

@@ -237,9 +361,11 @@

// We filled the `originals`, therefore we assume that somebody touched
// We had to backup selectors, therefore we assume that somebody touched
// `container` or `modifySelectors`. Let's see if they did, so that we
// can restore the selectors, and collect the format strings.
if (originals.size > 0) {
if (clone.raws.neededBackup) {
delete clone.raws.neededBackup
clone.walkRules((rule) => {
if (!originals.has(rule)) return
let before = originals.get(rule)
let before = rule.raws.originalSelector
if (!before) return
delete rule.raws.originalSelector
if (before === rule.selector) return // No mutation happened

@@ -270,3 +396,6 @@

// format: .foo &
collectedFormats.push(modified.replace(rebuiltBase, '&'))
collectedFormats.push({
format: modified.replace(rebuiltBase, '&'),
respectPrefix,
})
rule.selector = before

@@ -285,3 +414,7 @@ })

...meta,
sort: variantSort | meta.sort,
sort: context.offsets.applyVariantOffset(
meta.sort,
variantSort,
Object.assign(args, context.variantOptions.get(variant))
),
collectedFormats: (meta.collectedFormats ?? []).concat(collectedFormats),

@@ -350,3 +483,3 @@ },

node.walkDecls((decl) => {
if (!isParsableCssValue(decl.name, decl.value)) {
if (!isParsableCssValue(decl.prop, decl.value)) {
isParsable = false

@@ -391,3 +524,3 @@ return false

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

@@ -398,5 +531,7 @@ if (!isParsableCssValue(property, normalized)) {

let sort = context.offsets.arbitraryProperty(classCandidate)
return [
[
{ sort: context.arbitraryPropertiesSort, layer: 'utilities' },
{ sort, layer: 'utilities', options: { respectImportant: true } },
() => ({

@@ -453,3 +588,3 @@ [asClass(classCandidate)]: {

return Array.from(splitAtTopLevelOnly(input, separator))
return splitAtTopLevelOnly(input, separator)
}

@@ -459,3 +594,7 @@

for (const match of matches) {
match[1].raws.tailwind = { ...match[1].raws.tailwind, classCandidate }
match[1].raws.tailwind = {
...match[1].raws.tailwind,
classCandidate,
preserveSource: match[0].options?.preserveSource ?? false,
}

@@ -516,3 +655,15 @@ yield match

if (matchesPerPlugin.length > 0) {
typesByMatches.set(matchesPerPlugin, sort.options?.type)
let matchingTypes = Array.from(
getMatchingTypes(
sort.options?.types ?? [],
modifier,
sort.options ?? {},
context.tailwindConfig
)
).map(([_, type]) => type)
if (matchingTypes.length > 0) {
typesByMatches.set(matchesPerPlugin, matchingTypes)
}
matches.push(matchesPerPlugin)

@@ -523,58 +674,111 @@ }

if (isArbitraryValue(modifier)) {
// When generated arbitrary values are ambiguous, we can't know
// which to pick so don't generate any utilities for them
if (matches.length > 1) {
let typesPerPlugin = matches.map((match) => new Set([...(typesByMatches.get(match) ?? [])]))
// Partition plugins in 2 categories so that we can start searching in the plugins that
// don't have `any` as a type first.
let [withAny, withoutAny] = matches.reduce(
(group, plugin) => {
let hasAnyType = plugin.some(([{ options }]) =>
options.types.some(({ type }) => type === 'any')
)
// Remove duplicates, so that we can detect proper unique types for each plugin.
for (let pluginTypes of typesPerPlugin) {
for (let type of pluginTypes) {
let removeFromOwnGroup = false
if (hasAnyType) {
group[0].push(plugin)
} else {
group[1].push(plugin)
}
return group
},
[[], []]
)
for (let otherGroup of typesPerPlugin) {
if (pluginTypes === otherGroup) continue
function findFallback(matches) {
// If only a single plugin matches, let's take that one
if (matches.length === 1) {
return matches[0]
}
if (otherGroup.has(type)) {
otherGroup.delete(type)
removeFromOwnGroup = true
// Otherwise, find the plugin that creates a valid rule given the arbitrary value, and
// also has the correct type which preferOnConflicts the plugin in case of clashes.
return matches.find((rules) => {
let matchingTypes = typesByMatches.get(rules)
return rules.some(([{ options }, rule]) => {
if (!isParsableNode(rule)) {
return false
}
}
if (removeFromOwnGroup) pluginTypes.delete(type)
}
return options.types.some(
({ type, preferOnConflict }) => matchingTypes.includes(type) && preferOnConflict
)
})
})
}
let messages = []
// Try to find a fallback plugin, because we already know that multiple plugins matched for
// the given arbitrary value.
let fallback = findFallback(withoutAny) ?? findFallback(withAny)
if (fallback) {
matches = [fallback]
}
for (let [idx, group] of typesPerPlugin.entries()) {
for (let type of group) {
let rules = matches[idx]
.map(([, rule]) => rule)
.flat()
.map((rule) =>
rule
.toString()
.split('\n')
.slice(1, -1) // Remove selector and closing '}'
.map((line) => line.trim())
.map((x) => ` ${x}`) // Re-indent
.join('\n')
// We couldn't find a fallback plugin which means that there are now multiple plugins that
// generated css for the current candidate. This means that the result is ambiguous and this
// should not happen. We won't generate anything right now, so let's report this to the user
// by logging some options about what they can do.
else {
let typesPerPlugin = matches.map(
(match) => new Set([...(typesByMatches.get(match) ?? [])])
)
// Remove duplicates, so that we can detect proper unique types for each plugin.
for (let pluginTypes of typesPerPlugin) {
for (let type of pluginTypes) {
let removeFromOwnGroup = false
for (let otherGroup of typesPerPlugin) {
if (pluginTypes === otherGroup) continue
if (otherGroup.has(type)) {
otherGroup.delete(type)
removeFromOwnGroup = true
}
}
if (removeFromOwnGroup) pluginTypes.delete(type)
}
}
let messages = []
for (let [idx, group] of typesPerPlugin.entries()) {
for (let type of group) {
let rules = matches[idx]
.map(([, rule]) => rule)
.flat()
.map((rule) =>
rule
.toString()
.split('\n')
.slice(1, -1) // Remove selector and closing '}'
.map((line) => line.trim())
.map((x) => ` ${x}`) // Re-indent
.join('\n')
)
.join('\n\n')
messages.push(
` Use \`${candidate.replace('[', `[${type}:`)}\` for \`${rules.trim()}\``
)
.join('\n\n')
break
}
}
messages.push(
` Use \`${candidate.replace('[', `[${type}:`)}\` for \`${rules.trim()}\``
)
break
}
log.warn([
`The class \`${candidate}\` is ambiguous and matches multiple utilities.`,
...messages,
`If this is content and not a class, replace it with \`${candidate
.replace('[', '&lsqb;')
.replace(']', '&rsqb;')}\` to silence this warning.`,
])
continue
}
log.warn([
`The class \`${candidate}\` is ambiguous and matches multiple utilities.`,
...messages,
`If this is content and not a class, replace it with \`${candidate
.replace('[', '&lsqb;')
.replace(']', '&rsqb;')}\` to silence this warning.`,
])
continue
}

@@ -601,15 +805,9 @@

// Apply final format selector
if (match[0].collectedFormats) {
let finalFormat = formatVariantSelector('&', ...match[0].collectedFormats)
let container = postcss.root({ nodes: [match[1].clone()] })
container.walkRules((rule) => {
if (inKeyframes(rule)) return
match = applyFinalFormat(match, { context, candidate })
rule.selector = finalizeSelector(finalFormat, {
selector: rule.selector,
candidate,
context,
})
})
match[1] = container.nodes[0]
// Skip rules with invalid selectors
// This will cause the candidate to be added to the "not class"
// cache skipping it entirely for future builds
if (match === null) {
continue
}

@@ -622,2 +820,72 @@

function applyFinalFormat(match, { context, candidate }) {
if (!match[0].collectedFormats) {
return match
}
let isValid = true
let finalFormat
try {
finalFormat = formatVariantSelector(match[0].collectedFormats, {
context,
candidate,
})
} catch {
// The format selector we produced is invalid
// This could be because:
// - A bug exists
// - A plugin introduced an invalid variant selector (ex: `addVariant('foo', '&;foo')`)
// - The user used an invalid arbitrary variant (ex: `[&;foo]:underline`)
// Either way the build will fail because of this
// We would rather that the build pass "silently" given that this could
// happen because of picking up invalid things when scanning content
// So we'll throw out the candidate instead
return null
}
let container = postcss.root({ nodes: [match[1].clone()] })
container.walkRules((rule) => {
if (inKeyframes(rule)) {
return
}
try {
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 {
// If this selector is invalid we also want to skip it
// But it's likely that being invalid here means there's a bug in a plugin rather than too loosely matching content
isValid = false
return false
}
})
if (!isValid) {
return null
}
// If all rules have been eliminated we can skip this candidate entirely
if (container.nodes.length === 0) {
return null
}
match[1] = container.nodes[0]
return match
}
function inKeyframes(rule) {

@@ -627,4 +895,33 @@ return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes'

function generateRules(candidates, context) {
function getImportantStrategy(important) {
if (important === true) {
return (rule) => {
if (inKeyframes(rule)) {
return
}
rule.walkDecls((d) => {
if (d.parent.type === 'rule' && !inKeyframes(d.parent)) {
d.important = true
}
})
}
}
if (typeof important === 'string') {
return (rule) => {
if (inKeyframes(rule)) {
return
}
rule.selectors = rule.selectors.map((selector) => {
return applyImportantSelector(selector, important)
})
}
}
}
function generateRules(candidates, context, isSorting = false) {
let allRules = []
let strategy = getImportantStrategy(context.tailwindConfig.important)

@@ -636,4 +933,4 @@ for (let candidate of candidates) {

if (context.classCache.has(candidate)) {
allRules.push(context.classCache.get(candidate))
if (context.candidateRuleCache.has(candidate)) {
allRules = allRules.concat(Array.from(context.candidateRuleCache.get(candidate)))
continue

@@ -650,43 +947,25 @@ }

context.classCache.set(candidate, matches)
allRules.push(matches)
}
// Strategy based on `tailwindConfig.important`
let strategy = ((important) => {
if (important === true) {
return (rule) => {
rule.walkDecls((d) => {
if (d.parent.type === 'rule' && !inKeyframes(d.parent)) {
d.important = true
}
})
}
}
let rules = context.candidateRuleCache.get(candidate) ?? new Set()
context.candidateRuleCache.set(candidate, rules)
if (typeof important === 'string') {
return (rule) => {
rule.selectors = rule.selectors.map((selector) => {
return `${important} ${selector}`
})
}
}
})(context.tailwindConfig.important)
for (const match of matches) {
let [{ sort, options }, rule] = match
return allRules.flat(1).map(([{ sort, layer, options }, rule]) => {
if (options.respectImportant) {
if (strategy) {
if (options.respectImportant && strategy) {
let container = postcss.root({ nodes: [rule.clone()] })
container.walkRules((r) => {
if (inKeyframes(r)) {
return
}
strategy(r)
})
container.walkRules(strategy)
rule = container.nodes[0]
}
// 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)
context.ruleCache.add(newEntry)
allRules.push(newEntry)
}
}
return [sort | context.layerOrder[layer], rule]
})
return allRules
}

@@ -693,0 +972,0 @@

import fs from 'fs'
import path from 'path'
import resolve from 'resolve'
import detective from 'detective'
function createModule(file) {
const source = fs.readFileSync(file, 'utf-8')
const requires = detective(source)
let jsExtensions = ['.js', '.cjs', '.mjs']
return { file, requires }
// Given the current file `a.ts`, we want to make sure that when importing `b` that we resolve
// `b.ts` before `b.js`
//
// E.g.:
//
// a.ts
// b // .ts
// c // .ts
// a.js
// b // .js or .ts
let jsResolutionOrder = ['', '.js', '.cjs', '.mjs', '.ts', '.cts', '.mts', '.jsx', '.tsx']
let tsResolutionOrder = ['', '.ts', '.cts', '.mts', '.tsx', '.js', '.cjs', '.mjs', '.jsx']
function resolveWithExtension(file, extensions) {
// Try to find `./a.ts`, `./a.ts`, ... from `./a`
for (let ext of extensions) {
let full = `${file}${ext}`
if (fs.existsSync(full) && fs.statSync(full).isFile()) {
return full
}
}
// Try to find `./a/index.js` from `./a`
for (let ext of extensions) {
let full = `${file}/index${ext}`
if (fs.existsSync(full)) {
return full
}
}
return null
}
export default function getModuleDependencies(entryFile) {
const rootModule = createModule(entryFile)
const modules = [rootModule]
function* _getModuleDependencies(filename, base, seen, ext = path.extname(filename)) {
// Try to find the file
let absoluteFile = resolveWithExtension(
path.resolve(base, filename),
jsExtensions.includes(ext) ? jsResolutionOrder : tsResolutionOrder
)
if (absoluteFile === null) return // File doesn't exist
// Iterate over the modules, even when new
// ones are being added
for (const mdl of modules) {
mdl.requires
.filter((dep) => {
// Only track local modules, not node_modules
return dep.startsWith('./') || dep.startsWith('../')
})
.forEach((dep) => {
try {
const basedir = path.dirname(mdl.file)
const depPath = resolve.sync(dep, { basedir })
const depModule = createModule(depPath)
// Prevent infinite loops when there are circular dependencies
if (seen.has(absoluteFile)) return // Already seen
seen.add(absoluteFile)
modules.push(depModule)
} catch (_err) {
// eslint-disable-next-line no-empty
}
})
// Mark the file as a dependency
yield absoluteFile
// Resolve new base for new imports/requires
base = path.dirname(absoluteFile)
ext = path.extname(absoluteFile)
let contents = fs.readFileSync(absoluteFile, 'utf-8')
// Find imports/requires
for (let match of [
...contents.matchAll(/import[\s\S]*?['"](.{3,}?)['"]/gi),
...contents.matchAll(/import[\s\S]*from[\s\S]*?['"](.{3,}?)['"]/gi),
...contents.matchAll(/require\(['"`](.+)['"`]\)/gi),
]) {
// Bail out if it's not a relative file
if (!match[1].startsWith('.')) continue
yield* _getModuleDependencies(match[1], base, seen, ext)
}
}
return modules
export default function getModuleDependencies(absoluteFilePath) {
if (absoluteFilePath === null) return new Set()
return new Set(
_getModuleDependencies(absoluteFilePath, path.dirname(absoluteFilePath), new Set())
)
}

@@ -94,54 +94,75 @@ import postcss from 'postcss'

for (let universal of universals) {
/** @type {Map<string, Set<string>>} */
let selectorGroups = new Map()
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
for (let universal of universals) {
/** @type {Map<string, Set<string>>} */
let selectorGroups = new Map()
let rules = variableNodeMap.get(universal.params) ?? []
let rules = variableNodeMap.get(universal.params) ?? []
for (let rule of rules) {
for (let selector of extractElementSelector(rule.selector)) {
// If selector contains a vendor prefix after a pseudo element or class,
// we consider them separately because merging the declarations into
// a single rule will cause browsers that do not understand the
// vendor prefix to throw out the whole rule
let selectorGroupName =
selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
for (let rule of rules) {
for (let selector of extractElementSelector(rule.selector)) {
// If selector contains a vendor prefix after a pseudo element or class,
// we consider them separately because merging the declarations into
// a single rule will cause browsers that do not understand the
// vendor prefix to throw out the whole rule
// Additionally if a selector contains `:has` we also consider
// it separately because FF only recently gained support for it
let selectorGroupName =
selector.includes(':-') || selector.includes('::-') || selector.includes(':has')
? selector
: '__DEFAULT__'
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
selectorGroups.set(selectorGroupName, selectors)
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
selectorGroups.set(selectorGroupName, selectors)
selectors.add(selector)
selectors.add(selector)
}
}
}
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
if (selectorGroups.size === 0) {
universal.remove()
continue
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
if (selectorGroups.size === 0) {
universal.remove()
continue
}
for (let [, selectors] of selectorGroups) {
let universalRule = postcss.rule({
source: universal.source,
})
universalRule.selectors = [...selectors]
universalRule.append(universal.nodes.map((node) => node.clone()))
universal.before(universalRule)
}
}
for (let [, selectors] of selectorGroups) {
let universalRule = postcss.rule({
source: universal.source,
})
universal.remove()
}
} else if (universals.size) {
let universalRule = postcss.rule({
selectors: ['*', '::before', '::after'],
})
universalRule.selectors = [...selectors]
for (let universal of universals) {
universalRule.append(universal.nodes)
universalRule.append(universal.nodes.map((node) => node.clone()))
if (!universalRule.parent) {
universal.before(universalRule)
}
} else {
let universalRule = postcss.rule({
source: universal.source,
})
universalRule.selectors = ['*', '::before', '::after']
if (!universalRule.source) {
universalRule.source = universal.source
}
universalRule.append(universal.nodes)
universal.before(universalRule)
universal.remove()
}
universal.remove()
let backdropRule = universalRule.clone({
selectors: ['::backdrop'],
})
universalRule.after(backdropRule)
}
}
}

@@ -14,3 +14,2 @@ import fs from 'fs'

import { coerceValue } from '../util/pluginUtils'
import bigSign from '../util/bigSign'
import { variantPlugins, corePlugins } from '../corePlugins'

@@ -22,8 +21,21 @@ import * as sharedState from './sharedState'

import negateValue from '../util/negateValue'
import isValidArbitraryValue from '../util/isValidArbitraryValue'
import { generateRules } from './generateRules'
import isSyntacticallyValidPropertyValue from '../util/isSyntacticallyValidPropertyValue'
import { generateRules, getClassNameFromSelector } from './generateRules'
import { hasContentChanged } from './cacheInvalidation.js'
import { Offsets } from './offsets.js'
import { flagEnabled } from '../featureFlags.js'
import { finalizeSelector, formatVariantSelector } from '../util/formatVariantSelector'
let MATCH_VARIANT = Symbol()
export const INTERNAL_FEATURES = Symbol()
const VARIANT_TYPES = {
AddVariant: Symbol.for('ADD_VARIANT'),
MatchVariant: Symbol.for('MATCH_VARIANT'),
}
const VARIANT_INFO = {
Base: 1 << 0,
Dynamic: 1 << 1,
}
function prefix(context, selector) {

@@ -34,29 +46,61 @@ let prefix = context.tailwindConfig.prefix

function parseVariantFormatString(input) {
if (input.includes('{')) {
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)
function normalizeOptionTypes({ type = 'any', ...options }) {
let types = [].concat(type)
return input
.split(/{(.*)}/gim)
.flatMap((line) => parseVariantFormatString(line))
.filter(Boolean)
return {
...options,
types: types.map((type) => {
if (Array.isArray(type)) {
return { type: type[0], ...type[1] }
}
return { type, preferOnConflict: false }
}),
}
return [input.trim()]
}
function isBalanced(input) {
let count = 0
function parseVariantFormatString(input) {
/** @type {string[]} */
let parts = []
for (let char of input) {
if (char === '{') {
count++
// When parsing whitespace around special characters are insignificant
// However, _inside_ of a variant they could be
// Because the selector could look like this
// @media { &[data-name="foo bar"] }
// This is why we do not skip whitespace
let current = ''
let depth = 0
for (let idx = 0; idx < input.length; idx++) {
let char = input[idx]
if (char === '\\') {
// Escaped characters are not special
current += '\\' + input[++idx]
} else if (char === '{') {
// Nested rule: start
++depth
parts.push(current.trim())
current = ''
} else if (char === '}') {
if (--count < 0) {
return false // unbalanced
// Nested rule: end
if (--depth < 0) {
throw new Error(`Your { and } are unbalanced.`)
}
parts.push(current.trim())
current = ''
} else {
// Normal character
current += char
}
}
return count === 0
if (current.length > 0) {
parts.push(current.trim())
}
parts = parts.filter((part) => part !== '')
return parts
}

@@ -110,39 +154,41 @@

/**
* 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)
}
}

@@ -195,4 +241,4 @@

let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(str)
return ({ wrap }) => wrap(postcss.atRule({ name, params: params.trim() }))
let [, name, params] = /@(\S*)( .+|[({].*)?/g.exec(str)
return ({ wrap }) => wrap(postcss.atRule({ name, params: params?.trim() ?? '' }))
})

@@ -208,2 +254,9 @@ .reverse()

/**
*
* @param {any} tailwindConfig
* @param {any} context
* @param {object} param2
* @param {Offsets} param2.offsets
*/
function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) {

@@ -230,37 +283,10 @@ function getConfigValue(path, defaultValue) {

function resolveThemeValue(path, defaultValue, opts = {}) {
let parts = toPath(path)
let value = getConfigValue(['theme', ...parts], defaultValue)
return transformThemeValue(parts[0])(value, opts)
}
let variantIdentifier = 0
let api = {
addVariant(variantName, variantFunctions, options = {}) {
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
if (typeof variantFunction !== 'string') {
// Safelist public API functions
return ({ args, modifySelectors, container, separator, wrap, format }) => {
let result = variantFunction(
Object.assign(
{ modifySelectors, container, separator },
variantFunction[MATCH_VARIANT] && { args, wrap, format }
)
)
if (typeof result === 'string' && !isValidVariantFormatString(result)) {
throw new Error(
`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`
)
}
return result
}
}
if (!isValidVariantFormatString(variantFunction)) {
throw new Error(
`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`
)
}
return parseVariant(variantFunction)
})
insertInto(variantList, variantName, options)
variantMap.set(variantName, variantFunctions)
},
postcss,

@@ -270,7 +296,3 @@ prefix: applyConfiguredPrefix,

config: getConfigValue,
theme(path, defaultValue) {
const [pathRoot, ...subPaths] = toPath(path)
const value = getConfigValue(['theme', pathRoot, ...subPaths], defaultValue)
return transformThemeValue(pathRoot)(value)
},
theme: resolveThemeValue,
corePlugins: (path) => {

@@ -290,3 +312,3 @@ if (Array.isArray(tailwindConfig.corePlugins)) {

let prefixedIdentifier = prefixIdentifier(identifier, {})
let offset = offsets.base++
let offset = offsets.create('base')

@@ -320,3 +342,3 @@ if (!context.candidateRuleMap.has(prefixedIdentifier)) {

.get(prefixedIdentifier)
.push([{ sort: offsets.base++, layer: 'defaults' }, rule])
.push([{ sort: offsets.create('defaults'), layer: 'defaults' }, rule])
}

@@ -326,2 +348,3 @@ },

let defaultOptions = {
preserveSource: false,
respectPrefix: true,

@@ -344,3 +367,3 @@ respectImportant: false,

.get(prefixedIdentifier)
.push([{ sort: offsets.components++, layer: 'components', options }, rule])
.push([{ sort: offsets.create('components'), layer: 'components', options }, rule])
}

@@ -350,2 +373,3 @@ },

let defaultOptions = {
preserveSource: false,
respectPrefix: true,

@@ -368,3 +392,3 @@ respectImportant: true,

.get(prefixedIdentifier)
.push([{ sort: offsets.utilities++, layer: 'utilities', options }, rule])
.push([{ sort: offsets.create('utilities'), layer: 'utilities', options }, rule])
}

@@ -376,7 +400,8 @@ },

respectImportant: true,
modifiers: false,
}
options = { ...defaultOptions, ...options }
options = normalizeOptionTypes({ ...defaultOptions, ...options })
let offset = offsets.utilities++
let offset = offsets.create('utilities')

@@ -390,5 +415,8 @@ for (let identifier in utilities) {

function wrapped(modifier, { isOnlyPlugin }) {
let { type = 'any' } = options
type = [].concat(type)
let [value, coercedType] = coerceValue(type, modifier, options, tailwindConfig)
let [value, coercedType, utilityModifier] = coerceValue(
options.types,
modifier,
options,
tailwindConfig
)

@@ -399,12 +427,36 @@ if (value === undefined) {

if (!type.includes(coercedType) && !isOnlyPlugin) {
return []
if (!options.types.some(({ type }) => type === coercedType)) {
if (isOnlyPlugin) {
log.warn([
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
`You can safely update it to \`${identifier}-${modifier.replace(
coercedType + ':',
''
)}\`.`,
])
} else {
return []
}
}
if (!isValidArbitraryValue(value)) {
if (!isSyntacticallyValidPropertyValue(value)) {
return []
}
let extras = {
get modifier() {
if (!options.modifiers) {
log.warn(`modifier-used-without-options-for-${identifier}`, [
'Your plugin must set `modifiers: true` in its options to support modifiers.',
])
}
return utilityModifier
},
}
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
let ruleSets = []
.concat(rule(value))
.concat(modifiersEnabled ? rule(value, extras) : rule(value))
.filter(Boolean)

@@ -431,7 +483,8 @@ .map((declaration) => ({

respectImportant: false,
modifiers: false,
}
options = { ...defaultOptions, ...options }
options = normalizeOptionTypes({ ...defaultOptions, ...options })
let offset = offsets.components++
let offset = offsets.create('components')

@@ -445,5 +498,8 @@ for (let identifier in components) {

function wrapped(modifier, { isOnlyPlugin }) {
let { type = 'any' } = options
type = [].concat(type)
let [value, coercedType] = coerceValue(type, modifier, options, tailwindConfig)
let [value, coercedType, utilityModifier] = coerceValue(
options.types,
modifier,
options,
tailwindConfig
)

@@ -454,3 +510,3 @@ if (value === undefined) {

if (!type.includes(coercedType)) {
if (!options.types.some(({ type }) => type === coercedType)) {
if (isOnlyPlugin) {

@@ -469,8 +525,22 @@ log.warn([

if (!isValidArbitraryValue(value)) {
if (!isSyntacticallyValidPropertyValue(value)) {
return []
}
let extras = {
get modifier() {
if (!options.modifiers) {
log.warn(`modifier-used-without-options-for-${identifier}`, [
'Your plugin must set `modifiers: true` in its options to support modifiers.',
])
}
return utilityModifier
},
}
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
let ruleSets = []
.concat(rule(value))
.concat(modifiersEnabled ? rule(value, extras) : rule(value))
.filter(Boolean)

@@ -493,27 +563,101 @@ .map((declaration) => ({

},
matchVariant: function (variants, options) {
for (let variant in variants) {
for (let [k, v] of Object.entries(options?.values ?? {})) {
api.addVariant(`${variant}-${k}`, variants[variant](v))
addVariant(variantName, variantFunctions, options = {}) {
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
if (typeof variantFunction !== 'string') {
// Safelist public API functions
return (api = {}) => {
let { args, modifySelectors, container, separator, wrap, format } = api
let result = variantFunction(
Object.assign(
{ modifySelectors, container, separator },
options.type === VARIANT_TYPES.MatchVariant && { args, wrap, format }
)
)
if (typeof result === 'string' && !isValidVariantFormatString(result)) {
throw new Error(
`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`
)
}
if (Array.isArray(result)) {
return result
.filter((variant) => typeof variant === 'string')
.map((variant) => parseVariant(variant))
}
// result may be undefined with legacy variants that use APIs like `modifySelectors`
// result may also be a postcss node if someone was returning the result from `modifySelectors`
return result && typeof result === 'string' && parseVariant(result)(api)
}
}
if (!isValidVariantFormatString(variantFunction)) {
throw new Error(
`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`
)
}
return parseVariant(variantFunction)
})
insertInto(variantList, variantName, options)
variantMap.set(variantName, variantFunctions)
context.variantOptions.set(variantName, options)
},
matchVariant(variant, variantFn, options) {
// A unique identifier that "groups" these variants together.
// This is for internal use only which is why it is not present in the types
let id = options?.id ?? ++variantIdentifier
let isSpecial = variant === '@'
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
for (let [key, value] of Object.entries(options?.values ?? {})) {
if (key === 'DEFAULT') continue
api.addVariant(
variant,
Object.assign(
({ args, wrap }) => {
let formatString = variants[variant](args)
if (!formatString) return null
isSpecial ? `${variant}${key}` : `${variant}-${key}`,
({ args, container }) => {
return variantFn(
value,
modifiersEnabled ? { modifier: args?.modifier, container } : { container }
)
},
if (!formatString.startsWith('@')) {
return formatString
}
let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(formatString)
return wrap(postcss.atRule({ name, params: params.trim() }))
},
{ [MATCH_VARIANT]: true }
),
options
{
...options,
value,
id,
type: VARIANT_TYPES.MatchVariant,
variantInfo: VARIANT_INFO.Base,
}
)
}
let hasDefault = 'DEFAULT' in (options?.values ?? {})
api.addVariant(
variant,
({ args, container }) => {
if (args?.value === sharedState.NONE && !hasDefault) {
return null
}
return variantFn(
args?.value === sharedState.NONE
? options.values.DEFAULT
: // Falling back to args if it is a string, otherwise '' for older intellisense
// (JetBrains) plugins.
args?.value ?? (typeof args === 'string' ? args : ''),
modifiersEnabled ? { modifier: args?.modifier, container } : { container }
)
},
{
...options,
id,
type: VARIANT_TYPES.MatchVariant,
variantInfo: VARIANT_INFO.Dynamic,
}
)
},

@@ -535,2 +679,3 @@ }

let changed = false
let mtimesToCommit = new Map()

@@ -556,6 +701,6 @@ for (let file of files) {

fileModifiedMap.set(file, newModified)
mtimesToCommit.set(file, newModified)
}
return changed
return [changed, mtimesToCommit]
}

@@ -597,3 +742,3 @@

layerPlugins.push(function ({ addComponents }) {
addComponents(node, { respectPrefix: false })
addComponents(node, { respectPrefix: false, preserveSource: true })
})

@@ -605,3 +750,3 @@ }

layerPlugins.push(function ({ addUtilities }) {
addUtilities(node, { respectPrefix: false })
addUtilities(node, { respectPrefix: false, preserveSource: true })
})

@@ -640,14 +785,42 @@ }

let beforeVariants = [
variantPlugins['childVariant'],
variantPlugins['pseudoElementVariants'],
variantPlugins['pseudoClassVariants'],
variantPlugins['hasVariants'],
variantPlugins['ariaVariants'],
variantPlugins['dataVariants'],
]
let afterVariants = [
variantPlugins['supportsVariants'],
variantPlugins['reducedMotionVariants'],
variantPlugins['prefersContrastVariants'],
variantPlugins['screenVariants'],
variantPlugins['orientationVariants'],
variantPlugins['directionVariants'],
variantPlugins['reducedMotionVariants'],
variantPlugins['darkVariants'],
variantPlugins['forcedColorsVariants'],
variantPlugins['printVariant'],
variantPlugins['screenVariants'],
variantPlugins['orientationVariants'],
]
// This is a compatibility fix for the pre 3.4 dark mode behavior
// `class` retains the old behavior, but `selector` keeps the new behavior
let isLegacyDarkMode =
context.tailwindConfig.darkMode === 'class' ||
(Array.isArray(context.tailwindConfig.darkMode) &&
context.tailwindConfig.darkMode[0] === 'class')
if (isLegacyDarkMode) {
afterVariants = [
variantPlugins['supportsVariants'],
variantPlugins['reducedMotionVariants'],
variantPlugins['prefersContrastVariants'],
variantPlugins['darkVariants'],
variantPlugins['screenVariants'],
variantPlugins['orientationVariants'],
variantPlugins['directionVariants'],
variantPlugins['forcedColorsVariants'],
variantPlugins['printVariant'],
]
}
return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]

@@ -659,10 +832,7 @@ }

let variantMap = new Map()
let offsets = {
defaults: 0n,
base: 0n,
components: 0n,
utilities: 0n,
user: 0n,
}
context.variantMap = variantMap
let offsets = new Offsets()
context.offsets = offsets
let classList = new Set()

@@ -687,45 +857,13 @@

let highestOffset = ((args) => args.reduce((m, e) => (e > m ? e : m)))([
offsets.base,
offsets.defaults,
offsets.components,
offsets.utilities,
offsets.user,
])
let reservedBits = BigInt(highestOffset.toString(2).length)
// Make sure to record bit masks for every variant
offsets.recordVariants(variantList, (variant) => variantMap.get(variant).length)
// A number one less than the top range of the highest offset area
// so arbitrary properties are always sorted at the end.
context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n
context.layerOrder = {
defaults: (1n << reservedBits) << 0n,
base: (1n << reservedBits) << 1n,
components: (1n << reservedBits) << 2n,
utilities: (1n << reservedBits) << 3n,
user: (1n << reservedBits) << 4n,
}
reservedBits += 5n
let offset = 0
context.variantOrder = new Map(
variantList
.map((variant, i) => {
let variantFunctions = variantMap.get(variant).length
let bits = (1n << BigInt(i + offset)) << reservedBits
offset += variantFunctions - 1
return [variant, bits]
})
.sort(([, a], [, z]) => bigSign(a - z))
)
context.minimumScreen = [...context.variantOrder.values()].shift()
// Build variantMap
for (let [variantName, variantFunctions] of variantMap.entries()) {
let sort = context.variantOrder.get(variantName)
context.variantMap.set(
variantName,
variantFunctions.map((variantFunction, idx) => [sort << BigInt(idx), variantFunction])
variantFunctions.map((variantFunction, idx) => [
offsets.forVariant(variantName, idx),
variantFunction,
])
)

@@ -759,2 +897,3 @@ }

let prefixLength = context.tailwindConfig.prefix.length
let checkImportantUtils = checks.some((check) => check.pattern.source.includes('!'))

@@ -785,2 +924,17 @@ for (let util of classList) {

if (options.types.some(({ type }) => type === 'color')) {
classes = [
...classes,
...classes.flatMap((cls) =>
Object.keys(context.tailwindConfig.theme.opacity).map(
(opacity) => `${cls}/${opacity}`
)
),
]
}
if (checkImportantUtils && options?.respectImportant) {
classes = [...classes, ...classes.map((cls) => '!' + cls)]
}
return classes

@@ -827,12 +981,37 @@ })()

let darkClassName = [].concat(context.tailwindConfig.darkMode ?? 'media')[1] ?? 'dark'
// A list of utilities that are used by certain Tailwind CSS utilities but
// that don't exist on their own. This will result in them "not existing" and
// sorting could be weird since you still require them in order to make the
// host utitlies work properly. (Thanks Biology)
let parasiteUtilities = new Set([prefix(context, 'group'), prefix(context, 'peer')])
// host utilities work properly. (Thanks Biology)
let parasiteUtilities = [
prefix(context, darkClassName),
prefix(context, 'group'),
prefix(context, 'peer'),
]
context.getClassOrder = function getClassOrder(classes) {
let sortedClassNames = new Map()
for (let [sort, rule] of generateRules(new Set(classes), context)) {
if (sortedClassNames.has(rule.raws.tailwind.candidate)) continue
sortedClassNames.set(rule.raws.tailwind.candidate, sort)
// Sort classes so they're ordered in a deterministic manner
let sorted = [...classes].sort((a, z) => {
if (a === z) return 0
if (a < z) return -1
return 1
})
// Non-util classes won't be generated, so we default them to null
let sortedClassNames = new Map(sorted.map((className) => [className, null]))
// Sort all classes in order
// Non-tailwind classes won't be generated and will be left as `null`
let rules = generateRules(new Set(sorted), context, true)
rules = context.offsets.sort(rules)
let idx = BigInt(parasiteUtilities.length)
for (const [, rule] of rules) {
let candidate = rule.raws.tailwind.candidate
// When multiple rules match a candidate
// always take the position of the first one
sortedClassNames.set(candidate, sortedClassNames.get(candidate) ?? idx++)
}

@@ -842,8 +1021,9 @@

let order = sortedClassNames.get(className) ?? null
let parasiteIndex = parasiteUtilities.indexOf(className)
if (order === null && parasiteUtilities.has(className)) {
if (order === null && parasiteIndex !== -1) {
// This will make sure that it is at the very beginning of the
// `components` layer which technically means 'before any
// components'.
order = context.layerOrder.components
order = BigInt(parasiteIndex)
}

@@ -857,3 +1037,3 @@

// ['uppercase', 'lowercase', ...]
context.getClassList = function getClassList() {
context.getClassList = function getClassList(options = {}) {
let output = []

@@ -863,10 +1043,27 @@

if (Array.isArray(util)) {
let [utilName, options] = util
let [utilName, utilOptions] = util
let negativeClasses = []
for (let [key, value] of Object.entries(options?.values ?? {})) {
output.push(formatClass(utilName, key))
if (options?.supportsNegativeValues && negateValue(value)) {
negativeClasses.push(formatClass(utilName, `-${key}`))
let modifiers = Object.keys(utilOptions?.modifiers ?? {})
if (utilOptions?.types?.some(({ type }) => type === 'color')) {
modifiers.push(...Object.keys(context.tailwindConfig.theme.opacity ?? {}))
}
let metadata = { modifiers }
let includeMetadata = options.includeMetadata && modifiers.length > 0
for (let [key, value] of Object.entries(utilOptions?.values ?? {})) {
// Ignore undefined and null values
if (value == null) {
continue
}
let cls = formatClass(utilName, key)
output.push(includeMetadata ? [cls, metadata] : cls)
if (utilOptions?.supportsNegativeValues && negateValue(value)) {
let cls = formatClass(utilName, `-${key}`)
negativeClasses.push(includeMetadata ? [cls, metadata] : cls)
}
}

@@ -882,4 +1079,212 @@

}
// Generate a list of available variants with meta information of the type of variant.
context.getVariants = function getVariants() {
// We use a unique, random ID for candidate names to avoid conflicts
// We can't use characters like `_`, `:`, `@` or `.` because they might
// be used as a separator
let id = Math.random().toString(36).substring(7).toUpperCase()
let result = []
for (let [name, options] of context.variantOptions.entries()) {
if (options.variantInfo === VARIANT_INFO.Base) continue
result.push({
name,
isArbitrary: options.type === Symbol.for('MATCH_VARIANT'),
values: Object.keys(options.values ?? {}),
hasDash: name !== '@',
selectors({ modifier, value } = {}) {
let candidate = `TAILWINDPLACEHOLDER${id}`
let rule = postcss.rule({ selector: `.${candidate}` })
let container = postcss.root({ nodes: [rule.clone()] })
let before = container.toString()
let fns = (context.variantMap.get(name) ?? []).flatMap(([_, fn]) => fn)
let formatStrings = []
for (let fn of fns) {
let localFormatStrings = []
let api = {
args: { modifier, value: options.values?.[value] ?? value },
separator: context.tailwindConfig.separator,
modifySelectors(modifierFunction) {
// Run the modifierFunction over each rule
container.each((rule) => {
if (rule.type !== 'rule') {
return
}
rule.selectors = rule.selectors.map((selector) => {
return modifierFunction({
get className() {
return getClassNameFromSelector(selector)
},
selector,
})
})
})
return container
},
format(str) {
localFormatStrings.push(str)
},
wrap(wrapper) {
localFormatStrings.push(`@${wrapper.name} ${wrapper.params} { & }`)
},
container,
}
let ruleWithVariant = fn(api)
if (localFormatStrings.length > 0) {
formatStrings.push(localFormatStrings)
}
if (Array.isArray(ruleWithVariant)) {
for (let variantFunction of ruleWithVariant) {
localFormatStrings = []
variantFunction(api)
formatStrings.push(localFormatStrings)
}
}
}
// Reverse engineer the result of the `container`
let manualFormatStrings = []
let after = container.toString()
if (before !== after) {
// Figure out all selectors
container.walkRules((rule) => {
let modified = rule.selector
// Rebuild the base selector, this is what plugin authors would do
// as well. E.g.: `${variant}${separator}${className}`.
// However, plugin authors probably also prepend or append certain
// classes, pseudos, ids, ...
let rebuiltBase = selectorParser((selectors) => {
selectors.walkClasses((classNode) => {
classNode.value = `${name}${context.tailwindConfig.separator}${classNode.value}`
})
}).processSync(modified)
// Now that we know the original selector, the new selector, and
// the rebuild part in between, we can replace the part that plugin
// authors need to rebuild with `&`, and eventually store it in the
// collectedFormats. Similar to what `format('...')` would do.
//
// E.g.:
// variant: foo
// selector: .markdown > p
// modified (by plugin): .foo .foo\\:markdown > p
// rebuiltBase (internal): .foo\\:markdown > p
// format: .foo &
manualFormatStrings.push(modified.replace(rebuiltBase, '&').replace(candidate, '&'))
})
// Figure out all atrules
container.walkAtRules((atrule) => {
manualFormatStrings.push(`@${atrule.name} (${atrule.params}) { & }`)
})
}
let isArbitraryVariant = !(value in (options.values ?? {}))
let internalFeatures = options[INTERNAL_FEATURES] ?? {}
let respectPrefix = (() => {
if (isArbitraryVariant) return false
if (internalFeatures.respectPrefix === false) return false
return true
})()
formatStrings = formatStrings.map((format) =>
format.map((str) => ({
format: str,
respectPrefix,
}))
)
manualFormatStrings = manualFormatStrings.map((format) => ({
format,
respectPrefix,
}))
let opts = {
candidate,
context,
}
let result = formatStrings.map((formats) =>
finalizeSelector(`.${candidate}`, formatVariantSelector(formats, opts), opts)
.replace(`.${candidate}`, '&')
.replace('{ & }', '')
.trim()
)
if (manualFormatStrings.length > 0) {
result.push(
formatVariantSelector(manualFormatStrings, opts)
.toString()
.replace(`.${candidate}`, '&')
)
}
return result
},
})
}
return result
}
}
/**
* Mark as class as retroactively invalid
*
*
* @param {string} candidate
*/
function markInvalidUtilityCandidate(context, candidate) {
if (!context.classCache.has(candidate)) {
return
}
// Mark this as not being a real utility
context.notClassCache.add(candidate)
// Remove it from any candidate-specific caches
context.classCache.delete(candidate)
context.applyClassCache.delete(candidate)
context.candidateRuleMap.delete(candidate)
context.candidateRuleCache.delete(candidate)
// Ensure the stylesheet gets rebuilt
context.stylesheetCache = null
}
/**
* Mark as class as retroactively invalid
*
* @param {import('postcss').Node} node
*/
function markInvalidUtilityNode(context, node) {
let candidate = node.raws.tailwind.candidate
if (!candidate) {
return
}
for (const entry of context.ruleCache) {
if (entry[1].raws.tailwind.candidate === candidate) {
context.ruleCache.delete(entry)
// context.postCssNodeCache.delete(node)
}
}
markInvalidUtilityCandidate(context, candidate)
}
export function createContext(tailwindConfig, changedContent = [], root = postcss.root()) {

@@ -889,5 +1294,7 @@ let context = {

ruleCache: new Set(),
candidateRuleCache: new Map(),
classCache: new Map(),
applyClassCache: new Map(),
notClassCache: new Set(),
// Seed the not class cache with the blocklist (which is only strings)
notClassCache: new Set(tailwindConfig.blocklist ?? []),
postCssNodeCache: new Map(),

@@ -899,2 +1306,6 @@ candidateRuleMap: new Map(),

stylesheetCache: null,
variantOptions: new Map(),
markInvalidUtilityCandidate: (candidate) => markInvalidUtilityCandidate(context, candidate),
markInvalidUtilityNode: (node) => markInvalidUtilityNode(context, node),
}

@@ -942,3 +1353,3 @@

if (existingContext) {
let contextDependenciesChanged = trackModified(
let [contextDependenciesChanged, mtimesToCommit] = trackModified(
[...contextDependencies],

@@ -948,3 +1359,3 @@ getFileModifiedMap(existingContext)

if (!contextDependenciesChanged && !cssDidChange) {
return [existingContext, false]
return [existingContext, false, mtimesToCommit]
}

@@ -980,4 +1391,8 @@ }

trackModified([...contextDependencies], getFileModifiedMap(context))
Object.assign(context, {
userConfigPath,
})
let [, mtimesToCommit] = trackModified([...contextDependencies], getFileModifiedMap(context))
// ---

@@ -996,3 +1411,3 @@

return [context, true]
return [context, true, mtimesToCommit]
}

@@ -0,20 +1,15 @@

// @ts-check
import fs from 'fs'
import path from 'path'
import LRU from '@alloc/quick-lru'
import fastGlob from 'fast-glob'
import LRU from 'quick-lru'
import normalizePath from 'normalize-path'
import hash from '../util/hashConfig'
import getModuleDependencies from '../lib/getModuleDependencies'
import resolveConfig from '../public/resolve-config'
import resolveConfigPath from '../util/resolveConfigPath'
import { env } from './sharedState'
import { getContext, getFileModifiedMap } from './setupContextUtils'
import parseDependency from '../util/parseDependency'
import { validateConfig } from '../util/validateConfig.js'
import { parseCandidateFiles, resolvedChangedContent } from './content.js'
import { loadConfig } from '../lib/load-config'
import getModuleDependencies from './getModuleDependencies'

@@ -30,5 +25,3 @@ let configPathCache = new LRU({ maxSize: 100 })

let candidateFiles = tailwindConfig.content.files
.filter((item) => typeof item === 'string')
.map((contentPath) => normalizePath(contentPath))
let candidateFiles = parseCandidateFiles(context, tailwindConfig)

@@ -46,3 +39,3 @@ return candidateFilesCache.set(context, candidateFiles).get(context)

let newDeps = getModuleDependencies(userConfigPath).map((dep) => dep.file)
let newDeps = getModuleDependencies(userConfigPath)

@@ -68,4 +61,3 @@ let modified = false

}
let newConfig = resolveConfig(require(userConfigPath))
newConfig = validateConfig(newConfig)
let newConfig = validateConfig(resolveConfig(loadConfig(userConfigPath)))
let newHash = hash(newConfig)

@@ -77,5 +69,3 @@ configPathCache.set(userConfigPath, [newConfig, newHash, newDeps, newModified])

// It's a plain object, not a path
let newConfig = resolveConfig(
configOrPath.config === undefined ? configOrPath : configOrPath.config
)
let newConfig = resolveConfig(configOrPath?.config ?? configOrPath ?? {})

@@ -87,32 +77,2 @@ newConfig = validateConfig(newConfig)

function resolvedChangedContent(context, candidateFiles, fileModifiedMap) {
let changedContent = context.tailwindConfig.content.files
.filter((item) => typeof item.raw === 'string')
.map(({ raw, extension = 'html' }) => ({ content: raw, extension }))
for (let changedFile of resolveChangedFiles(candidateFiles, fileModifiedMap)) {
let content = fs.readFileSync(changedFile, 'utf8')
let extension = path.extname(changedFile).slice(1)
changedContent.push({ content, extension })
}
return changedContent
}
function resolveChangedFiles(candidateFiles, fileModifiedMap) {
let changedFiles = new Set()
env.DEBUG && console.time('Finding changed files')
let files = fastGlob.sync(candidateFiles)
for (let file of files) {
let prevModified = fileModifiedMap.has(file) ? fileModifiedMap.get(file) : -Infinity
let modified = fs.statSync(file).mtimeMs
if (modified > prevModified) {
changedFiles.add(file)
fileModifiedMap.set(file, modified)
}
}
env.DEBUG && console.timeEnd('Finding changed files')
return changedFiles
}
// DISABLE_TOUCH = TRUE

@@ -149,3 +109,3 @@

let [context] = getContext(
let [context, , mTimesToCommit] = getContext(
root,

@@ -159,2 +119,4 @@ result,

let fileModifiedMap = getFileModifiedMap(context)
let candidateFiles = getCandidateFiles(context, tailwindConfig)

@@ -168,8 +130,5 @@

if (tailwindDirectives.size > 0) {
let fileModifiedMap = getFileModifiedMap(context)
// Add template paths as postcss dependencies.
for (let fileOrGlob of candidateFiles) {
let dependency = parseDependency(fileOrGlob)
if (dependency) {
for (let contentPath of candidateFiles) {
for (let dependency of parseDependency(contentPath)) {
registerDependency(dependency)

@@ -179,9 +138,25 @@ }

for (let changedContent of resolvedChangedContent(
let [changedContent, contentMTimesToCommit] = resolvedChangedContent(
context,
candidateFiles,
fileModifiedMap
)) {
context.changedContent.push(changedContent)
)
for (let content of changedContent) {
context.changedContent.push(content)
}
// Add the mtimes of the content files to the commit list
// We can overwrite the existing values because unconditionally
// This is because:
// 1. Most of the files here won't be in the map yet
// 2. If they are that means it's a context dependency
// and we're reading this after the context. This means
// that the mtime we just read is strictly >= the context
// mtime. Unless the user / os is doing something weird
// in which the mtime would be going backwards. If that
// happens there's already going to be problems.
for (let [path, mtime] of contentMTimesToCommit.entries()) {
mTimesToCommit.set(path, mtime)
}
}

@@ -193,2 +168,9 @@

// "commit" the new modified time for all context deps
// We do this here because we want content tracking to
// read the "old" mtime even when it's a context dependency.
for (let [path, mtime] of mTimesToCommit.entries()) {
fileModifiedMap.set(path, mtime)
}
return context

@@ -195,0 +177,0 @@ }

@@ -1,5 +0,12 @@

export const env = {
NODE_ENV: process.env.NODE_ENV,
DEBUG: resolveDebug(process.env.DEBUG),
}
export const env =
typeof process !== 'undefined'
? {
NODE_ENV: process.env.NODE_ENV,
DEBUG: resolveDebug(process.env.DEBUG),
}
: {
NODE_ENV: 'production',
DEBUG: false,
}
export const contextMap = new Map()

@@ -11,2 +18,4 @@ export const configContextMap = new Map()

export const NONE = Symbol('__NONE__')
export function resolveDebug(debug) {

@@ -13,0 +22,0 @@ if (debug === undefined) {

@@ -10,3 +10,2 @@ import normalizeTailwindDirectives from './lib/normalizeTailwindDirectives'

import partitionApplyAtRules from './lib/partitionApplyAtRules'
import detectNesting from './lib/detectNesting'
import { createContext } from './lib/setupContextUtils'

@@ -16,7 +15,5 @@ import { issueFlagNotices } from './featureFlags'

export default function processTailwindFeatures(setupContext) {
return function (root, result) {
return async function (root, result) {
let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root)
detectNesting()(root, result)
// Partition apply rules that are found in the css

@@ -49,3 +46,4 @@ // itself.

expandTailwindAtRules(context)(root, result)
await expandTailwindAtRules(context)(root, result)
// Partition apply rules that are generated by

@@ -52,0 +50,0 @@ // addComponents, addUtilities and so on.

@@ -27,2 +27,3 @@ import log from '../util/log'

900: '#0f172a',
950: '#020617',
},

@@ -40,2 +41,3 @@ gray: {

900: '#111827',
950: '#030712',
},

@@ -53,2 +55,3 @@ zinc: {

900: '#18181b',
950: '#09090b',
},

@@ -66,2 +69,3 @@ neutral: {

900: '#171717',
950: '#0a0a0a',
},

@@ -79,2 +83,3 @@ stone: {

900: '#1c1917',
950: '#0c0a09',
},

@@ -92,2 +97,3 @@ red: {

900: '#7f1d1d',
950: '#450a0a',
},

@@ -105,2 +111,3 @@ orange: {

900: '#7c2d12',
950: '#431407',
},

@@ -118,2 +125,3 @@ amber: {

900: '#78350f',
950: '#451a03',
},

@@ -131,2 +139,3 @@ yellow: {

900: '#713f12',
950: '#422006',
},

@@ -144,2 +153,3 @@ lime: {

900: '#365314',
950: '#1a2e05',
},

@@ -157,2 +167,3 @@ green: {

900: '#14532d',
950: '#052e16',
},

@@ -170,2 +181,3 @@ emerald: {

900: '#064e3b',
950: '#022c22',
},

@@ -183,2 +195,3 @@ teal: {

900: '#134e4a',
950: '#042f2e',
},

@@ -196,2 +209,3 @@ cyan: {

900: '#164e63',
950: '#083344',
},

@@ -209,2 +223,3 @@ sky: {

900: '#0c4a6e',
950: '#082f49',
},

@@ -222,2 +237,3 @@ blue: {

900: '#1e3a8a',
950: '#172554',
},

@@ -235,2 +251,3 @@ indigo: {

900: '#312e81',
950: '#1e1b4b',
},

@@ -248,2 +265,3 @@ violet: {

900: '#4c1d95',
950: '#2e1065',
},

@@ -261,2 +279,3 @@ purple: {

900: '#581c87',
950: '#3b0764',
},

@@ -274,2 +293,3 @@ fuchsia: {

900: '#701a75',
950: '#4a044e',
},

@@ -287,2 +307,3 @@ pink: {

900: '#831843',
950: '#500724',
},

@@ -300,2 +321,3 @@ rose: {

900: '#881337',
950: '#4c0519',
},

@@ -302,0 +324,0 @@ get lightBlue() {

import { cloneDeep } from '../util/cloneDeep'
import defaultConfig from '../../stubs/defaultConfig.stub'
import defaultConfig from '../../stubs/config.full'
export default cloneDeep(defaultConfig)
import { cloneDeep } from '../util/cloneDeep'
import defaultConfig from '../../stubs/defaultConfig.stub'
import defaultFullConfig from '../../stubs/config.full'
export default cloneDeep(defaultConfig.theme)
export default cloneDeep(defaultFullConfig.theme)

@@ -5,4 +5,4 @@ export default function buildMediaQuery(screens) {

return screens
.map((screen) =>
screen.values.map((screen) => {
.map((screen) => {
let values = screen.values.map((screen) => {
if (screen.raw !== undefined) {

@@ -19,4 +19,6 @@ return screen.raw

})
)
return screen.not ? `not all and ${values}` : values
})
.join(', ')
}

@@ -0,1 +1,7 @@

/**
* @param {import('postcss').Container[]} nodes
* @param {any} source
* @param {any} raws
* @returns {import('postcss').Container[]}
*/
export default function cloneNodes(nodes, source = undefined, raws = undefined) {

@@ -5,12 +11,2 @@ return nodes.map((node) => {

if (source !== undefined) {
cloned.source = source
if ('walk' in cloned) {
cloned.walk((child) => {
child.source = source
})
}
}
if (raws !== undefined) {

@@ -23,4 +19,33 @@ cloned.raws.tailwind = {

if (source !== undefined) {
traverse(cloned, (node) => {
// Do not traverse nodes that have opted
// to preserve their original source
let shouldPreserveSource = node.raws.tailwind?.preserveSource === true && node.source
if (shouldPreserveSource) {
return false
}
// Otherwise we can safely replace the source
// And continue traversing
node.source = source
})
}
return cloned
})
}
/**
* Traverse a tree of nodes and don't traverse children if the callback
* returns false. Ideally we'd use Container#walk instead of this
* function but it stops traversing siblings too.
*
* @param {import('postcss').Container} node
* @param {(node: import('postcss').Container) => boolean} onNode
*/
function traverse(node, onNode) {
if (onNode(node) !== false) {
node.each?.((child) => traverse(child, onNode))
}
}

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

import namedColors from 'color-name'
import namedColors from './colorNames'

@@ -8,9 +8,9 @@ let HEX = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i

let ALPHA_SEP = /\s*[,/]\s*/
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/
let RGB = new RegExp(
`^(rgb)a?\\(\\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*\\)$`
`^(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*\\)$`
)
let HSL = new RegExp(
`^(hsl)a?\\(\\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*\\)$`
`^(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*\\)$`
)

@@ -56,2 +56,12 @@

// rgba(var(--my-color), 0.1)
// hsla(var(--my-color), 0.1)
if (color.length === 2 && color[0].startsWith('var(')) {
return {
mode: match[1],
color: [color[0]],
alpha: color[1],
}
}
if (!loose && color.length !== 3) {

@@ -74,3 +84,8 @@ return null

let hasAlpha = alpha !== undefined
if (mode === 'rgba' || mode === 'hsla') {
return `${mode}(${color.join(', ')}${hasAlpha ? `, ${alpha}` : ''})`
}
return `${mode}(${color.join(' ')}${hasAlpha ? ` / ${alpha}` : ''})`
}
import { parseColor } from './color'
import { parseBoxShadowValue } from './parseBoxShadowValue'
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'

@@ -8,8 +9,43 @@ let cssFunctions = ['min', 'max', 'clamp', 'calc']

let COMMA = /,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
let UNDERSCORE = /_(?![^(]*\))/g // Underscore separator that is not located between brackets. E.g.: `rgba(255,_255,_255)_black` these don't count.
function isCSSFunction(value) {
return cssFunctions.some((fn) => new RegExp(`^${fn}\\(.*\\)`).test(value))
}
// 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
// - https://www.w3.org/TR/css-anchor-position-1
//
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
// Concrete properties
'scroll-timeline-name',
'timeline-scope',
'view-timeline-name',
'font-palette',
'anchor-name',
'anchor-scope',
'position-anchor',
'position-try-options',
// Shorthand properties
'scroll-timeline',
'animation-timeline',
'view-timeline',
'position-try',
])
// This is not a data type, but rather a function that can normalize the
// correct values.
export function normalize(value, isRoot = true) {
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})`
}
// Keep raw strings if it starts with `url(`

@@ -25,3 +61,3 @@ if (value.includes('url(')) {

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

@@ -45,16 +81,149 @@ .join('')

// Add spaces around operators inside calc() that do not follow an operator
// or '('.
value = value.replace(/calc\(.+\)/g, (match) => {
return match.replace(
/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
'$1 $2 '
)
})
value = normalizeMathOperatorSpacing(value)
// Add spaces around some operators not inside calc() that do not follow an operator
// or '('.
return value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([\/])/g, '$1 $2 ')
return value
}
export function normalizeAttributeSelectors(value) {
// Wrap values in attribute selectors with quotes
if (value.includes('=')) {
value = value.replace(/(=.*)/g, (_fullMatch, match) => {
if (match[1] === "'" || match[1] === '"') {
return match
}
// Handle regex flags on unescaped values
if (match.length > 2) {
let trailingCharacter = match[match.length - 1]
if (
match[match.length - 2] === ' ' &&
(trailingCharacter === 'i' ||
trailingCharacter === 'I' ||
trailingCharacter === 's' ||
trailingCharacter === 'S')
) {
return `="${match.slice(1, -2)}" ${match[match.length - 1]}`
}
}
return `="${match.slice(1)}"`
})
}
return value
}
/**
* Add spaces around operators inside math functions
* like calc() that do not follow an operator, '(', or `,`.
*
* @param {string} value
* @returns {string}
*/
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',
'radial-gradient',
'linear-gradient',
'conic-gradient',
'repeating-radial-gradient',
'repeating-linear-gradient',
'repeating-conic-gradient',
]
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
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([')', ','])
}
// 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([')'])
}
// Don't break CSS grid track names
else if (peek('[')) {
result += consumeUntil([']'])
}
// Handle operators
else if (
['+', '-', '*', '/'].includes(char) &&
!['(', '+', '-', '*', '/', ','].includes(lastChar())
) {
result += ` ${char} `
} else {
result += char
}
}
// Simplify multiple spaces
return result.replace(/\s+/g, ' ')
})
}
export function url(value) {

@@ -65,11 +234,12 @@ return value.startsWith('url(')

export function number(value) {
return !isNaN(Number(value)) || cssFunctions.some((fn) => new RegExp(`^${fn}\\(.+?`).test(value))
return !isNaN(Number(value)) || isCSSFunction(value)
}
export function percentage(value) {
return value.split(UNDERSCORE).every((part) => {
return /%$/g.test(part) || cssFunctions.some((fn) => new RegExp(`^${fn}\\(.+?%`).test(part))
})
return (value.endsWith('%') && number(value.slice(0, -1))) || isCSSFunction(value)
}
// Please refer to MDN when updating this list:
// https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries#container_query_length_units
let lengthUnits = [

@@ -88,2 +258,3 @@ 'cm',

'lh',
'rlh',
'vw',

@@ -93,12 +264,24 @@ 'vh',

'vmax',
'vb',
'vi',
'svw',
'svh',
'lvw',
'lvh',
'dvw',
'dvh',
'cqw',
'cqh',
'cqi',
'cqb',
'cqmin',
'cqmax',
]
let lengthUnitsPattern = `(?:${lengthUnits.join('|')})`
export function length(value) {
return value.split(UNDERSCORE).every((part) => {
return (
part === '0' ||
new RegExp(`${lengthUnitsPattern}$`).test(part) ||
cssFunctions.some((fn) => new RegExp(`^${fn}\\(.+?${lengthUnitsPattern}`).test(part))
)
})
return (
value === '0' ||
new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`).test(value) ||
isCSSFunction(value)
)
}

@@ -126,3 +309,3 @@

let result = value.split(UNDERSCORE).every((part) => {
let result = splitAtTopLevelOnly(value, '_').every((part) => {
part = normalize(part)

@@ -142,3 +325,3 @@

let images = 0
let result = value.split(COMMA).every((part) => {
let result = splitAtTopLevelOnly(value, ',').every((part) => {
part = normalize(part)

@@ -164,7 +347,8 @@

let gradientTypes = new Set([
'conic-gradient',
'linear-gradient',
'radial-gradient',
'repeating-conic-gradient',
'repeating-linear-gradient',
'repeating-radial-gradient',
'conic-gradient',
])

@@ -185,3 +369,3 @@ export function gradient(value) {

let positions = 0
let result = value.split(UNDERSCORE).every((part) => {
let result = splitAtTopLevelOnly(value, '_').every((part) => {
part = normalize(part)

@@ -204,3 +388,3 @@

let fonts = 0
let result = value.split(COMMA).every((part) => {
let result = splitAtTopLevelOnly(value, ',').every((part) => {
part = normalize(part)

@@ -257,3 +441,3 @@

'x-large',
'x-large',
'xx-large',
'xxx-large',

@@ -260,0 +444,0 @@ ])

@@ -5,32 +5,152 @@ import selectorParser from 'postcss-selector-parser'

import prefixSelector from '../util/prefixSelector'
import { movePseudos } from './pseudoElements'
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
/** @typedef {import('postcss-selector-parser').Root} Root */
/** @typedef {import('postcss-selector-parser').Selector} Selector */
/** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */
/** @typedef {import('postcss-selector-parser').Node} Node */
/** @typedef {{format: string, respectPrefix: boolean}[]} RawFormats */
/** @typedef {import('postcss-selector-parser').Root} ParsedFormats */
/** @typedef {RawFormats | ParsedFormats} AcceptedFormats */
let MERGE = ':merge'
let PARENT = '&'
export let selectorFunctions = new Set([MERGE])
/**
* @param {RawFormats} formats
* @param {{context: any, candidate: string, base: string | null}} options
* @returns {ParsedFormats | null}
*/
export function formatVariantSelector(formats, { context, candidate }) {
let prefix = context?.tailwindConfig.prefix ?? ''
export function formatVariantSelector(current, ...others) {
for (let other of others) {
let incomingValue = resolveFunctionArgument(other, MERGE)
if (incomingValue !== null) {
let existingValue = resolveFunctionArgument(current, MERGE, incomingValue)
if (existingValue !== null) {
let existingTarget = `${MERGE}(${incomingValue})`
let splitIdx = other.indexOf(existingTarget)
let addition = other.slice(splitIdx + existingTarget.length).split(' ')[0]
// Parse the format selector into an AST
let parsedFormats = formats.map((format) => {
let ast = selectorParser().astSync(format.format)
current = current.replace(existingTarget, existingTarget + addition)
continue
}
return {
...format,
ast: format.respectPrefix ? prefixSelector(prefix, ast) : ast,
}
})
current = other.replace(PARENT, current)
// We start with the candidate selector
let formatAst = selectorParser.root({
nodes: [
selectorParser.selector({
nodes: [selectorParser.className({ value: escapeClassName(candidate) })],
}),
],
})
// And iteratively merge each format selector into the candidate selector
for (let { ast } of parsedFormats) {
// 1. Handle :merge() special pseudo-class
;[formatAst, ast] = handleMergePseudo(formatAst, ast)
// 2. Merge the format selector into the current selector AST
ast.walkNesting((nesting) => nesting.replaceWith(...formatAst.nodes[0].nodes))
// 3. Keep going!
formatAst = ast
}
return current
return formatAst
}
export function finalizeSelector(format, { selector, candidate, context }) {
let ast = selectorParser().astSync(selector)
/**
* Given any node in a selector this gets the "simple" selector it's a part of
* A simple selector is just a list of nodes without any combinators
* Technically :is(), :not(), :has(), etc… can have combinators but those are nested
* inside the relevant node and won't be picked up so they're fine to ignore
*
* @param {Node} node
* @returns {Node[]}
**/
function simpleSelectorForNode(node) {
/** @type {Node[]} */
let nodes = []
// Walk backwards until we hit a combinator node (or the start)
while (node.prev() && node.prev().type !== 'combinator') {
node = node.prev()
}
// Now record all non-combinator nodes until we hit one (or the end)
while (node && node.type !== 'combinator') {
nodes.push(node)
node = node.next()
}
return nodes
}
/**
* Resorts the nodes in a selector to ensure they're in the correct order
* Tags go before classes, and pseudo classes go after classes
*
* @param {Selector} sel
* @returns {Selector}
**/
function resortSelector(sel) {
sel.sort((a, b) => {
if (a.type === 'tag' && b.type === 'class') {
return -1
} else if (a.type === 'class' && b.type === 'tag') {
return 1
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) {
return -1
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') {
return 1
}
return sel.index(a) - sel.index(b)
})
return sel
}
/**
* Remove extraneous selectors that do not include the base class/candidate
*
* Example:
* Given the utility `.a, .b { color: red}`
* Given the candidate `sm:b`
*
* The final selector should be `.sm\:b` and not `.a, .sm\:b`
*
* @param {Selector} ast
* @param {string} base
*/
export function eliminateIrrelevantSelectors(sel, base) {
let hasClassesMatchingCandidate = false
sel.walk((child) => {
if (child.type === 'class' && child.value === base) {
hasClassesMatchingCandidate = true
return false // Stop walking
}
})
if (!hasClassesMatchingCandidate) {
sel.remove()
}
// We do NOT recursively eliminate sub selectors that don't have the base class
// as this is NOT a safe operation. For example, if we have:
// `.space-x-2 > :not([hidden]) ~ :not([hidden])`
// We cannot remove the [hidden] from the :not() because it would change the
// meaning of the selector.
// TODO: Can we do this for :matches, :is, and :where?
}
/**
* @param {string} current
* @param {AcceptedFormats} formats
* @param {{context: any, candidate: string, base: string | null}} options
* @returns {string}
*/
export function finalizeSelector(current, formats, { context, candidate, base }) {
let separator = context?.tailwindConfig?.separator ?? ':'

@@ -45,24 +165,7 @@

//
let splitter = new RegExp(`\\${separator}(?![^[]*\\])`)
let base = candidate.split(splitter).pop()
base = base ?? splitAtTopLevelOnly(candidate, separator).pop()
if (context?.tailwindConfig?.prefix) {
format = prefixSelector(context.tailwindConfig.prefix, format)
}
// Parse the selector into an AST
let selector = selectorParser().astSync(current)
format = format.replace(PARENT, `.${escapeClassName(candidate)}`)
let formatAst = selectorParser().astSync(format)
// Remove extraneous selectors that do not include the base class/candidate being matched against
// For example if we have a utility defined `.a, .b { color: red}`
// And the formatted variant is sm:b then we want the final selector to be `.sm\:b` and not `.a, .sm\:b`
ast.each((node) => {
let hasClassesMatchingCandidate = node.some((n) => n.type === 'class' && n.value === base)
if (!hasClassesMatchingCandidate) {
node.remove()
}
})
// Normalize escaped classes, e.g.:

@@ -79,3 +182,3 @@ //

//
ast.walkClasses((node) => {
selector.walkClasses((node) => {
if (node.raws && node.value.includes(base)) {

@@ -86,126 +189,140 @@ node.raws.value = escapeClassName(unescape(node.raws.value))

// Remove extraneous selectors that do not include the base candidate
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
// so we can just return the selector as-is
let formatAst = Array.isArray(formats)
? formatVariantSelector(formats, { context, candidate })
: formats
if (formatAst === null) {
return selector.toString()
}
let simpleStart = selectorParser.comment({ value: '/*__simple__*/' })
let simpleEnd = selectorParser.comment({ value: '/*__simple__*/' })
// We can safely replace the escaped base now, since the `base` section is
// now in a normalized escaped value.
ast.walkClasses((node) => {
if (node.value === base) {
node.replaceWith(...formatAst.nodes)
selector.walkClasses((node) => {
if (node.value !== base) {
return
}
})
// This will make sure to move pseudo's to the correct spot (the end for
// pseudo elements) because otherwise the selector will never work
// anyway.
//
// E.g.:
// - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
// - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
//
// `::before:hover` doesn't work, which means that we can make it work for you by flipping the order.
function collectPseudoElements(selector) {
let nodes = []
let parent = node.parent
let formatNodes = formatAst.nodes[0].nodes
for (let node of selector.nodes) {
if (isPseudoElement(node)) {
nodes.push(node)
selector.removeChild(node)
}
// Perf optimization: if the parent is a single class we can just replace it and be done
if (parent.nodes.length === 1) {
node.replaceWith(...formatNodes)
return
}
if (node?.nodes) {
nodes.push(...collectPseudoElements(node))
}
let simpleSelector = simpleSelectorForNode(node)
parent.insertBefore(simpleSelector[0], simpleStart)
parent.insertAfter(simpleSelector[simpleSelector.length - 1], simpleEnd)
for (let child of formatNodes) {
parent.insertBefore(simpleSelector[0], child.clone())
}
return nodes
}
node.remove()
// Re-sort the simple selector to ensure it's in the correct order
simpleSelector = simpleSelectorForNode(simpleStart)
let firstNode = parent.index(simpleStart)
parent.nodes.splice(
firstNode,
simpleSelector.length,
...resortSelector(selectorParser.selector({ nodes: simpleSelector })).nodes
)
simpleStart.remove()
simpleEnd.remove()
})
// Remove unnecessary pseudo selectors that we used as placeholders
ast.each((selector) => {
selector.walkPseudos((p) => {
if (selectorFunctions.has(p.value)) {
p.replaceWith(p.nodes)
}
})
let pseudoElements = collectPseudoElements(selector)
if (pseudoElements.length > 0) {
selector.nodes.push(pseudoElements.sort(sortSelector))
selector.walkPseudos((p) => {
if (p.value === MERGE) {
p.replaceWith(p.nodes)
}
})
return ast.toString()
// Move pseudo elements to the end of the selector (if necessary)
selector.each((sel) => movePseudos(sel))
return selector.toString()
}
// Note: As a rule, double colons (::) should be used instead of a single colon
// (:). This distinguishes pseudo-classes from pseudo-elements. However, since
// this distinction was not present in older versions of the W3C spec, most
// browsers support both syntaxes for the original pseudo-elements.
let pseudoElementsBC = [':before', ':after', ':first-line', ':first-letter']
/**
*
* @param {Selector} selector
* @param {Selector} format
*/
export function handleMergePseudo(selector, format) {
/** @type {{pseudo: Pseudo, value: string}[]} */
let merges = []
// These pseudo-elements _can_ be combined with other pseudo selectors AND the order does matter.
let pseudoElementExceptions = ['::file-selector-button']
// Find all :merge() pseudo-classes in `selector`
selector.walkPseudos((pseudo) => {
if (pseudo.value === MERGE) {
merges.push({
pseudo,
value: pseudo.nodes[0].toString(),
})
}
})
// This will make sure to move pseudo's to the correct spot (the end for
// pseudo elements) because otherwise the selector will never work
// anyway.
//
// E.g.:
// - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
// - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
//
// `::before:hover` doesn't work, which means that we can make it work
// for you by flipping the order.
function sortSelector(a, z) {
// Both nodes are non-pseudo's so we can safely ignore them and keep
// them in the same order.
if (a.type !== 'pseudo' && z.type !== 'pseudo') {
return 0
}
// Find all :merge() "attachments" in `format` and attach them to the matching selector in `selector`
format.walkPseudos((pseudo) => {
if (pseudo.value !== MERGE) {
return
}
// If one of them is a combinator, we need to keep it in the same order
// because that means it will start a new "section" in the selector.
if ((a.type === 'combinator') ^ (z.type === 'combinator')) {
return 0
}
let value = pseudo.nodes[0].toString()
// One of the items is a pseudo and the other one isn't. Let's move
// the pseudo to the right.
if ((a.type === 'pseudo') ^ (z.type === 'pseudo')) {
return (a.type === 'pseudo') - (z.type === 'pseudo')
}
// Does `selector` contain a :merge() pseudo-class with the same value?
let existing = merges.find((merge) => merge.value === value)
// Both are pseudo's, move the pseudo elements (except for
// ::file-selector-button) to the right.
return isPseudoElement(a) - isPseudoElement(z)
}
// Nope so there's nothing to do
if (!existing) {
return
}
function isPseudoElement(node) {
if (node.type !== 'pseudo') return false
if (pseudoElementExceptions.includes(node.value)) return false
// Everything after `:merge()` up to the next combinator is what is attached to the merged selector
let attachments = []
let next = pseudo.next()
while (next && next.type !== 'combinator') {
attachments.push(next)
next = next.next()
}
return node.value.startsWith('::') || pseudoElementsBC.includes(node.value)
}
let combinator = next
function resolveFunctionArgument(haystack, needle, arg) {
let startIdx = haystack.indexOf(arg ? `${needle}(${arg})` : needle)
if (startIdx === -1) return null
existing.pseudo.parent.insertAfter(
existing.pseudo,
selectorParser.selector({ nodes: attachments.map((node) => node.clone()) })
)
// Start inside the `(`
startIdx += needle.length + 1
pseudo.remove()
attachments.forEach((node) => node.remove())
let target = ''
let count = 0
for (let char of haystack.slice(startIdx)) {
if (char !== '(' && char !== ')') {
target += char
} else if (char === '(') {
target += char
count++
} else if (char === ')') {
if (--count < 0) break // unbalanced
target += char
// What about this case:
// :merge(.group):focus > &
// :merge(.group):hover &
if (combinator && combinator.type === 'combinator') {
combinator.remove()
}
}
})
return target
return [selector, format]
}

@@ -1,6 +0,6 @@

import defaultConfig from '../../stubs/defaultConfig.stub.js'
import defaultFullConfig from '../../stubs/config.full.js'
import { flagEnabled } from '../featureFlags'
export default function getAllConfigs(config) {
const configs = (config?.presets ?? [defaultConfig])
const configs = (config?.presets ?? [defaultFullConfig])
.slice()

@@ -12,2 +12,21 @@ .reverse()

// Add experimental configs here...
respectDefaultRingColorOpacity: {
theme: {
ringColor: ({ theme }) => ({
DEFAULT: '#3b82f67f',
...theme('colors'),
}),
},
},
disableColorOpacityUtilitiesByDefault: {
corePlugins: {
backgroundOpacity: false,
borderOpacity: false,
divideOpacity: false,
placeholderOpacity: false,
ringOpacity: false,
textOpacity: false,
},
},
}

@@ -14,0 +33,0 @@

@@ -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
}

@@ -6,3 +6,3 @@ import colors from 'picocolors'

function log(type, messages, key) {
if (process.env.JEST_WORKER_ID !== undefined) return
if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) return

@@ -9,0 +9,0 @@ if (key && alreadyShown.has(key)) return

@@ -25,3 +25,7 @@ import escapeClassName from './escapeClassName'

if (key.startsWith('/')) {
return `${classPrefix}${key}`
}
return `${classPrefix}-${key}`
}

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

export default function (value) {
export default function negateValue(value) {
value = `${value}`

@@ -13,5 +13,13 @@

if (value.includes('var(') || value.includes('calc(')) {
return `calc(${value} * -1)`
// What functions we support negating numeric values for
// var() isn't inherently a numeric function but we support it anyway
// The trigonometric functions are omitted because you'll need to use calc(…) with them _anyway_
// to produce generally useful results and that will be covered already
let numericFunctions = ['var', 'calc', 'min', 'max', 'clamp']
for (const fn of numericFunctions) {
if (value.includes(`${fn}(`)) {
return `calc(${value} * -1)`
}
}
}

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

import { flagEnabled } from '../featureFlags'
import log, { dim } from './log'

@@ -59,5 +60,7 @@

if (typeof config.content === 'object' && config.content !== null) {
// Only `files`, `extract` and `transform` can exist in `config.content`
// Only `files`, `relative`, `extract`, and `transform` can exist in `config.content`
if (
Object.keys(config.content).some((key) => !['files', 'extract', 'transform'].includes(key))
Object.keys(config.content).some(
(key) => !['files', 'relative', 'extract', 'transform'].includes(key)
)
) {

@@ -116,2 +119,10 @@ return false

}
// `config.content.relative` is optional and can be a boolean
if (
typeof config.content.relative !== 'boolean' &&
typeof config.content.relative !== 'undefined'
) {
return false
}
}

@@ -145,2 +156,20 @@

// Normalize the `blocklist`
config.blocklist = (() => {
let { blocklist } = config
if (Array.isArray(blocklist)) {
if (blocklist.every((item) => typeof item === 'string')) {
return blocklist
}
log.warn('blocklist-invalid', [
'The `blocklist` option must be an array of strings.',
'https://tailwindcss.com/docs/content-configuration#discarding-classes',
])
}
return []
})()
// Normalize prefix option

@@ -160,2 +189,12 @@ if (typeof config.prefix === 'function') {

config.content = {
relative: (() => {
let { content } = config
if (content?.relative) {
return content.relative
}
return flagEnabled(config, 'relativeContentPathsByDefault')
})(),
files: (() => {

@@ -242,5 +281,3 @@ let { content, purge } = config

transformers.DEFAULT = transform
}
if (typeof transform === 'object' && transform !== null) {
} else if (typeof transform === 'object' && transform !== null) {
Object.assign(transformers, transform)

@@ -247,0 +284,0 @@ }

/**
* @typedef {object} ScreenValue
* @property {number|undefined} min
* @property {number|undefined} max
* @property {string|undefined} raw
*/
/**
* @typedef {object} Screen
* @property {string} name
* @property {boolean} not
* @property {ScreenValue[]} values
*/
/**
* A function that normalizes the various forms that the screens object can be

@@ -13,2 +27,4 @@ * provided in.

* - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
*
* @returns {Screen[]}
*/

@@ -23,3 +39,3 @@ export function normalizeScreens(screens, root = true) {

if (typeof screen === 'string') {
return { name: screen.toString(), values: [{ min: screen, max: undefined }] }
return { name: screen.toString(), not: false, values: [{ min: screen, max: undefined }] }
}

@@ -31,10 +47,10 @@

if (typeof options === 'string') {
return { name, values: [{ min: options, max: undefined }] }
return { name, not: false, values: [{ min: options, max: undefined }] }
}
if (Array.isArray(options)) {
return { name, values: options.map((option) => resolveValue(option)) }
return { name, not: false, values: options.map((option) => resolveValue(option)) }
}
return { name, values: [resolveValue(options)] }
return { name, not: false, values: [resolveValue(options)] }
})

@@ -46,4 +62,83 @@ }

/**
* @param {Screen} screen
* @returns {{result: false, reason: string} | {result: true, reason: null}}
*/
export function isScreenSortable(screen) {
if (screen.values.length !== 1) {
return { result: false, reason: 'multiple-values' }
} else if (screen.values[0].raw !== undefined) {
return { result: false, reason: 'raw-values' }
} else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) {
return { result: false, reason: 'min-and-max' }
}
return { result: true, reason: null }
}
/**
* @param {'min' | 'max'} type
* @param {Screen | 'string'} a
* @param {Screen | 'string'} z
* @returns {number}
*/
export function compareScreens(type, a, z) {
let aScreen = toScreen(a, type)
let zScreen = toScreen(z, type)
let aSorting = isScreenSortable(aScreen)
let bSorting = isScreenSortable(zScreen)
// These cases should never happen and indicate a bug in Tailwind CSS itself
if (aSorting.reason === 'multiple-values' || bSorting.reason === 'multiple-values') {
throw new Error(
'Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.'
)
} else if (aSorting.reason === 'raw-values' || bSorting.reason === 'raw-values') {
throw new Error(
'Attempted to sort a screen with raw values. This should never happen. Please open a bug report.'
)
} else if (aSorting.reason === 'min-and-max' || bSorting.reason === 'min-and-max') {
throw new Error(
'Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.'
)
}
// Let the sorting begin
let { min: aMin, max: aMax } = aScreen.values[0]
let { min: zMin, max: zMax } = zScreen.values[0]
// Negating screens flip their behavior. Basically `not min-width` is `max-width`
if (a.not) [aMin, aMax] = [aMax, aMin]
if (z.not) [zMin, zMax] = [zMax, zMin]
aMin = aMin === undefined ? aMin : parseFloat(aMin)
aMax = aMax === undefined ? aMax : parseFloat(aMax)
zMin = zMin === undefined ? zMin : parseFloat(zMin)
zMax = zMax === undefined ? zMax : parseFloat(zMax)
let [aValue, zValue] = type === 'min' ? [aMin, zMin] : [zMax, aMax]
return aValue - zValue
}
/**
*
* @param {PartialScreen> | string} value
* @param {'min' | 'max'} type
* @returns {Screen}
*/
export function toScreen(value, type) {
if (typeof value === 'object') {
return value
}
return {
name: 'arbitrary-screen',
values: [{ [type]: value }],
}
}
function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) {
return { min, max, raw }
}

@@ -16,3 +16,3 @@ const DIRECTIONS = new Set(['normal', 'reverse', 'alternate', 'alternate-reverse'])

const COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
const COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubic-bezier(a, b, c)` these don't count.
const SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.

@@ -19,0 +19,0 @@ const TIME = /^(-?[\d.]+m?s)$/

@@ -8,3 +8,3 @@ import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'

export function parseBoxShadowValue(input) {
let shadows = Array.from(splitAtTopLevelOnly(input, ','))
let shadows = splitAtTopLevelOnly(input, ',')
return shadows.map((shadow) => {

@@ -11,0 +11,0 @@ let value = shadow.trim()

@@ -1,49 +0,44 @@

import isGlob from 'is-glob'
import globParent from 'glob-parent'
import path from 'path'
// @ts-check
// Based on `glob-base`
// https://github.com/micromatch/glob-base/blob/master/index.js
function parseGlob(pattern) {
let glob = pattern
let base = globParent(pattern)
/**
* @typedef {{type: 'dependency', file: string} | {type: 'dir-dependency', dir: string, glob: string}} Dependency
*/
if (base !== '.') {
glob = pattern.substr(base.length)
if (glob.charAt(0) === '/') {
glob = glob.substr(1)
}
/**
*
* @param {import('../lib/content.js').ContentPath} contentPath
* @returns {Dependency[]}
*/
export default function parseDependency(contentPath) {
if (contentPath.ignore) {
return []
}
if (glob.substr(0, 2) === './') {
glob = glob.substr(2)
if (!contentPath.glob) {
return [
{
type: 'dependency',
file: contentPath.base,
},
]
}
if (glob.charAt(0) === '/') {
glob = glob.substr(1)
}
return { base, glob }
}
export default function parseDependency(normalizedFileOrGlob) {
if (normalizedFileOrGlob.startsWith('!')) {
return null
if (process.env.ROLLUP_WATCH === 'true') {
// rollup-plugin-postcss does not support dir-dependency messages
// but directories can be watched in the same way as files
return [
{
type: 'dependency',
file: contentPath.base,
},
]
}
let message
if (isGlob(normalizedFileOrGlob)) {
let { base, glob } = parseGlob(normalizedFileOrGlob)
message = { type: 'dir-dependency', dir: path.resolve(base), glob }
} else {
message = { type: 'dependency', file: path.resolve(normalizedFileOrGlob) }
}
// rollup-plugin-postcss does not support dir-dependency messages
// but directories can be watched in the same way as files
if (message.type === 'dir-dependency' && process.env.ROLLUP_WATCH === 'true') {
message = { type: 'dependency', file: message.dir }
}
return message
return [
{
type: 'dir-dependency',
dir: contentPath.base,
glob: contentPath.glob,
},
]
}

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

import selectorParser from 'postcss-selector-parser'
import escapeCommas from './escapeCommas'

@@ -21,17 +20,18 @@ import { withAlphaValue } from './withAlphaVariable'

import negateValue from './negateValue'
import { backgroundSize } from './validateFormalSyntax'
import { flagEnabled } from '../featureFlags.js'
/**
* @param {import('postcss-selector-parser').Container} selectors
* @param {(className: string) => string} updateClass
* @returns {string}
*/
export function updateAllClasses(selectors, updateClass) {
let parser = selectorParser((selectors) => {
selectors.walkClasses((sel) => {
let updatedClass = updateClass(sel.value)
sel.value = updatedClass
if (sel.raws && sel.raws.value) {
sel.raws.value = escapeCommas(sel.raws.value)
}
})
selectors.walkClasses((sel) => {
sel.value = updateClass(sel.value)
if (sel.raws && sel.raws.value) {
sel.raws.value = escapeCommas(sel.raws.value)
}
})
let result = parser.processSync(selectors)
return result
}

@@ -89,18 +89,59 @@

function splitAlpha(modifier) {
function splitUtilityModifier(modifier) {
let slashIdx = modifier.lastIndexOf('/')
// If the `/` is inside an arbitrary, we want to find the previous one if any
// This logic probably isn't perfect but it should work for most cases
let arbitraryStartIdx = modifier.lastIndexOf('[', slashIdx)
let arbitraryEndIdx = modifier.indexOf(']', slashIdx)
let isNextToArbitrary = modifier[slashIdx - 1] === ']' || modifier[slashIdx + 1] === '['
// Backtrack to the previous `/` if the one we found was inside an arbitrary
if (!isNextToArbitrary) {
if (arbitraryStartIdx !== -1 && arbitraryEndIdx !== -1) {
if (arbitraryStartIdx < slashIdx && slashIdx < arbitraryEndIdx) {
slashIdx = modifier.lastIndexOf('/', arbitraryStartIdx)
}
}
}
if (slashIdx === -1 || slashIdx === modifier.length - 1) {
return [modifier]
return [modifier, undefined]
}
let arbitrary = isArbitraryValue(modifier)
// The modifier could be of the form `[foo]/[bar]`
// We want to handle this case properly
// without affecting `[foo/bar]`
if (arbitrary && !modifier.includes(']/[')) {
return [modifier, undefined]
}
return [modifier.slice(0, slashIdx), modifier.slice(slashIdx + 1)]
}
export function parseColorFormat(value) {
if (typeof value === 'string' && value.includes('<alpha-value>')) {
let oldValue = value
return ({ opacityValue = 1 }) => oldValue.replace(/<alpha-value>/g, opacityValue)
}
return value
}
function unwrapArbitraryModifier(modifier) {
return normalize(modifier.slice(1, -1))
}
export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
if (options.values?.[modifier] !== undefined) {
return options.values?.[modifier]
return parseColorFormat(options.values?.[modifier])
}
let [color, alpha] = splitAlpha(modifier)
// TODO: Hoist this up to getMatchingTypes or something
// We do this here because we need the alpha value (if any)
let [color, alpha] = splitUtilityModifier(modifier)

@@ -115,4 +156,6 @@ if (alpha !== undefined) {

normalizedColor = parseColorFormat(normalizedColor)
if (isArbitraryValue(alpha)) {
return withAlphaValue(normalizedColor, alpha.slice(1, -1))
return withAlphaValue(normalizedColor, unwrapArbitraryModifier(alpha))
}

@@ -140,3 +183,3 @@

let typeMap = {
export let typeMap = {
any: asValue,

@@ -157,2 +200,3 @@ color: asColor,

shadow: guess(shadow),
size: guess(backgroundSize),
}

@@ -169,2 +213,16 @@

export function coerceValue(types, modifier, options, tailwindConfig) {
if (options.values && modifier in options.values) {
for (let { type } of types ?? []) {
let result = typeMap[type](modifier, options, {
tailwindConfig,
})
if (result === undefined) {
continue
}
return [result, type, null]
}
}
if (isArbitraryValue(modifier)) {

@@ -187,10 +245,11 @@ let arbitraryValue = modifier.slice(1, -1)

if (value.length > 0 && supportedTypes.includes(explicitType)) {
return [asValue(`[${value}]`, options), explicitType]
return [asValue(`[${value}]`, options), explicitType, null]
}
}
let matches = getMatchingTypes(types, modifier, options, tailwindConfig)
// Find first matching type
for (let type of [].concat(types)) {
let result = typeMap[type](modifier, options, { tailwindConfig })
if (result !== undefined) return [result, type]
for (let match of matches) {
return match
}

@@ -200,1 +259,57 @@

}
/**
*
* @param {{type: string}[]} types
* @param {string} rawModifier
* @param {any} options
* @param {any} tailwindConfig
* @returns {Iterator<[value: string, type: string, modifier: string | null]>}
*/
export function* getMatchingTypes(types, rawModifier, options, tailwindConfig) {
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
let [modifier, utilityModifier] = splitUtilityModifier(rawModifier)
let canUseUtilityModifier =
modifiersEnabled &&
options.modifiers != null &&
(options.modifiers === 'any' ||
(typeof options.modifiers === 'object' &&
((utilityModifier && isArbitraryValue(utilityModifier)) ||
utilityModifier in options.modifiers)))
if (!canUseUtilityModifier) {
modifier = rawModifier
utilityModifier = undefined
}
if (utilityModifier !== undefined && modifier === '') {
modifier = 'DEFAULT'
}
// Check the full value first
// TODO: Move to asValue… somehow
if (utilityModifier !== undefined) {
if (typeof options.modifiers === 'object') {
let configValue = options.modifiers?.[utilityModifier] ?? null
if (configValue !== null) {
utilityModifier = configValue
} else if (isArbitraryValue(utilityModifier)) {
utilityModifier = unwrapArbitraryModifier(utilityModifier)
}
}
}
for (let { type } of types ?? []) {
let result = typeMap[type](modifier, options, {
tailwindConfig,
})
if (result === undefined) {
continue
}
yield [result, type, utilityModifier ?? null]
}
}
import parser from 'postcss-selector-parser'
/**
* @template {string | import('postcss-selector-parser').Root} T
*
* Prefix all classes in the selector with the given prefix
*
* It can take either a string or a selector AST and will return the same type
*
* @param {string} prefix
* @param {T} selector
* @param {boolean} prependNegative
* @returns {T}
*/
export default function (prefix, selector, prependNegative = false) {
return parser((selectors) => {
selectors.walkClasses((classSelector) => {
let baseClass = classSelector.value
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith('-')
if (prefix === '') {
return selector
}
classSelector.value = shouldPlaceNegativeBeforePrefix
? `-${prefix}${baseClass.slice(1)}`
: `${prefix}${baseClass}`
})
}).processSync(selector)
/** @type {import('postcss-selector-parser').Root} */
let ast = typeof selector === 'string' ? parser().astSync(selector) : selector
ast.walkClasses((classSelector) => {
let baseClass = classSelector.value
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith('-')
classSelector.value = shouldPlaceNegativeBeforePrefix
? `-${prefix}${baseClass.slice(1)}`
: `${prefix}${baseClass}`
})
return typeof selector === 'string' ? ast.toString() : ast
}
import negateValue from './negateValue'
import corePluginList from '../corePluginList'
import configurePlugins from './configurePlugins'
import defaultConfig from '../../stubs/defaultConfig.stub'
import colors from '../public/colors'

@@ -11,2 +10,5 @@ import { defaults } from './defaults'

import { cloneDeep } from './cloneDeep'
import { parseColorFormat } from './pluginUtils'
import { withAlphaValue } from './withAlphaVariable'
import toColorValue from './toColorValue'

@@ -17,6 +19,2 @@ function isFunction(input) {

function isObject(input) {
return typeof input === 'object' && input !== null
}
function mergeWith(target, ...sources) {

@@ -30,4 +28,4 @@ let customizer = sources.pop()

if (merged === undefined) {
if (isObject(target[k]) && isObject(source[k])) {
target[k] = mergeWith(target[k], source[k], customizer)
if (isPlainObject(target[k]) && isPlainObject(source[k])) {
target[k] = mergeWith({}, target[k], source[k], customizer)
} else {

@@ -72,32 +70,2 @@ target[k] = source[k]

},
rgb(property) {
if (!property.startsWith('--')) {
throw new Error(
'The rgb() helper requires a custom property name to be passed as the first argument.'
)
}
return ({ opacityValue }) => {
if (opacityValue === undefined || opacityValue === 1) {
return `rgb(var(${property}) / 1.0)`
}
return `rgb(var(${property}) / ${opacityValue})`
}
},
hsl(property) {
if (!property.startsWith('--')) {
throw new Error(
'The hsl() helper requires a custom property name to be passed as the first argument.'
)
}
return ({ opacityValue }) => {
if (opacityValue === undefined || opacityValue === 1) {
return `hsl(var(${property}) / 1)`
}
return `hsl(var(${property}) / ${opacityValue})`
}
},
}

@@ -137,3 +105,3 @@

// When we have an array of objects, we do want to merge it
if (Array.isArray(merged) && isObject(merged[0])) {
if (Array.isArray(merged) && isPlainObject(merged[0])) {
return merged.concat(value)

@@ -143,3 +111,3 @@ }

// When the incoming value is an array, and the existing config is an object, prepend the existing object
if (Array.isArray(value) && isObject(value[0]) && isObject(merged)) {
if (Array.isArray(value) && isPlainObject(value[0]) && isPlainObject(merged)) {
return [merged, ...value]

@@ -173,36 +141,77 @@ }

/**
*
* @param {string} key
* @return {Iterable<string[] & {alpha: string | undefined}>}
*/
function* toPaths(key) {
let path = toPath(key)
if (path.length === 0) {
return
}
yield path
if (Array.isArray(key)) {
return
}
let pattern = /^(.*?)\s*\/\s*([^/]+)$/
let matches = key.match(pattern)
if (matches !== null) {
let [, prefix, alpha] = matches
let newPath = toPath(prefix)
newPath.alpha = alpha
yield newPath
}
}
function resolveFunctionKeys(object) {
// theme('colors.red.500 / 0.5') -> ['colors', 'red', '500 / 0', '5]
const resolvePath = (key, defaultValue) => {
const path = toPath(key)
for (const path of toPaths(key)) {
let index = 0
let val = object
let index = 0
let val = object
while (val !== undefined && val !== null && index < path.length) {
val = val[path[index++]]
while (val !== undefined && val !== null && index < path.length) {
val = val[path[index++]]
val = isFunction(val) ? val(resolvePath, configUtils) : val
}
let shouldResolveAsFn =
isFunction(val) && (path.alpha === undefined || index <= path.length - 1)
if (val === undefined) {
return defaultValue
}
val = shouldResolveAsFn ? val(resolvePath, configUtils) : val
}
if (isPlainObject(val)) {
return cloneDeep(val)
if (val !== undefined) {
if (path.alpha !== undefined) {
let normalized = parseColorFormat(val)
return withAlphaValue(normalized, path.alpha, toColorValue(normalized))
}
if (isPlainObject(val)) {
return cloneDeep(val)
}
return val
}
}
return val
return defaultValue
}
resolvePath.theme = resolvePath
Object.assign(resolvePath, {
theme: resolvePath,
...configUtils,
})
for (let key in configUtils) {
resolvePath[key] = configUtils[key]
}
return Object.keys(object).reduce((resolved, key) => {
resolved[key] = isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key]
return Object.keys(object).reduce((resolved, key) => {
return {
...resolved,
[key]: isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key],
}
return resolved
}, {})

@@ -260,3 +269,2 @@ }

separator: ':',
variantOrder: defaultConfig.variantOrder,
},

@@ -263,0 +271,0 @@ ]

import fs from 'fs'
import path from 'path'
const defaultConfigFiles = [
'./tailwind.config.js',
'./tailwind.config.cjs',
'./tailwind.config.mjs',
'./tailwind.config.ts',
'./tailwind.config.cts',
'./tailwind.config.mts',
]
function isObject(value) {

@@ -46,3 +55,7 @@ return typeof value === 'object' && value !== null

// require('tailwindcss')
for (const configFile of ['./tailwind.config.js', './tailwind.config.cjs']) {
return resolveDefaultConfigPath()
}
export function resolveDefaultConfigPath() {
for (const configFile of defaultConfigFiles) {
try {

@@ -49,0 +62,0 @@ const configPath = path.resolve(configFile)

@@ -1,3 +0,1 @@

import * as regex from '../lib/regex'
/**

@@ -18,55 +16,34 @@ * This splits a string on a top-level character.

*/
export function* splitAtTopLevelOnly(input, separator) {
let SPECIALS = new RegExp(`[(){}\\[\\]${regex.escape(separator)}]`, 'g')
export function splitAtTopLevelOnly(input, separator) {
let stack = []
let parts = []
let lastPos = 0
let isEscaped = false
let depth = 0
let lastIndex = 0
let found = false
let separatorIndex = 0
let separatorStart = 0
let separatorLength = separator.length
for (let idx = 0; idx < input.length; idx++) {
let char = input[idx]
// Find all paren-like things & character
// And only split on commas if they're top-level
for (let match of input.matchAll(SPECIALS)) {
let matchesSeparator = match[0] === separator[separatorIndex]
let atEndOfSeparator = separatorIndex === separatorLength - 1
let matchesFullSeparator = matchesSeparator && atEndOfSeparator
if (match[0] === '(') depth++
if (match[0] === ')') depth--
if (match[0] === '[') depth++
if (match[0] === ']') depth--
if (match[0] === '{') depth++
if (match[0] === '}') depth--
if (matchesSeparator && depth === 0) {
if (separatorStart === 0) {
separatorStart = match.index
if (stack.length === 0 && char === separator[0] && !isEscaped) {
if (separator.length === 1 || input.slice(idx, idx + separator.length) === separator) {
parts.push(input.slice(lastPos, idx))
lastPos = idx + separator.length
}
separatorIndex++
}
if (matchesFullSeparator && depth === 0) {
found = true
isEscaped = isEscaped ? false : char === '\\'
yield input.substring(lastIndex, separatorStart)
lastIndex = separatorStart + separatorLength
if (char === '(' || char === '[' || char === '{') {
stack.push(char)
} else if (
(char === ')' && stack[stack.length - 1] === '(') ||
(char === ']' && stack[stack.length - 1] === '[') ||
(char === '}' && stack[stack.length - 1] === '{')
) {
stack.pop()
}
if (separatorIndex === separatorLength) {
separatorIndex = 0
separatorStart = 0
}
}
// Provide the last segment of the string if available
// Otherwise the whole string since no `char`s were found
// This mirrors the behavior of string.split()
if (found) {
yield input.substring(lastIndex)
} else {
yield input
}
parts.push(input.slice(lastPos))
return parts
}

@@ -7,3 +7,3 @@ /**

* Example:
* a -> ['a]
* a -> ['a']
* a.b.c -> ['a', 'b', 'c']

@@ -10,0 +10,0 @@ * a[b].c -> ['a', 'b', 'c']

import postcss from 'postcss'
import isPlainObject from './isPlainObject'

@@ -13,5 +14,12 @@ export default function transformThemeValue(themeSection) {

if (themeSection === 'fontFamily') {
return (value) => {
if (typeof value === 'function') value = value({})
let families = Array.isArray(value) && isPlainObject(value[1]) ? value[0] : value
return Array.isArray(families) ? families.join(', ') : families
}
}
if (
[
'fontFamily',
'boxShadow',

@@ -48,4 +56,6 @@ 'transitionProperty',

return (value) => {
if (typeof value === 'function') value = value({})
return (value, opts = {}) => {
if (typeof value === 'function') {
value = value(opts)
}

@@ -52,0 +62,0 @@ return value

@@ -12,3 +12,16 @@ import log from './log'

// Warn if the line-clamp plugin is installed
try {
let plugin = require('@tailwindcss/line-clamp')
if (config.plugins.includes(plugin)) {
log.warn('line-clamp-in-core', [
'As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.',
'Remove it from the `plugins` array in your configuration to eliminate this warning.',
])
config.plugins = config.plugins.filter((p) => p !== plugin)
}
} catch {}
return config
}

@@ -8,3 +8,3 @@ import { parseColor, formatColor } from './color'

let parsed = parseColor(color)
let parsed = parseColor(color, { loose: true })

@@ -11,0 +11,0 @@ if (parsed === null) {

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

import type { CorePluginList } from './generated/CorePluginList'
import type { CorePluginList } from './generated/corePluginList'
import type { DefaultColors } from './generated/colors'

@@ -14,3 +14,4 @@

}
type ResolvableTo<T> = T | ((utils: PluginUtils) => T)
export type ResolvableTo<T> = T | ((utils: PluginUtils) => T)
type CSSRuleObject = RecursiveKeyValuePair<string, null | string | string[]>

@@ -34,2 +35,3 @@ interface PluginUtils {

files: (FilePath | RawFile)[]
relative?: boolean
extract?: ExtractorFn | { [extension: string]: ExtractorFn }

@@ -49,18 +51,20 @@ transform?: TransformerFn | { [extension: string]: TransformerFn }

// Safelist related config
type SafelistConfig =
| string[]
| {
pattern: RegExp
variants: string[]
}[]
type SafelistConfig = string | { pattern: RegExp; variants?: string[] }
// Blocklist related config
type BlocklistConfig = string
// Presets related config
type PresetsConfig = Config[]
type PresetsConfig = Partial<Config>
// Future related config
type FutureConfigValues = never // Replace with 'future-feature-1' | 'future-feature-2'
type FutureConfigValues =
| 'hoverOnlyWhenSupported'
| 'respectDefaultRingColorOpacity'
| 'disableColorOpacityUtilitiesByDefault'
| 'relativeContentPathsByDefault'
type FutureConfig = Expand<'all' | Partial<Record<FutureConfigValues, boolean>>> | []
// Experimental related config
type ExperimentalConfigValues = 'optimizeUniversalDefaults' // Replace with 'experimental-feature-1' | 'experimental-feature-2'
type ExperimentalConfigValues = 'optimizeUniversalDefaults' | 'matchVariant'
type ExperimentalConfig = Expand<'all' | Partial<Record<ExperimentalConfigValues, boolean>>> | []

@@ -70,8 +74,15 @@

type DarkModeConfig =
/** Use the `media` query strategy. */
// Use the `media` query strategy.
| 'media'
/** Use the `class` stategy, which requires a `.dark` class on the `html`. */
// Use the `class` strategy, which requires a `.dark` class on the `html`.
| 'class'
/** Use the `class` stategy with a custom class instead of `.dark`. */
// Use the `class` strategy with a custom class instead of `.dark`.
| ['class', string]
// Use the `selector` strategy — same as `class` but uses `:where()` for more predicable behavior
| 'selector'
// Use the `selector` strategy with a custom selector instead of `.dark`.
| ['selector', string]
// Use the `variant` strategy, which allows you to completely customize the selector
// It takes a string or an array of strings, which are passed directly to `addVariant()`
| ['variant', string | string[]]

@@ -82,13 +93,13 @@ type Screen = { raw: string } | { min: string } | { max: string } | { min: string; max: string }

// Theme related config
interface ThemeConfig {
extend: Partial<Omit<ThemeConfig, 'extend'>>
/** Responsiveness */
export interface ThemeConfig {
// Responsiveness
screens: ResolvableTo<ScreensConfig>
supports: ResolvableTo<Record<string, string>>
data: ResolvableTo<Record<string, string>>
/** Reusable base configs */
// Reusable base configs
colors: ResolvableTo<RecursiveKeyValuePair>
spacing: ResolvableTo<KeyValuePair>
/** Components */
// Components
container: ResolvableTo<

@@ -102,3 +113,3 @@ Partial<{

/** Utilities */
// Utilities
inset: ThemeConfig['spacing']

@@ -163,3 +174,16 @@ zIndex: ResolvableTo<KeyValuePair>

textIndent: ThemeConfig['spacing']
fontFamily: ResolvableTo<KeyValuePair<string, string[]>>
fontFamily: ResolvableTo<
KeyValuePair<
string,
| string
| string[]
| [
fontFamily: string | string[],
configuration: Partial<{
fontFeatureSettings: string
fontVariationSettings: string
}>
]
>
>
fontSize: ResolvableTo<

@@ -175,2 +199,3 @@ KeyValuePair<

letterSpacing: string
fontWeight: string | number
}>

@@ -206,3 +231,3 @@ ]

contrast: ResolvableTo<KeyValuePair>
dropShadow: ResolvableTo<KeyValuePair>
dropShadow: ResolvableTo<KeyValuePair<string, string | string[]>>
grayscale: ResolvableTo<KeyValuePair>

@@ -228,4 +253,5 @@ hueRotate: ResolvableTo<KeyValuePair>

content: ResolvableTo<KeyValuePair>
}
/** Custom */
interface CustomThemeConfig extends ThemeConfig {
[key: string]: any

@@ -255,5 +281,5 @@ }

export interface PluginAPI {
/** for registering new static utility styles */
// for registering new static utility styles
addUtilities(
utilities: RecursiveKeyValuePair | RecursiveKeyValuePair[],
utilities: CSSRuleObject | CSSRuleObject[],
options?: Partial<{

@@ -264,5 +290,8 @@ respectPrefix: boolean

): void
/** for registering new dynamic utility styles */
matchUtilities<T>(
utilities: KeyValuePair<string, (value: T) => RecursiveKeyValuePair>,
// for registering new dynamic utility styles
matchUtilities<T = string, U = string>(
utilities: KeyValuePair<
string,
(value: T | string, extra: { modifier: U | string | null }) => CSSRuleObject | null
>,
options?: Partial<{

@@ -273,8 +302,9 @@ respectPrefix: boolean

values: KeyValuePair<string, T>
modifiers: 'any' | KeyValuePair<string, U>
supportsNegativeValues: boolean
}>
): void
/** for registering new static component styles */
// for registering new static component styles
addComponents(
components: RecursiveKeyValuePair | RecursiveKeyValuePair[],
components: CSSRuleObject | CSSRuleObject[],
options?: Partial<{

@@ -285,5 +315,8 @@ respectPrefix: boolean

): void
/** for registering new dynamic component styles */
matchComponents<T>(
components: KeyValuePair<string, (value: T) => RecursiveKeyValuePair>,
// for registering new dynamic component styles
matchComponents<T = string, U = string>(
components: KeyValuePair<
string,
(value: T | string, extra: { modifier: U | string | null }) => CSSRuleObject | null
>,
options?: Partial<{

@@ -294,10 +327,22 @@ respectPrefix: boolean

values: KeyValuePair<string, T>
modifiers: 'any' | KeyValuePair<string, U>
supportsNegativeValues: boolean
}>
): void
/** for registering new base styles */
addBase(base: RecursiveKeyValuePair | RecursiveKeyValuePair[]): void
/** for registering custom variants */
// for registering new base styles
addBase(base: CSSRuleObject | CSSRuleObject[]): void
// for registering custom variants
addVariant(name: string, definition: string | string[] | (() => string) | (() => string)[]): void
/** for looking up values in the user’s theme configuration */
matchVariant<T = string>(
name: string,
cb: (value: T | string, extra: { modifier: string | null }) => string | string[],
options?: {
values?: KeyValuePair<string, T>
sort?(
a: { value: T | string; modifier: string | null },
b: { value: T | string; modifier: string | null }
): number
}
): void
// for looking up values in the user’s theme configuration
theme: <TDefaultValue = Config['theme']>(

@@ -307,11 +352,18 @@ path?: string,

) => TDefaultValue
/** for looking up values in the user’s Tailwind configuration */
// for looking up values in the user’s Tailwind configuration
config: <TDefaultValue = Config>(path?: string, defaultValue?: TDefaultValue) => TDefaultValue
/** for checking if a core plugin is enabled */
// for checking if a core plugin is enabled
corePlugins(path: string): boolean
/** for manually escaping strings meant to be used in class names */
// for manually escaping strings meant to be used in class names
e: (className: string) => string
}
export type PluginCreator = (api: PluginAPI) => void
export type PluginsConfig = (PluginCreator | { handler: PluginCreator; config?: Config })[]
export type PluginsConfig = (
| PluginCreator
| { handler: PluginCreator; config?: Partial<Config> }
| {
(options: any): { handler: PluginCreator; config?: Partial<Config> }
__isOptionsFunction: true
}
)[]

@@ -327,11 +379,12 @@ // Top level config related

separator: Partial<SeparatorConfig>
safelist: Partial<SafelistConfig>
presets: Partial<PresetsConfig>
safelist: Array<SafelistConfig>
blocklist: Array<BlocklistConfig>
presets: Array<PresetsConfig>
future: Partial<FutureConfig>
experimental: Partial<ExperimentalConfig>
darkMode: Partial<DarkModeConfig>
theme: Partial<ThemeConfig>
theme: Partial<CustomThemeConfig & { extend: Partial<CustomThemeConfig> }>
corePlugins: Partial<CorePluginsConfig>
plugins: Partial<PluginsConfig>
/** Custom */
// Custom
[key: string]: any

@@ -338,0 +391,0 @@ }

@@ -18,2 +18,3 @@ export interface DefaultColors {

'900': '#0f172a'
'950': '#020617'
}

@@ -31,2 +32,3 @@ gray: {

'900': '#111827'
'950': '#030712'
}

@@ -44,2 +46,3 @@ zinc: {

'900': '#18181b'
'950': '#09090b'
}

@@ -57,2 +60,3 @@ neutral: {

'900': '#171717'
'950': '#0a0a0a'
}

@@ -70,2 +74,3 @@ stone: {

'900': '#1c1917'
'950': '#0c0a09'
}

@@ -83,2 +88,3 @@ red: {

'900': '#7f1d1d'
'950': '#450a0a'
}

@@ -96,2 +102,3 @@ orange: {

'900': '#7c2d12'
'950': '#431407'
}

@@ -109,2 +116,3 @@ amber: {

'900': '#78350f'
'950': '#451a03'
}

@@ -122,2 +130,3 @@ yellow: {

'900': '#713f12'
'950': '#422006'
}

@@ -135,2 +144,3 @@ lime: {

'900': '#365314'
'950': '#1a2e05'
}

@@ -148,2 +158,3 @@ green: {

'900': '#14532d'
'950': '#052e16'
}

@@ -161,2 +172,3 @@ emerald: {

'900': '#064e3b'
'950': '#022c22'
}

@@ -174,2 +186,3 @@ teal: {

'900': '#134e4a'
'950': '#042f2e'
}

@@ -187,2 +200,3 @@ cyan: {

'900': '#164e63'
'950': '#083344'
}

@@ -200,2 +214,3 @@ sky: {

'900': '#0c4a6e'
'950': '#082f49'
}

@@ -213,2 +228,3 @@ blue: {

'900': '#1e3a8a'
'950': '#172554'
}

@@ -226,2 +242,3 @@ indigo: {

'900': '#312e81'
'950': '#1e1b4b'
}

@@ -239,2 +256,3 @@ violet: {

'900': '#4c1d95'
'950': '#2e1065'
}

@@ -252,2 +270,3 @@ purple: {

'900': '#581c87'
'950': '#3b0764'
}

@@ -265,2 +284,3 @@ fuchsia: {

'900': '#701a75'
'950': '#4a044e'
}

@@ -278,2 +298,3 @@ pink: {

'900': '#831843'
'950': '#500724'
}

@@ -291,2 +312,3 @@ rose: {

'900': '#881337'
'950': '#4c0519'
}

@@ -293,0 +315,0 @@ /** @deprecated As of Tailwind CSS v2.2, `lightBlue` has been renamed to `sky`. Update your configuration file to silence this warning. */ lightBlue: DefaultColors['sky']

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

export type CorePluginList = 'preflight' | 'container' | 'accessibility' | 'pointerEvents' | 'visibility' | 'position' | 'inset' | 'isolation' | 'zIndex' | 'order' | 'gridColumn' | 'gridColumnStart' | 'gridColumnEnd' | 'gridRow' | 'gridRowStart' | 'gridRowEnd' | 'float' | 'clear' | 'margin' | 'boxSizing' | 'display' | 'aspectRatio' | 'height' | 'maxHeight' | 'minHeight' | 'width' | 'minWidth' | 'maxWidth' | 'flex' | 'flexShrink' | 'flexGrow' | 'flexBasis' | 'tableLayout' | 'borderCollapse' | 'borderSpacing' | 'transformOrigin' | 'translate' | 'rotate' | 'skew' | 'scale' | 'transform' | 'animation' | 'cursor' | 'touchAction' | 'userSelect' | 'resize' | 'scrollSnapType' | 'scrollSnapAlign' | 'scrollSnapStop' | 'scrollMargin' | 'scrollPadding' | 'listStylePosition' | 'listStyleType' | 'appearance' | 'columns' | 'breakBefore' | 'breakInside' | 'breakAfter' | 'gridAutoColumns' | 'gridAutoFlow' | 'gridAutoRows' | 'gridTemplateColumns' | 'gridTemplateRows' | 'flexDirection' | 'flexWrap' | 'placeContent' | 'placeItems' | 'alignContent' | 'alignItems' | 'justifyContent' | 'justifyItems' | 'gap' | 'space' | 'divideWidth' | 'divideStyle' | 'divideColor' | 'divideOpacity' | 'placeSelf' | 'alignSelf' | 'justifySelf' | 'overflow' | 'overscrollBehavior' | 'scrollBehavior' | 'textOverflow' | 'whitespace' | 'wordBreak' | 'borderRadius' | 'borderWidth' | 'borderStyle' | 'borderColor' | 'borderOpacity' | 'backgroundColor' | 'backgroundOpacity' | 'backgroundImage' | 'gradientColorStops' | 'boxDecorationBreak' | 'backgroundSize' | 'backgroundAttachment' | 'backgroundClip' | 'backgroundPosition' | 'backgroundRepeat' | 'backgroundOrigin' | 'fill' | 'stroke' | 'strokeWidth' | 'objectFit' | 'objectPosition' | 'padding' | 'textAlign' | 'textIndent' | 'verticalAlign' | 'fontFamily' | 'fontSize' | 'fontWeight' | 'textTransform' | 'fontStyle' | 'fontVariantNumeric' | 'lineHeight' | 'letterSpacing' | 'textColor' | 'textOpacity' | 'textDecoration' | 'textDecorationColor' | 'textDecorationStyle' | 'textDecorationThickness' | 'textUnderlineOffset' | 'fontSmoothing' | 'placeholderColor' | 'placeholderOpacity' | 'caretColor' | 'accentColor' | 'opacity' | 'backgroundBlendMode' | 'mixBlendMode' | 'boxShadow' | 'boxShadowColor' | 'outlineStyle' | 'outlineWidth' | 'outlineOffset' | 'outlineColor' | 'ringWidth' | 'ringColor' | 'ringOpacity' | 'ringOffsetWidth' | 'ringOffsetColor' | 'blur' | 'brightness' | 'contrast' | 'dropShadow' | 'grayscale' | 'hueRotate' | 'invert' | 'saturate' | 'sepia' | 'filter' | 'backdropBlur' | 'backdropBrightness' | 'backdropContrast' | 'backdropGrayscale' | 'backdropHueRotate' | 'backdropInvert' | 'backdropOpacity' | 'backdropSaturate' | 'backdropSepia' | 'backdropFilter' | 'transitionProperty' | 'transitionDelay' | 'transitionDuration' | 'transitionTimingFunction' | 'willChange' | 'content'
export type CorePluginList = 'preflight' | 'container' | 'accessibility' | 'pointerEvents' | 'visibility' | 'position' | 'inset' | 'isolation' | 'zIndex' | 'order' | 'gridColumn' | 'gridColumnStart' | 'gridColumnEnd' | 'gridRow' | 'gridRowStart' | 'gridRowEnd' | 'float' | 'clear' | 'margin' | 'boxSizing' | 'lineClamp' | 'display' | 'aspectRatio' | 'size' | 'height' | 'maxHeight' | 'minHeight' | 'width' | 'minWidth' | 'maxWidth' | 'flex' | 'flexShrink' | 'flexGrow' | 'flexBasis' | 'tableLayout' | 'captionSide' | 'borderCollapse' | 'borderSpacing' | 'transformOrigin' | 'translate' | 'rotate' | 'skew' | 'scale' | 'transform' | 'animation' | 'cursor' | 'touchAction' | 'userSelect' | 'resize' | 'scrollSnapType' | 'scrollSnapAlign' | 'scrollSnapStop' | 'scrollMargin' | 'scrollPadding' | 'listStylePosition' | 'listStyleType' | 'listStyleImage' | 'appearance' | 'columns' | 'breakBefore' | 'breakInside' | 'breakAfter' | 'gridAutoColumns' | 'gridAutoFlow' | 'gridAutoRows' | 'gridTemplateColumns' | 'gridTemplateRows' | 'flexDirection' | 'flexWrap' | 'placeContent' | 'placeItems' | 'alignContent' | 'alignItems' | 'justifyContent' | 'justifyItems' | 'gap' | 'space' | 'divideWidth' | 'divideStyle' | 'divideColor' | 'divideOpacity' | 'placeSelf' | 'alignSelf' | 'justifySelf' | 'overflow' | 'overscrollBehavior' | 'scrollBehavior' | 'textOverflow' | 'hyphens' | 'whitespace' | 'textWrap' | 'wordBreak' | 'borderRadius' | 'borderWidth' | 'borderStyle' | 'borderColor' | 'borderOpacity' | 'backgroundColor' | 'backgroundOpacity' | 'backgroundImage' | 'gradientColorStops' | 'boxDecorationBreak' | 'backgroundSize' | 'backgroundAttachment' | 'backgroundClip' | 'backgroundPosition' | 'backgroundRepeat' | 'backgroundOrigin' | 'fill' | 'stroke' | 'strokeWidth' | 'objectFit' | 'objectPosition' | 'padding' | 'textAlign' | 'textIndent' | 'verticalAlign' | 'fontFamily' | 'fontSize' | 'fontWeight' | 'textTransform' | 'fontStyle' | 'fontVariantNumeric' | 'lineHeight' | 'letterSpacing' | 'textColor' | 'textOpacity' | 'textDecoration' | 'textDecorationColor' | 'textDecorationStyle' | 'textDecorationThickness' | 'textUnderlineOffset' | 'fontSmoothing' | 'placeholderColor' | 'placeholderOpacity' | 'caretColor' | 'accentColor' | 'opacity' | 'backgroundBlendMode' | 'mixBlendMode' | 'boxShadow' | 'boxShadowColor' | 'outlineStyle' | 'outlineWidth' | 'outlineOffset' | 'outlineColor' | 'ringWidth' | 'ringColor' | 'ringOpacity' | 'ringOffsetWidth' | 'ringOffsetColor' | 'blur' | 'brightness' | 'contrast' | 'dropShadow' | 'grayscale' | 'hueRotate' | 'invert' | 'saturate' | 'sepia' | 'filter' | 'backdropBlur' | 'backdropBrightness' | 'backdropContrast' | 'backdropGrayscale' | 'backdropHueRotate' | 'backdropInvert' | 'backdropOpacity' | 'backdropSaturate' | 'backdropSepia' | 'backdropFilter' | 'transitionProperty' | 'transitionDelay' | 'transitionDuration' | 'transitionTimingFunction' | 'willChange' | 'contain' | 'content' | 'forcedColorAdjust'

@@ -1,1 +0,11 @@

declare namespace tailwindcss {}
import type { PluginCreator } from 'postcss'
import type { Config } from './config.d'
declare const plugin: PluginCreator<string | Config | { config: string | Config }>
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 not supported yet

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

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

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc