tailwindcss
Advanced tools
Comparing version 0.0.0-insiders.8f788e2 to 0.0.0-insiders.8f91c27
#!/usr/bin/env node | ||
"use strict"; | ||
module.exports = require('./cli/index'); | ||
module.exports = require("./cli/index"); |
@@ -22,22 +22,19 @@ // @ts-check | ||
async function build(args) { | ||
let input = args['--input']; | ||
let shouldWatch = args['--watch']; | ||
let input = args["--input"]; | ||
let shouldWatch = args["--watch"]; | ||
// 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 && 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.`); | ||
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.`); | ||
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); | ||
} | ||
if (args['--no-autoprefixer']) { | ||
console.error('[deprecation] The --no-autoprefixer flag is deprecated and has no effect.'); | ||
} | ||
// TODO: Reference the @config path here if exists | ||
let configPath = args['--config'] ? args['--config'] : (0, _resolveConfigPath.resolveDefaultConfigPath)(); | ||
let configPath = args["--config"] ? args["--config"] : (0, _resolveConfigPath.resolveDefaultConfigPath)(); | ||
let processor = await (0, _plugin.createProcessor)(args, configPath); | ||
@@ -47,4 +44,4 @@ if (shouldWatch) { | ||
// You can disable this behavior with --watch=always | ||
if (args['--watch'] !== 'always') { | ||
process.stdin.on('end', ()=>process.exit(0)); | ||
if (args["--watch"] !== "always") { | ||
process.stdin.on("end", ()=>process.exit(0)); | ||
} | ||
@@ -51,0 +48,0 @@ process.stdin.resume(); |
@@ -12,9 +12,5 @@ // @ts-check | ||
}); | ||
const _packagejson = /*#__PURE__*/ _interop_require_default(require("../../../package.json")); | ||
const _path = /*#__PURE__*/ _interop_require_default(require("path")); | ||
const _fs = /*#__PURE__*/ _interop_require_default(require("fs")); | ||
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss")); | ||
const _postcssloadconfig = /*#__PURE__*/ _interop_require_default(require("postcss-load-config")); | ||
const _browserslist = /*#__PURE__*/ _interop_require_default(require("browserslist")); | ||
const _lightningcss = /*#__PURE__*/ _interop_require_wildcard(require("lightningcss")); | ||
const _lilconfig = require("lilconfig"); | ||
@@ -26,2 +22,3 @@ const _plugins = /*#__PURE__*/ _interop_require_default(require("postcss-load-config/src/plugins" // Little bit scary, looking at private/internal API | ||
const _processTailwindFeatures = /*#__PURE__*/ _interop_require_default(require("../../processTailwindFeatures")); | ||
const _deps = require("./deps"); | ||
const _utils = require("./utils"); | ||
@@ -37,5 +34,2 @@ const _sharedState = require("../../lib/sharedState"); | ||
const _getModuleDependencies = /*#__PURE__*/ _interop_require_default(require("../../lib/getModuleDependencies")); | ||
const _validateConfig = require("../../util/validateConfig"); | ||
const _handleImportAtRules = require("../../lib/handleImportAtRules"); | ||
const _featureFlags = require("../../featureFlags"); | ||
function _interop_require_default(obj) { | ||
@@ -46,78 +40,2 @@ return obj && obj.__esModule ? 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 = { | ||
__proto__: null | ||
}; | ||
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; | ||
} | ||
function license() { | ||
return `/* ! tailwindcss v${_packagejson.default.version} | MIT License | https://tailwindcss.com */\n`; | ||
} | ||
async function lightningcss(result, { map = true, minify = true } = {}) { | ||
try { | ||
var _browserslist_findConfig; | ||
var _result_opts_from; | ||
let resolvedBrowsersListConfig = (_browserslist_findConfig = _browserslist.default.findConfig((_result_opts_from = result.opts.from) !== null && _result_opts_from !== void 0 ? _result_opts_from : process.cwd())) === null || _browserslist_findConfig === void 0 ? void 0 : _browserslist_findConfig.defaults; | ||
let defaultBrowsersListConfig = _packagejson.default.browserslist; | ||
let browsersListConfig = resolvedBrowsersListConfig !== null && resolvedBrowsersListConfig !== void 0 ? resolvedBrowsersListConfig : defaultBrowsersListConfig; | ||
let transformed = _lightningcss.default.transform({ | ||
filename: result.opts.from || 'input.css', | ||
code: Buffer.from(result.css, 'utf-8'), | ||
minify, | ||
sourceMap: result.map === undefined ? map : !!result.map, | ||
inputSourceMap: result.map ? result.map.toString() : undefined, | ||
targets: _lightningcss.default.browserslistToTargets((0, _browserslist.default)(browsersListConfig)), | ||
include: _lightningcss.Features.Nesting, | ||
exclude: _lightningcss.Features.LogicalProperties | ||
}); | ||
return Object.assign(result, { | ||
css: transformed.code.toString(), | ||
map: result.map ? Object.assign(result.map, { | ||
toString () { | ||
var _transformed_map; | ||
return (_transformed_map = transformed.map) === null || _transformed_map === void 0 ? void 0 : _transformed_map.toString(); | ||
} | ||
}) : result.map | ||
}); | ||
} catch (err) { | ||
console.error('Unable to use Lightning CSS. Using raw version instead.'); | ||
console.error(err); | ||
return result; | ||
} | ||
} | ||
/** | ||
@@ -132,4 +50,4 @@ * | ||
// @ts-ignore | ||
let { config = {} } = await (0, _lilconfig.lilconfig)('postcss').load(file); | ||
if (typeof config === 'function') { | ||
let { config ={} } = await (0, _lilconfig.lilconfig)("postcss").load(file); | ||
if (typeof config === "function") { | ||
config = config(); | ||
@@ -150,6 +68,6 @@ } else { | ||
let configPluginTailwindIdx = configPlugins.findIndex((plugin)=>{ | ||
if (typeof plugin === 'function' && plugin.name === 'tailwindcss') { | ||
if (typeof plugin === "function" && plugin.name === "tailwindcss") { | ||
return true; | ||
} | ||
if (typeof plugin === 'object' && plugin !== null && plugin.postcssPlugin === 'tailwindcss') { | ||
if (typeof plugin === "object" && plugin !== null && plugin.postcssPlugin === "tailwindcss") { | ||
return true; | ||
@@ -167,2 +85,34 @@ } | ||
} | ||
function loadBuiltinPostcssPlugins() { | ||
let postcss = (0, _deps.loadPostcss)(); | ||
let IMPORT_COMMENT = "__TAILWIND_RESTORE_IMPORT__: "; | ||
return [ | ||
[ | ||
(root)=>{ | ||
root.walkAtRules("import", (rule)=>{ | ||
if (rule.params.slice(1).startsWith("tailwindcss/")) { | ||
rule.after(postcss.comment({ | ||
text: IMPORT_COMMENT + rule.params | ||
})); | ||
rule.remove(); | ||
} | ||
}); | ||
}, | ||
(0, _deps.loadPostcssImport)(), | ||
(root)=>{ | ||
root.walkComments((rule)=>{ | ||
if (rule.text.startsWith(IMPORT_COMMENT)) { | ||
rule.after(postcss.atRule({ | ||
name: "import", | ||
params: rule.text.replace(IMPORT_COMMENT, "") | ||
})); | ||
rule.remove(); | ||
} | ||
}); | ||
} | ||
], | ||
[], | ||
{} | ||
]; | ||
} | ||
let state = { | ||
@@ -172,3 +122,3 @@ /** @type {any} */ context: null, | ||
/** @type {{content: string, extension: string}[]} */ changedContent: [], | ||
/** @type {{config: import('../../../types').Config, dependencies: Set<string>, dispose: Function } | null} */ configBag: null, | ||
/** @type {ReturnType<typeof load> | null} */ configBag: null, | ||
contextDependencies: new Set(), | ||
@@ -204,3 +154,8 @@ /** @type {import('../../lib/content.js').ContentPath[]} */ contentPaths: [], | ||
}; | ||
this.configBag.config = (0, _validateConfig.validateConfig)((0, _resolveConfig.default)(this.configBag.config)); | ||
// @ts-ignore | ||
this.configBag.config = (0, _resolveConfig.default)(this.configBag.config, { | ||
content: { | ||
files: [] | ||
} | ||
}); | ||
// Override content files if `--content` has been passed explicitly | ||
@@ -214,5 +169,5 @@ if ((content === null || content === void 0 ? void 0 : content.length) > 0) { | ||
var _this_configBag; | ||
_sharedState.env.DEBUG && console.time('Module dependencies'); | ||
_sharedState.env.DEBUG && console.time("Module dependencies"); | ||
(_this_configBag = this.configBag) === null || _this_configBag === void 0 ? void 0 : _this_configBag.dispose(); | ||
_sharedState.env.DEBUG && console.timeEnd('Module dependencies'); | ||
_sharedState.env.DEBUG && console.timeEnd("Module dependencies"); | ||
}, | ||
@@ -224,20 +179,15 @@ readContentPaths () { | ||
let files = _fastglob.default.sync(this.contentPatterns.all); | ||
let checkBroadPattern = (0, _content.createBroadPatternCheck)(this.contentPatterns.all); | ||
for (let file of files){ | ||
if ((0, _featureFlags.flagEnabled)(this.config, 'oxideParser')) { | ||
content.push({ | ||
file, | ||
extension: _path.default.extname(file).slice(1) | ||
}); | ||
} else { | ||
content.push({ | ||
content: _fs.default.readFileSync(_path.default.resolve(file), 'utf8'), | ||
extension: _path.default.extname(file).slice(1) | ||
}); | ||
} | ||
checkBroadPattern(file); | ||
content.push({ | ||
content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"), | ||
extension: _path.default.extname(file).slice(1) | ||
}); | ||
} | ||
// Resolve raw content in the tailwind config | ||
let rawContent = this.config.content.files.filter((file)=>{ | ||
return file !== null && typeof file === 'object'; | ||
return file !== null && typeof file === "object"; | ||
}); | ||
for (let { raw: htmlContent, extension = 'html' } of rawContent){ | ||
for (let { raw: htmlContent , extension ="html" } of rawContent){ | ||
content.push({ | ||
@@ -250,3 +200,7 @@ content: htmlContent, | ||
}, | ||
getContext ({ createContext, cliConfigPath, root, result, content }) { | ||
getContext ({ createContext , cliConfigPath , root , result , content }) { | ||
_sharedState.env.DEBUG && console.time("Searching for config"); | ||
var _findAtConfigPath1; | ||
let configPath = (_findAtConfigPath1 = (0, _findAtConfigPath.findAtConfigPath)(root, result)) !== null && _findAtConfigPath1 !== void 0 ? _findAtConfigPath1 : cliConfigPath; | ||
_sharedState.env.DEBUG && console.timeEnd("Searching for config"); | ||
if (this.context) { | ||
@@ -256,10 +210,6 @@ this.context.changedContent = this.changedContent.splice(0); | ||
} | ||
_sharedState.env.DEBUG && console.time('Searching for config'); | ||
var _findAtConfigPath1; | ||
let configPath = (_findAtConfigPath1 = (0, _findAtConfigPath.findAtConfigPath)(root, result)) !== null && _findAtConfigPath1 !== void 0 ? _findAtConfigPath1 : cliConfigPath; | ||
_sharedState.env.DEBUG && console.timeEnd('Searching for config'); | ||
_sharedState.env.DEBUG && console.time('Loading config'); | ||
_sharedState.env.DEBUG && console.time("Loading config"); | ||
let config = this.loadConfig(configPath, content); | ||
_sharedState.env.DEBUG && console.timeEnd('Loading config'); | ||
_sharedState.env.DEBUG && console.time('Creating context'); | ||
_sharedState.env.DEBUG && console.timeEnd("Loading config"); | ||
_sharedState.env.DEBUG && console.time("Creating context"); | ||
this.context = createContext(config, []); | ||
@@ -269,10 +219,10 @@ Object.assign(this.context, { | ||
}); | ||
_sharedState.env.DEBUG && console.timeEnd('Creating context'); | ||
_sharedState.env.DEBUG && console.time('Resolving content paths'); | ||
_sharedState.env.DEBUG && console.timeEnd("Creating context"); | ||
_sharedState.env.DEBUG && console.time("Resolving content paths"); | ||
this.refreshContentPaths(); | ||
_sharedState.env.DEBUG && console.timeEnd('Resolving content paths'); | ||
_sharedState.env.DEBUG && console.timeEnd("Resolving content paths"); | ||
if (this.watcher) { | ||
_sharedState.env.DEBUG && console.time('Watch new files'); | ||
_sharedState.env.DEBUG && console.time("Watch new files"); | ||
this.watcher.refreshWatchedFiles(); | ||
_sharedState.env.DEBUG && console.timeEnd('Watch new files'); | ||
_sharedState.env.DEBUG && console.timeEnd("Watch new files"); | ||
} | ||
@@ -287,31 +237,27 @@ for (let file of this.readContentPaths()){ | ||
var _args_content; | ||
let input = args['--input']; | ||
let output = args['--output']; | ||
let includePostCss = args['--postcss']; | ||
let customPostCssPath = typeof args['--postcss'] === 'string' ? args['--postcss'] : undefined; | ||
let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins(customPostCssPath) : [ | ||
[], | ||
[], | ||
{} | ||
]; | ||
beforePlugins.unshift(...(0, _handleImportAtRules.handleImportAtRules)()); | ||
if (args['--purge']) { | ||
_log.default.warn('purge-flag-deprecated', [ | ||
'The `--purge` flag has been deprecated.', | ||
'Please use `--content` instead.' | ||
let postcss = (0, _deps.loadPostcss)(); | ||
let input = args["--input"]; | ||
let output = args["--output"]; | ||
let includePostCss = args["--postcss"]; | ||
let customPostCssPath = typeof args["--postcss"] === "string" ? args["--postcss"] : undefined; | ||
let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins(customPostCssPath) : loadBuiltinPostcssPlugins(); | ||
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"]) { | ||
args["--content"] = args["--purge"]; | ||
} | ||
} | ||
var _args_content_split; | ||
let content = (_args_content_split = (_args_content = args['--content']) === null || _args_content === void 0 ? void 0 : _args_content.split(RegExp("(?<!{[^}]+),"))) !== null && _args_content_split !== void 0 ? _args_content_split : []; | ||
let content = (_args_content_split = (_args_content = args["--content"]) === null || _args_content === void 0 ? void 0 : _args_content.split(/(?<!{[^}]+),/)) !== null && _args_content_split !== void 0 ? _args_content_split : []; | ||
let tailwindPlugin = ()=>{ | ||
return { | ||
postcssPlugin: 'tailwindcss', | ||
async Once (root, { result }) { | ||
_sharedState.env.DEBUG && console.time('Compiling CSS'); | ||
await (0, _processTailwindFeatures.default)(({ createContext })=>{ | ||
postcssPlugin: "tailwindcss", | ||
async Once (root, { result }) { | ||
_sharedState.env.DEBUG && console.time("Compiling CSS"); | ||
await (0, _processTailwindFeatures.default)(({ createContext })=>{ | ||
console.error(); | ||
console.error('Rebuilding...'); | ||
console.error("Rebuilding..."); | ||
return ()=>{ | ||
@@ -327,3 +273,3 @@ return state.getContext({ | ||
})(root, result); | ||
_sharedState.env.DEBUG && console.timeEnd('Compiling CSS'); | ||
_sharedState.env.DEBUG && console.timeEnd("Compiling CSS"); | ||
} | ||
@@ -336,10 +282,12 @@ }; | ||
tailwindPlugin, | ||
!args['--minify'] && _utils.formatNodes, | ||
...afterPlugins | ||
!args["--minify"] && _utils.formatNodes, | ||
...afterPlugins, | ||
!args["--no-autoprefixer"] && (0, _deps.loadAutoprefixer)(), | ||
args["--minify"] && (0, _deps.loadCssNano)() | ||
].filter(Boolean); | ||
/** @type {import('postcss').Processor} */ // @ts-ignore | ||
let processor = (0, _postcss.default)(plugins); | ||
let processor = postcss(plugins); | ||
async function readInput() { | ||
// Piping in data, let's drain the stdin | ||
if (input === '-') { | ||
if (input === "-") { | ||
return (0, _utils.drainStdin)(); | ||
@@ -349,17 +297,13 @@ } | ||
if (input) { | ||
return _fs.default.promises.readFile(_path.default.resolve(input), 'utf8'); | ||
return _fs.default.promises.readFile(_path.default.resolve(input), "utf8"); | ||
} | ||
// No input file provided, fallback to default atrules | ||
return '@tailwind base; @tailwind components; @tailwind utilities'; | ||
// No input file provided, fallback to default at-rules | ||
return "@tailwind base; @tailwind components; @tailwind utilities"; | ||
} | ||
async function build() { | ||
let start = process.hrtime.bigint(); | ||
let options = { | ||
...postcssOptions, | ||
from: input, | ||
to: output | ||
}; | ||
return readInput().then((css)=>processor.process(css, options)).then((result)=>lightningcss(result, { | ||
...options, | ||
minify: !!args['--minify'] | ||
return readInput().then((css)=>processor.process(css, { | ||
...postcssOptions, | ||
from: input, | ||
to: output | ||
})).then((result)=>{ | ||
@@ -369,22 +313,22 @@ if (!state.watcher) { | ||
} | ||
_sharedState.env.DEBUG && console.time('Recording PostCSS dependencies'); | ||
_sharedState.env.DEBUG && console.time("Recording PostCSS dependencies"); | ||
for (let message of result.messages){ | ||
if (message.type === 'dependency') { | ||
if (message.type === "dependency") { | ||
state.contextDependencies.add(message.file); | ||
} | ||
} | ||
_sharedState.env.DEBUG && console.timeEnd('Recording PostCSS dependencies'); | ||
_sharedState.env.DEBUG && console.timeEnd("Recording PostCSS dependencies"); | ||
// TODO: This needs to be in a different spot | ||
_sharedState.env.DEBUG && console.time('Watch new files'); | ||
_sharedState.env.DEBUG && console.time("Watch new files"); | ||
state.watcher.refreshWatchedFiles(); | ||
_sharedState.env.DEBUG && console.timeEnd('Watch new files'); | ||
_sharedState.env.DEBUG && console.timeEnd("Watch new files"); | ||
return result; | ||
}).then((result)=>{ | ||
if (!output) { | ||
process.stdout.write(license() + result.css); | ||
process.stdout.write(result.css); | ||
return; | ||
} | ||
return Promise.all([ | ||
(0, _utils.outputFile)(result.opts.to, license() + result.css), | ||
result.map && (0, _utils.outputFile)(result.opts.to + '.map', result.map.toString()) | ||
(0, _utils.outputFile)(result.opts.to, result.css), | ||
result.map && (0, _utils.outputFile)(result.opts.to + ".map", result.map.toString()) | ||
]); | ||
@@ -394,3 +338,3 @@ }).then(()=>{ | ||
console.error(); | ||
console.error('Done in', (end - start) / BigInt(1e6) + 'ms.'); | ||
console.error("Done in", (end - start) / BigInt(1e6) + "ms."); | ||
}).then(()=>{}, (err)=>{ | ||
@@ -421,3 +365,3 @@ // TODO: If an initial build fails we can't easily pick up any PostCSS dependencies | ||
} | ||
if (input !== undefined && input !== '-') { | ||
if (input !== undefined && input !== "-") { | ||
state.contextDependencies.add(_path.default.resolve(input)); | ||
@@ -424,0 +368,0 @@ } |
@@ -13,4 +13,4 @@ // @ts-check | ||
_export(exports, { | ||
drainStdin: function() { | ||
return drainStdin; | ||
indentRecursive: function() { | ||
return indentRecursive; | ||
}, | ||
@@ -20,10 +20,10 @@ formatNodes: function() { | ||
}, | ||
indentRecursive: function() { | ||
return indentRecursive; | ||
readFileWithRetries: function() { | ||
return readFileWithRetries; | ||
}, | ||
drainStdin: function() { | ||
return drainStdin; | ||
}, | ||
outputFile: function() { | ||
return outputFile; | ||
}, | ||
readFileWithRetries: function() { | ||
return readFileWithRetries; | ||
} | ||
@@ -40,6 +40,6 @@ }); | ||
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)}`; | ||
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)}`; | ||
child.raws.after = `\n${" ".repeat(indent)}`; | ||
indentRecursive(child, indent + 1); | ||
@@ -51,3 +51,3 @@ }); | ||
if (root.first) { | ||
root.first.raws.before = ''; | ||
root.first.raws.before = ""; | ||
} | ||
@@ -58,6 +58,6 @@ } | ||
try { | ||
return await _fs.default.promises.readFile(path, 'utf8'); | ||
return await _fs.default.promises.readFile(path, "utf8"); | ||
} catch (err) { | ||
if (n !== tries) { | ||
if (err.code === 'ENOENT' || err.code === 'EBUSY') { | ||
if (err.code === "ENOENT" || err.code === "EBUSY") { | ||
await new Promise((resolve)=>setTimeout(resolve, 10)); | ||
@@ -73,8 +73,8 @@ continue; | ||
return new Promise((resolve, reject)=>{ | ||
let result = ''; | ||
process.stdin.on('data', (chunk)=>{ | ||
let result = ""; | ||
process.stdin.on("data", (chunk)=>{ | ||
result += chunk; | ||
}); | ||
process.stdin.on('end', ()=>resolve(result)); | ||
process.stdin.on('error', (err)=>reject(err)); | ||
process.stdin.on("end", ()=>resolve(result)); | ||
process.stdin.on("error", (err)=>reject(err)); | ||
}); | ||
@@ -84,7 +84,7 @@ } | ||
try { | ||
let currentContents = await _fs.default.promises.readFile(file, 'utf8'); | ||
let currentContents = await _fs.default.promises.readFile(file, "utf8"); | ||
if (currentContents === newContents) { | ||
return; // Skip writing the file | ||
} | ||
} catch (e) {} | ||
} catch {} | ||
// Write the file | ||
@@ -94,3 +94,3 @@ await _fs.default.promises.mkdir(_path.default.dirname(file), { | ||
}); | ||
await _fs.default.promises.writeFile(file, newContents, 'utf8'); | ||
await _fs.default.promises.writeFile(file, newContents, "utf8"); | ||
} |
@@ -23,5 +23,5 @@ // @ts-check | ||
} | ||
function createWatcher(args, { state, rebuild }) { | ||
let shouldPoll = args['--poll']; | ||
let shouldCoalesceWriteEvents = shouldPoll || process.platform === 'win32'; | ||
function createWatcher(args, { state , rebuild }) { | ||
let shouldPoll = args["--poll"]; | ||
let shouldCoalesceWriteEvents = shouldPoll || process.platform === "win32"; | ||
// Polling interval in milliseconds | ||
@@ -92,3 +92,3 @@ // Used only when polling or coalescing add/change events on Windows | ||
file, | ||
content: content !== null && content !== void 0 ? content : ()=>_fs.default.promises.readFile(file, 'utf8'), | ||
content: content !== null && content !== void 0 ? content : ()=>_fs.default.promises.readFile(file, "utf8"), | ||
extension: _path.default.extname(file).slice(1) | ||
@@ -112,8 +112,8 @@ }); | ||
} | ||
watcher.on('change', (file)=>recordChangedFile(file)); | ||
watcher.on('add', (file)=>recordChangedFile(file)); | ||
watcher.on("change", (file)=>recordChangedFile(file)); | ||
watcher.on("add", (file)=>recordChangedFile(file)); | ||
// Restore watching any files that are "removed" | ||
// This can happen when a file is pseudo-atomically replaced (a copy is created, overwritten, the old one is unlinked, and the new one is renamed) | ||
// TODO: An an optimization we should allow removal when the config changes | ||
watcher.on('unlink', (file)=>{ | ||
watcher.on("unlink", (file)=>{ | ||
file = (0, _normalizepath.default)(file); | ||
@@ -131,4 +131,4 @@ // Only re-add the file if it's not covered by a dynamic pattern | ||
// We treat this as a change event and rebuild the CSS | ||
watcher.on('raw', (evt, filePath, meta)=>{ | ||
if (evt !== 'rename' || filePath === null) { | ||
watcher.on("raw", (evt, filePath, meta)=>{ | ||
if (evt !== "rename" || filePath === null) { | ||
return; | ||
@@ -168,3 +168,3 @@ } | ||
await recordChangedFile(filePath, ()=>content, true); | ||
} catch (e) { | ||
} catch { | ||
// If reading the file fails, it's was probably a deleted temporary file | ||
@@ -171,0 +171,0 @@ // So we can ignore it and no rebuild is needed |
@@ -18,3 +18,3 @@ // @ts-check | ||
} | ||
function help({ message, usage, commands, options }) { | ||
function help({ message , usage , commands , options }) { | ||
let indent = 2; | ||
@@ -27,3 +27,3 @@ // Render header | ||
console.log(); | ||
for (let msg of message.split('\n')){ | ||
for (let msg of message.split("\n")){ | ||
console.log(msg); | ||
@@ -35,5 +35,5 @@ } | ||
console.log(); | ||
console.log('Usage:'); | ||
console.log("Usage:"); | ||
for (let example of usage){ | ||
console.log(' '.repeat(indent), example); | ||
console.log(" ".repeat(indent), example); | ||
} | ||
@@ -44,5 +44,5 @@ } | ||
console.log(); | ||
console.log('Commands:'); | ||
console.log("Commands:"); | ||
for (let command of commands){ | ||
console.log(' '.repeat(indent), command); | ||
console.log(" ".repeat(indent), command); | ||
} | ||
@@ -54,3 +54,3 @@ } | ||
for (let [key, value] of Object.entries(options)){ | ||
if (typeof value === 'object') { | ||
if (typeof value === "object") { | ||
groupedOptions[key] = { | ||
@@ -67,9 +67,9 @@ ...value, | ||
console.log(); | ||
console.log('Options:'); | ||
for (let { flags, description, deprecated } of Object.values(groupedOptions)){ | ||
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); | ||
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(" ".repeat(indent), flags.slice().reverse().join(", ").padEnd(24, " "), description); | ||
} | ||
@@ -76,0 +76,0 @@ } |
@@ -25,3 +25,3 @@ #!/usr/bin/env node | ||
} | ||
throw new Error('...'); | ||
throw new Error("..."); | ||
}, { | ||
@@ -35,20 +35,20 @@ manualParsing: true | ||
args: { | ||
'--esm': { | ||
"--esm": { | ||
type: Boolean, | ||
description: `Initialize configuration file as ESM` | ||
}, | ||
'--ts': { | ||
"--ts": { | ||
type: Boolean, | ||
description: `Initialize configuration file as TypeScript` | ||
}, | ||
'--postcss': { | ||
"--postcss": { | ||
type: Boolean, | ||
description: `Initialize a \`postcss.config.js\` file` | ||
}, | ||
'--full': { | ||
"--full": { | ||
type: Boolean, | ||
description: `Include the default values for all options in the generated configuration file` | ||
}, | ||
'-f': '--full', | ||
'-p': '--postcss' | ||
"-f": "--full", | ||
"-p": "--postcss" | ||
} | ||
@@ -59,49 +59,48 @@ }, | ||
args: { | ||
'--input': { | ||
"--input": { | ||
type: String, | ||
description: 'Input file' | ||
description: "Input file" | ||
}, | ||
'--output': { | ||
"--output": { | ||
type: String, | ||
description: 'Output file' | ||
description: "Output file" | ||
}, | ||
'--watch': { | ||
"--watch": { | ||
type: oneOf(String, Boolean), | ||
description: 'Watch for changes and rebuild as needed' | ||
description: "Watch for changes and rebuild as needed" | ||
}, | ||
'--poll': { | ||
"--poll": { | ||
type: Boolean, | ||
description: 'Use polling instead of filesystem events when watching' | ||
description: "Use polling instead of filesystem events when watching" | ||
}, | ||
'--content': { | ||
"--content": { | ||
type: String, | ||
description: 'Content paths to use for removing unused classes' | ||
description: "Content paths to use for removing unused classes" | ||
}, | ||
'--purge': { | ||
"--purge": { | ||
type: String, | ||
deprecated: true | ||
}, | ||
'--postcss': { | ||
"--postcss": { | ||
type: oneOf(String, Boolean), | ||
description: 'Load custom PostCSS configuration' | ||
description: "Load custom PostCSS configuration" | ||
}, | ||
'--minify': { | ||
"--minify": { | ||
type: Boolean, | ||
description: 'Minify the output' | ||
description: "Minify the output" | ||
}, | ||
'--config': { | ||
"--config": { | ||
type: String, | ||
description: 'Path to a custom config file' | ||
description: "Path to a custom config file" | ||
}, | ||
'--no-autoprefixer': { | ||
deprecated: true, | ||
"--no-autoprefixer": { | ||
type: Boolean, | ||
description: 'Disable autoprefixer' | ||
description: "Disable autoprefixer" | ||
}, | ||
'-c': '--config', | ||
'-i': '--input', | ||
'-o': '--output', | ||
'-m': '--minify', | ||
'-w': '--watch', | ||
'-p': '--poll' | ||
"-c": "--config", | ||
"-i": "--input", | ||
"-o": "--output", | ||
"-m": "--minify", | ||
"-w": "--watch", | ||
"-p": "--poll" | ||
} | ||
@@ -111,7 +110,7 @@ } | ||
let sharedFlags = { | ||
'--help': { | ||
"--help": { | ||
type: Boolean, | ||
description: 'Display usage information' | ||
description: "Display usage information" | ||
}, | ||
'-h': '--help' | ||
"-h": "--help" | ||
}; | ||
@@ -121,6 +120,6 @@ if (process.stdout.isTTY /* Detect redirecting output to a file */ && (process.argv[2] === undefined || process.argv.slice(2).every((flag)=>sharedFlags[flag] !== undefined))) { | ||
usage: [ | ||
'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]', | ||
'tailwindcss init [--full] [--postcss] [options...]' | ||
"tailwindcss [--input input.css] [--output output.css] [--watch] [options...]", | ||
"tailwindcss init [--full] [--postcss] [options...]" | ||
], | ||
commands: Object.keys(commands).filter((command)=>command !== 'build').map((command)=>`${command} [options]`), | ||
commands: Object.keys(commands).filter((command)=>command !== "build").map((command)=>`${command} [options]`), | ||
options: { | ||
@@ -133,3 +132,3 @@ ...commands.build.args, | ||
} | ||
let command = ((arg = '')=>arg.startsWith('-') ? undefined : arg)(process.argv[2]) || 'build'; | ||
let command = ((arg = "")=>arg.startsWith("-") ? undefined : arg)(process.argv[2]) || "build"; | ||
if (commands[command] === undefined) { | ||
@@ -139,3 +138,3 @@ if (_fs.default.existsSync(_path.default.resolve(command))) { | ||
// Check if non-existing command, might be a file. | ||
command = 'build'; | ||
command = "build"; | ||
} else { | ||
@@ -145,5 +144,5 @@ (0, _help.help)({ | ||
usage: [ | ||
'tailwindcss <command> [options]' | ||
"tailwindcss <command> [options]" | ||
], | ||
commands: Object.keys(commands).filter((command)=>command !== 'build').map((command)=>`${command} [options]`), | ||
commands: Object.keys(commands).filter((command)=>command !== "build").map((command)=>`${command} [options]`), | ||
options: sharedFlags | ||
@@ -155,3 +154,3 @@ }); | ||
// Execute command | ||
let { args: flags, run } = commands[command]; | ||
let { args: flags , run } = commands[command]; | ||
let args = (()=>{ | ||
@@ -167,3 +166,3 @@ try { | ||
key, | ||
typeof value === 'object' ? value.type : value | ||
typeof value === "object" ? value.type : value | ||
])), { | ||
@@ -173,9 +172,9 @@ 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, flagValue] = flag.split('='); | ||
for(let i = result["_"].length - 1; i >= 0; --i){ | ||
let flag = result["_"][i]; | ||
if (!flag.startsWith("-")) continue; | ||
let [flagName, flagValue] = flag.split("="); | ||
let handler = flags[flagName]; | ||
// Resolve flagName & handler | ||
while(typeof handler === 'string'){ | ||
while(typeof handler === "string"){ | ||
flagName = handler; | ||
@@ -190,7 +189,7 @@ handler = flags[handler]; | ||
// Parse args for current flag | ||
while(result['_'][offset] && !result['_'][offset].startsWith('-')){ | ||
args.push(result['_'][offset++]); | ||
while(result["_"][offset] && !result["_"][offset].startsWith("-")){ | ||
args.push(result["_"][offset++]); | ||
} | ||
// Cleanup manually parsed flags + args | ||
result['_'].splice(i, 1 + args.length); | ||
result["_"].splice(i, 1 + args.length); | ||
// No args were provided, use default value defined in handler | ||
@@ -202,3 +201,3 @@ // One arg was provided, use that directly | ||
// Remove the whole flag from the args array | ||
result['_'].splice(i, 1); | ||
result["_"].splice(i, 1); | ||
} | ||
@@ -214,12 +213,12 @@ // Set the resolved value in the `result` object | ||
// E.g.: tailwindcss build input.css -> _: ['build', 'input.css'] | ||
if (result['_'][0] !== command) { | ||
result['_'].unshift(command); | ||
if (result["_"][0] !== command) { | ||
result["_"].unshift(command); | ||
} | ||
return result; | ||
} catch (err) { | ||
if (err.code === 'ARG_UNKNOWN_OPTION') { | ||
if (err.code === "ARG_UNKNOWN_OPTION") { | ||
(0, _help.help)({ | ||
message: err.message, | ||
usage: [ | ||
'tailwindcss <command> [options]' | ||
"tailwindcss <command> [options]" | ||
], | ||
@@ -233,3 +232,3 @@ options: sharedFlags | ||
})(); | ||
if (args['--help']) { | ||
if (args["--help"]) { | ||
(0, _help.help)({ | ||
@@ -236,0 +235,0 @@ options: { |
@@ -20,6 +20,6 @@ // @ts-check | ||
function isESM() { | ||
const pkgPath = _path.default.resolve('./package.json'); | ||
const pkgPath = _path.default.resolve("./package.json"); | ||
try { | ||
let pkg = JSON.parse(_fs.default.readFileSync(pkgPath, 'utf8')); | ||
return pkg.type && pkg.type === 'module'; | ||
let pkg = JSON.parse(_fs.default.readFileSync(pkgPath, "utf8")); | ||
return pkg.type && pkg.type === "module"; | ||
} catch (err) { | ||
@@ -31,26 +31,26 @@ return false; | ||
let messages = []; | ||
let isProjectESM = args['--ts'] || args['--esm'] || isESM(); | ||
let syntax = args['--ts'] ? 'ts' : isProjectESM ? 'js' : 'cjs'; | ||
let extension = args['--ts'] ? 'ts' : 'js'; | ||
let isProjectESM = args["--ts"] || args["--esm"] || isESM(); | ||
let syntax = args["--ts"] ? "ts" : isProjectESM ? "js" : "cjs"; | ||
let extension = args["--ts"] ? "ts" : "js"; | ||
var _args___; | ||
let tailwindConfigLocation = _path.default.resolve((_args___ = args['_'][1]) !== null && _args___ !== void 0 ? _args___ : `./tailwind.config.${extension}`); | ||
let tailwindConfigLocation = _path.default.resolve((_args___ = args["_"][1]) !== null && _args___ !== void 0 ? _args___ : `./tailwind.config.${extension}`); | ||
if (_fs.default.existsSync(tailwindConfigLocation)) { | ||
messages.push(`${_path.default.basename(tailwindConfigLocation)} already exists.`); | ||
} else { | ||
let stubContentsFile = _fs.default.readFileSync(args['--full'] ? _path.default.resolve(__dirname, '../../../stubs/config.full.js') : _path.default.resolve(__dirname, '../../../stubs/config.simple.js'), 'utf8'); | ||
let stubFile = _fs.default.readFileSync(_path.default.resolve(__dirname, `../../../stubs/tailwind.config.${syntax}`), 'utf8'); | ||
let stubContentsFile = _fs.default.readFileSync(args["--full"] ? _path.default.resolve(__dirname, "../../../stubs/config.full.js") : _path.default.resolve(__dirname, "../../../stubs/config.simple.js"), "utf8"); | ||
let stubFile = _fs.default.readFileSync(_path.default.resolve(__dirname, `../../../stubs/tailwind.config.${syntax}`), "utf8"); | ||
// Change colors import | ||
stubContentsFile = stubContentsFile.replace('../colors', 'tailwindcss/colors'); | ||
stubContentsFile = stubContentsFile.replace("../colors", "tailwindcss/colors"); | ||
// Replace contents of {ts,js,cjs} file with the stub {simple,full}. | ||
stubFile = stubFile.replace('__CONFIG__', stubContentsFile.replace('module.exports =', '').trim()).trim() + '\n\n'; | ||
_fs.default.writeFileSync(tailwindConfigLocation, stubFile, 'utf8'); | ||
stubFile = stubFile.replace("__CONFIG__", stubContentsFile.replace("module.exports =", "").trim()).trim() + "\n\n"; | ||
_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('./postcss.config.js'); | ||
if (args["--postcss"]) { | ||
let postcssConfigLocation = _path.default.resolve("./postcss.config.js"); | ||
if (_fs.default.existsSync(postcssConfigLocation)) { | ||
messages.push(`${_path.default.basename(postcssConfigLocation)} already exists.`); | ||
} else { | ||
let stubFile = _fs.default.readFileSync(isProjectESM ? _path.default.resolve(__dirname, '../../../stubs/postcss.config.js') : _path.default.resolve(__dirname, '../../../stubs/postcss.config.cjs'), 'utf8'); | ||
_fs.default.writeFileSync(postcssConfigLocation, stubFile, 'utf8'); | ||
let stubFile = _fs.default.readFileSync(isProjectESM ? _path.default.resolve(__dirname, "../../../stubs/postcss.config.js") : _path.default.resolve(__dirname, "../../../stubs/postcss.config.cjs"), "utf8"); | ||
_fs.default.writeFileSync(postcssConfigLocation, stubFile, "utf8"); | ||
messages.push(`Created PostCSS config file: ${_path.default.basename(postcssConfigLocation)}`); | ||
@@ -57,0 +57,0 @@ } |
@@ -188,3 +188,5 @@ "use strict"; | ||
"willChange", | ||
"content" | ||
"contain", | ||
"content", | ||
"forcedColorAdjust" | ||
]; |
@@ -12,8 +12,2 @@ "use strict"; | ||
_export(exports, { | ||
default: function() { | ||
return _default; | ||
}, | ||
featureFlags: function() { | ||
return featureFlags; | ||
}, | ||
flagEnabled: function() { | ||
@@ -24,2 +18,5 @@ return flagEnabled; | ||
return issueFlagNotices; | ||
}, | ||
default: function() { | ||
return _default; | ||
} | ||
@@ -36,18 +33,16 @@ }); | ||
optimizeUniversalDefaults: false, | ||
generalizedModifiers: true, | ||
disableColorOpacityUtilitiesByDefault: false, | ||
relativeContentPathsByDefault: false, | ||
oxideParser: true, | ||
logicalSiblingUtilities: false | ||
relativeContentPathsByDefault: false | ||
}; | ||
let featureFlags = { | ||
future: [ | ||
'hoverOnlyWhenSupported', | ||
'respectDefaultRingColorOpacity', | ||
'disableColorOpacityUtilitiesByDefault', | ||
'relativeContentPathsByDefault', | ||
'logicalSiblingUtilities' | ||
"hoverOnlyWhenSupported", | ||
"respectDefaultRingColorOpacity", | ||
"disableColorOpacityUtilitiesByDefault", | ||
"relativeContentPathsByDefault" | ||
], | ||
experimental: [ | ||
'optimizeUniversalDefaults', | ||
'oxideParser' | ||
"optimizeUniversalDefaults", | ||
"generalizedModifiers" | ||
] | ||
@@ -59,3 +54,3 @@ }; | ||
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); | ||
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); | ||
} | ||
@@ -65,3 +60,3 @@ if (featureFlags.experimental.includes(flag)) { | ||
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); | ||
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); | ||
} | ||
@@ -71,3 +66,3 @@ return false; | ||
function experimentalFlagsEnabled(config) { | ||
if (config.experimental === 'all') { | ||
if (config.experimental === "all") { | ||
return featureFlags.experimental; | ||
@@ -83,6 +78,6 @@ } | ||
if (experimentalFlagsEnabled(config).length > 0) { | ||
let changes = experimentalFlagsEnabled(config).map((s)=>_picocolors.default.yellow(s)).join(', '); | ||
_log.default.warn('experimental-flags-enabled', [ | ||
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." | ||
]); | ||
@@ -89,0 +84,0 @@ } |
"use strict"; | ||
module.exports = require('./plugin'); | ||
module.exports = require("./plugin"); |
@@ -39,5 +39,3 @@ "use strict"; | ||
} | ||
var newObj = { | ||
__proto__: null | ||
}; | ||
var newObj = {}; | ||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; | ||
@@ -78,5 +76,5 @@ for(var key in obj){ | ||
try { | ||
return _crypto.default.createHash('md5').update(str, 'utf-8').digest('binary'); | ||
return _crypto.default.createHash("md5").update(str, "utf-8").digest("binary"); | ||
} catch (err) { | ||
return ''; | ||
return ""; | ||
} | ||
@@ -88,3 +86,3 @@ } | ||
// Other files use an existing context | ||
if (!css.includes('@tailwind')) { | ||
if (!css.includes("@tailwind")) { | ||
return false; | ||
@@ -91,0 +89,0 @@ } |
@@ -13,7 +13,7 @@ "use strict"; | ||
atrule: [ | ||
'name', | ||
'params' | ||
"name", | ||
"params" | ||
], | ||
rule: [ | ||
'selector' | ||
"selector" | ||
] | ||
@@ -35,8 +35,6 @@ }; | ||
let properties = comparisonMap[node.type]; | ||
if (node.type === 'atrule' && node.name === 'font-face') { | ||
var _node_property, _currentRule_property; | ||
if (node.type === "atrule" && node.name === "font-face") { | ||
currentRule = node; | ||
} else if (properties.every((property)=>{ | ||
var _node_property, _currentRule_property; | ||
return ((_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, ' '); | ||
})) { | ||
} 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) | ||
@@ -57,3 +55,3 @@ if (node.nodes) { | ||
root.each((node)=>{ | ||
if (node.type === 'atrule') { | ||
if (node.type === "atrule") { | ||
collapseRulesIn(node); | ||
@@ -60,0 +58,0 @@ } |
@@ -77,3 +77,3 @@ "use strict"; | ||
} | ||
let UNITLESS_NUMBER = Symbol('unitless-number'); | ||
let UNITLESS_NUMBER = Symbol("unitless-number"); | ||
function resolveUnit(input) { | ||
@@ -80,0 +80,0 @@ let result = /^-?\d*.?\d+([\w%]+)?$/g.exec(input); |
@@ -18,2 +18,5 @@ // @ts-check | ||
return resolvedChangedContent; | ||
}, | ||
createBroadPatternCheck: function() { | ||
return createBroadPatternCheck; | ||
} | ||
@@ -28,3 +31,4 @@ }); | ||
const _sharedState = require("./sharedState"); | ||
const _oxide = require("@tailwindcss/oxide"); | ||
const _log = /*#__PURE__*/ _interop_require_default(require("../util/log")); | ||
const _micromatch = /*#__PURE__*/ _interop_require_default(require("micromatch")); | ||
function _interop_require_default(obj) { | ||
@@ -35,31 +39,6 @@ return obj && obj.__esModule ? obj : { | ||
} | ||
/** @typedef {import('../../types/config.js').RawFile} RawFile */ /** @typedef {import('../../types/config.js').FilePath} FilePath */ /* | ||
* @param {import('tailwindcss').Config} tailwindConfig | ||
* @param {{skip:string[]}} options | ||
* @returns {ContentPath[]} | ||
*/ function resolveContentFiles(tailwindConfig, { skip = [] } = {}) { | ||
if (Array.isArray(tailwindConfig.content.files) && tailwindConfig.content.files.includes('auto')) { | ||
let idx = tailwindConfig.content.files.indexOf('auto'); | ||
if (idx !== -1) { | ||
_sharedState.env.DEBUG && console.time('Calculating resolve content paths'); | ||
let resolved = (0, _oxide.resolveContentPaths)({ | ||
base: process.cwd() | ||
}); | ||
_sharedState.env.DEBUG && console.timeEnd('Calculating resolve content paths'); | ||
tailwindConfig.content.files.splice(idx, 1, ...resolved); | ||
} | ||
} | ||
if (skip.length > 0) { | ||
tailwindConfig.content.files = tailwindConfig.content.files.filter((filePath)=>!skip.includes(filePath)); | ||
} | ||
return tailwindConfig.content.files; | ||
} | ||
function parseCandidateFiles(context, tailwindConfig) { | ||
let files = resolveContentFiles(tailwindConfig, { | ||
skip: [ | ||
context.userConfigPath | ||
] | ||
}); | ||
let files = tailwindConfig.content.files; | ||
// Normalize the file globs | ||
files = files.filter((filePath)=>typeof filePath === 'string'); | ||
files = files.filter((filePath)=>typeof filePath === "string"); | ||
files = files.map(_normalizepath.default); | ||
@@ -161,3 +140,3 @@ // Split into included and excluded globs | ||
} | ||
} catch (e) { | ||
} catch { | ||
// TODO: log this? | ||
@@ -168,3 +147,3 @@ } | ||
function resolvedChangedContent(context, candidateFiles, fileModifiedMap) { | ||
let changedContent = context.tailwindConfig.content.files.filter((item)=>typeof item.raw === 'string').map(({ raw, extension = 'html' })=>({ | ||
let changedContent = context.tailwindConfig.content.files.filter((item)=>typeof item.raw === "string").map(({ raw , extension ="html" })=>({ | ||
content: raw, | ||
@@ -186,2 +165,61 @@ extension | ||
} | ||
const LARGE_DIRECTORIES = [ | ||
"node_modules" | ||
]; | ||
// Ensures that `node_modules` has to match as-is, otherwise `mynode_modules` | ||
// would match as well, but that is not a known large directory. | ||
const LARGE_DIRECTORIES_REGEX = new RegExp(`(${LARGE_DIRECTORIES.map((dir)=>String.raw`\b${dir}\b`).join("|")})`); | ||
function createBroadPatternCheck(paths) { | ||
// Detect whether a glob pattern might be too broad. This means that it: | ||
// - Includes `**` | ||
// - Does not include any of the known large directories (e.g.: node_modules) | ||
let maybeBroadPattern = paths.some((path)=>path.includes("**") && !LARGE_DIRECTORIES_REGEX.test(path)); | ||
// Didn't detect any potentially broad patterns, so we can skip further | ||
// checks. | ||
if (!maybeBroadPattern) { | ||
return ()=>{}; | ||
} | ||
// All glob matchers | ||
let matchers = []; | ||
// All glob matchers that explicitly contain any of the known large | ||
// directories (e.g.: node_modules). | ||
let explicitMatchers = []; | ||
// Create matchers for all paths | ||
for (let path of paths){ | ||
let matcher = _micromatch.default.matcher(path); | ||
if (LARGE_DIRECTORIES_REGEX.test(path)) { | ||
explicitMatchers.push(matcher); | ||
} | ||
matchers.push(matcher); | ||
} | ||
// Keep track of whether we already warned about the broad pattern issue or | ||
// not. The `log.warn` function already does something similar where we only | ||
// output the log once. However, with this we can also skip the other checks | ||
// when we already warned about the broad pattern. | ||
let warned = false; | ||
/** | ||
* @param {string} file | ||
*/ return (file)=>{ | ||
if (warned) return; // Already warned about the broad pattern | ||
if (explicitMatchers.some((matcher)=>matcher(file))) return; // Explicitly included, so we can skip further checks | ||
// When a broad pattern is used, we have to double check that the file was | ||
// not explicitly included in the globs. | ||
let matchingGlobIndex = matchers.findIndex((matcher)=>matcher(file)); | ||
if (matchingGlobIndex === -1) return; // This should never happen | ||
let matchingGlob = paths[matchingGlobIndex]; | ||
// Create relative paths to make the output a bit more readable. | ||
let relativeMatchingGlob = _path.default.relative(process.cwd(), matchingGlob); | ||
if (relativeMatchingGlob[0] !== ".") relativeMatchingGlob = `./${relativeMatchingGlob}`; | ||
let largeDirectory = LARGE_DIRECTORIES.find((directory)=>file.includes(directory)); | ||
if (largeDirectory) { | ||
warned = true; | ||
_log.default.warn("broad-content-glob-pattern", [ | ||
`Your \`content\` configuration includes a pattern which looks like it's accidentally matching all of \`${largeDirectory}\` and can cause serious performance issues.`, | ||
`Pattern: \`${relativeMatchingGlob}\``, | ||
`See our documentation for recommendations:`, | ||
"https://tailwindcss.com/docs/content-configuration#pattern-recommendations" | ||
]); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -195,4 +233,5 @@ * | ||
let mTimesToCommit = new Map(); | ||
let checkBroadPattern = createBroadPatternCheck(paths); | ||
let changedFiles = new Set(); | ||
_sharedState.env.DEBUG && console.time('Finding changed files'); | ||
_sharedState.env.DEBUG && console.time("Finding changed files"); | ||
let files = _fastglob.default.sync(paths, { | ||
@@ -202,2 +241,3 @@ absolute: true | ||
for (let file of files){ | ||
checkBroadPattern(file); | ||
let prevModified = fileModifiedMap.get(file) || -Infinity; | ||
@@ -210,3 +250,3 @@ let modified = _fs.default.statSync(file).mtimeMs; | ||
} | ||
_sharedState.env.DEBUG && console.timeEnd('Finding changed files'); | ||
_sharedState.env.DEBUG && console.timeEnd("Finding changed files"); | ||
return [ | ||
@@ -213,0 +253,0 @@ changedFiles, |
@@ -12,2 +12,3 @@ "use strict"; | ||
const _regex = /*#__PURE__*/ _interop_require_wildcard(require("./regex")); | ||
const _splitAtTopLevelOnly = require("../util/splitAtTopLevelOnly"); | ||
function _getRequireWildcardCache(nodeInterop) { | ||
@@ -34,5 +35,3 @@ if (typeof WeakMap !== "function") return null; | ||
} | ||
var newObj = { | ||
__proto__: null | ||
}; | ||
var newObj = {}; | ||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; | ||
@@ -67,2 +66,23 @@ for(var key in obj){ | ||
} | ||
// 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; | ||
@@ -73,6 +93,6 @@ }; | ||
let separator = context.tailwindConfig.separator; | ||
let prefix = context.tailwindConfig.prefix !== '' ? _regex.optional(_regex.pattern([ | ||
let prefix = context.tailwindConfig.prefix !== "" ? _regex.optional(_regex.pattern([ | ||
/-?/, | ||
_regex.escape(context.tailwindConfig.prefix) | ||
])) : ''; | ||
])) : ""; | ||
let utility = _regex.any([ | ||
@@ -89,3 +109,7 @@ // Arbitrary properties (without square brackets) | ||
// Utility Name / Group Name | ||
/-?(?:\w+)/, | ||
_regex.any([ | ||
/-?(?:\w+)/, | ||
// This is here to make sure @container supports everything that other utilities do | ||
/@(?:\w+)/ | ||
]), | ||
// Normal/Arbitrary values | ||
@@ -95,3 +119,8 @@ _regex.optional(_regex.any([ | ||
// Arbitrary values | ||
/-(?:\w+-)*\[[^\s:]+\]/, | ||
_regex.any([ | ||
/-(?:\w+-)*\['[^\s]+'\]/, | ||
/-(?:\w+-)*\["[^\s]+"\]/, | ||
/-(?:\w+-)*\[`[^\s]+`\]/, | ||
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/ | ||
]), | ||
// Not immediately followed by an `{[(` | ||
@@ -104,3 +133,8 @@ /(?![{([]])/, | ||
// Arbitrary values | ||
/-(?:\w+-)*\[[^\s]+\]/, | ||
_regex.any([ | ||
/-(?:\w+-)*\['[^\s]+'\]/, | ||
/-(?:\w+-)*\["[^\s]+"\]/, | ||
/-(?:\w+-)*\[`[^\s]+`\]/, | ||
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/ | ||
]), | ||
// Not immediately followed by an `{[(` | ||
@@ -126,3 +160,3 @@ /(?![{([]])/, | ||
_regex.pattern([ | ||
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/\w+/, | ||
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/, | ||
separator | ||
@@ -143,3 +177,3 @@ ]), | ||
_regex.pattern([ | ||
/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/\w+/, | ||
/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/, | ||
separator | ||
@@ -160,5 +194,5 @@ ]), | ||
// Variants | ||
'((?=((', | ||
"((?=((", | ||
variantPattern, | ||
')+))\\2)?', | ||
")+))\\2)?", | ||
// Important (optional) | ||
@@ -171,3 +205,3 @@ /!?/, | ||
// 5. Inner matches | ||
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g; | ||
yield /[^<>"'`\s.(){}[\]#=%$][^<>"'`\s(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g; | ||
} | ||
@@ -193,3 +227,3 @@ // We want to capture any "special" characters | ||
// We are care about this for arbitrary values | ||
if (!input.includes('-[')) { | ||
if (!input.includes("-[")) { | ||
return input; | ||
@@ -218,3 +252,3 @@ } | ||
openStringTypes.pop(); | ||
} else if (char === "'" || char === '"' || char === '`') { | ||
} else if (char === "'" || char === '"' || char === "`") { | ||
openStringTypes.push(char); | ||
@@ -224,6 +258,6 @@ } | ||
continue; | ||
} else if (char === '[') { | ||
} else if (char === "[") { | ||
depth++; | ||
continue; | ||
} else if (char === ']') { | ||
} else if (char === "]") { | ||
depth--; | ||
@@ -230,0 +264,0 @@ continue; |
@@ -27,3 +27,3 @@ "use strict"; | ||
function isObject(input) { | ||
return typeof input === 'object' && input !== null; | ||
return typeof input === "object" && input !== null; | ||
} | ||
@@ -35,14 +35,14 @@ function findClosestExistingPath(theme, path) { | ||
if ((0, _dlv.default)(theme, parts) !== undefined) break; | ||
}while (parts.length) | ||
}while (parts.length); | ||
return parts.length ? parts : undefined; | ||
} | ||
function pathToString(path) { | ||
if (typeof path === 'string') return path; | ||
if (typeof path === "string") return path; | ||
return path.reduce((acc, cur, i)=>{ | ||
if (cur.includes('.')) return `${acc}[${cur}]`; | ||
if (cur.includes(".")) return `${acc}[${cur}]`; | ||
return i === 0 ? cur : `${acc}.${cur}`; | ||
}, ''); | ||
}, ""); | ||
} | ||
function list(items) { | ||
return items.map((key)=>`'${key}'`).join(', '); | ||
return items.map((key)=>`'${key}'`).join(", "); | ||
} | ||
@@ -53,3 +53,3 @@ function listKeys(obj) { | ||
function validatePath(config, path, defaultValue, themeOpts = {}) { | ||
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, ''); | ||
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, ""); | ||
const pathSegments = Array.isArray(path) ? path : (0, _toPath.toPath)(pathString); | ||
@@ -93,3 +93,3 @@ const value = (0, _dlv.default)(config.theme, pathSegments, defaultValue); | ||
} | ||
if (!(typeof value === 'string' || typeof value === 'number' || typeof value === 'function' || value instanceof String || value instanceof Number || Array.isArray(value))) { | ||
if (!(typeof value === "string" || typeof value === "number" || typeof value === "function" || value instanceof String || value instanceof Number || Array.isArray(value))) { | ||
let error = `'${pathString}' was found but does not resolve to a string.`; | ||
@@ -122,7 +122,7 @@ if (isObject(value)) { | ||
let args = [ | ||
'' | ||
"" | ||
]; | ||
for (let vNode of vNodes){ | ||
if (vNode.type === 'div' && vNode.value === ',') { | ||
args.push(''); | ||
if (vNode.type === "div" && vNode.value === ",") { | ||
args.push(""); | ||
} else { | ||
@@ -135,5 +135,5 @@ args[args.length - 1] += _index.default.stringify(vNode); | ||
function resolveVNode(node, vNode, functions) { | ||
if (vNode.type === 'function' && functions[vNode.value] !== undefined) { | ||
if (vNode.type === "function" && functions[vNode.value] !== undefined) { | ||
let args = extractArgs(node, vNode.nodes, functions); | ||
vNode.type = 'word'; | ||
vNode.type = "word"; | ||
vNode.value = functions[vNode.value](node, ...args); | ||
@@ -151,4 +151,4 @@ } | ||
let nodeTypePropertyMap = { | ||
atrule: 'params', | ||
decl: 'value' | ||
atrule: "params", | ||
decl: "value" | ||
}; | ||
@@ -161,3 +161,3 @@ /** | ||
// This allows the alpha value to be present inside of quotes | ||
path = path.replace(/^['"]+|['"]+$/g, ''); | ||
path = path.replace(/^['"]+|['"]+$/g, ""); | ||
let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/); | ||
@@ -199,7 +199,7 @@ let alpha = undefined; | ||
theme: (node, path, ...defaultValue)=>{ | ||
let { isValid, value, error, alpha } = resolvePath(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 === null || parentNode === void 0 ? void 0 : (_parentNode_raws_tailwind = parentNode.raws.tailwind) === null || _parentNode_raws_tailwind === void 0 ? void 0 : _parentNode_raws_tailwind.candidate; | ||
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) { | ||
@@ -211,3 +211,3 @@ // Remove this utility from any caches | ||
// Show a warning | ||
_log.default.warn('invalid-theme-key-in-class', [ | ||
_log.default.warn("invalid-theme-key-in-class", [ | ||
`The utility \`${candidate}\` contains an invalid theme value and was not generated.` | ||
@@ -220,3 +220,3 @@ ]); | ||
let maybeColor = (0, _pluginUtils.parseColorFormat)(value); | ||
let isColorFunction = maybeColor !== undefined && typeof maybeColor === 'function'; | ||
let isColorFunction = maybeColor !== undefined && typeof maybeColor === "function"; | ||
if (alpha !== undefined || isColorFunction) { | ||
@@ -231,5 +231,5 @@ if (alpha === undefined) { | ||
screen: (node, screen)=>{ | ||
screen = screen.replace(/^['"]+/g, '').replace(/['"]+$/g, ''); | ||
screen = screen.replace(/^['"]+/g, "").replace(/['"]+$/g, ""); | ||
let screens = (0, _normalizeScreens.normalizeScreens)(config.theme.screens); | ||
let screenDefinition = screens.find(({ name })=>name === screen); | ||
let screenDefinition = screens.find(({ name })=>name === screen); | ||
if (!screenDefinition) { | ||
@@ -236,0 +236,0 @@ throw node.error(`The '${screen}' screen does not exist in your theme.`); |
@@ -62,3 +62,3 @@ "use strict"; | ||
let prefix = context.tailwindConfig.prefix; | ||
return typeof prefix === 'function' ? prefix(selector) : prefix + selector; | ||
return typeof prefix === "function" ? prefix(selector) : prefix + selector; | ||
} | ||
@@ -129,3 +129,3 @@ function* pathToRoot(node) { | ||
} | ||
if (parent.type === 'root') { | ||
if (parent.type === "root") { | ||
break; | ||
@@ -155,3 +155,3 @@ } | ||
let container = nestedClone(rule); | ||
let sort = context.offsets.create('user'); | ||
let sort = context.offsets.create("user"); | ||
for (let className of extractClasses(rule)){ | ||
@@ -162,3 +162,3 @@ let list = cache.get(className) || []; | ||
{ | ||
layer: 'user', | ||
layer: "user", | ||
sort, | ||
@@ -228,3 +228,3 @@ important: false | ||
let candidates = params.split(/[\s\t\n]+/g); | ||
if (candidates[candidates.length - 1] === '!important') { | ||
if (candidates[candidates.length - 1] === "!important") { | ||
return [ | ||
@@ -244,3 +244,3 @@ candidates.slice(0, -1), | ||
let applies = []; | ||
root.walkAtRules('apply', (rule)=>{ | ||
root.walkAtRules("apply", (rule)=>{ | ||
let [candidates] = extractApplyCandidates(rule.params); | ||
@@ -327,3 +327,3 @@ for (let util of candidates){ | ||
for (let node of sel.nodes){ | ||
if (node.type === 'combinator') { | ||
if (node.type === "combinator") { | ||
groups.push(node); | ||
@@ -340,9 +340,9 @@ groups.push([]); | ||
group.sort((a, b)=>{ | ||
if (a.type === 'tag' && b.type === 'class') { | ||
if (a.type === "tag" && b.type === "class") { | ||
return -1; | ||
} else if (a.type === 'class' && b.type === 'tag') { | ||
} else if (a.type === "class" && b.type === "tag") { | ||
return 1; | ||
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) { | ||
} else if (a.type === "class" && b.type === "pseudo" && b.value.startsWith("::")) { | ||
return -1; | ||
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') { | ||
} else if (a.type === "pseudo" && a.value.startsWith("::") && b.type === "class") { | ||
return 1; | ||
@@ -372,6 +372,6 @@ } | ||
let [applyCandidates, important] = extractApplyCandidates(apply.params); | ||
if (apply.parent.type === 'atrule') { | ||
if (apply.parent.name === 'screen') { | ||
if (apply.parent.type === "atrule") { | ||
if (apply.parent.name === "screen") { | ||
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.`); | ||
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.`); | ||
} | ||
@@ -382,4 +382,4 @@ 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}.`); | ||
if ([ | ||
prefix(context, 'group'), | ||
prefix(context, 'peer') | ||
prefix(context, "group"), | ||
prefix(context, "peer") | ||
].includes(applyCandidate)) { | ||
@@ -393,2 +393,15 @@ // TODO: Link to specific documentation page with error code. | ||
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([ | ||
@@ -452,3 +465,3 @@ applyCandidate, | ||
}); | ||
let canRewriteSelector = node.type !== 'atrule' || node.type === 'atrule' && node.name !== 'keyframes'; | ||
let canRewriteSelector = node.type !== "atrule" || node.type === "atrule" && node.name !== "keyframes"; | ||
if (canRewriteSelector) { | ||
@@ -492,3 +505,3 @@ root.walkRules((rule)=>{ | ||
// Strip the important selector from the parent selector if at the beginning | ||
let importantSelector = typeof context.tailwindConfig.important === 'string' ? context.tailwindConfig.important : null; | ||
let importantSelector = typeof context.tailwindConfig.important === "string" ? context.tailwindConfig.important : null; | ||
// We only want to move the "important" selector if this is a Tailwind-generated utility | ||
@@ -501,3 +514,3 @@ // We do *not* want to do this for user CSS that happens to be structured the same | ||
// Otherwise we'll crash | ||
if (parentSelector === '') { | ||
if (parentSelector === "") { | ||
parentSelector = parent.selector; | ||
@@ -504,0 +517,0 @@ } |
@@ -13,3 +13,2 @@ "use strict"; | ||
const _quicklru = /*#__PURE__*/ _interop_require_default(require("@alloc/quick-lru")); | ||
const _oxide = require("@tailwindcss/oxide"); | ||
const _sharedState = /*#__PURE__*/ _interop_require_wildcard(require("./sharedState")); | ||
@@ -20,3 +19,2 @@ const _generateRules = require("./generateRules"); | ||
const _defaultExtractor = require("./defaultExtractor"); | ||
const _featureFlags = require("../featureFlags"); | ||
function _interop_require_default(obj) { | ||
@@ -48,5 +46,3 @@ return obj && obj.__esModule ? obj : { | ||
} | ||
var newObj = { | ||
__proto__: null | ||
}; | ||
var newObj = {}; | ||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; | ||
@@ -75,12 +71,7 @@ for(var key in obj){ | ||
DEFAULT: (content)=>content, | ||
svelte: (content)=>content.replace(/(?:^|\s)class:/g, ' ') | ||
svelte: (content)=>content.replace(/(?:^|\s)class:/g, " ") | ||
}; | ||
function getExtractor(context, fileExtension) { | ||
let extractors = context.tailwindConfig.content.extract; | ||
return extractors[fileExtension] || extractors.DEFAULT || builtInExtractors[fileExtension] || // Because we call `DEFAULT(context)`, the returning function is always a new function without a | ||
// stable identity. Marking it with `DEFAULT_EXTRACTOR` allows us to check if it is the default | ||
// extractor without relying on the function identity. | ||
Object.assign(builtInExtractors.DEFAULT(context), { | ||
DEFAULT_EXTRACTOR: true | ||
}); | ||
return extractors[fileExtension] || extractors.DEFAULT || builtInExtractors[fileExtension] || builtInExtractors.DEFAULT(context); | ||
} | ||
@@ -101,3 +92,3 @@ function getTransformer(tailwindConfig, fileExtension) { | ||
} | ||
for (let line of content.split('\n')){ | ||
for (let line of content.split("\n")){ | ||
line = line.trim(); | ||
@@ -113,3 +104,3 @@ if (seen.has(line)) { | ||
} else { | ||
let extractorMatches = extractor(line).filter((s)=>s !== '!*'); | ||
let extractorMatches = extractor(line).filter((s)=>s !== "!*"); | ||
let lineMatchesSet = new Set(extractorMatches); | ||
@@ -154,3 +145,3 @@ for (let match of lineMatchesSet){ | ||
// the source of any templates. Think Vue <style> blocks for example. | ||
if (rule.name === 'tailwind') { | ||
if (rule.name === "tailwind") { | ||
if (Object.keys(layerNodes).includes(rule.params)) { | ||
@@ -172,46 +163,29 @@ layerNodes[rule.params] = rule; | ||
let seen = new Set(); | ||
env.DEBUG && console.time('Reading changed files'); | ||
env.DEBUG && console.time("Reading changed files"); | ||
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */ let regexParserContent = []; | ||
/** @type {{file?: string, content?: string}[]} */ let rustParserContent = []; | ||
for (let item of context.changedContent){ | ||
let transformer = getTransformer(context.tailwindConfig, item.extension); | ||
let extractor = getExtractor(context, item.extension); | ||
if ((0, _featureFlags.flagEnabled)(context.tailwindConfig, 'oxideParser') && transformer === builtInTransformers.DEFAULT && (extractor === null || extractor === void 0 ? void 0 : extractor.DEFAULT_EXTRACTOR) === true) { | ||
rustParserContent.push(item); | ||
} else { | ||
regexParserContent.push([ | ||
item, | ||
{ | ||
transformer, | ||
extractor | ||
} | ||
]); | ||
} | ||
regexParserContent.push([ | ||
item, | ||
{ | ||
transformer, | ||
extractor | ||
} | ||
]); | ||
} | ||
// Read files using our newer, faster parser when: | ||
// - Oxide is enabled; AND | ||
// - The file is using default transfomers and extractors | ||
if (rustParserContent.length > 0) { | ||
for (let candidate of (0, _oxide.parseCandidateStrings)(rustParserContent, _oxide.IO.Parallel | _oxide.Parsing.Parallel)){ | ||
candidates.add(candidate); | ||
} | ||
} | ||
// Otherwise, read any files in node and parse with regexes | ||
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; | ||
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'); | ||
env.DEBUG && console.timeEnd("Reading changed files"); | ||
// --- | ||
// Generate the actual CSS | ||
let classCacheCount = context.classCache.size; | ||
env.DEBUG && console.time('Generate rules'); | ||
env.DEBUG && console.time('Sorting candidates'); | ||
// TODO: only sort if we are not using the oxide parser (flagEnabled(context.tailwindConfig, | ||
// 'oxideParser')) AND if we got all the candidates form the oxideParser alone. This will not | ||
// be the case currently if you have custom transformers / extractors. | ||
env.DEBUG && console.time("Generate rules"); | ||
env.DEBUG && console.time("Sorting candidates"); | ||
let sortedCandidates = new Set([ | ||
@@ -224,7 +198,7 @@ ...candidates | ||
})); | ||
env.DEBUG && console.timeEnd('Sorting candidates'); | ||
env.DEBUG && console.timeEnd("Sorting candidates"); | ||
(0, _generateRules.generateRules)(sortedCandidates, context); | ||
env.DEBUG && console.timeEnd('Generate rules'); | ||
env.DEBUG && console.timeEnd("Generate rules"); | ||
// We only ever add to the classCache, so if it didn't grow, there is nothing new. | ||
env.DEBUG && console.time('Build stylesheet'); | ||
env.DEBUG && console.time("Build stylesheet"); | ||
if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) { | ||
@@ -235,4 +209,4 @@ context.stylesheetCache = buildStylesheet([ | ||
} | ||
env.DEBUG && console.timeEnd('Build stylesheet'); | ||
let { defaults: defaultNodes, base: baseNodes, components: componentNodes, utilities: utilityNodes, variants: screenNodes } = context.stylesheetCache; | ||
env.DEBUG && console.timeEnd("Build stylesheet"); | ||
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes } = context.stylesheetCache; | ||
// --- | ||
@@ -242,6 +216,6 @@ // Replace any Tailwind directives with generated CSS | ||
layerNodes.base.before((0, _cloneNodes.default)([ | ||
...baseNodes, | ||
...defaultNodes | ||
...defaultNodes, | ||
...baseNodes | ||
], layerNodes.base.source, { | ||
layer: 'base' | ||
layer: "base" | ||
})); | ||
@@ -254,3 +228,3 @@ layerNodes.base.remove(); | ||
], layerNodes.components.source, { | ||
layer: 'components' | ||
layer: "components" | ||
})); | ||
@@ -263,3 +237,3 @@ layerNodes.components.remove(); | ||
], layerNodes.utilities.source, { | ||
layer: 'utilities' | ||
layer: "utilities" | ||
})); | ||
@@ -272,6 +246,6 @@ layerNodes.utilities.remove(); | ||
const parentLayer = (_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer; | ||
if (parentLayer === 'components') { | ||
if (parentLayer === "components") { | ||
return layerNodes.components !== null; | ||
} | ||
if (parentLayer === 'utilities') { | ||
if (parentLayer === "utilities") { | ||
return layerNodes.utilities !== null; | ||
@@ -283,30 +257,22 @@ } | ||
layerNodes.variants.before((0, _cloneNodes.default)(variantNodes, layerNodes.variants.source, { | ||
layer: 'variants' | ||
layer: "variants" | ||
})); | ||
layerNodes.variants.remove(); | ||
} else if (variantNodes.length > 0) { | ||
let cloned = (0, _cloneNodes.default)(variantNodes, undefined, { | ||
layer: 'variants' | ||
}); | ||
cloned.forEach((node)=>{ | ||
var _node_raws_tailwind; | ||
var _node_raws_tailwind_parentLayer; | ||
let parentLayer = (_node_raws_tailwind_parentLayer = (_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer) !== null && _node_raws_tailwind_parentLayer !== void 0 ? _node_raws_tailwind_parentLayer : null; | ||
node.walk((n)=>{ | ||
if (!n.source) { | ||
n.source = layerNodes[parentLayer].source; | ||
} | ||
}); | ||
}); | ||
root.append(cloned); | ||
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 _node_raws_tailwind; | ||
return ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer) === 'utilities'; | ||
return ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer) === "utilities"; | ||
}); | ||
if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) { | ||
_log.default.warn('content-problems', [ | ||
'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' | ||
_log.default.warn("content-problems", [ | ||
"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" | ||
]); | ||
@@ -316,4 +282,4 @@ } | ||
if (env.DEBUG) { | ||
console.log('Potential classes: ', candidates.size); | ||
console.log('Active contexts: ', _sharedState.contextSourcesMap.size); | ||
console.log("Potential classes: ", candidates.size); | ||
console.log("Active contexts: ", _sharedState.contextSourcesMap.size); | ||
} | ||
@@ -323,3 +289,3 @@ // Clear the cache for the changed files | ||
// Cleanup any leftover @layer atrules | ||
root.walkAtRules('layer', (rule)=>{ | ||
root.walkAtRules("layer", (rule)=>{ | ||
if (Object.keys(layerNodes).includes(rule.params)) { | ||
@@ -326,0 +292,0 @@ rule.remove(); |
@@ -21,3 +21,3 @@ "use strict"; | ||
let relativeTo = null; | ||
root.walkAtRules('config', (rule)=>{ | ||
root.walkAtRules("config", (rule)=>{ | ||
var _rule_source; | ||
@@ -27,14 +27,14 @@ var _rule_source_input_file, _ref; | ||
if (relativeTo === null) { | ||
throw rule.error('The `@config` directive cannot be used without setting `from` in your PostCSS config.'); | ||
throw rule.error("The `@config` directive cannot be used without setting `from` in your PostCSS config."); | ||
} | ||
if (configPath) { | ||
throw rule.error('Only one `@config` directive is allowed per file.'); | ||
throw rule.error("Only one `@config` directive is allowed per file."); | ||
} | ||
let matches = rule.params.match(/(['"])(.*?)\1/); | ||
if (!matches) { | ||
throw rule.error('A path is required when using the `@config` directive.'); | ||
throw rule.error("A path is required when using the `@config` directive."); | ||
} | ||
let inputPath = matches[2]; | ||
if (_path.default.isAbsolute(inputPath)) { | ||
throw rule.error('The `@config` directive cannot be used with an absolute path.'); | ||
throw rule.error("The `@config` directive cannot be used with an absolute path."); | ||
} | ||
@@ -41,0 +41,0 @@ configPath = _path.default.resolve(_path.default.dirname(relativeTo), inputPath); |
@@ -12,5 +12,2 @@ "use strict"; | ||
_export(exports, { | ||
generateRules: function() { | ||
return generateRules; | ||
}, | ||
getClassNameFromSelector: function() { | ||
@@ -21,2 +18,5 @@ return getClassNameFromSelector; | ||
return resolveMatches; | ||
}, | ||
generateRules: function() { | ||
return generateRules; | ||
} | ||
@@ -38,2 +38,3 @@ }); | ||
const _splitAtTopLevelOnly = require("../util/splitAtTopLevelOnly.js"); | ||
const _featureFlags = require("../featureFlags"); | ||
const _applyImportantSelector = require("../util/applyImportantSelector"); | ||
@@ -66,5 +67,3 @@ function _interop_require_default(obj) { | ||
} | ||
var newObj = { | ||
__proto__: null | ||
}; | ||
var newObj = {}; | ||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; | ||
@@ -88,3 +87,3 @@ for(var key in obj){ | ||
let classNameParser = (0, _postcssselectorparser.default)((selectors)=>{ | ||
return selectors.first.filter(({ type })=>type === 'class').pop().value; | ||
return selectors.first.filter(({ type })=>type === "class").pop().value; | ||
}); | ||
@@ -106,9 +105,9 @@ function getClassNameFromSelector(selector) { | ||
let wasSlash = false; | ||
if (lastIndex === Infinity && candidate.endsWith(']')) { | ||
let bracketIdx = candidate.indexOf('['); | ||
if (lastIndex === Infinity && candidate.endsWith("]")) { | ||
let bracketIdx = candidate.indexOf("["); | ||
// If character before `[` isn't a dash or a slash, this isn't a dynamic class | ||
// e.g. string[] | ||
if (candidate[bracketIdx - 1] === '-') { | ||
// eg. string[] | ||
if (candidate[bracketIdx - 1] === "-") { | ||
dashIdx = bracketIdx - 1; | ||
} else if (candidate[bracketIdx - 1] === '/') { | ||
} else if (candidate[bracketIdx - 1] === "/") { | ||
dashIdx = bracketIdx - 1; | ||
@@ -119,7 +118,7 @@ wasSlash = true; | ||
} | ||
} else if (lastIndex === Infinity && candidate.includes('/')) { | ||
dashIdx = candidate.lastIndexOf('/'); | ||
} else if (lastIndex === Infinity && candidate.includes("/")) { | ||
dashIdx = candidate.lastIndexOf("/"); | ||
wasSlash = true; | ||
} else { | ||
dashIdx = candidate.lastIndexOf('-', lastIndex); | ||
dashIdx = candidate.lastIndexOf("-", lastIndex); | ||
} | ||
@@ -133,3 +132,3 @@ if (dashIdx < 0) { | ||
// TODO: This feels a bit hacky | ||
if (prefix === '' || modifier === '/') { | ||
if (prefix === "" || modifier === "/") { | ||
continue; | ||
@@ -144,3 +143,3 @@ } | ||
function applyPrefix(matches, context) { | ||
if (matches.length === 0 || context.tailwindConfig.prefix === '') { | ||
if (matches.length === 0 || context.tailwindConfig.prefix === "") { | ||
return matches; | ||
@@ -162,3 +161,3 @@ } | ||
// The disconnect between candidate <-> class can cause @apply to hard crash. | ||
let shouldPrependNegative = classCandidate.startsWith('-'); | ||
let shouldPrependNegative = classCandidate.startsWith("-"); | ||
r.selector = (0, _prefixSelector.default)(context.tailwindConfig.prefix, r.selector, shouldPrependNegative); | ||
@@ -176,2 +175,5 @@ }); | ||
let result = []; | ||
function isInKeyframes(rule) { | ||
return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes"; | ||
} | ||
for (let [meta, rule] of matches){ | ||
@@ -184,2 +186,7 @@ let container = _postcss.default.root({ | ||
container.walkRules((r)=>{ | ||
// 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); | ||
@@ -221,7 +228,7 @@ // Remove extraneous selectors that do not include the base candidate | ||
{ | ||
let [baseVariant, ...modifiers] = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(variant, '/'); | ||
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('/'); | ||
baseVariant = baseVariant + "/" + modifiers.slice(0, -1).join("/"); | ||
modifiers = modifiers.slice(-1); | ||
@@ -232,6 +239,9 @@ } | ||
args.modifier = modifiers[0]; | ||
if (!(0, _featureFlags.flagEnabled)(context.tailwindConfig, "generalizedModifiers")) { | ||
return []; | ||
} | ||
} | ||
} | ||
// Retrieve "arbitrary value" | ||
if (variant.endsWith(']') && !variant.startsWith('[')) { | ||
if (variant.endsWith("]") && !variant.startsWith("[")) { | ||
// We either have: | ||
@@ -248,6 +258,6 @@ // @[200px] | ||
// @-[200px] case | ||
if (char === '@' && separator === '-') return []; | ||
if (char === "@" && separator === "-") return []; | ||
// group[:hover] case | ||
if (char !== '@' && separator === '') return []; | ||
variant = variant.replace(`${separator}[${value}]`, ''); | ||
if (char !== "@" && separator === "") return []; | ||
variant = variant.replace(`${separator}[${value}]`, ""); | ||
args.value = value; | ||
@@ -260,3 +270,3 @@ } | ||
let selector = (0, _dataTypes.normalize)(variant.slice(1, -1)); | ||
let selectors = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(selector, ','); | ||
let selectors = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(selector, ","); | ||
// We do not support multiple selectors for arbitrary variants | ||
@@ -289,3 +299,3 @@ if (selectors.length > 1) { | ||
// Don't generate variants for user css | ||
if (meta.layer === 'user') { | ||
if (meta.layer === "user") { | ||
continue; | ||
@@ -312,3 +322,3 @@ } | ||
clone.each((rule)=>{ | ||
if (rule.type !== 'rule') { | ||
if (rule.type !== "rule") { | ||
return; | ||
@@ -368,3 +378,3 @@ } | ||
} | ||
if (typeof ruleWithVariant === 'string') { | ||
if (typeof ruleWithVariant === "string") { | ||
collectedFormats.push({ | ||
@@ -410,3 +420,3 @@ format: ruleWithVariant, | ||
collectedFormats.push({ | ||
format: modified.replace(rebuiltBase, '&'), | ||
format: modified.replace(rebuiltBase, "&"), | ||
respectPrefix | ||
@@ -474,3 +484,3 @@ }); | ||
// This doesn't support schemes that don't use a leading // but that's unlikely to be a problem | ||
if (!declaration.includes('://')) { | ||
if (!declaration.includes("://")) { | ||
return false; | ||
@@ -480,3 +490,3 @@ } | ||
const url = new URL(declaration); | ||
return url.scheme !== '' && url.host !== ''; | ||
return url.scheme !== "" && url.host !== ""; | ||
} catch (err) { | ||
@@ -498,5 +508,5 @@ // Definitely not a valid url | ||
function isParsableCssValue(property, value) { | ||
// We don't want to treat [https://example.com] as a custom property | ||
// We don't want to to treat [https://example.com] as a custom property | ||
// Even though, according to the CSS grammar, it's a totally valid CSS declaration | ||
// So we short-circuit here by checking if the custom property looks like a URL | ||
// So we short-circuit here by checking if the custom property looks like a url | ||
if (looksLikeUri(`${property}:${value}`)) { | ||
@@ -530,3 +540,3 @@ return false; | ||
} | ||
let sort = context.offsets.arbitraryProperty(); | ||
let sort = context.offsets.arbitraryProperty(classCandidate); | ||
return [ | ||
@@ -536,3 +546,6 @@ [ | ||
sort, | ||
layer: 'utilities' | ||
layer: "utilities", | ||
options: { | ||
respectImportant: true | ||
} | ||
}, | ||
@@ -551,3 +564,3 @@ ()=>({ | ||
context.candidateRuleMap.get(classCandidate), | ||
'DEFAULT' | ||
"DEFAULT" | ||
]; | ||
@@ -559,3 +572,3 @@ } | ||
arbitraryPropertyRule, | ||
'DEFAULT' | ||
"DEFAULT" | ||
]; | ||
@@ -569,3 +582,3 @@ } | ||
const hasMatchingPrefix = candidatePrefix.startsWith(twConfigPrefix) || candidatePrefix.startsWith(`-${twConfigPrefix}`); | ||
if (candidatePrefix[twConfigPrefixLen] === '-' && hasMatchingPrefix) { | ||
if (candidatePrefix[twConfigPrefixLen] === "-" && hasMatchingPrefix) { | ||
negative = true; | ||
@@ -577,3 +590,3 @@ candidatePrefix = twConfigPrefix + candidatePrefix.slice(twConfigPrefixLen + 1); | ||
context.candidateRuleMap.get(candidatePrefix), | ||
'-DEFAULT' | ||
"-DEFAULT" | ||
]; | ||
@@ -614,3 +627,3 @@ } | ||
let important = false; | ||
if (classCandidate.startsWith('!')) { | ||
if (classCandidate.startsWith("!")) { | ||
important = true; | ||
@@ -637,3 +650,3 @@ classCandidate = classCandidate.slice(1); | ||
let matchesPerPlugin = []; | ||
if (typeof plugin === 'function') { | ||
if (typeof plugin === "function") { | ||
for (let ruleSet of [].concat(plugin(modifier, { | ||
@@ -656,3 +669,3 @@ isOnlyPlugin | ||
} | ||
} else if (modifier === 'DEFAULT' || modifier === '-DEFAULT') { | ||
} else if (modifier === "DEFAULT" || modifier === "-DEFAULT") { | ||
let ruleSet = plugin; | ||
@@ -688,3 +701,3 @@ let [rules, options] = parseRules(ruleSet, context.postCssNodeCache); | ||
let [withAny, withoutAny] = matches.reduce((group, plugin)=>{ | ||
let hasAnyType = plugin.some(([{ options }])=>options.types.some(({ type })=>type === 'any')); | ||
let hasAnyType = plugin.some(([{ options }])=>options.types.some(({ type })=>type === "any")); | ||
if (hasAnyType) { | ||
@@ -709,7 +722,7 @@ group[0].push(plugin); | ||
let matchingTypes = typesByMatches.get(rules); | ||
return rules.some(([{ options }, rule])=>{ | ||
return rules.some(([{ options }, rule])=>{ | ||
if (!isParsableNode(rule)) { | ||
return false; | ||
} | ||
return options.types.some(({ type, preferOnConflict })=>matchingTypes.includes(type) && preferOnConflict); | ||
return options.types.some(({ type , preferOnConflict })=>matchingTypes.includes(type) && preferOnConflict); | ||
}); | ||
@@ -727,8 +740,6 @@ }); | ||
} else { | ||
let typesPerPlugin = matches.map((match)=>{ | ||
var _typesByMatches_get; | ||
return new Set([ | ||
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. | ||
@@ -751,6 +762,6 @@ for (let pluginTypes of typesPerPlugin){ | ||
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 '}' | ||
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")).join("\n\n"); | ||
messages.push(` Use \`${candidate.replace("[", `[${type}:`)}\` for \`${rules.trim()}\``); | ||
break; | ||
@@ -762,3 +773,3 @@ } | ||
...messages, | ||
`If this is content and not a class, replace it with \`${candidate.replace('[', '[').replace(']', ']')}\` to silence this warning.` | ||
`If this is content and not a class, replace it with \`${candidate.replace("[", "[").replace("]", "]")}\` to silence this warning.` | ||
]); | ||
@@ -799,3 +810,3 @@ continue; | ||
} | ||
function applyFinalFormat(match, { context, candidate }) { | ||
function applyFinalFormat(match, { context , candidate }) { | ||
if (!match[0].collectedFormats) { | ||
@@ -811,3 +822,3 @@ return match; | ||
}); | ||
} catch (e) { | ||
} catch { | ||
// The format selector we produced is invalid | ||
@@ -845,3 +856,3 @@ // This could be because: | ||
rule.selector = selector; | ||
} catch (e) { | ||
} catch { | ||
// If this selector is invalid we also want to skip it | ||
@@ -856,2 +867,6 @@ // But it's likely that being invalid here means there's a bug in a plugin rather than too loosely matching content | ||
} | ||
// If all rules have been eliminated we can skip this candidate entirely | ||
if (container.nodes.length === 0) { | ||
return null; | ||
} | ||
match[1] = container.nodes[0]; | ||
@@ -861,3 +876,3 @@ return match; | ||
function inKeyframes(rule) { | ||
return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes'; | ||
return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes"; | ||
} | ||
@@ -871,3 +886,3 @@ function getImportantStrategy(important) { | ||
rule.walkDecls((d)=>{ | ||
if (d.parent.type === 'rule' && !inKeyframes(d.parent)) { | ||
if (d.parent.type === "rule" && !inKeyframes(d.parent)) { | ||
d.important = true; | ||
@@ -878,3 +893,3 @@ } | ||
} | ||
if (typeof important === 'string') { | ||
if (typeof important === "string") { | ||
return (rule)=>{ | ||
@@ -911,3 +926,3 @@ if (inKeyframes(rule)) { | ||
for (const match of matches){ | ||
let [{ sort, options }, rule] = match; | ||
let [{ sort , options }, rule] = match; | ||
if (options.respectImportant && strategy) { | ||
@@ -936,3 +951,3 @@ let container = _postcss.default.root({ | ||
function isArbitraryValue(input) { | ||
return input.startsWith('[') && input.endsWith(']'); | ||
return input.startsWith("[") && input.endsWith("]"); | ||
} |
@@ -19,5 +19,5 @@ "use strict"; | ||
let jsExtensions = [ | ||
'.js', | ||
'.cjs', | ||
'.mjs' | ||
".js", | ||
".cjs", | ||
".mjs" | ||
]; | ||
@@ -35,22 +35,22 @@ // Given the current file `a.ts`, we want to make sure that when importing `b` that we resolve | ||
let jsResolutionOrder = [ | ||
'', | ||
'.js', | ||
'.cjs', | ||
'.mjs', | ||
'.ts', | ||
'.cts', | ||
'.mts', | ||
'.jsx', | ||
'.tsx' | ||
"", | ||
".js", | ||
".cjs", | ||
".mjs", | ||
".ts", | ||
".cts", | ||
".mts", | ||
".jsx", | ||
".tsx" | ||
]; | ||
let tsResolutionOrder = [ | ||
'', | ||
'.ts', | ||
'.cts', | ||
'.mts', | ||
'.tsx', | ||
'.js', | ||
'.cjs', | ||
'.mjs', | ||
'.jsx' | ||
"", | ||
".ts", | ||
".cts", | ||
".mts", | ||
".tsx", | ||
".js", | ||
".cjs", | ||
".mjs", | ||
".jsx" | ||
]; | ||
@@ -86,3 +86,3 @@ function resolveWithExtension(file, extensions) { | ||
ext = _path.default.extname(absoluteFile); | ||
let contents = _fs.default.readFileSync(absoluteFile, 'utf-8'); | ||
let contents = _fs.default.readFileSync(absoluteFile, "utf-8"); | ||
// Find imports/requires | ||
@@ -95,3 +95,3 @@ for (let match of [ | ||
// Bail out if it's not a relative file | ||
if (!match[1].startsWith('.')) continue; | ||
if (!match[1].startsWith(".")) continue; | ||
yield* _getModuleDependencies(match[1], base, seen, ext); | ||
@@ -98,0 +98,0 @@ } |
@@ -5,5 +5,13 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "loadConfig", { | ||
enumerable: true, | ||
get: function() { | ||
function _export(target, all) { | ||
for(var name in all)Object.defineProperty(target, name, { | ||
enumerable: true, | ||
get: all[name] | ||
}); | ||
} | ||
_export(exports, { | ||
useCustomJiti: function() { | ||
return useCustomJiti; | ||
}, | ||
loadConfig: function() { | ||
return loadConfig; | ||
@@ -20,2 +28,5 @@ } | ||
let jiti = null; | ||
function useCustomJiti(_jiti) { | ||
jiti = _jiti(); | ||
} | ||
function lazyJiti() { | ||
@@ -25,6 +36,10 @@ return jiti !== null && jiti !== void 0 ? jiti : jiti = (0, _jiti.default)(__filename, { | ||
transform: (opts)=>{ | ||
// Sucrase can't transform import.meta so we have to use Babel | ||
if (opts.source.includes("import.meta")) { | ||
return require("jiti/dist/babel.js")(opts); | ||
} | ||
return (0, _sucrase.transform)(opts.source, { | ||
transforms: [ | ||
'typescript', | ||
'imports' | ||
"typescript", | ||
"imports" | ||
] | ||
@@ -37,5 +52,9 @@ }); | ||
let config = function() { | ||
// Always use jiti for ESM or TS files | ||
if (path && (path.endsWith(".mjs") || path.endsWith(".ts") || path.endsWith(".cts") || path.endsWith(".mts"))) { | ||
return lazyJiti()(path); | ||
} | ||
try { | ||
return path ? require(path) : {}; | ||
} catch (e) { | ||
} catch { | ||
return lazyJiti()(path); | ||
@@ -42,0 +61,0 @@ } |
@@ -22,19 +22,34 @@ "use strict"; | ||
root.walkAtRules((atRule)=>{ | ||
if (atRule.name === 'apply') { | ||
if (atRule.name === "apply") { | ||
applyDirectives.add(atRule); | ||
} | ||
if (atRule.name === 'tailwind') { | ||
if (atRule.params === 'screens') { | ||
atRule.params = 'variants'; | ||
if (atRule.name === "import") { | ||
if (atRule.params === '"tailwindcss/base"' || atRule.params === "'tailwindcss/base'") { | ||
atRule.name = "tailwind"; | ||
atRule.params = "base"; | ||
} else if (atRule.params === '"tailwindcss/components"' || atRule.params === "'tailwindcss/components'") { | ||
atRule.name = "tailwind"; | ||
atRule.params = "components"; | ||
} else if (atRule.params === '"tailwindcss/utilities"' || atRule.params === "'tailwindcss/utilities'") { | ||
atRule.name = "tailwind"; | ||
atRule.params = "utilities"; | ||
} else if (atRule.params === '"tailwindcss/screens"' || atRule.params === "'tailwindcss/screens'" || atRule.params === '"tailwindcss/variants"' || atRule.params === "'tailwindcss/variants'") { | ||
atRule.name = "tailwind"; | ||
atRule.params = "variants"; | ||
} | ||
} | ||
if (atRule.name === "tailwind") { | ||
if (atRule.params === "screens") { | ||
atRule.params = "variants"; | ||
} | ||
tailwindDirectives.add(atRule.params); | ||
} | ||
if ([ | ||
'layer', | ||
'responsive', | ||
'variants' | ||
"layer", | ||
"responsive", | ||
"variants" | ||
].includes(atRule.name)) { | ||
if ([ | ||
'responsive', | ||
'variants' | ||
"responsive", | ||
"variants" | ||
].includes(atRule.name)) { | ||
@@ -44,3 +59,3 @@ _log.default.warn(`${atRule.name}-at-rule-deprecated`, [ | ||
`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" | ||
]); | ||
@@ -51,8 +66,8 @@ } | ||
}); | ||
if (!tailwindDirectives.has('base') || !tailwindDirectives.has('components') || !tailwindDirectives.has('utilities')) { | ||
if (!tailwindDirectives.has("base") || !tailwindDirectives.has("components") || !tailwindDirectives.has("utilities")) { | ||
for (let rule of layerDirectives){ | ||
if (rule.name === 'layer' && [ | ||
'base', | ||
'components', | ||
'utilities' | ||
if (rule.name === "layer" && [ | ||
"base", | ||
"components", | ||
"utilities" | ||
].includes(rule.params)) { | ||
@@ -62,9 +77,9 @@ if (!tailwindDirectives.has(rule.params)) { | ||
} | ||
} else if (rule.name === 'responsive') { | ||
if (!tailwindDirectives.has('utilities')) { | ||
throw rule.error('`@responsive` is used but `@tailwind utilities` is missing.'); | ||
} else if (rule.name === "responsive") { | ||
if (!tailwindDirectives.has("utilities")) { | ||
throw rule.error("`@responsive` is used but `@tailwind utilities` is missing."); | ||
} | ||
} else if (rule.name === 'variants') { | ||
if (!tailwindDirectives.has('utilities')) { | ||
throw rule.error('`@variants` is used but `@tailwind utilities` is missing.'); | ||
} else if (rule.name === "variants") { | ||
if (!tailwindDirectives.has("utilities")) { | ||
throw rule.error("`@variants` is used but `@tailwind utilities` is missing."); | ||
} | ||
@@ -71,0 +86,0 @@ } |
@@ -20,2 +20,40 @@ // @ts-check | ||
class Offsets { | ||
constructor(){ | ||
/** | ||
* Offsets for the next rule in a given layer | ||
* | ||
* @type {Record<Layer, bigint>} | ||
*/ this.offsets = { | ||
defaults: 0n, | ||
base: 0n, | ||
components: 0n, | ||
utilities: 0n, | ||
variants: 0n, | ||
user: 0n | ||
}; | ||
/** | ||
* Positions for a given layer | ||
* | ||
* @type {Record<Layer, bigint>} | ||
*/ this.layerPositions = { | ||
defaults: 0n, | ||
base: 1n, | ||
components: 2n, | ||
utilities: 3n, | ||
// There isn't technically a "user" layer, but we need to give it a position | ||
// Because it's used for ordering user-css from @apply | ||
user: 4n, | ||
variants: 5n | ||
}; | ||
/** | ||
* The total number of functions currently registered across all variants (including arbitrary variants) | ||
* | ||
* @type {bigint} | ||
*/ this.reservedVariantBits = 0n; | ||
/** | ||
* Positions for a given variant | ||
* | ||
* @type {Map<string, bigint>} | ||
*/ this.variantOffsets = new Map(); | ||
} | ||
/** | ||
@@ -32,2 +70,4 @@ * @param {Layer} layer | ||
index: this.offsets[layer]++, | ||
propertyOffset: 0n, | ||
property: "", | ||
options: [] | ||
@@ -37,7 +77,9 @@ }; | ||
/** | ||
* @param {string} name | ||
* @returns {RuleOffset} | ||
*/ arbitraryProperty() { | ||
*/ arbitraryProperty(name) { | ||
return { | ||
...this.create('utilities'), | ||
arbitrary: 1n | ||
...this.create("utilities"), | ||
arbitrary: 1n, | ||
property: name | ||
}; | ||
@@ -57,3 +99,3 @@ } | ||
return { | ||
...this.create('variants'), | ||
...this.create("variants"), | ||
variants: offset << BigInt(index) | ||
@@ -71,4 +113,4 @@ }; | ||
...rule, | ||
layer: 'variants', | ||
parentLayer: rule.layer === 'variants' ? rule.parentLayer : rule.layer, | ||
layer: "variants", | ||
parentLayer: rule.layer === "variants" ? rule.parentLayer : rule.layer, | ||
variants: rule.variants | variant.variants, | ||
@@ -126,3 +168,3 @@ options: options.sort ? [].concat(options, rule.options) : rule.options, | ||
return { | ||
...this.create('variants'), | ||
...this.create("variants"), | ||
variants: this.variantOffsets.get(variant) | ||
@@ -185,2 +227,6 @@ }; | ||
} | ||
// Always sort arbitrary properties alphabetically | ||
if (a.propertyOffset !== b.propertyOffset) { | ||
return a.propertyOffset - b.propertyOffset; | ||
} | ||
// Sort utilities, components, etc… in the order they were registered | ||
@@ -197,3 +243,3 @@ return a.index - b.index; | ||
// Sort the variants by their name | ||
let variants = Array.from(this.variantOffsets.entries()).filter(([v])=>v.startsWith('[')).sort(([a], [z])=>fastCompare(a, z)); | ||
let variants = Array.from(this.variantOffsets.entries()).filter(([v])=>v.startsWith("[")).sort(([a], [z])=>fastCompare(a, z)); | ||
// Sort the list of offsets | ||
@@ -219,3 +265,3 @@ // This is not necessarily a discrete range of numbers which is why | ||
// No arbitrary variants? Nothing to do. | ||
// Everything already in order? Nothing to do. | ||
// Everyhing already in order? Nothing to do. | ||
if (mapping.length === 0) { | ||
@@ -241,44 +287,47 @@ return list; | ||
* @returns {[RuleOffset, T][]} | ||
*/ sortArbitraryProperties(list) { | ||
// Collect all known arbitrary properties | ||
let known = new Set(); | ||
for (let [offset] of list){ | ||
if (offset.arbitrary === 1n) { | ||
known.add(offset.property); | ||
} | ||
} | ||
// No arbitrary properties? Nothing to do. | ||
if (known.size === 0) { | ||
return list; | ||
} | ||
// Sort the properties alphabetically | ||
let properties = Array.from(known).sort(); | ||
// Create a map from the property name to its offset | ||
let offsets = new Map(); | ||
let offset = 1n; | ||
for (let property of properties){ | ||
offsets.set(property, offset++); | ||
} | ||
// Apply the sorted offsets to the list | ||
return list.map((item)=>{ | ||
let [offset, rule] = item; | ||
var _offsets_get; | ||
offset = { | ||
...offset, | ||
propertyOffset: (_offsets_get = offsets.get(offset.property)) !== null && _offsets_get !== void 0 ? _offsets_get : 0n | ||
}; | ||
return [ | ||
offset, | ||
rule | ||
]; | ||
}); | ||
} | ||
/** | ||
* @template T | ||
* @param {[RuleOffset, T][]} list | ||
* @returns {[RuleOffset, T][]} | ||
*/ sort(list) { | ||
// Sort arbitrary variants so they're in alphabetical order | ||
list = this.remapArbitraryVariantOffsets(list); | ||
// Sort arbitrary properties so they're in alphabetical order | ||
list = this.sortArbitraryProperties(list); | ||
return list.sort(([a], [b])=>(0, _bigSign.default)(this.compare(a, b))); | ||
} | ||
constructor(){ | ||
/** | ||
* Offsets for the next rule in a given layer | ||
* | ||
* @type {Record<Layer, bigint>} | ||
*/ this.offsets = { | ||
defaults: 0n, | ||
base: 0n, | ||
components: 0n, | ||
utilities: 0n, | ||
variants: 0n, | ||
user: 0n | ||
}; | ||
/** | ||
* Positions for a given layer | ||
* | ||
* @type {Record<Layer, bigint>} | ||
*/ this.layerPositions = { | ||
defaults: 0n, | ||
base: 1n, | ||
components: 2n, | ||
utilities: 3n, | ||
// There isn't technically a "user" layer, but we need to give it a position | ||
// Because it's used for ordering user-css from @apply | ||
user: 4n, | ||
variants: 5n | ||
}; | ||
/** | ||
* The total number of functions currently registered across all variants (including arbitrary variants) | ||
* | ||
* @type {bigint} | ||
*/ this.reservedVariantBits = 0n; | ||
/** | ||
* Positions for a given variant | ||
* | ||
* @type {Map<string, bigint>} | ||
*/ this.variantOffsets = new Map(); | ||
} | ||
} | ||
@@ -303,3 +352,3 @@ /** | ||
* only strings. If you're sorting strings inside objects | ||
* or arrays, you need to use a custom compare function. | ||
* or arrays, you need must use a custom compare function. | ||
* | ||
@@ -306,0 +355,0 @@ * @param {string} a |
@@ -14,3 +14,3 @@ "use strict"; | ||
let applyParents = new Set(); | ||
root.walkAtRules('apply', (rule)=>{ | ||
root.walkAtRules("apply", (rule)=>{ | ||
applyParents.add(rule.parent); | ||
@@ -25,3 +25,3 @@ }); | ||
for (let node of rule.nodes){ | ||
if (node.type === 'atrule' && node.name === 'apply') { | ||
if (node.type === "atrule" && node.name === "apply") { | ||
if (lastGroup.length > 0) { | ||
@@ -28,0 +28,0 @@ nodeGroups.push(lastGroup); |
@@ -12,22 +12,22 @@ "use strict"; | ||
_export(exports, { | ||
pattern: function() { | ||
return pattern; | ||
}, | ||
withoutCapturing: function() { | ||
return withoutCapturing; | ||
}, | ||
any: function() { | ||
return any; | ||
}, | ||
escape: function() { | ||
return escape; | ||
}, | ||
nestedBrackets: function() { | ||
return nestedBrackets; | ||
}, | ||
optional: function() { | ||
return optional; | ||
}, | ||
pattern: function() { | ||
return pattern; | ||
zeroOrMore: function() { | ||
return zeroOrMore; | ||
}, | ||
withoutCapturing: function() { | ||
return withoutCapturing; | ||
nestedBrackets: function() { | ||
return nestedBrackets; | ||
}, | ||
zeroOrMore: function() { | ||
return zeroOrMore; | ||
escape: function() { | ||
return escape; | ||
} | ||
@@ -44,12 +44,12 @@ }); | ||
source = source.map((item)=>item instanceof RegExp ? item.source : item); | ||
return source.join(''); | ||
return source.join(""); | ||
} | ||
function pattern(source) { | ||
return new RegExp(toSource(source), 'g'); | ||
return new RegExp(toSource(source), "g"); | ||
} | ||
function withoutCapturing(source) { | ||
return new RegExp(`(?:${toSource(source)})`, 'g'); | ||
return new RegExp(`(?:${toSource(source)})`, "g"); | ||
} | ||
function any(sources) { | ||
return `(?:${sources.map(toSource).join('|')})`; | ||
return `(?:${sources.map(toSource).join("|")})`; | ||
} | ||
@@ -75,3 +75,3 @@ function optional(source) { | ||
function escape(string) { | ||
return string && REGEX_HAS_SPECIAL.test(string) ? string.replace(REGEX_SPECIAL, '\\$&') : string || ''; | ||
return string && REGEX_HAS_SPECIAL.test(string) ? string.replace(REGEX_SPECIAL, "\\$&") : string || ""; | ||
} |
@@ -12,7 +12,7 @@ "use strict"; | ||
_export(exports, { | ||
elementSelectorParser: function() { | ||
return elementSelectorParser; | ||
}, | ||
default: function() { | ||
return resolveDefaultsAtRules; | ||
}, | ||
elementSelectorParser: function() { | ||
return elementSelectorParser; | ||
} | ||
@@ -31,4 +31,4 @@ }); | ||
return _postcssselectorparser.default.attribute({ | ||
attribute: 'id', | ||
operator: '=', | ||
attribute: "id", | ||
operator: "=", | ||
value: node.value, | ||
@@ -42,3 +42,3 @@ quoteMark: '"' | ||
// Keep non-pseudo nodes | ||
if (node.type !== 'pseudo') return true; | ||
if (node.type !== "pseudo") return true; | ||
// Keep pseudo nodes that have subnodes | ||
@@ -49,21 +49,21 @@ // E.g.: `:not()` contains subnodes inside the parentheses | ||
// This implicitly means that we ignore pseudo `classes` | ||
return node.value.startsWith('::') || [ | ||
':before', | ||
':after', | ||
':first-line', | ||
':first-letter' | ||
return node.value.startsWith("::") || [ | ||
":before", | ||
":after", | ||
":first-line", | ||
":first-letter" | ||
].includes(node.value); | ||
}).reverse(); | ||
let searchFor = new Set([ | ||
'tag', | ||
'class', | ||
'id', | ||
'attribute' | ||
"tag", | ||
"class", | ||
"id", | ||
"attribute" | ||
]); | ||
let splitPointIdx = rest.findIndex((n)=>searchFor.has(n.type)); | ||
if (splitPointIdx === -1) return rest.reverse().join('').trim(); | ||
if (splitPointIdx === -1) return rest.reverse().join("").trim(); | ||
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) { | ||
@@ -76,7 +76,7 @@ rest.splice(0, combinatorIdx); | ||
...rest.reverse() | ||
].join('').trim(); | ||
].join("").trim(); | ||
} | ||
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); | ||
@@ -92,7 +92,7 @@ }); | ||
} | ||
function resolveDefaultsAtRules({ tailwindConfig }) { | ||
function resolveDefaultsAtRules({ tailwindConfig }) { | ||
return (root)=>{ | ||
let variableNodeMap = new Map(); | ||
/** @type {Set<import('postcss').AtRule>} */ let universals = new Set(); | ||
root.walkAtRules('defaults', (rule)=>{ | ||
root.walkAtRules("defaults", (rule)=>{ | ||
if (rule.nodes && rule.nodes.length > 0) { | ||
@@ -109,3 +109,3 @@ universals.add(rule); | ||
}); | ||
if ((0, _featureFlags.flagEnabled)(tailwindConfig, 'optimizeUniversalDefaults')) { | ||
if ((0, _featureFlags.flagEnabled)(tailwindConfig, "optimizeUniversalDefaults")) { | ||
for (let universal of universals){ | ||
@@ -121,3 +121,5 @@ /** @type {Map<string, Set<string>>} */ let selectorGroups = new Map(); | ||
// vendor prefix to throw out the whole rule | ||
let selectorGroupName = selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'; | ||
// 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; | ||
@@ -129,18 +131,16 @@ let selectors = (_selectorGroups_get = selectorGroups.get(selectorGroupName)) !== null && _selectorGroups_get !== void 0 ? _selectorGroups_get : new Set(); | ||
} | ||
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); | ||
} | ||
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(); | ||
@@ -151,5 +151,5 @@ } | ||
selectors: [ | ||
'*', | ||
'::before', | ||
'::after' | ||
"*", | ||
"::before", | ||
"::after" | ||
] | ||
@@ -169,3 +169,3 @@ }); | ||
selectors: [ | ||
'::backdrop' | ||
"::backdrop" | ||
] | ||
@@ -172,0 +172,0 @@ }); |
@@ -15,7 +15,7 @@ "use strict"; | ||
}, | ||
createContext: function() { | ||
return createContext; | ||
isValidVariantFormatString: function() { | ||
return isValidVariantFormatString; | ||
}, | ||
getContext: function() { | ||
return getContext; | ||
parseVariant: function() { | ||
return parseVariant; | ||
}, | ||
@@ -25,7 +25,7 @@ getFileModifiedMap: function() { | ||
}, | ||
isValidVariantFormatString: function() { | ||
return isValidVariantFormatString; | ||
createContext: function() { | ||
return createContext; | ||
}, | ||
parseVariant: function() { | ||
return parseVariant; | ||
getContext: function() { | ||
return getContext; | ||
} | ||
@@ -54,2 +54,3 @@ }); | ||
const _offsets = require("./offsets.js"); | ||
const _featureFlags = require("../featureFlags.js"); | ||
const _formatVariantSelector = require("../util/formatVariantSelector"); | ||
@@ -82,5 +83,3 @@ function _interop_require_default(obj) { | ||
} | ||
var newObj = { | ||
__proto__: null | ||
}; | ||
var newObj = {}; | ||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; | ||
@@ -105,4 +104,4 @@ for(var key in obj){ | ||
const VARIANT_TYPES = { | ||
AddVariant: Symbol.for('ADD_VARIANT'), | ||
MatchVariant: Symbol.for('MATCH_VARIANT') | ||
AddVariant: Symbol.for("ADD_VARIANT"), | ||
MatchVariant: Symbol.for("MATCH_VARIANT") | ||
}; | ||
@@ -115,5 +114,5 @@ const VARIANT_INFO = { | ||
let prefix = context.tailwindConfig.prefix; | ||
return typeof prefix === 'function' ? prefix(selector) : prefix + selector; | ||
return typeof prefix === "function" ? prefix(selector) : prefix + selector; | ||
} | ||
function normalizeOptionTypes({ type = 'any', ...options }) { | ||
function normalizeOptionTypes({ type ="any" , ...options }) { | ||
let types = [].concat(type); | ||
@@ -143,15 +142,15 @@ return { | ||
// This is why we do not skip whitespace | ||
let current = ''; | ||
let current = ""; | ||
let depth = 0; | ||
for(let idx = 0; idx < input.length; idx++){ | ||
let char = input[idx]; | ||
if (char === '\\') { | ||
if (char === "\\") { | ||
// Escaped characters are not special | ||
current += '\\' + input[++idx]; | ||
} else if (char === '{') { | ||
current += "\\" + input[++idx]; | ||
} else if (char === "{") { | ||
// Nested rule: start | ||
++depth; | ||
parts.push(current.trim()); | ||
current = ''; | ||
} else if (char === '}') { | ||
current = ""; | ||
} else if (char === "}") { | ||
// Nested rule: end | ||
@@ -162,3 +161,3 @@ if (--depth < 0) { | ||
parts.push(current.trim()); | ||
current = ''; | ||
current = ""; | ||
} else { | ||
@@ -172,6 +171,6 @@ // Normal character | ||
} | ||
parts = parts.filter((part)=>part !== ''); | ||
parts = parts.filter((part)=>part !== ""); | ||
return parts; | ||
} | ||
function insertInto(list, value, { before = [] } = {}) { | ||
function insertInto(list, value, { before =[] } = {}) { | ||
before = [].concat(before); | ||
@@ -223,3 +222,3 @@ if (before.length <= 0) { | ||
selectors.walkPseudos((pseudo)=>{ | ||
if (pseudo.value === ':not') { | ||
if (pseudo.value === ":not") { | ||
pseudo.remove(); | ||
@@ -234,6 +233,6 @@ } | ||
let selectors = []; | ||
if (node.type === 'rule') { | ||
if (node.type === "rule") { | ||
// Handle normal rules | ||
selectors.push(...node.selectors); | ||
} else if (node.type === 'atrule') { | ||
} else if (node.type === "atrule") { | ||
// Handle at-rules (which contains nested rules) | ||
@@ -283,16 +282,16 @@ node.walkRules((rule)=>selectors.push(...rule.selectors)); | ||
function isValidVariantFormatString(format) { | ||
return format.startsWith('@') || format.includes('&'); | ||
return format.startsWith("@") || format.includes("&"); | ||
} | ||
function parseVariant(variant) { | ||
variant = variant.replace(/\n+/g, '').replace(/\s{1,}/g, ' ').trim(); | ||
variant = variant.replace(/\n+/g, "").replace(/\s{1,}/g, " ").trim(); | ||
let fns = parseVariantFormatString(variant).map((str)=>{ | ||
if (!str.startsWith('@')) { | ||
return ({ format })=>format(str); | ||
if (!str.startsWith("@")) { | ||
return ({ format })=>format(str); | ||
} | ||
let [, name, params] = /@(\S*)( .+|[({].*)?/g.exec(str); | ||
return ({ wrap })=>{ | ||
var _params_trim; | ||
var _params_trim; | ||
return ({ wrap })=>{ | ||
return wrap(_postcss.default.atRule({ | ||
name, | ||
params: (_params_trim = params === null || params === void 0 ? void 0 : params.trim()) !== null && _params_trim !== void 0 ? _params_trim : '' | ||
params: (_params_trim = params === null || params === void 0 ? void 0 : params.trim()) !== null && _params_trim !== void 0 ? _params_trim : "" | ||
})); | ||
@@ -313,3 +312,3 @@ }; | ||
* @param {Offsets} param2.offsets | ||
*/ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) { | ||
*/ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , offsets , classList }) { | ||
function getConfigValue(path, defaultValue) { | ||
@@ -333,3 +332,3 @@ return path ? (0, _dlv.default)(tailwindConfig, path, defaultValue) : tailwindConfig; | ||
let value = getConfigValue([ | ||
'theme', | ||
"theme", | ||
...parts | ||
@@ -351,3 +350,3 @@ ], defaultValue); | ||
return getConfigValue([ | ||
'corePlugins', | ||
"corePlugins", | ||
path | ||
@@ -363,3 +362,3 @@ ], true); | ||
let prefixedIdentifier = prefixIdentifier(identifier, {}); | ||
let offset = offsets.create('base'); | ||
let offset = offsets.create("base"); | ||
if (!context.candidateRuleMap.has(prefixedIdentifier)) { | ||
@@ -371,3 +370,3 @@ context.candidateRuleMap.set(prefixedIdentifier, []); | ||
sort: offset, | ||
layer: 'base' | ||
layer: "base" | ||
}, | ||
@@ -392,4 +391,4 @@ rule | ||
{ | ||
sort: offsets.create('defaults'), | ||
layer: 'defaults' | ||
sort: offsets.create("defaults"), | ||
layer: "defaults" | ||
}, | ||
@@ -415,4 +414,4 @@ rule | ||
{ | ||
sort: offsets.create('components'), | ||
layer: 'components', | ||
sort: offsets.create("components"), | ||
layer: "components", | ||
options | ||
@@ -439,4 +438,4 @@ }, | ||
{ | ||
sort: offsets.create('utilities'), | ||
layer: 'utilities', | ||
sort: offsets.create("utilities"), | ||
layer: "utilities", | ||
options | ||
@@ -458,3 +457,3 @@ }, | ||
}); | ||
let offset = offsets.create('utilities'); | ||
let offset = offsets.create("utilities"); | ||
for(let identifier in utilities){ | ||
@@ -467,3 +466,3 @@ let prefixedIdentifier = prefixIdentifier(identifier, options); | ||
]); | ||
function wrapped(modifier, { isOnlyPlugin }) { | ||
function wrapped(modifier, { isOnlyPlugin }) { | ||
let [value, coercedType, utilityModifier] = (0, _pluginUtils.coerceValue)(options.types, modifier, options, tailwindConfig); | ||
@@ -473,7 +472,7 @@ if (value === undefined) { | ||
} | ||
if (!options.types.some(({ type })=>type === 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 + ":", "")}\`.` | ||
]); | ||
@@ -491,3 +490,3 @@ } else { | ||
_log.default.warn(`modifier-used-without-options-for-${identifier}`, [ | ||
'Your plugin must set `modifiers: true` in its options to support modifiers.' | ||
"Your plugin must set `modifiers: true` in its options to support modifiers." | ||
]); | ||
@@ -498,3 +497,4 @@ } | ||
}; | ||
let ruleSets = [].concat(rule(value, extras)).filter(Boolean).map((declaration)=>({ | ||
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 | ||
@@ -507,3 +507,3 @@ })); | ||
sort: offset, | ||
layer: 'utilities', | ||
layer: "utilities", | ||
options | ||
@@ -529,3 +529,3 @@ }, | ||
}); | ||
let offset = offsets.create('components'); | ||
let offset = offsets.create("components"); | ||
for(let identifier in components){ | ||
@@ -538,3 +538,3 @@ let prefixedIdentifier = prefixIdentifier(identifier, options); | ||
]); | ||
function wrapped(modifier, { isOnlyPlugin }) { | ||
function wrapped(modifier, { isOnlyPlugin }) { | ||
let [value, coercedType, utilityModifier] = (0, _pluginUtils.coerceValue)(options.types, modifier, options, tailwindConfig); | ||
@@ -544,7 +544,7 @@ if (value === undefined) { | ||
} | ||
if (!options.types.some(({ type })=>type === 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 + ":", "")}\`.` | ||
]); | ||
@@ -562,3 +562,3 @@ } else { | ||
_log.default.warn(`modifier-used-without-options-for-${identifier}`, [ | ||
'Your plugin must set `modifiers: true` in its options to support modifiers.' | ||
"Your plugin must set `modifiers: true` in its options to support modifiers." | ||
]); | ||
@@ -569,3 +569,4 @@ } | ||
}; | ||
let ruleSets = [].concat(rule(value, extras)).filter(Boolean).map((declaration)=>({ | ||
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 | ||
@@ -578,3 +579,3 @@ })); | ||
sort: offset, | ||
layer: 'components', | ||
layer: "components", | ||
options | ||
@@ -592,6 +593,6 @@ }, | ||
variantFunctions = [].concat(variantFunctions).map((variantFunction)=>{ | ||
if (typeof variantFunction !== 'string') { | ||
if (typeof variantFunction !== "string") { | ||
// Safelist public API functions | ||
return (api = {})=>{ | ||
let { args, modifySelectors, container, separator, wrap, format } = api; | ||
let { args , modifySelectors , container , separator , wrap , format } = api; | ||
let result = variantFunction(Object.assign({ | ||
@@ -606,11 +607,11 @@ modifySelectors, | ||
})); | ||
if (typeof result === 'string' && !isValidVariantFormatString(result)) { | ||
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)); | ||
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); | ||
return result && typeof result === "string" && parseVariant(result)(api); | ||
}; | ||
@@ -632,10 +633,13 @@ } | ||
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 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, { | ||
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 | ||
}); | ||
@@ -651,4 +655,4 @@ }, { | ||
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 })=>{ | ||
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) { | ||
@@ -659,5 +663,7 @@ return null; | ||
_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 : '', { | ||
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 | ||
}); | ||
@@ -688,4 +694,4 @@ }, { | ||
let parsed = _url.default.parse(file); | ||
let pathname = parsed.hash ? parsed.href.replace(parsed.hash, '') : parsed.href; | ||
pathname = parsed.search ? pathname.replace(parsed.search, '') : pathname; | ||
let pathname = parsed.hash ? parsed.href.replace(parsed.hash, "") : parsed.href; | ||
pathname = parsed.search ? pathname.replace(parsed.search, "") : pathname; | ||
let newModified = (_fs_statSync = _fs.default.statSync(decodeURIComponent(pathname), { | ||
@@ -710,4 +716,4 @@ throwIfNoEntry: false | ||
if ([ | ||
'responsive', | ||
'variants' | ||
"responsive", | ||
"variants" | ||
].includes(atRule.name)) { | ||
@@ -723,16 +729,16 @@ extractVariantAtRules(atRule); | ||
root.each((node)=>{ | ||
if (node.type === 'atrule' && [ | ||
'responsive', | ||
'variants' | ||
if (node.type === "atrule" && [ | ||
"responsive", | ||
"variants" | ||
].includes(node.name)) { | ||
node.name = 'layer'; | ||
node.params = 'utilities'; | ||
node.name = "layer"; | ||
node.params = "utilities"; | ||
} | ||
}); | ||
// Walk @layer rules and treat them like plugins | ||
root.walkAtRules('layer', (layerRule)=>{ | ||
root.walkAtRules("layer", (layerRule)=>{ | ||
extractVariantAtRules(layerRule); | ||
if (layerRule.params === 'base') { | ||
if (layerRule.params === "base") { | ||
for (let node of layerRule.nodes){ | ||
layerPlugins.push(function({ addBase }) { | ||
layerPlugins.push(function({ addBase }) { | ||
addBase(node, { | ||
@@ -744,5 +750,5 @@ respectPrefix: false | ||
layerRule.remove(); | ||
} else if (layerRule.params === 'components') { | ||
} else if (layerRule.params === "components") { | ||
for (let node of layerRule.nodes){ | ||
layerPlugins.push(function({ addComponents }) { | ||
layerPlugins.push(function({ addComponents }) { | ||
addComponents(node, { | ||
@@ -755,5 +761,5 @@ respectPrefix: false, | ||
layerRule.remove(); | ||
} else if (layerRule.params === 'utilities') { | ||
} else if (layerRule.params === "utilities") { | ||
for (let node of layerRule.nodes){ | ||
layerPlugins.push(function({ addUtilities }) { | ||
layerPlugins.push(function({ addUtilities }) { | ||
addUtilities(node, { | ||
@@ -771,3 +777,6 @@ respectPrefix: false, | ||
function resolvePlugins(context, root) { | ||
let corePluginList = Object.entries(_corePlugins.corePlugins).map(([name, plugin])=>{ | ||
let corePluginList = Object.entries({ | ||
..._corePlugins.variantPlugins, | ||
..._corePlugins.corePlugins | ||
}).map(([name, plugin])=>{ | ||
if (!context.tailwindConfig.corePlugins.includes(name)) { | ||
@@ -782,3 +791,3 @@ return null; | ||
} | ||
return typeof plugin === 'function' ? plugin : plugin.handler; | ||
return typeof plugin === "function" ? plugin : plugin.handler; | ||
}); | ||
@@ -789,18 +798,36 @@ let layerPlugins = collectLayerPlugins(root); | ||
let beforeVariants = [ | ||
_corePlugins.variantPlugins['pseudoElementVariants'], | ||
_corePlugins.variantPlugins['pseudoClassVariants'], | ||
_corePlugins.variantPlugins['hasVariants'], | ||
_corePlugins.variantPlugins['ariaVariants'], | ||
_corePlugins.variantPlugins['dataVariants'] | ||
_corePlugins.variantPlugins["childVariant"], | ||
_corePlugins.variantPlugins["pseudoElementVariants"], | ||
_corePlugins.variantPlugins["pseudoClassVariants"], | ||
_corePlugins.variantPlugins["hasVariants"], | ||
_corePlugins.variantPlugins["ariaVariants"], | ||
_corePlugins.variantPlugins["dataVariants"] | ||
]; | ||
let afterVariants = [ | ||
_corePlugins.variantPlugins['supportsVariants'], | ||
_corePlugins.variantPlugins['directionVariants'], | ||
_corePlugins.variantPlugins['reducedMotionVariants'], | ||
_corePlugins.variantPlugins['prefersContrastVariants'], | ||
_corePlugins.variantPlugins['darkVariants'], | ||
_corePlugins.variantPlugins['printVariant'], | ||
_corePlugins.variantPlugins['screenVariants'], | ||
_corePlugins.variantPlugins['orientationVariants'] | ||
_corePlugins.variantPlugins["supportsVariants"], | ||
_corePlugins.variantPlugins["reducedMotionVariants"], | ||
_corePlugins.variantPlugins["prefersContrastVariants"], | ||
_corePlugins.variantPlugins["screenVariants"], | ||
_corePlugins.variantPlugins["orientationVariants"], | ||
_corePlugins.variantPlugins["directionVariants"], | ||
_corePlugins.variantPlugins["darkVariants"], | ||
_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 [ | ||
@@ -850,6 +877,6 @@ ...corePluginList, | ||
for (let value of safelist){ | ||
if (typeof value === 'string') { | ||
if (typeof value === "string") { | ||
context.changedContent.push({ | ||
content: value, | ||
extension: 'html' | ||
extension: "html" | ||
}); | ||
@@ -859,6 +886,6 @@ continue; | ||
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' | ||
_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" | ||
]); | ||
@@ -872,3 +899,3 @@ continue; | ||
let prefixLength = context.tailwindConfig.prefix.length; | ||
let checkImportantUtils = checks.some((check)=>check.pattern.source.includes('!')); | ||
let checkImportantUtils = checks.some((check)=>check.pattern.source.includes("!")); | ||
for (let util of classList){ | ||
@@ -885,3 +912,3 @@ let utils = Array.isArray(util) ? (()=>{ | ||
...classes, | ||
...classes.map((cls)=>'-' + cls) | ||
...classes.map((cls)=>"-" + cls) | ||
]; | ||
@@ -894,6 +921,6 @@ // 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')) { | ||
if (options.types.some(({ type })=>type === "color")) { | ||
classes = [ | ||
@@ -907,3 +934,3 @@ ...classes, | ||
...classes, | ||
...classes.map((cls)=>'!' + cls) | ||
...classes.map((cls)=>"!" + cls) | ||
]; | ||
@@ -916,3 +943,3 @@ } | ||
for (let util of utils){ | ||
for (let { pattern, variants = [] } of checks){ | ||
for (let { pattern , variants =[] } of checks){ | ||
// RegExp with the /g flag are stateful, so let's reset the last | ||
@@ -928,3 +955,3 @@ // index pointer to reset the state. | ||
content: util, | ||
extension: 'html' | ||
extension: "html" | ||
}); | ||
@@ -934,3 +961,3 @@ for (let variant of variants){ | ||
content: variant + context.tailwindConfig.separator + util, | ||
extension: 'html' | ||
extension: "html" | ||
}); | ||
@@ -945,4 +972,4 @@ } | ||
`The safelist pattern \`${regex}\` doesn't match any Tailwind CSS classes.`, | ||
'Fix this pattern or remove it from your `safelist` configuration.', | ||
'https://tailwindcss.com/docs/content-configuration#safelisting-classes' | ||
"Fix this pattern or remove it from your `safelist` configuration.", | ||
"https://tailwindcss.com/docs/content-configuration#safelisting-classes" | ||
]); | ||
@@ -953,3 +980,3 @@ } | ||
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'; | ||
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 | ||
@@ -961,4 +988,4 @@ // that don't exist on their own. This will result in them "not existing" and | ||
prefix(context, darkClassName), | ||
prefix(context, 'group'), | ||
prefix(context, 'peer') | ||
prefix(context, "group"), | ||
prefix(context, "peer") | ||
]; | ||
@@ -1018,3 +1045,3 @@ context.getClassOrder = function getClassOrder(classes) { | ||
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')) { | ||
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; | ||
@@ -1055,2 +1082,6 @@ modifiers.push(...Object.keys((_context_tailwindConfig_theme_opacity = context.tailwindConfig.theme.opacity) !== null && _context_tailwindConfig_theme_opacity !== void 0 ? _context_tailwindConfig_theme_opacity : {})); | ||
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 = []; | ||
@@ -1062,7 +1093,7 @@ for (let [name, options] of context.variantOptions.entries()){ | ||
name, | ||
isArbitrary: options.type === Symbol.for('MATCH_VARIANT'), | ||
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 = '__TAILWIND_PLACEHOLDER__'; | ||
hasDash: name !== "@", | ||
selectors ({ modifier , value } = {}) { | ||
let candidate = `TAILWINDPLACEHOLDER${id}`; | ||
let rule = _postcss.default.rule({ | ||
@@ -1093,3 +1124,3 @@ selector: `.${candidate}` | ||
container.each((rule)=>{ | ||
if (rule.type !== 'rule') { | ||
if (rule.type !== "rule") { | ||
return; | ||
@@ -1155,3 +1186,3 @@ } | ||
// format: .foo & | ||
manualFormatStrings.push(modified.replace(rebuiltBase, '&').replace(candidate, '&')); | ||
manualFormatStrings.push(modified.replace(rebuiltBase, "&").replace(candidate, "&")); | ||
}); | ||
@@ -1184,5 +1215,5 @@ // Figure out all atrules | ||
}; | ||
let result = formatStrings.map((formats)=>(0, _formatVariantSelector.finalizeSelector)(`.${candidate}`, (0, _formatVariantSelector.formatVariantSelector)(formats, opts), opts).replace(`.${candidate}`, '&').replace('{ & }', '').trim()); | ||
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}`, '&')); | ||
result.push((0, _formatVariantSelector.formatVariantSelector)(manualFormatStrings, opts).toString().replace(`.${candidate}`, "&")); | ||
} | ||
@@ -1262,3 +1293,3 @@ return result; | ||
let isConfigFile = userConfigPath !== null; | ||
_sharedState.env.DEBUG && console.log('Source path:', sourcePath); | ||
_sharedState.env.DEBUG && console.log("Source path:", sourcePath); | ||
let existingContext; | ||
@@ -1310,3 +1341,3 @@ if (isConfigFile && contextMap.has(sourcePath)) { | ||
} | ||
_sharedState.env.DEBUG && console.log('Setting up new context...'); | ||
_sharedState.env.DEBUG && console.log("Setting up new context..."); | ||
let context = createContext(tailwindConfig, [], root); | ||
@@ -1313,0 +1344,0 @@ Object.assign(context, { |
@@ -98,3 +98,3 @@ // @ts-check | ||
function setupTrackingContext(configOrPath) { | ||
return ({ tailwindDirectives, registerDependency })=>{ | ||
return ({ tailwindDirectives , registerDependency })=>{ | ||
return (root, result)=>{ | ||
@@ -114,3 +114,3 @@ let [tailwindConfig, userConfigPath, tailwindConfigHash, configDependencies] = getTailwindConfig(configOrPath); | ||
for (let message of result.messages){ | ||
if (message.type === 'dependency') { | ||
if (message.type === "dependency") { | ||
contextDependencies.add(message.file); | ||
@@ -155,3 +155,3 @@ } | ||
registerDependency({ | ||
type: 'dependency', | ||
type: "dependency", | ||
file | ||
@@ -158,0 +158,0 @@ }); |
@@ -12,7 +12,7 @@ "use strict"; | ||
_export(exports, { | ||
NONE: function() { | ||
return NONE; | ||
env: function() { | ||
return env; | ||
}, | ||
NOT_ON_DEMAND: function() { | ||
return NOT_ON_DEMAND; | ||
contextMap: function() { | ||
return contextMap; | ||
}, | ||
@@ -22,23 +22,23 @@ configContextMap: function() { | ||
}, | ||
contextMap: function() { | ||
return contextMap; | ||
}, | ||
contextSourcesMap: function() { | ||
return contextSourcesMap; | ||
}, | ||
env: function() { | ||
return env; | ||
sourceHashMap: function() { | ||
return sourceHashMap; | ||
}, | ||
NOT_ON_DEMAND: function() { | ||
return NOT_ON_DEMAND; | ||
}, | ||
NONE: function() { | ||
return NONE; | ||
}, | ||
resolveDebug: function() { | ||
return resolveDebug; | ||
}, | ||
sourceHashMap: function() { | ||
return sourceHashMap; | ||
} | ||
}); | ||
const env = typeof process !== 'undefined' ? { | ||
const env = typeof process !== "undefined" ? { | ||
NODE_ENV: process.env.NODE_ENV, | ||
DEBUG: resolveDebug(process.env.DEBUG) | ||
} : { | ||
NODE_ENV: 'production', | ||
NODE_ENV: "production", | ||
DEBUG: false | ||
@@ -50,4 +50,4 @@ }; | ||
const sourceHashMap = new Map(); | ||
const NOT_ON_DEMAND = new String('*'); | ||
const NONE = Symbol('__NONE__'); | ||
const NOT_ON_DEMAND = new String("*"); | ||
const NONE = Symbol("__NONE__"); | ||
function resolveDebug(debug) { | ||
@@ -58,6 +58,6 @@ if (debug === undefined) { | ||
// Environment variables are strings, so convert to boolean | ||
if (debug === 'true' || debug === '1') { | ||
if (debug === "true" || debug === "1") { | ||
return true; | ||
} | ||
if (debug === 'false' || debug === '0') { | ||
if (debug === "false" || debug === "0") { | ||
return false; | ||
@@ -70,12 +70,12 @@ } | ||
// DEBUG=projectA,-projectB -> This enables debug for projectA and explicitly disables it for projectB | ||
if (debug === '*') { | ||
if (debug === "*") { | ||
return true; | ||
} | ||
let debuggers = debug.split(',').map((d)=>d.split(':')[0]); | ||
let debuggers = debug.split(",").map((d)=>d.split(":")[0]); | ||
// Ignoring tailwindcss | ||
if (debuggers.includes('-tailwindcss')) { | ||
if (debuggers.includes("-tailwindcss")) { | ||
return false; | ||
} | ||
// Including tailwindcss | ||
if (debuggers.includes('tailwindcss')) { | ||
if (debuggers.includes("tailwindcss")) { | ||
return true; | ||
@@ -82,0 +82,0 @@ } |
@@ -18,12 +18,12 @@ "use strict"; | ||
} | ||
function _default({ tailwindConfig: { theme } }) { | ||
function _default({ tailwindConfig: { theme } }) { | ||
return function(css) { | ||
css.walkAtRules('screen', (atRule)=>{ | ||
css.walkAtRules("screen", (atRule)=>{ | ||
let screen = atRule.params; | ||
let screens = (0, _normalizeScreens.normalizeScreens)(theme.screens); | ||
let screenDefinition = screens.find(({ name })=>name === screen); | ||
let screenDefinition = screens.find(({ name })=>name === screen); | ||
if (!screenDefinition) { | ||
throw atRule.error(`No \`${screen}\` screen found.`); | ||
} | ||
atRule.name = 'media'; | ||
atRule.name = "media"; | ||
atRule.params = (0, _buildMediaQuery.default)(screenDefinition); | ||
@@ -30,0 +30,0 @@ }); |
@@ -5,5 +5,2 @@ "use strict"; | ||
}); | ||
const _postcss = /*#__PURE__*/ _interop_require_default(require("postcss")); | ||
const _lightningcss = /*#__PURE__*/ _interop_require_wildcard(require("lightningcss")); | ||
const _browserslist = /*#__PURE__*/ _interop_require_default(require("browserslist")); | ||
const _setupTrackingContext = /*#__PURE__*/ _interop_require_default(require("./lib/setupTrackingContext")); | ||
@@ -13,4 +10,2 @@ const _processTailwindFeatures = /*#__PURE__*/ _interop_require_default(require("./processTailwindFeatures")); | ||
const _findAtConfigPath = require("./lib/findAtConfigPath"); | ||
const _handleImportAtRules = require("./lib/handleImportAtRules"); | ||
const _packagejson = require("../package.json"); | ||
function _interop_require_default(obj) { | ||
@@ -21,56 +16,11 @@ return obj && obj.__esModule ? 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 = { | ||
__proto__: null | ||
}; | ||
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; | ||
} | ||
function license() { | ||
return `/* ! tailwindcss v${_packagejson.version} | MIT License | https://tailwindcss.com */\n`; | ||
} | ||
module.exports = function tailwindcss(configOrPath) { | ||
return { | ||
postcssPlugin: 'tailwindcss', | ||
postcssPlugin: "tailwindcss", | ||
plugins: [ | ||
_sharedState.env.DEBUG && function(root) { | ||
console.log('\n'); | ||
console.time('JIT TOTAL'); | ||
console.log("\n"); | ||
console.time("JIT TOTAL"); | ||
return root; | ||
}, | ||
...(0, _handleImportAtRules.handleImportAtRules)(), | ||
async function(root, result) { | ||
@@ -82,6 +32,6 @@ var _findAtConfigPath1; | ||
let context = (0, _setupTrackingContext.default)(configOrPath); | ||
if (root.type === 'document') { | ||
let roots = root.nodes.filter((node)=>node.type === 'root'); | ||
if (root.type === "document") { | ||
let roots = root.nodes.filter((node)=>node.type === "root"); | ||
for (const root of roots){ | ||
if (root.type === 'root') { | ||
if (root.type === "root") { | ||
await (0, _processTailwindFeatures.default)(context)(root, result); | ||
@@ -94,73 +44,5 @@ } | ||
}, | ||
function lightningCssPlugin(_root, result) { | ||
var _intermediateResult_map_toJSON, _intermediateResult_map; | ||
var _result_map; | ||
let map = (_result_map = result.map) !== null && _result_map !== void 0 ? _result_map : result.opts.map; | ||
let intermediateResult = result.root.toResult({ | ||
map: map ? { | ||
inline: true | ||
} : false | ||
}); | ||
var _intermediateResult_map_toJSON1; | ||
let intermediateMap = (_intermediateResult_map_toJSON1 = (_intermediateResult_map = intermediateResult.map) === null || _intermediateResult_map === void 0 ? void 0 : (_intermediateResult_map_toJSON = _intermediateResult_map.toJSON) === null || _intermediateResult_map_toJSON === void 0 ? void 0 : _intermediateResult_map_toJSON.call(_intermediateResult_map)) !== null && _intermediateResult_map_toJSON1 !== void 0 ? _intermediateResult_map_toJSON1 : map; | ||
try { | ||
var _browserslist_findConfig; | ||
var _result_opts_from; | ||
let resolvedBrowsersListConfig = (_browserslist_findConfig = _browserslist.default.findConfig((_result_opts_from = result.opts.from) !== null && _result_opts_from !== void 0 ? _result_opts_from : process.cwd())) === null || _browserslist_findConfig === void 0 ? void 0 : _browserslist_findConfig.defaults; | ||
let defaultBrowsersListConfig = require('../package.json').browserslist; | ||
let browsersListConfig = resolvedBrowsersListConfig !== null && resolvedBrowsersListConfig !== void 0 ? resolvedBrowsersListConfig : defaultBrowsersListConfig; | ||
let transformed = _lightningcss.default.transform({ | ||
filename: result.opts.from, | ||
code: Buffer.from(intermediateResult.css), | ||
minify: false, | ||
sourceMap: !!intermediateMap, | ||
targets: _lightningcss.default.browserslistToTargets((0, _browserslist.default)(browsersListConfig)), | ||
errorRecovery: true, | ||
drafts: { | ||
customMedia: true | ||
}, | ||
nonStandard: { | ||
deepSelectorCombinator: true | ||
}, | ||
include: _lightningcss.Features.Nesting, | ||
exclude: _lightningcss.Features.LogicalProperties | ||
}); | ||
let code = transformed.code.toString(); | ||
// https://postcss.org/api/#sourcemapoptions | ||
if (intermediateMap && transformed.map != null) { | ||
let prev = transformed.map.toString(); | ||
if (typeof intermediateMap === 'object') { | ||
intermediateMap.prev = prev; | ||
} else { | ||
code = `${code}\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(prev).toString('base64')} */`; | ||
} | ||
} | ||
result.root = _postcss.default.parse(license() + code, { | ||
...result.opts, | ||
map: intermediateMap | ||
}); | ||
} catch (err) { | ||
if (err.source && typeof process !== 'undefined' && process.env.JEST_WORKER_ID) { | ||
let lines = err.source.split('\n'); | ||
err = new Error([ | ||
'Error formatting using Lightning CSS:', | ||
'', | ||
...[ | ||
'```css', | ||
...lines.slice(Math.max(err.loc.line - 3, 0), err.loc.line), | ||
' '.repeat(err.loc.column - 1) + '^-- ' + err.toString(), | ||
...lines.slice(err.loc.line, err.loc.line + 2), | ||
'```' | ||
] | ||
].join('\n')); | ||
} | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(err, lightningCssPlugin); | ||
} | ||
throw err; | ||
} | ||
}, | ||
_sharedState.env.DEBUG && function(root) { | ||
console.timeEnd('JIT TOTAL'); | ||
console.log('\n'); | ||
console.timeEnd("JIT TOTAL"); | ||
console.log("\n"); | ||
return root; | ||
@@ -167,0 +49,0 @@ } |
@@ -14,4 +14,4 @@ "use strict"; | ||
return { | ||
postcssPlugin: 'tailwindcss/nesting', | ||
Once (root, { result }) { | ||
postcssPlugin: "tailwindcss/nesting", | ||
Once (root, { result }) { | ||
return (0, _plugin.nesting)(opts)(root, result); | ||
@@ -18,0 +18,0 @@ } |
@@ -20,9 +20,9 @@ "use strict"; | ||
return (root, result)=>{ | ||
root.walkAtRules('screen', (rule)=>{ | ||
rule.name = 'media'; | ||
root.walkAtRules("screen", (rule)=>{ | ||
rule.name = "media"; | ||
rule.params = `screen(${rule.params})`; | ||
}); | ||
root.walkAtRules('apply', (rule)=>{ | ||
root.walkAtRules("apply", (rule)=>{ | ||
rule.before(_postcss.default.decl({ | ||
prop: '__apply', | ||
prop: "__apply", | ||
value: rule.params, | ||
@@ -35,6 +35,6 @@ source: rule.source | ||
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'))) { | ||
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; | ||
} | ||
if (typeof opts === 'string') { | ||
if (typeof opts === "string") { | ||
return require(opts); | ||
@@ -45,3 +45,3 @@ } | ||
} | ||
throw new Error('tailwindcss/nesting should be loaded with a nesting plugin.'); | ||
throw new Error("tailwindcss/nesting should be loaded with a nesting plugin."); | ||
})(); | ||
@@ -51,5 +51,5 @@ (0, _postcss.default)([ | ||
]).process(root, result.opts).sync(); | ||
root.walkDecls('__apply', (decl)=>{ | ||
root.walkDecls("__apply", (decl)=>{ | ||
decl.before(_postcss.default.atRule({ | ||
name: 'apply', | ||
name: "apply", | ||
params: decl.value, | ||
@@ -74,3 +74,3 @@ source: decl.source | ||
*/ function markDirty(node) { | ||
if (!('markDirty' in node)) { | ||
if (!("markDirty" in node)) { | ||
return; | ||
@@ -77,0 +77,0 @@ } |
@@ -20,3 +20,2 @@ "use strict"; | ||
const _partitionApplyAtRules = /*#__PURE__*/ _interop_require_default(require("./lib/partitionApplyAtRules")); | ||
const _detectNesting = /*#__PURE__*/ _interop_require_default(require("./lib/detectNesting")); | ||
const _setupContextUtils = require("./lib/setupContextUtils"); | ||
@@ -31,4 +30,3 @@ const _featureFlags = require("./featureFlags"); | ||
return async function(root, result) { | ||
let { tailwindDirectives, applyDirectives } = (0, _normalizeTailwindDirectives.default)(root); | ||
(0, _detectNesting.default)()(root, result); | ||
let { tailwindDirectives , applyDirectives } = (0, _normalizeTailwindDirectives.default)(root); | ||
// Partition apply rules that are found in the css | ||
@@ -42,3 +40,3 @@ // itself. | ||
result.messages.push({ | ||
plugin: 'tailwindcss', | ||
plugin: "tailwindcss", | ||
parent: result.opts.from, | ||
@@ -52,3 +50,3 @@ ...dependency | ||
})(root, result); | ||
if (context.tailwindConfig.separator === '-') { | ||
if (context.tailwindConfig.separator === "-") { | ||
throw new Error("The '-' character cannot be used as a custom separator in JIT mode due to parsing ambiguity. Please use another character like '_' instead."); | ||
@@ -55,0 +53,0 @@ } |
@@ -17,305 +17,305 @@ "use strict"; | ||
} | ||
function warn({ version, from, to }) { | ||
function warn({ version , from , to }) { | ||
_log.default.warn(`${from}-color-renamed`, [ | ||
`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." | ||
]); | ||
} | ||
const _default = { | ||
inherit: 'inherit', | ||
current: 'currentColor', | ||
transparent: 'transparent', | ||
black: '#000', | ||
white: '#fff', | ||
inherit: "inherit", | ||
current: "currentColor", | ||
transparent: "transparent", | ||
black: "#000", | ||
white: "#fff", | ||
slate: { | ||
50: '#f8fafc', | ||
100: '#f1f5f9', | ||
200: '#e2e8f0', | ||
300: '#cbd5e1', | ||
400: '#94a3b8', | ||
500: '#64748b', | ||
600: '#475569', | ||
700: '#334155', | ||
800: '#1e293b', | ||
900: '#0f172a', | ||
950: '#020617' | ||
50: "#f8fafc", | ||
100: "#f1f5f9", | ||
200: "#e2e8f0", | ||
300: "#cbd5e1", | ||
400: "#94a3b8", | ||
500: "#64748b", | ||
600: "#475569", | ||
700: "#334155", | ||
800: "#1e293b", | ||
900: "#0f172a", | ||
950: "#020617" | ||
}, | ||
gray: { | ||
50: '#f9fafb', | ||
100: '#f3f4f6', | ||
200: '#e5e7eb', | ||
300: '#d1d5db', | ||
400: '#9ca3af', | ||
500: '#6b7280', | ||
600: '#4b5563', | ||
700: '#374151', | ||
800: '#1f2937', | ||
900: '#111827', | ||
950: '#030712' | ||
50: "#f9fafb", | ||
100: "#f3f4f6", | ||
200: "#e5e7eb", | ||
300: "#d1d5db", | ||
400: "#9ca3af", | ||
500: "#6b7280", | ||
600: "#4b5563", | ||
700: "#374151", | ||
800: "#1f2937", | ||
900: "#111827", | ||
950: "#030712" | ||
}, | ||
zinc: { | ||
50: '#fafafa', | ||
100: '#f4f4f5', | ||
200: '#e4e4e7', | ||
300: '#d4d4d8', | ||
400: '#a1a1aa', | ||
500: '#71717a', | ||
600: '#52525b', | ||
700: '#3f3f46', | ||
800: '#27272a', | ||
900: '#18181b', | ||
950: '#09090b' | ||
50: "#fafafa", | ||
100: "#f4f4f5", | ||
200: "#e4e4e7", | ||
300: "#d4d4d8", | ||
400: "#a1a1aa", | ||
500: "#71717a", | ||
600: "#52525b", | ||
700: "#3f3f46", | ||
800: "#27272a", | ||
900: "#18181b", | ||
950: "#09090b" | ||
}, | ||
neutral: { | ||
50: '#fafafa', | ||
100: '#f5f5f5', | ||
200: '#e5e5e5', | ||
300: '#d4d4d4', | ||
400: '#a3a3a3', | ||
500: '#737373', | ||
600: '#525252', | ||
700: '#404040', | ||
800: '#262626', | ||
900: '#171717', | ||
950: '#0a0a0a' | ||
50: "#fafafa", | ||
100: "#f5f5f5", | ||
200: "#e5e5e5", | ||
300: "#d4d4d4", | ||
400: "#a3a3a3", | ||
500: "#737373", | ||
600: "#525252", | ||
700: "#404040", | ||
800: "#262626", | ||
900: "#171717", | ||
950: "#0a0a0a" | ||
}, | ||
stone: { | ||
50: '#fafaf9', | ||
100: '#f5f5f4', | ||
200: '#e7e5e4', | ||
300: '#d6d3d1', | ||
400: '#a8a29e', | ||
500: '#78716c', | ||
600: '#57534e', | ||
700: '#44403c', | ||
800: '#292524', | ||
900: '#1c1917', | ||
950: '#0c0a09' | ||
50: "#fafaf9", | ||
100: "#f5f5f4", | ||
200: "#e7e5e4", | ||
300: "#d6d3d1", | ||
400: "#a8a29e", | ||
500: "#78716c", | ||
600: "#57534e", | ||
700: "#44403c", | ||
800: "#292524", | ||
900: "#1c1917", | ||
950: "#0c0a09" | ||
}, | ||
red: { | ||
50: '#fef2f2', | ||
100: '#fee2e2', | ||
200: '#fecaca', | ||
300: '#fca5a5', | ||
400: '#f87171', | ||
500: '#ef4444', | ||
600: '#dc2626', | ||
700: '#b91c1c', | ||
800: '#991b1b', | ||
900: '#7f1d1d', | ||
950: '#450a0a' | ||
50: "#fef2f2", | ||
100: "#fee2e2", | ||
200: "#fecaca", | ||
300: "#fca5a5", | ||
400: "#f87171", | ||
500: "#ef4444", | ||
600: "#dc2626", | ||
700: "#b91c1c", | ||
800: "#991b1b", | ||
900: "#7f1d1d", | ||
950: "#450a0a" | ||
}, | ||
orange: { | ||
50: '#fff7ed', | ||
100: '#ffedd5', | ||
200: '#fed7aa', | ||
300: '#fdba74', | ||
400: '#fb923c', | ||
500: '#f97316', | ||
600: '#ea580c', | ||
700: '#c2410c', | ||
800: '#9a3412', | ||
900: '#7c2d12', | ||
950: '#431407' | ||
50: "#fff7ed", | ||
100: "#ffedd5", | ||
200: "#fed7aa", | ||
300: "#fdba74", | ||
400: "#fb923c", | ||
500: "#f97316", | ||
600: "#ea580c", | ||
700: "#c2410c", | ||
800: "#9a3412", | ||
900: "#7c2d12", | ||
950: "#431407" | ||
}, | ||
amber: { | ||
50: '#fffbeb', | ||
100: '#fef3c7', | ||
200: '#fde68a', | ||
300: '#fcd34d', | ||
400: '#fbbf24', | ||
500: '#f59e0b', | ||
600: '#d97706', | ||
700: '#b45309', | ||
800: '#92400e', | ||
900: '#78350f', | ||
950: '#451a03' | ||
50: "#fffbeb", | ||
100: "#fef3c7", | ||
200: "#fde68a", | ||
300: "#fcd34d", | ||
400: "#fbbf24", | ||
500: "#f59e0b", | ||
600: "#d97706", | ||
700: "#b45309", | ||
800: "#92400e", | ||
900: "#78350f", | ||
950: "#451a03" | ||
}, | ||
yellow: { | ||
50: '#fefce8', | ||
100: '#fef9c3', | ||
200: '#fef08a', | ||
300: '#fde047', | ||
400: '#facc15', | ||
500: '#eab308', | ||
600: '#ca8a04', | ||
700: '#a16207', | ||
800: '#854d0e', | ||
900: '#713f12', | ||
950: '#422006' | ||
50: "#fefce8", | ||
100: "#fef9c3", | ||
200: "#fef08a", | ||
300: "#fde047", | ||
400: "#facc15", | ||
500: "#eab308", | ||
600: "#ca8a04", | ||
700: "#a16207", | ||
800: "#854d0e", | ||
900: "#713f12", | ||
950: "#422006" | ||
}, | ||
lime: { | ||
50: '#f7fee7', | ||
100: '#ecfccb', | ||
200: '#d9f99d', | ||
300: '#bef264', | ||
400: '#a3e635', | ||
500: '#84cc16', | ||
600: '#65a30d', | ||
700: '#4d7c0f', | ||
800: '#3f6212', | ||
900: '#365314', | ||
950: '#1a2e05' | ||
50: "#f7fee7", | ||
100: "#ecfccb", | ||
200: "#d9f99d", | ||
300: "#bef264", | ||
400: "#a3e635", | ||
500: "#84cc16", | ||
600: "#65a30d", | ||
700: "#4d7c0f", | ||
800: "#3f6212", | ||
900: "#365314", | ||
950: "#1a2e05" | ||
}, | ||
green: { | ||
50: '#f0fdf4', | ||
100: '#dcfce7', | ||
200: '#bbf7d0', | ||
300: '#86efac', | ||
400: '#4ade80', | ||
500: '#22c55e', | ||
600: '#16a34a', | ||
700: '#15803d', | ||
800: '#166534', | ||
900: '#14532d', | ||
950: '#052e16' | ||
50: "#f0fdf4", | ||
100: "#dcfce7", | ||
200: "#bbf7d0", | ||
300: "#86efac", | ||
400: "#4ade80", | ||
500: "#22c55e", | ||
600: "#16a34a", | ||
700: "#15803d", | ||
800: "#166534", | ||
900: "#14532d", | ||
950: "#052e16" | ||
}, | ||
emerald: { | ||
50: '#ecfdf5', | ||
100: '#d1fae5', | ||
200: '#a7f3d0', | ||
300: '#6ee7b7', | ||
400: '#34d399', | ||
500: '#10b981', | ||
600: '#059669', | ||
700: '#047857', | ||
800: '#065f46', | ||
900: '#064e3b', | ||
950: '#022c22' | ||
50: "#ecfdf5", | ||
100: "#d1fae5", | ||
200: "#a7f3d0", | ||
300: "#6ee7b7", | ||
400: "#34d399", | ||
500: "#10b981", | ||
600: "#059669", | ||
700: "#047857", | ||
800: "#065f46", | ||
900: "#064e3b", | ||
950: "#022c22" | ||
}, | ||
teal: { | ||
50: '#f0fdfa', | ||
100: '#ccfbf1', | ||
200: '#99f6e4', | ||
300: '#5eead4', | ||
400: '#2dd4bf', | ||
500: '#14b8a6', | ||
600: '#0d9488', | ||
700: '#0f766e', | ||
800: '#115e59', | ||
900: '#134e4a', | ||
950: '#042f2e' | ||
50: "#f0fdfa", | ||
100: "#ccfbf1", | ||
200: "#99f6e4", | ||
300: "#5eead4", | ||
400: "#2dd4bf", | ||
500: "#14b8a6", | ||
600: "#0d9488", | ||
700: "#0f766e", | ||
800: "#115e59", | ||
900: "#134e4a", | ||
950: "#042f2e" | ||
}, | ||
cyan: { | ||
50: '#ecfeff', | ||
100: '#cffafe', | ||
200: '#a5f3fc', | ||
300: '#67e8f9', | ||
400: '#22d3ee', | ||
500: '#06b6d4', | ||
600: '#0891b2', | ||
700: '#0e7490', | ||
800: '#155e75', | ||
900: '#164e63', | ||
950: '#083344' | ||
50: "#ecfeff", | ||
100: "#cffafe", | ||
200: "#a5f3fc", | ||
300: "#67e8f9", | ||
400: "#22d3ee", | ||
500: "#06b6d4", | ||
600: "#0891b2", | ||
700: "#0e7490", | ||
800: "#155e75", | ||
900: "#164e63", | ||
950: "#083344" | ||
}, | ||
sky: { | ||
50: '#f0f9ff', | ||
100: '#e0f2fe', | ||
200: '#bae6fd', | ||
300: '#7dd3fc', | ||
400: '#38bdf8', | ||
500: '#0ea5e9', | ||
600: '#0284c7', | ||
700: '#0369a1', | ||
800: '#075985', | ||
900: '#0c4a6e', | ||
950: '#082f49' | ||
50: "#f0f9ff", | ||
100: "#e0f2fe", | ||
200: "#bae6fd", | ||
300: "#7dd3fc", | ||
400: "#38bdf8", | ||
500: "#0ea5e9", | ||
600: "#0284c7", | ||
700: "#0369a1", | ||
800: "#075985", | ||
900: "#0c4a6e", | ||
950: "#082f49" | ||
}, | ||
blue: { | ||
50: '#eff6ff', | ||
100: '#dbeafe', | ||
200: '#bfdbfe', | ||
300: '#93c5fd', | ||
400: '#60a5fa', | ||
500: '#3b82f6', | ||
600: '#2563eb', | ||
700: '#1d4ed8', | ||
800: '#1e40af', | ||
900: '#1e3a8a', | ||
950: '#172554' | ||
50: "#eff6ff", | ||
100: "#dbeafe", | ||
200: "#bfdbfe", | ||
300: "#93c5fd", | ||
400: "#60a5fa", | ||
500: "#3b82f6", | ||
600: "#2563eb", | ||
700: "#1d4ed8", | ||
800: "#1e40af", | ||
900: "#1e3a8a", | ||
950: "#172554" | ||
}, | ||
indigo: { | ||
50: '#eef2ff', | ||
100: '#e0e7ff', | ||
200: '#c7d2fe', | ||
300: '#a5b4fc', | ||
400: '#818cf8', | ||
500: '#6366f1', | ||
600: '#4f46e5', | ||
700: '#4338ca', | ||
800: '#3730a3', | ||
900: '#312e81', | ||
950: '#1e1b4b' | ||
50: "#eef2ff", | ||
100: "#e0e7ff", | ||
200: "#c7d2fe", | ||
300: "#a5b4fc", | ||
400: "#818cf8", | ||
500: "#6366f1", | ||
600: "#4f46e5", | ||
700: "#4338ca", | ||
800: "#3730a3", | ||
900: "#312e81", | ||
950: "#1e1b4b" | ||
}, | ||
violet: { | ||
50: '#f5f3ff', | ||
100: '#ede9fe', | ||
200: '#ddd6fe', | ||
300: '#c4b5fd', | ||
400: '#a78bfa', | ||
500: '#8b5cf6', | ||
600: '#7c3aed', | ||
700: '#6d28d9', | ||
800: '#5b21b6', | ||
900: '#4c1d95', | ||
950: '#2e1065' | ||
50: "#f5f3ff", | ||
100: "#ede9fe", | ||
200: "#ddd6fe", | ||
300: "#c4b5fd", | ||
400: "#a78bfa", | ||
500: "#8b5cf6", | ||
600: "#7c3aed", | ||
700: "#6d28d9", | ||
800: "#5b21b6", | ||
900: "#4c1d95", | ||
950: "#2e1065" | ||
}, | ||
purple: { | ||
50: '#faf5ff', | ||
100: '#f3e8ff', | ||
200: '#e9d5ff', | ||
300: '#d8b4fe', | ||
400: '#c084fc', | ||
500: '#a855f7', | ||
600: '#9333ea', | ||
700: '#7e22ce', | ||
800: '#6b21a8', | ||
900: '#581c87', | ||
950: '#3b0764' | ||
50: "#faf5ff", | ||
100: "#f3e8ff", | ||
200: "#e9d5ff", | ||
300: "#d8b4fe", | ||
400: "#c084fc", | ||
500: "#a855f7", | ||
600: "#9333ea", | ||
700: "#7e22ce", | ||
800: "#6b21a8", | ||
900: "#581c87", | ||
950: "#3b0764" | ||
}, | ||
fuchsia: { | ||
50: '#fdf4ff', | ||
100: '#fae8ff', | ||
200: '#f5d0fe', | ||
300: '#f0abfc', | ||
400: '#e879f9', | ||
500: '#d946ef', | ||
600: '#c026d3', | ||
700: '#a21caf', | ||
800: '#86198f', | ||
900: '#701a75', | ||
950: '#4a044e' | ||
50: "#fdf4ff", | ||
100: "#fae8ff", | ||
200: "#f5d0fe", | ||
300: "#f0abfc", | ||
400: "#e879f9", | ||
500: "#d946ef", | ||
600: "#c026d3", | ||
700: "#a21caf", | ||
800: "#86198f", | ||
900: "#701a75", | ||
950: "#4a044e" | ||
}, | ||
pink: { | ||
50: '#fdf2f8', | ||
100: '#fce7f3', | ||
200: '#fbcfe8', | ||
300: '#f9a8d4', | ||
400: '#f472b6', | ||
500: '#ec4899', | ||
600: '#db2777', | ||
700: '#be185d', | ||
800: '#9d174d', | ||
900: '#831843', | ||
950: '#500724' | ||
50: "#fdf2f8", | ||
100: "#fce7f3", | ||
200: "#fbcfe8", | ||
300: "#f9a8d4", | ||
400: "#f472b6", | ||
500: "#ec4899", | ||
600: "#db2777", | ||
700: "#be185d", | ||
800: "#9d174d", | ||
900: "#831843", | ||
950: "#500724" | ||
}, | ||
rose: { | ||
50: '#fff1f2', | ||
100: '#ffe4e6', | ||
200: '#fecdd3', | ||
300: '#fda4af', | ||
400: '#fb7185', | ||
500: '#f43f5e', | ||
600: '#e11d48', | ||
700: '#be123c', | ||
800: '#9f1239', | ||
900: '#881337', | ||
950: '#4c0519' | ||
50: "#fff1f2", | ||
100: "#ffe4e6", | ||
200: "#fecdd3", | ||
300: "#fda4af", | ||
400: "#fb7185", | ||
500: "#f43f5e", | ||
600: "#e11d48", | ||
700: "#be123c", | ||
800: "#9f1239", | ||
900: "#881337", | ||
950: "#4c0519" | ||
}, | ||
get lightBlue () { | ||
warn({ | ||
version: 'v2.2', | ||
from: 'lightBlue', | ||
to: 'sky' | ||
version: "v2.2", | ||
from: "lightBlue", | ||
to: "sky" | ||
}); | ||
@@ -326,5 +326,5 @@ return this.sky; | ||
warn({ | ||
version: 'v3.0', | ||
from: 'warmGray', | ||
to: 'stone' | ||
version: "v3.0", | ||
from: "warmGray", | ||
to: "stone" | ||
}); | ||
@@ -335,5 +335,5 @@ return this.stone; | ||
warn({ | ||
version: 'v3.0', | ||
from: 'trueGray', | ||
to: 'neutral' | ||
version: "v3.0", | ||
from: "trueGray", | ||
to: "neutral" | ||
}); | ||
@@ -344,5 +344,5 @@ return this.neutral; | ||
warn({ | ||
version: 'v3.0', | ||
from: 'coolGray', | ||
to: 'gray' | ||
version: "v3.0", | ||
from: "coolGray", | ||
to: "gray" | ||
}); | ||
@@ -353,5 +353,5 @@ return this.gray; | ||
warn({ | ||
version: 'v3.0', | ||
from: 'blueGray', | ||
to: 'slate' | ||
version: "v3.0", | ||
from: "blueGray", | ||
to: "slate" | ||
}); | ||
@@ -358,0 +358,0 @@ return this.slate; |
@@ -21,8 +21,10 @@ "use strict"; | ||
sel.each((sel)=>{ | ||
// Wrap with :is if it's not already wrapped | ||
let isWrapped = sel.nodes[0].type === 'pseudo' && sel.nodes[0].value === ':is' && sel.nodes.every((node)=>node.type !== 'combinator'); | ||
if (!isWrapped) { | ||
// For nesting, we only need to wrap a selector with :is() if it has a top-level combinator, | ||
// e.g. `.dark .text-white`, to be independent of DOM order. Any other selector, including | ||
// combinators inside of pseudos like `:where()`, are ok to nest. | ||
let shouldWrap = sel.nodes.some((node)=>node.type === "combinator"); | ||
if (shouldWrap) { | ||
sel.nodes = [ | ||
_postcssselectorparser.default.pseudo({ | ||
value: ':is', | ||
value: ":is", | ||
nodes: [ | ||
@@ -29,0 +31,0 @@ sel.clone() |
@@ -23,6 +23,6 @@ "use strict"; | ||
screen.max && `(max-width: ${screen.max})` | ||
].filter(Boolean).join(' and '); | ||
].filter(Boolean).join(" and "); | ||
}); | ||
return screen.not ? `not all and ${values}` : values; | ||
}).join(', '); | ||
}).join(", "); | ||
} |
@@ -15,3 +15,3 @@ "use strict"; | ||
} | ||
if (typeof value === 'object' && value !== null) { | ||
if (typeof value === "object" && value !== null) { | ||
return Object.fromEntries(Object.entries(value).map(([k, v])=>[ | ||
@@ -18,0 +18,0 @@ k, |
@@ -1,2 +0,7 @@ | ||
"use strict"; | ||
/** | ||
* @param {import('postcss').Container[]} nodes | ||
* @param {any} source | ||
* @param {any} raws | ||
* @returns {import('postcss').Container[]} | ||
*/ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -13,15 +18,3 @@ value: true | ||
return nodes.map((node)=>{ | ||
var _node_raws_tailwind; | ||
let cloned = node.clone(); | ||
// We always want override the source map | ||
// except when explicitly told not to | ||
let shouldOverwriteSource = ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.preserveSource) !== true || !cloned.source; | ||
if (source !== undefined && shouldOverwriteSource) { | ||
cloned.source = source; | ||
if ('walk' in cloned) { | ||
cloned.walk((child)=>{ | ||
child.source = source; | ||
}); | ||
} | ||
} | ||
if (raws !== undefined) { | ||
@@ -33,4 +26,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)); | ||
} | ||
} |
@@ -12,7 +12,7 @@ "use strict"; | ||
_export(exports, { | ||
parseColor: function() { | ||
return parseColor; | ||
}, | ||
formatColor: function() { | ||
return formatColor; | ||
}, | ||
parseColor: function() { | ||
return parseColor; | ||
} | ||
@@ -34,17 +34,17 @@ }); | ||
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 _match__toString, _match_; | ||
if (typeof value !== 'string') { | ||
function parseColor(value, { loose =false } = {}) { | ||
var _match_, _match__toString; | ||
if (typeof value !== "string") { | ||
return null; | ||
} | ||
value = value.trim(); | ||
if (value === 'transparent') { | ||
if (value === "transparent") { | ||
return { | ||
mode: 'rgb', | ||
mode: "rgb", | ||
color: [ | ||
'0', | ||
'0', | ||
'0' | ||
"0", | ||
"0", | ||
"0" | ||
], | ||
alpha: '0' | ||
alpha: "0" | ||
}; | ||
@@ -54,3 +54,3 @@ } | ||
return { | ||
mode: 'rgb', | ||
mode: "rgb", | ||
color: _colorNames.default[value].map((v)=>v.toString()) | ||
@@ -60,3 +60,3 @@ }; | ||
let hex = value.replace(SHORT_HEX, (_, r, g, b, a)=>[ | ||
'#', | ||
"#", | ||
r, | ||
@@ -68,7 +68,7 @@ r, | ||
b, | ||
a ? a + a : '' | ||
].join('')).match(HEX); | ||
a ? a + a : "" | ||
].join("")).match(HEX); | ||
if (hex !== null) { | ||
return { | ||
mode: 'rgb', | ||
mode: "rgb", | ||
color: [ | ||
@@ -94,3 +94,3 @@ parseInt(hex[1], 16), | ||
// hsla(var(--my-color), 0.1) | ||
if (color.length === 2 && color[0].startsWith('var(')) { | ||
if (color.length === 2 && color[0].startsWith("var(")) { | ||
return { | ||
@@ -116,8 +116,8 @@ mode: match[1], | ||
} | ||
function formatColor({ mode, color, alpha }) { | ||
function formatColor({ mode , color , alpha }) { | ||
let hasAlpha = alpha !== undefined; | ||
if (mode === 'rgba' || mode === 'hsla') { | ||
return `${mode}(${color.join(', ')}${hasAlpha ? `, ${alpha}` : ''})`; | ||
if (mode === "rgba" || mode === "hsla") { | ||
return `${mode}(${color.join(", ")}${hasAlpha ? `, ${alpha}` : ""})`; | ||
} | ||
return `${mode}(${color.join(' ')}${hasAlpha ? ` / ${alpha}` : ''})`; | ||
return `${mode}(${color.join(" ")}${hasAlpha ? ` / ${alpha}` : ""})`; | ||
} |
@@ -24,5 +24,5 @@ "use strict"; | ||
] | ||
], { filterDefault = false, ...options } = {}) { | ||
], { filterDefault =false , ...options } = {}) { | ||
let transformValue = (0, _transformThemeValue.default)(themeKey); | ||
return function({ matchUtilities, theme }) { | ||
return function({ matchUtilities , theme }) { | ||
for (let utilityVariation of utilityVariations){ | ||
@@ -50,3 +50,3 @@ let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [ | ||
...options, | ||
values: filterDefault ? Object.fromEntries(Object.entries((_theme = theme(themeKey)) !== null && _theme !== void 0 ? _theme : {}).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) | ||
}); | ||
@@ -53,0 +53,0 @@ } |
@@ -12,20 +12,17 @@ "use strict"; | ||
_export(exports, { | ||
absoluteSize: function() { | ||
return absoluteSize; | ||
normalize: function() { | ||
return normalize; | ||
}, | ||
color: function() { | ||
return color; | ||
normalizeAttributeSelectors: function() { | ||
return normalizeAttributeSelectors; | ||
}, | ||
familyName: function() { | ||
return familyName; | ||
url: function() { | ||
return url; | ||
}, | ||
genericName: function() { | ||
return genericName; | ||
number: function() { | ||
return number; | ||
}, | ||
gradient: function() { | ||
return gradient; | ||
percentage: function() { | ||
return percentage; | ||
}, | ||
image: function() { | ||
return image; | ||
}, | ||
length: function() { | ||
@@ -37,22 +34,28 @@ return length; | ||
}, | ||
normalize: function() { | ||
return normalize; | ||
shadow: function() { | ||
return shadow; | ||
}, | ||
number: function() { | ||
return number; | ||
color: function() { | ||
return color; | ||
}, | ||
percentage: function() { | ||
return percentage; | ||
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; | ||
}, | ||
shadow: function() { | ||
return shadow; | ||
}, | ||
url: function() { | ||
return url; | ||
} | ||
@@ -64,11 +67,10 @@ }); | ||
let cssFunctions = [ | ||
'min', | ||
'max', | ||
'clamp', | ||
'calc' | ||
"min", | ||
"max", | ||
"clamp", | ||
"calc" | ||
]; | ||
let IS_CSS_FN = new RegExp(`^(${cssFunctions.join('|')})\\(.*\\)`); | ||
// Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types | ||
function isCSSFunction(value) { | ||
return IS_CSS_FN.test(value); | ||
return cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.*\\)`).test(value)); | ||
} | ||
@@ -84,21 +86,27 @@ // These properties accept a `<dashed-ident>` as one of the values. This means that you can use them | ||
// - 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', | ||
"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' | ||
"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) { | ||
if (value.startsWith("--") && !isVarException) { | ||
return `var(${value})`; | ||
} | ||
// Keep raw strings if it starts with `url(` | ||
if (value.includes('url(')) { | ||
if (value.includes("url(")) { | ||
return value.split(/(url\(.*?\))/g).filter(Boolean).map((part)=>{ | ||
@@ -109,6 +117,6 @@ if (/^url\(.*?\)$/.test(part)) { | ||
return normalize(part, context, false); | ||
}).join(''); | ||
}).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 | ||
@@ -121,5 +129,24 @@ if (isRoot) { | ||
} | ||
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 '('. | ||
* like calc() that do not follow an operator, '(', or `,`. | ||
* | ||
@@ -130,26 +157,33 @@ * @param {string} value | ||
let preventFormattingInFunctions = [ | ||
'theme' | ||
"theme" | ||
]; | ||
let preventFormattingKeywords = [ | ||
'min-content', | ||
'max-content', | ||
'fit-content', | ||
"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' | ||
"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", | ||
"anchor-size" | ||
]; | ||
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{ | ||
let result = ''; | ||
let result = ""; | ||
function lastChar() { | ||
@@ -161,3 +195,3 @@ let char = result.trimEnd(); | ||
function peek(word) { | ||
return word.split('').every((char, j)=>match[i + j] === char); | ||
return word.split("").every((char, j)=>match[i + j] === char); | ||
} | ||
@@ -178,3 +212,3 @@ function consumeUntil(chars) { | ||
// Handle `var(--variable)` | ||
if (peek('var')) { | ||
if (peek("var")) { | ||
// When we consume until `)`, then we are dealing with this scenario: | ||
@@ -188,4 +222,4 @@ // `var(--example)` | ||
result += consumeUntil([ | ||
')', | ||
',' | ||
")", | ||
"," | ||
]); | ||
@@ -198,15 +232,20 @@ } else if (preventFormattingKeywords.some((keyword)=>peek(keyword))) { | ||
result += consumeUntil([ | ||
')' | ||
")" | ||
]); | ||
} else if (peek("[")) { | ||
result += consumeUntil([ | ||
"]" | ||
]); | ||
} else if ([ | ||
'+', | ||
'-', | ||
'*', | ||
'/' | ||
"+", | ||
"-", | ||
"*", | ||
"/" | ||
].includes(char) && ![ | ||
'(', | ||
'+', | ||
'-', | ||
'*', | ||
'/' | ||
"(", | ||
"+", | ||
"-", | ||
"*", | ||
"/", | ||
"," | ||
].includes(lastChar())) { | ||
@@ -219,7 +258,7 @@ result += ` ${char} `; | ||
// Simplify multiple spaces | ||
return result.replace(/\s+/g, ' '); | ||
return result.replace(/\s+/g, " "); | ||
}); | ||
} | ||
function url(value) { | ||
return value.startsWith('url('); | ||
return value.startsWith("url("); | ||
} | ||
@@ -230,3 +269,3 @@ function number(value) { | ||
function percentage(value) { | ||
return value.endsWith('%') && number(value.slice(0, -1)) || isCSSFunction(value); | ||
return value.endsWith("%") && number(value.slice(0, -1)) || isCSSFunction(value); | ||
} | ||
@@ -237,43 +276,42 @@ // Please refer to MDN when updating this list: | ||
let lengthUnits = [ | ||
'cm', | ||
'mm', | ||
'Q', | ||
'in', | ||
'pc', | ||
'pt', | ||
'px', | ||
'em', | ||
'ex', | ||
'ch', | ||
'rem', | ||
'lh', | ||
'rlh', | ||
'vw', | ||
'vh', | ||
'vmin', | ||
'vmax', | ||
'vb', | ||
'vi', | ||
'svw', | ||
'svh', | ||
'lvw', | ||
'lvh', | ||
'dvw', | ||
'dvh', | ||
'cqw', | ||
'cqh', | ||
'cqi', | ||
'cqb', | ||
'cqmin', | ||
'cqmax' | ||
"cm", | ||
"mm", | ||
"Q", | ||
"in", | ||
"pc", | ||
"pt", | ||
"px", | ||
"em", | ||
"ex", | ||
"ch", | ||
"rem", | ||
"lh", | ||
"rlh", | ||
"vw", | ||
"vh", | ||
"vmin", | ||
"vmax", | ||
"vb", | ||
"vi", | ||
"svw", | ||
"svh", | ||
"lvw", | ||
"lvh", | ||
"dvw", | ||
"dvh", | ||
"cqw", | ||
"cqh", | ||
"cqi", | ||
"cqb", | ||
"cqmin", | ||
"cqmax" | ||
]; | ||
let lengthUnitsPattern = `(?:${lengthUnits.join('|')})`; | ||
let lengthRegExp = new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`); | ||
let lengthUnitsPattern = `(?:${lengthUnits.join("|")})`; | ||
function length(value) { | ||
return value === '0' || lengthRegExp.test(value) || isCSSFunction(value); | ||
return value === "0" || new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`).test(value) || isCSSFunction(value); | ||
} | ||
let lineWidths = new Set([ | ||
'thin', | ||
'medium', | ||
'thick' | ||
"thin", | ||
"medium", | ||
"thick" | ||
]); | ||
@@ -294,5 +332,5 @@ function lineWidth(value) { | ||
let colors = 0; | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, '_').every((part)=>{ | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, "_").every((part)=>{ | ||
part = normalize(part); | ||
if (part.startsWith('var(')) return true; | ||
if (part.startsWith("var(")) return true; | ||
if ((0, _color.parseColor)(part, { | ||
@@ -308,10 +346,10 @@ loose: true | ||
let images = 0; | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ',').every((part)=>{ | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ",").every((part)=>{ | ||
part = normalize(part); | ||
if (part.startsWith('var(')) return true; | ||
if (part.startsWith("var(")) return true; | ||
if (url(part) || gradient(part) || [ | ||
'element(', | ||
'image(', | ||
'cross-fade(', | ||
'image-set(' | ||
"element(", | ||
"image(", | ||
"cross-fade(", | ||
"image-set(" | ||
].some((fn)=>part.startsWith(fn))) { | ||
@@ -327,8 +365,8 @@ images++; | ||
let gradientTypes = new Set([ | ||
'conic-gradient', | ||
'linear-gradient', | ||
'radial-gradient', | ||
'repeating-conic-gradient', | ||
'repeating-linear-gradient', | ||
'repeating-radial-gradient' | ||
"conic-gradient", | ||
"linear-gradient", | ||
"radial-gradient", | ||
"repeating-conic-gradient", | ||
"repeating-linear-gradient", | ||
"repeating-radial-gradient" | ||
]); | ||
@@ -345,13 +383,13 @@ function gradient(value) { | ||
let validPositions = new Set([ | ||
'center', | ||
'top', | ||
'right', | ||
'bottom', | ||
'left' | ||
"center", | ||
"top", | ||
"right", | ||
"bottom", | ||
"left" | ||
]); | ||
function position(value) { | ||
let positions = 0; | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, '_').every((part)=>{ | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, "_").every((part)=>{ | ||
part = normalize(part); | ||
if (part.startsWith('var(')) return true; | ||
if (part.startsWith("var(")) return true; | ||
if (validPositions.has(part) || length(part) || percentage(part)) { | ||
@@ -368,7 +406,7 @@ positions++; | ||
let fonts = 0; | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ',').every((part)=>{ | ||
let result = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ",").every((part)=>{ | ||
part = normalize(part); | ||
if (part.startsWith('var(')) return true; | ||
if (part.startsWith("var(")) return true; | ||
// If it contains spaces, then it should be quoted | ||
if (part.includes(' ')) { | ||
if (part.includes(" ")) { | ||
if (!/(['"])([^"']+)\1/g.test(part)) { | ||
@@ -389,15 +427,15 @@ return false; | ||
let genericNames = new Set([ | ||
'serif', | ||
'sans-serif', | ||
'monospace', | ||
'cursive', | ||
'fantasy', | ||
'system-ui', | ||
'ui-serif', | ||
'ui-sans-serif', | ||
'ui-monospace', | ||
'ui-rounded', | ||
'math', | ||
'emoji', | ||
'fangsong' | ||
"serif", | ||
"sans-serif", | ||
"monospace", | ||
"cursive", | ||
"fantasy", | ||
"system-ui", | ||
"ui-serif", | ||
"ui-sans-serif", | ||
"ui-monospace", | ||
"ui-rounded", | ||
"math", | ||
"emoji", | ||
"fangsong" | ||
]); | ||
@@ -408,10 +446,10 @@ function genericName(value) { | ||
let absoluteSizes = new Set([ | ||
'xx-small', | ||
'x-small', | ||
'small', | ||
'medium', | ||
'large', | ||
'x-large', | ||
'x-large', | ||
'xxx-large' | ||
"xx-small", | ||
"x-small", | ||
"small", | ||
"medium", | ||
"large", | ||
"x-large", | ||
"xx-large", | ||
"xxx-large" | ||
]); | ||
@@ -422,4 +460,4 @@ function absoluteSize(value) { | ||
let relativeSizes = new Set([ | ||
'larger', | ||
'smaller' | ||
"larger", | ||
"smaller" | ||
]); | ||
@@ -426,0 +464,0 @@ function relativeSize(value) { |
@@ -12,3 +12,3 @@ "use strict"; | ||
function escapeCommas(className) { | ||
return className.replace(/\\,/g, '\\2c '); | ||
return className.replace(/\\,/g, "\\2c "); | ||
} |
@@ -11,4 +11,4 @@ "use strict"; | ||
}); | ||
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 | ||
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 | ||
})) : [ | ||
@@ -15,0 +15,0 @@ { |
@@ -12,2 +12,5 @@ "use strict"; | ||
_export(exports, { | ||
formatVariantSelector: function() { | ||
return formatVariantSelector; | ||
}, | ||
eliminateIrrelevantSelectors: function() { | ||
@@ -19,5 +22,2 @@ return eliminateIrrelevantSelectors; | ||
}, | ||
formatVariantSelector: function() { | ||
return formatVariantSelector; | ||
}, | ||
handleMergePseudo: function() { | ||
@@ -38,6 +38,6 @@ return handleMergePseudo; | ||
} | ||
/** @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 }) { | ||
/** @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 : ''; | ||
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 | ||
@@ -64,3 +64,3 @@ let parsedFormats = formats.map((format)=>{ | ||
// And iteratively merge each format selector into the candidate selector | ||
for (let { ast } of parsedFormats){ | ||
for (let { ast } of parsedFormats){ | ||
[formatAst, ast] = handleMergePseudo(formatAst, ast); | ||
@@ -85,7 +85,7 @@ // 2. Merge the format selector into the current selector AST | ||
// Walk backwards until we hit a combinator node (or the start) | ||
while(node.prev() && node.prev().type !== 'combinator'){ | ||
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'){ | ||
while(node && node.type !== "combinator"){ | ||
nodes.push(node); | ||
@@ -104,9 +104,9 @@ node = node.next(); | ||
sel.sort((a, b)=>{ | ||
if (a.type === 'tag' && b.type === 'class') { | ||
if (a.type === "tag" && b.type === "class") { | ||
return -1; | ||
} else if (a.type === 'class' && b.type === 'tag') { | ||
} else if (a.type === "class" && b.type === "tag") { | ||
return 1; | ||
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) { | ||
} else if (a.type === "class" && b.type === "pseudo" && b.value.startsWith("::")) { | ||
return -1; | ||
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') { | ||
} else if (a.type === "pseudo" && a.value.startsWith("::") && b.type === "class") { | ||
return 1; | ||
@@ -121,3 +121,3 @@ } | ||
sel.walk((child)=>{ | ||
if (child.type === 'class' && child.value === base) { | ||
if (child.type === "class" && child.value === base) { | ||
hasClassesMatchingCandidate = true; | ||
@@ -138,6 +138,6 @@ return false // Stop walking | ||
} | ||
function finalizeSelector(current, formats, { context, candidate, base }) { | ||
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 : ':'; | ||
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: | ||
@@ -171,3 +171,3 @@ // | ||
selector.each((sel)=>eliminateIrrelevantSelectors(sel, base)); | ||
// If after eliminating irrelevant selectors, we end up with nothing | ||
// If ffter eliminating irrelevant selectors, we end up with nothing | ||
// Then the whole "rule" this is associated with does not need to exist | ||
@@ -188,6 +188,6 @@ // We use `null` as a marker value for that case | ||
let simpleStart = _postcssselectorparser.default.comment({ | ||
value: '/*__simple__*/' | ||
value: "/*__simple__*/" | ||
}); | ||
let simpleEnd = _postcssselectorparser.default.comment({ | ||
value: '/*__simple__*/' | ||
value: "/*__simple__*/" | ||
}); | ||
@@ -259,3 +259,3 @@ // We can safely replace the escaped base now, since the `base` section is | ||
let next = pseudo.next(); | ||
while(next && next.type !== 'combinator'){ | ||
while(next && next.type !== "combinator"){ | ||
attachments.push(next); | ||
@@ -273,3 +273,3 @@ next = next.next(); | ||
// :merge(.group):hover & | ||
if (combinator && combinator.type === 'combinator') { | ||
if (combinator && combinator.type === "combinator") { | ||
combinator.remove(); | ||
@@ -276,0 +276,0 @@ } |
@@ -27,5 +27,5 @@ "use strict"; | ||
theme: { | ||
ringColor: ({ theme })=>({ | ||
DEFAULT: '#3b82f67f', | ||
...theme('colors') | ||
ringColor: ({ theme })=>({ | ||
DEFAULT: "#3b82f67f", | ||
...theme("colors") | ||
}) | ||
@@ -32,0 +32,0 @@ } |
@@ -12,3 +12,3 @@ "use strict"; | ||
function isKeyframeRule(rule) { | ||
return rule.parent && rule.parent.type === 'atrule' && /keyframes$/.test(rule.parent.name); | ||
return rule.parent && rule.parent.type === "atrule" && /keyframes$/.test(rule.parent.name); | ||
} |
@@ -12,3 +12,3 @@ "use strict"; | ||
function isPlainObject(value) { | ||
if (Object.prototype.toString.call(value) !== '[object Object]') { | ||
if (Object.prototype.toString.call(value) !== "[object Object]") { | ||
return false; | ||
@@ -15,0 +15,0 @@ } |
@@ -19,12 +19,12 @@ "use strict"; | ||
[ | ||
'{', | ||
'}' | ||
"{", | ||
"}" | ||
], | ||
[ | ||
'[', | ||
']' | ||
"[", | ||
"]" | ||
], | ||
[ | ||
'(', | ||
')' | ||
"(", | ||
")" | ||
] | ||
@@ -39,3 +39,3 @@ ]); | ||
"'", | ||
'`' | ||
"`" | ||
]); | ||
@@ -47,11 +47,11 @@ function isSyntacticallyValidPropertyValue(value) { | ||
let char = value[i]; | ||
if (char === ':' && !inQuotes && stack.length === 0) { | ||
if (char === ":" && !inQuotes && stack.length === 0) { | ||
return false; | ||
} | ||
// Non-escaped quotes allow us to "allow" anything in between | ||
if (quotes.has(char) && value[i - 1] !== '\\') { | ||
if (quotes.has(char) && value[i - 1] !== "\\") { | ||
inQuotes = !inQuotes; | ||
} | ||
if (inQuotes) continue; | ||
if (value[i - 1] === '\\') continue; // Escaped | ||
if (value[i - 1] === "\\") continue; // Escaped | ||
if (matchingBrackets.has(char)) { | ||
@@ -58,0 +58,0 @@ stack.push(char); |
@@ -12,7 +12,7 @@ "use strict"; | ||
_export(exports, { | ||
dim: function() { | ||
return dim; | ||
}, | ||
default: function() { | ||
return _default; | ||
}, | ||
dim: function() { | ||
return dim; | ||
} | ||
@@ -28,7 +28,7 @@ }); | ||
function log(type, messages, key) { | ||
if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) 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)); | ||
console.warn(""); | ||
messages.forEach((message)=>console.warn(type, "-", message)); | ||
} | ||
@@ -39,21 +39,4 @@ function dim(input) { | ||
const _default = { | ||
group (key, cb) { | ||
if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) return; | ||
if (key && alreadyShown.has(key)) return; | ||
if (key) alreadyShown.add(key); | ||
console.warn(''); | ||
cb({ | ||
info (messages) { | ||
messages.forEach((message)=>console.warn(_picocolors.default.bold(_picocolors.default.cyan('info')), '-', message)); | ||
}, | ||
warn (messages) { | ||
messages.forEach((message)=>console.warn(_picocolors.default.bold(_picocolors.default.yellow('warn')), '-', message)); | ||
}, | ||
risk (messages) { | ||
messages.forEach((message)=>console.warn(_picocolors.default.bold(_picocolors.default.magenta('risk')), '-', message)); | ||
} | ||
}); | ||
}, | ||
info (key, messages) { | ||
log(_picocolors.default.bold(_picocolors.default.cyan('info')), ...Array.isArray(key) ? [ | ||
log(_picocolors.default.bold(_picocolors.default.cyan("info")), ...Array.isArray(key) ? [ | ||
key | ||
@@ -66,3 +49,3 @@ ] : [ | ||
warn (key, messages) { | ||
log(_picocolors.default.bold(_picocolors.default.yellow('warn')), ...Array.isArray(key) ? [ | ||
log(_picocolors.default.bold(_picocolors.default.yellow("warn")), ...Array.isArray(key) ? [ | ||
key | ||
@@ -75,3 +58,3 @@ ] : [ | ||
risk (key, messages) { | ||
log(_picocolors.default.bold(_picocolors.default.magenta('risk')), ...Array.isArray(key) ? [ | ||
log(_picocolors.default.bold(_picocolors.default.magenta("risk")), ...Array.isArray(key) ? [ | ||
key | ||
@@ -78,0 +61,0 @@ ] : [ |
@@ -36,12 +36,12 @@ "use strict"; | ||
function formatClass(classPrefix, key) { | ||
if (key === 'DEFAULT') { | ||
if (key === "DEFAULT") { | ||
return classPrefix; | ||
} | ||
if (key === '-' || key === '-DEFAULT') { | ||
if (key === "-" || key === "-DEFAULT") { | ||
return `-${classPrefix}`; | ||
} | ||
if (key.startsWith('-')) { | ||
if (key.startsWith("-")) { | ||
return `-${classPrefix}${key}`; | ||
} | ||
if (key.startsWith('/')) { | ||
if (key.startsWith("/")) { | ||
return `${classPrefix}${key}`; | ||
@@ -48,0 +48,0 @@ } |
@@ -13,8 +13,8 @@ "use strict"; | ||
value = `${value}`; | ||
if (value === '0') { | ||
return '0'; | ||
if (value === "0") { | ||
return "0"; | ||
} | ||
// Flip sign of numbers | ||
if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(value)) { | ||
return value.replace(/^[+-]?/, (sign)=>sign === '-' ? '' : '-'); | ||
return value.replace(/^[+-]?/, (sign)=>sign === "-" ? "" : "-"); | ||
} | ||
@@ -26,7 +26,7 @@ // What functions we support negating numeric values for | ||
let numericFunctions = [ | ||
'var', | ||
'calc', | ||
'min', | ||
'max', | ||
'clamp' | ||
"var", | ||
"calc", | ||
"min", | ||
"max", | ||
"clamp" | ||
]; | ||
@@ -33,0 +33,0 @@ for (const fn of numericFunctions){ |
@@ -34,5 +34,3 @@ "use strict"; | ||
} | ||
var newObj = { | ||
__proto__: null | ||
}; | ||
var newObj = {}; | ||
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; | ||
@@ -71,5 +69,2 @@ for(var key in obj){ | ||
*/ let valid = (()=>{ | ||
if (config.content === 'auto') { | ||
return true; | ||
} | ||
// `config.purge` should not exist anymore | ||
@@ -84,3 +79,3 @@ if (config.purge) { | ||
// `config.content` should be an object or an array | ||
if (!Array.isArray(config.content) && !(typeof config.content === 'object' && config.content !== null)) { | ||
if (!Array.isArray(config.content) && !(typeof config.content === "object" && config.content !== null)) { | ||
return false; | ||
@@ -92,8 +87,8 @@ } | ||
// `path` can be a string | ||
if (typeof path === 'string') return true; | ||
if (typeof path === "string") return true; | ||
// `path` can be an object { raw: string, extension?: string } | ||
// `raw` must be a string | ||
if (typeof (path === null || path === void 0 ? void 0 : path.raw) !== 'string') return false; | ||
if (typeof (path === null || path === void 0 ? void 0 : path.raw) !== "string") return false; | ||
// `extension` (if provided) should also be a string | ||
if ((path === null || path === void 0 ? void 0 : path.extension) && typeof (path === null || path === void 0 ? void 0 : path.extension) !== 'string') { | ||
if ((path === null || path === void 0 ? void 0 : path.extension) && typeof (path === null || path === void 0 ? void 0 : path.extension) !== "string") { | ||
return false; | ||
@@ -105,9 +100,9 @@ } | ||
// When `config.content` is an object | ||
if (typeof config.content === 'object' && config.content !== null) { | ||
if (typeof config.content === "object" && config.content !== null) { | ||
// Only `files`, `relative`, `extract`, and `transform` can exist in `config.content` | ||
if (Object.keys(config.content).some((key)=>![ | ||
'files', | ||
'relative', | ||
'extract', | ||
'transform' | ||
"files", | ||
"relative", | ||
"extract", | ||
"transform" | ||
].includes(key))) { | ||
@@ -120,8 +115,8 @@ return false; | ||
// `path` can be a string | ||
if (typeof path === 'string') return true; | ||
if (typeof path === "string") return true; | ||
// `path` can be an object { raw: string, extension?: string } | ||
// `raw` must be a string | ||
if (typeof (path === null || path === void 0 ? void 0 : path.raw) !== 'string') return false; | ||
if (typeof (path === null || path === void 0 ? void 0 : path.raw) !== "string") return false; | ||
// `extension` (if provided) should also be a string | ||
if ((path === null || path === void 0 ? void 0 : path.extension) && typeof (path === null || path === void 0 ? void 0 : path.extension) !== 'string') { | ||
if ((path === null || path === void 0 ? void 0 : path.extension) && typeof (path === null || path === void 0 ? void 0 : path.extension) !== "string") { | ||
return false; | ||
@@ -134,23 +129,23 @@ } | ||
// `config.content.extract` is optional, and can be a Function or a Record<String, Function> | ||
if (typeof config.content.extract === 'object') { | ||
if (typeof config.content.extract === "object") { | ||
for (let value of Object.values(config.content.extract)){ | ||
if (typeof value !== 'function') { | ||
if (typeof value !== "function") { | ||
return false; | ||
} | ||
} | ||
} else if (!(config.content.extract === undefined || typeof config.content.extract === 'function')) { | ||
} else if (!(config.content.extract === undefined || typeof config.content.extract === "function")) { | ||
return false; | ||
} | ||
// `config.content.transform` is optional, and can be a Function or a Record<String, Function> | ||
if (typeof config.content.transform === 'object') { | ||
if (typeof config.content.transform === "object") { | ||
for (let value of Object.values(config.content.transform)){ | ||
if (typeof value !== 'function') { | ||
if (typeof value !== "function") { | ||
return false; | ||
} | ||
} | ||
} else if (!(config.content.transform === undefined || typeof config.content.transform === 'function')) { | ||
} else if (!(config.content.transform === undefined || typeof config.content.transform === "function")) { | ||
return false; | ||
} | ||
// `config.content.relative` is optional and can be a boolean | ||
if (typeof config.content.relative !== 'boolean' && typeof config.content.relative !== 'undefined') { | ||
if (typeof config.content.relative !== "boolean" && typeof config.content.relative !== "undefined") { | ||
return false; | ||
@@ -164,6 +159,6 @@ } | ||
if (!valid) { | ||
_log.default.warn('purge-deprecation', [ | ||
'The `purge`/`content` options have changed in Tailwind CSS v3.0.', | ||
'Update your configuration file to eliminate this warning.', | ||
'https://tailwindcss.com/docs/upgrade-guide#configure-content-sources' | ||
_log.default.warn("purge-deprecation", [ | ||
"The `purge`/`content` options have changed in Tailwind CSS v3.0.", | ||
"Update your configuration file to eliminate this warning.", | ||
"https://tailwindcss.com/docs/upgrade-guide#configure-content-sources" | ||
]); | ||
@@ -174,3 +169,3 @@ } | ||
var _purge_options; | ||
let { content, purge, safelist } = config; | ||
let { content , purge , safelist } = config; | ||
if (Array.isArray(safelist)) return safelist; | ||
@@ -184,10 +179,10 @@ if (Array.isArray(content === null || content === void 0 ? void 0 : content.safelist)) return content.safelist; | ||
config.blocklist = (()=>{ | ||
let { blocklist } = config; | ||
let { blocklist } = config; | ||
if (Array.isArray(blocklist)) { | ||
if (blocklist.every((item)=>typeof item === 'string')) { | ||
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' | ||
_log.default.warn("blocklist-invalid", [ | ||
"The `blocklist` option must be an array of strings.", | ||
"https://tailwindcss.com/docs/content-configuration#discarding-classes" | ||
]); | ||
@@ -198,12 +193,12 @@ } | ||
// Normalize prefix option | ||
if (typeof config.prefix === 'function') { | ||
_log.default.warn('prefix-function', [ | ||
'As of Tailwind CSS v3.0, `prefix` cannot be a 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' | ||
if (typeof config.prefix === "function") { | ||
_log.default.warn("prefix-function", [ | ||
"As of Tailwind CSS v3.0, `prefix` cannot be a 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" | ||
]); | ||
config.prefix = ''; | ||
config.prefix = ""; | ||
} else { | ||
var _config_prefix; | ||
config.prefix = (_config_prefix = config.prefix) !== null && _config_prefix !== void 0 ? _config_prefix : ''; | ||
config.prefix = (_config_prefix = config.prefix) !== null && _config_prefix !== void 0 ? _config_prefix : ""; | ||
} | ||
@@ -213,22 +208,15 @@ // Normalize the `content` | ||
relative: (()=>{ | ||
let { content } = config; | ||
let { content } = config; | ||
if (content === null || content === void 0 ? void 0 : content.relative) { | ||
return content.relative; | ||
} | ||
return (0, _featureFlags.flagEnabled)(config, 'relativeContentPathsByDefault'); | ||
return (0, _featureFlags.flagEnabled)(config, "relativeContentPathsByDefault"); | ||
})(), | ||
files: (()=>{ | ||
let { content, purge } = config; | ||
if (content === undefined && purge === undefined) return []; | ||
if (purge) { | ||
if (Array.isArray(purge)) return purge; | ||
if (Array.isArray(purge === null || purge === void 0 ? void 0 : purge.content)) return purge.content; | ||
return []; | ||
} | ||
let { content , purge } = config; | ||
if (Array.isArray(purge)) return purge; | ||
if (Array.isArray(purge === null || purge === void 0 ? void 0 : purge.content)) return purge.content; | ||
if (Array.isArray(content)) return content; | ||
if (Array.isArray(content === null || content === void 0 ? void 0 : content.content)) return content.content; | ||
if (Array.isArray(content === null || content === void 0 ? void 0 : content.files)) return content.files; | ||
if (content === 'auto') return [ | ||
'auto' | ||
]; | ||
return []; | ||
@@ -238,3 +226,3 @@ })(), | ||
let extract = (()=>{ | ||
var _config_purge, _config_content, _config_purge_extract, _config_purge1, _config_content_extract, _config_content1, _config_purge_options, _config_purge2, _config_content_options, _config_content2; | ||
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; | ||
@@ -250,3 +238,3 @@ if ((_config_content = config.content) === null || _config_content === void 0 ? void 0 : _config_content.extract) return config.content.extract; | ||
let defaultExtractor = (()=>{ | ||
var _config_purge_options, _config_purge, _config_content_options, _config_content; | ||
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) { | ||
@@ -264,6 +252,6 @@ return config.purge.options.defaultExtractor; | ||
// Functions | ||
if (typeof extract === 'function') { | ||
if (typeof extract === "function") { | ||
extractors.DEFAULT = extract; | ||
} else if (Array.isArray(extract)) { | ||
for (let { extensions, extractor } of extract !== null && extract !== void 0 ? extract : []){ | ||
for (let { extensions , extractor } of extract !== null && extract !== void 0 ? extract : []){ | ||
for (let extension of extensions){ | ||
@@ -273,3 +261,3 @@ extractors[extension] = extractor; | ||
} | ||
} else if (typeof extract === 'object' && extract !== null) { | ||
} else if (typeof extract === "object" && extract !== null) { | ||
Object.assign(extractors, extract); | ||
@@ -281,3 +269,3 @@ } | ||
let transform = (()=>{ | ||
var _config_purge, _config_content, _config_purge_transform, _config_purge1, _config_content_transform, _config_content1; | ||
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; | ||
@@ -290,6 +278,5 @@ if ((_config_content = config.content) === null || _config_content === void 0 ? void 0 : _config_content.transform) return config.content.transform; | ||
let transformers = {}; | ||
if (typeof transform === 'function') { | ||
if (typeof transform === "function") { | ||
transformers.DEFAULT = transform; | ||
} | ||
if (typeof transform === 'object' && transform !== null) { | ||
} else if (typeof transform === "object" && transform !== null) { | ||
Object.assign(transformers, transform); | ||
@@ -300,27 +287,11 @@ } | ||
}; | ||
// Force disable the `oxideParser` feature flag when using unsupported features. | ||
// TODO: Remove once we have prefix or separator support in the oxide parser. | ||
if (config.prefix !== '' || config.separator !== ':') { | ||
if (config.experimental === 'all') { | ||
config.experimental = {}; | ||
for (let key of _featureFlags.featureFlags.experimental){ | ||
config.experimental[key] = true; | ||
} | ||
} else { | ||
var _config_experimental; | ||
config.experimental = (_config_experimental = config.experimental) !== null && _config_experimental !== void 0 ? _config_experimental : {}; | ||
} | ||
config.experimental.oxideParser = false; | ||
} | ||
// Validate globs to prevent bogus globs. | ||
// E.g.: `./src/*.{html}` is invalid, the `{html}` should just be `html` | ||
if (config.content.files !== 'auto') { | ||
for (let file of config.content.files){ | ||
if (typeof file === 'string' && /{([^,]*?)}/g.test(file)) { | ||
_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.` | ||
]); | ||
break; | ||
} | ||
for (let file of config.content.files){ | ||
if (typeof file === "string" && /{([^,]*?)}/g.test(file)) { | ||
_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.` | ||
]); | ||
break; | ||
} | ||
@@ -327,0 +298,0 @@ } |
@@ -36,4 +36,4 @@ /** | ||
_export(exports, { | ||
compareScreens: function() { | ||
return compareScreens; | ||
normalizeScreens: function() { | ||
return normalizeScreens; | ||
}, | ||
@@ -43,4 +43,4 @@ isScreenSortable: function() { | ||
}, | ||
normalizeScreens: function() { | ||
return normalizeScreens; | ||
compareScreens: function() { | ||
return compareScreens; | ||
}, | ||
@@ -55,5 +55,5 @@ toScreen: function() { | ||
if (root && Array.isArray(screen)) { | ||
throw new Error('The tuple syntax is not supported for `screens`.'); | ||
throw new Error("The tuple syntax is not supported for `screens`."); | ||
} | ||
if (typeof screen === 'string') { | ||
if (typeof screen === "string") { | ||
return { | ||
@@ -72,3 +72,3 @@ name: screen.toString(), | ||
name = name.toString(); | ||
if (typeof options === 'string') { | ||
if (typeof options === "string") { | ||
return { | ||
@@ -107,3 +107,3 @@ name, | ||
result: false, | ||
reason: 'multiple-values' | ||
reason: "multiple-values" | ||
}; | ||
@@ -113,3 +113,3 @@ } else if (screen.values[0].raw !== undefined) { | ||
result: false, | ||
reason: 'raw-values' | ||
reason: "raw-values" | ||
}; | ||
@@ -119,3 +119,3 @@ } else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) { | ||
result: false, | ||
reason: 'min-and-max' | ||
reason: "min-and-max" | ||
}; | ||
@@ -134,12 +134,12 @@ } | ||
// 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.'); | ||
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]; | ||
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` | ||
@@ -158,3 +158,3 @@ if (a.not) [aMin, aMax] = [ | ||
zMax = zMax === undefined ? zMax : parseFloat(zMax); | ||
let [aValue, zValue] = type === 'min' ? [ | ||
let [aValue, zValue] = type === "min" ? [ | ||
aMin, | ||
@@ -169,7 +169,7 @@ zMin | ||
function toScreen(value, type) { | ||
if (typeof value === 'object') { | ||
if (typeof value === "object") { | ||
return value; | ||
} | ||
return { | ||
name: 'arbitrary-screen', | ||
name: "arbitrary-screen", | ||
values: [ | ||
@@ -182,3 +182,3 @@ { | ||
} | ||
function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) { | ||
function resolveValue({ "min-width": _minWidth , min =_minWidth , max , raw } = {}) { | ||
return { | ||
@@ -185,0 +185,0 @@ min, |
@@ -12,34 +12,34 @@ "use strict"; | ||
const DIRECTIONS = new Set([ | ||
'normal', | ||
'reverse', | ||
'alternate', | ||
'alternate-reverse' | ||
"normal", | ||
"reverse", | ||
"alternate", | ||
"alternate-reverse" | ||
]); | ||
const PLAY_STATES = new Set([ | ||
'running', | ||
'paused' | ||
"running", | ||
"paused" | ||
]); | ||
const FILL_MODES = new Set([ | ||
'none', | ||
'forwards', | ||
'backwards', | ||
'both' | ||
"none", | ||
"forwards", | ||
"backwards", | ||
"both" | ||
]); | ||
const ITERATION_COUNTS = new Set([ | ||
'infinite' | ||
"infinite" | ||
]); | ||
const TIMINGS = new Set([ | ||
'linear', | ||
'ease', | ||
'ease-in', | ||
'ease-out', | ||
'ease-in-out', | ||
'step-start', | ||
'step-end' | ||
"linear", | ||
"ease", | ||
"ease-in", | ||
"ease-out", | ||
"ease-in-out", | ||
"step-start", | ||
"step-end" | ||
]); | ||
const TIMING_FNS = [ | ||
'cubic-bezier', | ||
'steps' | ||
"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 COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubic-bezier(a, b, c)` these don't count. | ||
; | ||
@@ -60,29 +60,29 @@ const SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead. | ||
for (let part of parts){ | ||
if (!seen.has('DIRECTIONS') && DIRECTIONS.has(part)) { | ||
if (!seen.has("DIRECTIONS") && DIRECTIONS.has(part)) { | ||
result.direction = part; | ||
seen.add('DIRECTIONS'); | ||
} else if (!seen.has('PLAY_STATES') && PLAY_STATES.has(part)) { | ||
seen.add("DIRECTIONS"); | ||
} else if (!seen.has("PLAY_STATES") && PLAY_STATES.has(part)) { | ||
result.playState = part; | ||
seen.add('PLAY_STATES'); | ||
} else if (!seen.has('FILL_MODES') && FILL_MODES.has(part)) { | ||
seen.add("PLAY_STATES"); | ||
} else if (!seen.has("FILL_MODES") && FILL_MODES.has(part)) { | ||
result.fillMode = part; | ||
seen.add('FILL_MODES'); | ||
} else if (!seen.has('ITERATION_COUNTS') && (ITERATION_COUNTS.has(part) || DIGIT.test(part))) { | ||
seen.add("FILL_MODES"); | ||
} else if (!seen.has("ITERATION_COUNTS") && (ITERATION_COUNTS.has(part) || DIGIT.test(part))) { | ||
result.iterationCount = part; | ||
seen.add('ITERATION_COUNTS'); | ||
} else if (!seen.has('TIMING_FUNCTION') && TIMINGS.has(part)) { | ||
seen.add("ITERATION_COUNTS"); | ||
} else if (!seen.has("TIMING_FUNCTION") && TIMINGS.has(part)) { | ||
result.timingFunction = part; | ||
seen.add('TIMING_FUNCTION'); | ||
} else if (!seen.has('TIMING_FUNCTION') && TIMING_FNS.some((f)=>part.startsWith(`${f}(`))) { | ||
seen.add("TIMING_FUNCTION"); | ||
} else if (!seen.has("TIMING_FUNCTION") && TIMING_FNS.some((f)=>part.startsWith(`${f}(`))) { | ||
result.timingFunction = part; | ||
seen.add('TIMING_FUNCTION'); | ||
} else if (!seen.has('DURATION') && TIME.test(part)) { | ||
seen.add("TIMING_FUNCTION"); | ||
} else if (!seen.has("DURATION") && TIME.test(part)) { | ||
result.duration = part; | ||
seen.add('DURATION'); | ||
} else if (!seen.has('DELAY') && TIME.test(part)) { | ||
seen.add("DURATION"); | ||
} else if (!seen.has("DELAY") && TIME.test(part)) { | ||
result.delay = part; | ||
seen.add('DELAY'); | ||
} else if (!seen.has('NAME')) { | ||
seen.add("DELAY"); | ||
} else if (!seen.has("NAME")) { | ||
result.name = part; | ||
seen.add('NAME'); | ||
seen.add("NAME"); | ||
} else { | ||
@@ -89,0 +89,0 @@ if (!result.unknown) result.unknown = []; |
@@ -12,7 +12,7 @@ "use strict"; | ||
_export(exports, { | ||
parseBoxShadowValue: function() { | ||
return parseBoxShadowValue; | ||
}, | ||
formatBoxShadowValue: function() { | ||
return formatBoxShadowValue; | ||
}, | ||
parseBoxShadowValue: function() { | ||
return parseBoxShadowValue; | ||
} | ||
@@ -22,7 +22,7 @@ }); | ||
let KEYWORDS = new Set([ | ||
'inset', | ||
'inherit', | ||
'initial', | ||
'revert', | ||
'unset' | ||
"inset", | ||
"inherit", | ||
"initial", | ||
"revert", | ||
"unset" | ||
]); | ||
@@ -33,3 +33,3 @@ let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead. | ||
function parseBoxShadowValue(input) { | ||
let shadows = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(input, ','); | ||
let shadows = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(input, ","); | ||
return shadows.map((shadow)=>{ | ||
@@ -46,18 +46,18 @@ let value = shadow.trim(); | ||
// Keyword | ||
if (!seen.has('KEYWORD') && KEYWORDS.has(part)) { | ||
if (!seen.has("KEYWORD") && KEYWORDS.has(part)) { | ||
result.keyword = part; | ||
seen.add('KEYWORD'); | ||
seen.add("KEYWORD"); | ||
} else if (LENGTH.test(part)) { | ||
if (!seen.has('X')) { | ||
if (!seen.has("X")) { | ||
result.x = part; | ||
seen.add('X'); | ||
} else if (!seen.has('Y')) { | ||
seen.add("X"); | ||
} else if (!seen.has("Y")) { | ||
result.y = part; | ||
seen.add('Y'); | ||
} else if (!seen.has('BLUR')) { | ||
seen.add("Y"); | ||
} else if (!seen.has("BLUR")) { | ||
result.blur = part; | ||
seen.add('BLUR'); | ||
} else if (!seen.has('SPREAD')) { | ||
seen.add("BLUR"); | ||
} else if (!seen.has("SPREAD")) { | ||
result.spread = part; | ||
seen.add('SPREAD'); | ||
seen.add("SPREAD"); | ||
} | ||
@@ -90,4 +90,4 @@ } else { | ||
shadow.color | ||
].filter(Boolean).join(' '); | ||
}).join(', '); | ||
].filter(Boolean).join(" "); | ||
}).join(", "); | ||
} |
@@ -25,3 +25,3 @@ // @ts-check | ||
{ | ||
type: 'dependency', | ||
type: "dependency", | ||
file: contentPath.base | ||
@@ -31,3 +31,3 @@ } | ||
} | ||
if (process.env.ROLLUP_WATCH === 'true') { | ||
if (process.env.ROLLUP_WATCH === "true") { | ||
// rollup-plugin-postcss does not support dir-dependency messages | ||
@@ -37,3 +37,3 @@ // but directories can be watched in the same way as files | ||
{ | ||
type: 'dependency', | ||
type: "dependency", | ||
file: contentPath.base | ||
@@ -45,3 +45,3 @@ } | ||
{ | ||
type: 'dir-dependency', | ||
type: "dir-dependency", | ||
dir: contentPath.base, | ||
@@ -48,0 +48,0 @@ glob: contentPath.glob |
@@ -20,12 +20,11 @@ "use strict"; | ||
let base = (0, _globparent.default)(pattern); | ||
if (base !== '.') { | ||
if (base !== ".") { | ||
glob = pattern.substr(base.length); | ||
if (glob.charAt(0) === '/') { | ||
if (glob.charAt(0) === "/") { | ||
glob = glob.substr(1); | ||
} | ||
} | ||
if (glob.substr(0, 2) === './') { | ||
if (glob.substr(0, 2) === "./") { | ||
glob = glob.substr(2); | ||
} | ||
if (glob.charAt(0) === '/') { | ||
} else if (glob.charAt(0) === "/") { | ||
glob = glob.substr(1); | ||
@@ -32,0 +31,0 @@ } |
@@ -29,3 +29,3 @@ "use strict"; | ||
bubble: [ | ||
'screen' | ||
"screen" | ||
] | ||
@@ -32,0 +32,0 @@ }) |
@@ -12,2 +12,11 @@ "use strict"; | ||
_export(exports, { | ||
updateAllClasses: function() { | ||
return updateAllClasses; | ||
}, | ||
asValue: function() { | ||
return asValue; | ||
}, | ||
parseColorFormat: function() { | ||
return parseColorFormat; | ||
}, | ||
asColor: function() { | ||
@@ -19,4 +28,4 @@ return asColor; | ||
}, | ||
asValue: function() { | ||
return asValue; | ||
typeMap: function() { | ||
return typeMap; | ||
}, | ||
@@ -28,11 +37,2 @@ coerceValue: function() { | ||
return getMatchingTypes; | ||
}, | ||
parseColorFormat: function() { | ||
return parseColorFormat; | ||
}, | ||
typeMap: function() { | ||
return typeMap; | ||
}, | ||
updateAllClasses: function() { | ||
return updateAllClasses; | ||
} | ||
@@ -45,2 +45,3 @@ }); | ||
const _validateFormalSyntax = require("./validateFormalSyntax"); | ||
const _featureFlags = require("../featureFlags.js"); | ||
function _interop_require_default(obj) { | ||
@@ -82,3 +83,3 @@ return obj && obj.__esModule ? obj : { | ||
} | ||
function asValue(modifier, options = {}, { validate = ()=>true } = {}) { | ||
function asValue(modifier, options = {}, { validate =()=>true } = {}) { | ||
var _options_values; | ||
@@ -89,3 +90,3 @@ let value = (_options_values = options.values) === null || _options_values === void 0 ? void 0 : _options_values[modifier]; | ||
} | ||
if (options.supportsNegativeValues && modifier.startsWith('-')) { | ||
if (options.supportsNegativeValues && modifier.startsWith("-")) { | ||
return asNegativeValue(modifier.slice(1), options.values, validate); | ||
@@ -96,6 +97,19 @@ } | ||
function isArbitraryValue(input) { | ||
return input.startsWith('[') && input.endsWith(']'); | ||
return input.startsWith("[") && input.endsWith("]"); | ||
} | ||
function splitUtilityModifier(modifier) { | ||
let slashIdx = modifier.lastIndexOf('/'); | ||
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) { | ||
@@ -111,3 +125,3 @@ return [ | ||
// without affecting `[foo/bar]` | ||
if (arbitrary && !modifier.includes(']/[')) { | ||
if (arbitrary && !modifier.includes("]/[")) { | ||
return [ | ||
@@ -124,5 +138,5 @@ modifier, | ||
function parseColorFormat(value) { | ||
if (typeof value === 'string' && value.includes('<alpha-value>')) { | ||
if (typeof value === "string" && value.includes("<alpha-value>")) { | ||
let oldValue = value; | ||
return ({ opacityValue = 1 })=>oldValue.replace('<alpha-value>', opacityValue); | ||
return ({ opacityValue =1 })=>oldValue.replace(/<alpha-value>/g, opacityValue); | ||
} | ||
@@ -134,3 +148,3 @@ return value; | ||
} | ||
function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) { | ||
function asColor(modifier, options = {}, { tailwindConfig ={} } = {}) { | ||
var _options_values; | ||
@@ -145,3 +159,3 @@ if (((_options_values = options.values) === null || _options_values === void 0 ? void 0 : _options_values[modifier]) !== undefined) { | ||
if (alpha !== undefined) { | ||
var _options_values2, _tailwindConfig_theme_opacity, _tailwindConfig_theme; | ||
var _options_values2, _tailwindConfig_theme, _tailwindConfig_theme_opacity; | ||
var _options_values_color; | ||
@@ -185,8 +199,8 @@ 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; | ||
lookup: asLookupValue, | ||
'generic-name': guess(_dataTypes.genericName), | ||
'family-name': guess(_dataTypes.familyName), | ||
"generic-name": guess(_dataTypes.genericName), | ||
"family-name": guess(_dataTypes.familyName), | ||
number: guess(_dataTypes.number), | ||
'line-width': guess(_dataTypes.lineWidth), | ||
'absolute-size': guess(_dataTypes.absoluteSize), | ||
'relative-size': guess(_dataTypes.relativeSize), | ||
"line-width": guess(_dataTypes.lineWidth), | ||
"absolute-size": guess(_dataTypes.absoluteSize), | ||
"relative-size": guess(_dataTypes.relativeSize), | ||
shadow: guess(_dataTypes.shadow), | ||
@@ -209,3 +223,3 @@ size: guess(_validateFormalSyntax.backgroundSize) | ||
if (options.values && modifier in options.values) { | ||
for (let { type } of types !== null && types !== void 0 ? types : []){ | ||
for (let { type } of types !== null && types !== void 0 ? types : []){ | ||
let result = typeMap[type](modifier, options, { | ||
@@ -226,3 +240,3 @@ tailwindConfig | ||
let arbitraryValue = modifier.slice(1, -1); | ||
let [explicitType, value] = splitAtFirst(arbitraryValue, ':'); | ||
let [explicitType, value] = splitAtFirst(arbitraryValue, ":"); | ||
// It could be that this resolves to `url(https` which is not a valid | ||
@@ -252,4 +266,5 @@ // identifier. We currently only support "simple" words with dashes or | ||
function* getMatchingTypes(types, rawModifier, options, tailwindConfig) { | ||
let modifiersEnabled = (0, _featureFlags.flagEnabled)(tailwindConfig, "generalizedModifiers"); | ||
let [modifier, utilityModifier] = splitUtilityModifier(rawModifier); | ||
let canUseUtilityModifier = options.modifiers != null && (options.modifiers === 'any' || typeof options.modifiers === 'object' && (utilityModifier && isArbitraryValue(utilityModifier) || utilityModifier in options.modifiers)); | ||
let canUseUtilityModifier = modifiersEnabled && options.modifiers != null && (options.modifiers === "any" || typeof options.modifiers === "object" && (utilityModifier && isArbitraryValue(utilityModifier) || utilityModifier in options.modifiers)); | ||
if (!canUseUtilityModifier) { | ||
@@ -259,4 +274,4 @@ modifier = rawModifier; | ||
} | ||
if (utilityModifier !== undefined && modifier === '') { | ||
modifier = 'DEFAULT'; | ||
if (utilityModifier !== undefined && modifier === "") { | ||
modifier = "DEFAULT"; | ||
} | ||
@@ -266,3 +281,3 @@ // Check the full value first | ||
if (utilityModifier !== undefined) { | ||
if (typeof options.modifiers === 'object') { | ||
if (typeof options.modifiers === "object") { | ||
var _options_modifiers; | ||
@@ -278,3 +293,3 @@ var _options_modifiers_utilityModifier; | ||
} | ||
for (let { type } of types !== null && types !== void 0 ? types : []){ | ||
for (let { type } of types !== null && types !== void 0 ? types : []){ | ||
let result = typeMap[type](modifier, options, { | ||
@@ -281,0 +296,0 @@ tailwindConfig |
@@ -29,12 +29,12 @@ "use strict"; | ||
function _default(prefix, selector, prependNegative = false) { | ||
if (prefix === '') { | ||
if (prefix === "") { | ||
return selector; | ||
} | ||
/** @type {import('postcss-selector-parser').Root} */ let ast = typeof selector === 'string' ? (0, _postcssselectorparser.default)().astSync(selector) : 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('-'); | ||
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith("-"); | ||
classSelector.value = shouldPlaceNegativeBeforePrefix ? `-${prefix}${baseClass.slice(1)}` : `${prefix}${baseClass}`; | ||
}); | ||
return typeof selector === 'string' ? ast.toString() : ast; | ||
return typeof selector === "string" ? ast.toString() : ast; | ||
} |
@@ -27,71 +27,71 @@ /** @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 */ // There are some pseudo-elements that may or may not be: | ||
// Pseudo elements from the spec | ||
'::after': [ | ||
'terminal', | ||
'jumpable' | ||
"::after": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::backdrop': [ | ||
'terminal', | ||
'jumpable' | ||
"::backdrop": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::before': [ | ||
'terminal', | ||
'jumpable' | ||
"::before": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::cue': [ | ||
'terminal' | ||
"::cue": [ | ||
"terminal" | ||
], | ||
'::cue-region': [ | ||
'terminal' | ||
"::cue-region": [ | ||
"terminal" | ||
], | ||
'::first-letter': [ | ||
'terminal', | ||
'jumpable' | ||
"::first-letter": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::first-line': [ | ||
'terminal', | ||
'jumpable' | ||
"::first-line": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::grammar-error': [ | ||
'terminal' | ||
"::grammar-error": [ | ||
"terminal" | ||
], | ||
'::marker': [ | ||
'terminal', | ||
'jumpable' | ||
"::marker": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::part': [ | ||
'terminal', | ||
'actionable' | ||
"::part": [ | ||
"terminal", | ||
"actionable" | ||
], | ||
'::placeholder': [ | ||
'terminal', | ||
'jumpable' | ||
"::placeholder": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::selection': [ | ||
'terminal', | ||
'jumpable' | ||
"::selection": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
'::slotted': [ | ||
'terminal' | ||
"::slotted": [ | ||
"terminal" | ||
], | ||
'::spelling-error': [ | ||
'terminal' | ||
"::spelling-error": [ | ||
"terminal" | ||
], | ||
'::target-text': [ | ||
'terminal' | ||
"::target-text": [ | ||
"terminal" | ||
], | ||
// Pseudo elements from the spec with special rules | ||
'::file-selector-button': [ | ||
'terminal', | ||
'actionable' | ||
"::file-selector-button": [ | ||
"terminal", | ||
"actionable" | ||
], | ||
// Library-specific pseudo elements used by component libraries | ||
// These are Shadow DOM-like | ||
'::deep': [ | ||
'actionable' | ||
"::deep": [ | ||
"actionable" | ||
], | ||
'::v-deep': [ | ||
'actionable' | ||
"::v-deep": [ | ||
"actionable" | ||
], | ||
'::ng-deep': [ | ||
'actionable' | ||
"::ng-deep": [ | ||
"actionable" | ||
], | ||
@@ -102,18 +102,21 @@ // Note: As a rule, double colons (::) should be used instead of a single colon | ||
// browsers support both syntaxes for the original pseudo-elements. | ||
':after': [ | ||
'terminal', | ||
'jumpable' | ||
":after": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
':before': [ | ||
'terminal', | ||
'jumpable' | ||
":before": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
':first-letter': [ | ||
'terminal', | ||
'jumpable' | ||
":first-letter": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
':first-line': [ | ||
'terminal', | ||
'jumpable' | ||
":first-line": [ | ||
"terminal", | ||
"jumpable" | ||
], | ||
":where": [], | ||
":is": [], | ||
":has": [], | ||
// The default value is used when the pseudo-element is not recognized | ||
@@ -123,4 +126,4 @@ // Because it's not recognized, we don't know if it's terminal or not | ||
__default__: [ | ||
'terminal', | ||
'actionable' | ||
"terminal", | ||
"actionable" | ||
] | ||
@@ -152,6 +155,6 @@ }; | ||
for (let node of sel.nodes){ | ||
if (node.type === 'combinator') { | ||
buffer = buffer.filter(([, node])=>propertiesForPseudo(node).includes('jumpable')); | ||
if (node.type === "combinator") { | ||
buffer = buffer.filter(([, node])=>propertiesForPseudo(node).includes("jumpable")); | ||
lastSeenElement = null; | ||
} else if (node.type === 'pseudo') { | ||
} else if (node.type === "pseudo") { | ||
if (isMovablePseudoElement(node)) { | ||
@@ -190,3 +193,3 @@ lastSeenElement = node; | ||
*/ function isPseudoElement(node) { | ||
return node.value.startsWith('::') || elementProperties[node.value] !== undefined; | ||
return node.value.startsWith("::") || elementProperties[node.value] !== undefined; | ||
} | ||
@@ -197,3 +200,3 @@ /** | ||
*/ function isMovablePseudoElement(node) { | ||
return isPseudoElement(node) && propertiesForPseudo(node).includes('terminal'); | ||
return isPseudoElement(node) && propertiesForPseudo(node).includes("terminal"); | ||
} | ||
@@ -205,5 +208,5 @@ /** | ||
*/ function isAttachablePseudoClass(node, pseudo) { | ||
if (node.type !== 'pseudo') return false; | ||
if (node.type !== "pseudo") return false; | ||
if (isPseudoElement(node)) return false; | ||
return propertiesForPseudo(pseudo).includes('actionable'); | ||
return propertiesForPseudo(pseudo).includes("actionable"); | ||
} | ||
@@ -210,0 +213,0 @@ /** |
@@ -27,3 +27,5 @@ /** | ||
if (decl.value.includes(`/ var(${varName})`)) { | ||
decl.value = decl.value.replace(`/ var(${varName})`, ''); | ||
decl.value = decl.value.replace(`/ var(${varName})`, ""); | ||
} else if (decl.value.includes(`/ var(${varName}, 1)`)) { | ||
decl.value = decl.value.replace(`/ var(${varName}, 1)`, ""); | ||
} | ||
@@ -30,0 +32,0 @@ } |
@@ -29,3 +29,3 @@ "use strict"; | ||
function isFunction(input) { | ||
return typeof input === 'function'; | ||
return typeof input === "function"; | ||
} | ||
@@ -54,3 +54,3 @@ function mergeWith(target, ...sources) { | ||
// TODO: Log that this function isn't really needed anymore? | ||
return Object.keys(scale).filter((key)=>scale[key] !== '0').reduce((negativeScale, key)=>{ | ||
return Object.keys(scale).filter((key)=>scale[key] !== "0").reduce((negativeScale, key)=>{ | ||
let negativeValue = (0, _negateValue.default)(scale[key]); | ||
@@ -64,3 +64,3 @@ if (negativeValue !== undefined) { | ||
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, | ||
@@ -75,3 +75,3 @@ [`screen-${key}`]: screens[key] | ||
function collectExtends(items) { | ||
return items.reduce((merged, { extend })=>{ | ||
return items.reduce((merged, { extend })=>{ | ||
return mergeWith(merged, extend, (mergedValue, extendValue)=>{ | ||
@@ -123,3 +123,3 @@ if (mergedValue === undefined) { | ||
} | ||
function mergeExtensions({ extend, ...theme }) { | ||
function mergeExtensions({ extend , ...theme }) { | ||
return mergeWith(theme, extend, (themeValue, extensions)=>{ | ||
@@ -191,25 +191,15 @@ // The `extend` property is an array, so we need to check if it contains any functions | ||
} | ||
function resolvePlugins(configs) { | ||
let pluginGroups = []; | ||
function extractPluginConfigs(configs) { | ||
let allConfigs = []; | ||
for (let config of configs){ | ||
allConfigs.push(config); | ||
let plugins = []; | ||
configs.forEach((config)=>{ | ||
allConfigs = [ | ||
...allConfigs, | ||
config | ||
]; | ||
var _config_plugins; | ||
for (let plugin of (_config_plugins = config === null || config === void 0 ? void 0 : config.plugins) !== null && _config_plugins !== void 0 ? _config_plugins : []){ | ||
// TODO: If we want to support ESM plugins then a handful of things will have to become async | ||
if (typeof plugin === 'string') { | ||
// If the plugin is specified as a string then it's just the package name | ||
plugin = require(plugin); | ||
var _plugin_default; | ||
plugin = (_plugin_default = plugin.default) !== null && _plugin_default !== void 0 ? _plugin_default : plugin; | ||
} else if (Array.isArray(plugin)) { | ||
// If the plugin is specified as an array then it's a package name and optional options object | ||
// [name] or [name, options] | ||
let [pkg, options = undefined] = plugin; | ||
plugin = require(pkg); | ||
var _plugin_default1; | ||
plugin = (_plugin_default1 = plugin.default) !== null && _plugin_default1 !== void 0 ? _plugin_default1 : plugin; | ||
plugin = plugin(options); | ||
} | ||
const plugins = (_config_plugins = config === null || config === void 0 ? void 0 : config.plugins) !== null && _config_plugins !== void 0 ? _config_plugins : []; | ||
if (plugins.length === 0) { | ||
return; | ||
} | ||
plugins.forEach((plugin)=>{ | ||
if (plugin.__isOptionsFunction) { | ||
@@ -219,20 +209,11 @@ plugin = plugin(); | ||
var _plugin_config; | ||
// We're explicitly skipping registering child plugins | ||
// This will change in v4 | ||
let [, childConfigs] = resolvePlugins([ | ||
(_plugin_config = plugin === null || plugin === void 0 ? void 0 : plugin.config) !== null && _plugin_config !== void 0 ? _plugin_config : {} | ||
]); | ||
plugins.push(plugin); | ||
allConfigs.push(...childConfigs); | ||
} | ||
pluginGroups.push(plugins); | ||
} | ||
// Reverse the order of the plugin groups | ||
// This matches the old `reduceRight` behavior of the old `resolvePluginLists` | ||
// Why? No idea. | ||
let plugins = pluginGroups.reverse().flat(); | ||
return [ | ||
plugins, | ||
allConfigs | ||
]; | ||
allConfigs = [ | ||
...allConfigs, | ||
...extractPluginConfigs([ | ||
(_plugin_config = plugin === null || plugin === void 0 ? void 0 : plugin.config) !== null && _plugin_config !== void 0 ? _plugin_config : {} | ||
]) | ||
]; | ||
}); | ||
}); | ||
return allConfigs; | ||
} | ||
@@ -252,20 +233,32 @@ function resolveCorePlugins(corePluginConfigs) { | ||
} | ||
function resolvePluginLists(pluginLists) { | ||
const result = [ | ||
...pluginLists | ||
].reduceRight((resolved, pluginList)=>{ | ||
return [ | ||
...resolved, | ||
...pluginList | ||
]; | ||
}, []); | ||
return result; | ||
} | ||
function resolveConfig(configs) { | ||
let [plugins, pluginConfigs] = resolvePlugins(configs); | ||
let allConfigs = [ | ||
...pluginConfigs, | ||
...extractPluginConfigs(configs), | ||
{ | ||
prefix: '', | ||
prefix: "", | ||
important: false, | ||
separator: ':' | ||
separator: ":" | ||
} | ||
]; | ||
var _t_theme, _c_plugins; | ||
return (0, _normalizeConfig.normalizeConfig)((0, _defaults.defaults)({ | ||
theme: resolveFunctionKeys(mergeExtensions(mergeThemes(allConfigs.map((t)=>{ | ||
var _t_theme; | ||
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 | ||
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)); | ||
} |
@@ -27,9 +27,11 @@ "use strict"; | ||
const defaultConfigFiles = [ | ||
'./tailwind.config.js', | ||
'./tailwind.config.cjs', | ||
'./tailwind.config.mjs', | ||
'./tailwind.config.ts' | ||
"./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; | ||
return typeof value === "object" && value !== null; | ||
} | ||
@@ -40,3 +42,3 @@ function isEmpty(obj) { | ||
function isString(value) { | ||
return typeof value === 'string' || value instanceof String; | ||
return typeof value === "string" || value instanceof String; | ||
} | ||
@@ -43,0 +45,0 @@ function resolveConfigPath(pathOrConfig) { |
@@ -20,3 +20,3 @@ "use strict"; | ||
return _postcss.default.atRule({ | ||
name: 'responsive' | ||
name: "responsive" | ||
}).append((0, _cloneNodes.default)(Array.isArray(rules) ? rules : [ | ||
@@ -23,0 +23,0 @@ rules |
@@ -38,10 +38,6 @@ /** | ||
} | ||
if (isEscaped) { | ||
isEscaped = false; | ||
} else if (char === '\\') { | ||
isEscaped = true; | ||
} | ||
if (char === '(' || char === '[' || char === '{') { | ||
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] === '{') { | ||
} else if (char === ")" && stack[stack.length - 1] === "(" || char === "]" && stack[stack.length - 1] === "[" || char === "}" && stack[stack.length - 1] === "{") { | ||
stack.pop(); | ||
@@ -48,0 +44,0 @@ } |
@@ -12,3 +12,3 @@ "use strict"; | ||
function toColorValue(maybeFunction) { | ||
return typeof maybeFunction === 'function' ? maybeFunction({}) : maybeFunction; | ||
return typeof maybeFunction === "function" ? maybeFunction({}) : maybeFunction; | ||
} |
@@ -26,4 +26,4 @@ /** | ||
if (Array.isArray(path)) return path; | ||
let openBrackets = path.split('[').length - 1; | ||
let closedBrackets = path.split(']').length - 1; | ||
let openBrackets = path.split("[").length - 1; | ||
let closedBrackets = path.split("]").length - 1; | ||
if (openBrackets !== closedBrackets) { | ||
@@ -30,0 +30,0 @@ throw new Error(`Path is invalid. Has unbalanced brackets: ${path}`); |
@@ -20,7 +20,7 @@ "use strict"; | ||
if ([ | ||
'fontSize', | ||
'outline' | ||
"fontSize", | ||
"outline" | ||
].includes(themeSection)) { | ||
return (value)=>{ | ||
if (typeof value === 'function') value = value({}); | ||
if (typeof value === "function") value = value({}); | ||
if (Array.isArray(value)) value = value[0]; | ||
@@ -30,24 +30,24 @@ return value; | ||
} | ||
if (themeSection === 'fontFamily') { | ||
if (themeSection === "fontFamily") { | ||
return (value)=>{ | ||
if (typeof value === 'function') value = 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; | ||
return Array.isArray(families) ? families.join(", ") : families; | ||
}; | ||
} | ||
if ([ | ||
'boxShadow', | ||
'transitionProperty', | ||
'transitionDuration', | ||
'transitionDelay', | ||
'transitionTimingFunction', | ||
'backgroundImage', | ||
'backgroundSize', | ||
'backgroundColor', | ||
'cursor', | ||
'animation' | ||
"boxShadow", | ||
"transitionProperty", | ||
"transitionDuration", | ||
"transitionDelay", | ||
"transitionTimingFunction", | ||
"backgroundImage", | ||
"backgroundSize", | ||
"backgroundColor", | ||
"cursor", | ||
"animation" | ||
].includes(themeSection)) { | ||
return (value)=>{ | ||
if (typeof value === 'function') value = value({}); | ||
if (Array.isArray(value)) value = value.join(', '); | ||
if (typeof value === "function") value = value({}); | ||
if (Array.isArray(value)) value = value.join(", "); | ||
return value; | ||
@@ -59,9 +59,9 @@ }; | ||
if ([ | ||
'gridTemplateColumns', | ||
'gridTemplateRows', | ||
'objectPosition' | ||
"gridTemplateColumns", | ||
"gridTemplateRows", | ||
"objectPosition" | ||
].includes(themeSection)) { | ||
return (value)=>{ | ||
if (typeof value === 'function') value = value({}); | ||
if (typeof value === 'string') value = _postcss.default.list.comma(value).join(' '); | ||
if (typeof value === "function") value = value({}); | ||
if (typeof value === "string") value = _postcss.default.list.comma(value).join(" "); | ||
return value; | ||
@@ -71,3 +71,3 @@ }; | ||
return (value, opts = {})=>{ | ||
if (typeof value === 'function') { | ||
if (typeof value === "function") { | ||
value = value(opts); | ||
@@ -74,0 +74,0 @@ } |
@@ -11,3 +11,2 @@ "use strict"; | ||
}); | ||
const _picocolors = /*#__PURE__*/ _interop_require_default(require("picocolors")); | ||
const _log = /*#__PURE__*/ _interop_require_default(require("./log")); | ||
@@ -21,30 +20,20 @@ function _interop_require_default(obj) { | ||
if (config.content.files.length === 0) { | ||
_log.default.warn('content-problems', [ | ||
'The `content` option in your Tailwind CSS configuration is missing or empty.', | ||
'Configure your content sources or your generated CSS will be missing styles.', | ||
'https://tailwindcss.com/docs/content-configuration' | ||
_log.default.warn("content-problems", [ | ||
"The `content` option in your Tailwind CSS configuration is missing or empty.", | ||
"Configure your content sources or your generated CSS will be missing styles.", | ||
"https://tailwindcss.com/docs/content-configuration" | ||
]); | ||
} | ||
if (config.content.files.includes('auto')) { | ||
_log.default.group('auto-content-experimental', (log)=>{ | ||
log.info([ | ||
_picocolors.default.bold('Automatically detecting Tailwind CSS content sources...') | ||
]); | ||
log.warn([ | ||
'Automatic content detection is experimental, and the behavior may change at any time.' | ||
]); | ||
}); | ||
} | ||
// Warn if the line-clamp plugin is installed | ||
try { | ||
let plugin = require('@tailwindcss/line-clamp'); | ||
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.' | ||
_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 (e) {} | ||
} catch {} | ||
return config; | ||
} |
@@ -15,13 +15,13 @@ "use strict"; | ||
let keywordValues = [ | ||
'cover', | ||
'contain' | ||
"cover", | ||
"contain" | ||
]; | ||
// the <length-percentage> type will probably be a css function | ||
// so we have to use `splitAtTopLevelOnly` | ||
return (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ',').every((part)=>{ | ||
let sizes = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(part, '_').filter(Boolean); | ||
return (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(value, ",").every((part)=>{ | ||
let sizes = (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(part, "_").filter(Boolean); | ||
if (sizes.length === 1 && keywordValues.includes(sizes[0])) return true; | ||
if (sizes.length !== 1 && sizes.length !== 2) return false; | ||
return sizes.every((size)=>(0, _dataTypes.length)(size) || (0, _dataTypes.percentage)(size) || size === 'auto'); | ||
return sizes.every((size)=>(0, _dataTypes.length)(size) || (0, _dataTypes.percentage)(size) || size === "auto"); | ||
}); | ||
} |
@@ -12,7 +12,7 @@ "use strict"; | ||
_export(exports, { | ||
withAlphaValue: function() { | ||
return withAlphaValue; | ||
}, | ||
default: function() { | ||
return withAlphaVariable; | ||
}, | ||
withAlphaValue: function() { | ||
return withAlphaValue; | ||
} | ||
@@ -22,3 +22,3 @@ }); | ||
function withAlphaValue(color, alphaValue, defaultValue) { | ||
if (typeof color === 'function') { | ||
if (typeof color === "function") { | ||
return color({ | ||
@@ -39,7 +39,7 @@ opacityValue: alphaValue | ||
} | ||
function withAlphaVariable({ color, property, variable }) { | ||
function withAlphaVariable({ color , property , variable }) { | ||
let properties = [].concat(property); | ||
if (typeof color === 'function') { | ||
if (typeof color === "function") { | ||
return { | ||
[variable]: '1', | ||
[variable]: "1", | ||
...Object.fromEntries(properties.map((p)=>{ | ||
@@ -50,3 +50,3 @@ return [ | ||
opacityVariable: variable, | ||
opacityValue: `var(${variable})` | ||
opacityValue: `var(${variable}, 1)` | ||
}) | ||
@@ -72,3 +72,3 @@ ]; | ||
return { | ||
[variable]: '1', | ||
[variable]: "1", | ||
...Object.fromEntries(properties.map((p)=>{ | ||
@@ -79,3 +79,3 @@ return [ | ||
...parsed, | ||
alpha: `var(${variable})` | ||
alpha: `var(${variable}, 1)` | ||
}) | ||
@@ -82,0 +82,0 @@ ]; |
"use strict"; | ||
var parse = require('./parse'); | ||
var walk = require('./walk'); | ||
var stringify = require('./stringify'); | ||
var parse = require("./parse"); | ||
var walk = require("./walk"); | ||
var stringify = require("./stringify"); | ||
function ValueParser(value) { | ||
@@ -13,3 +13,3 @@ if (this instanceof ValueParser) { | ||
ValueParser.prototype.toString = function() { | ||
return Array.isArray(this.nodes) ? stringify(this.nodes) : ''; | ||
return Array.isArray(this.nodes) ? stringify(this.nodes) : ""; | ||
}; | ||
@@ -20,5 +20,5 @@ ValueParser.prototype.walk = function(cb, bubble) { | ||
}; | ||
ValueParser.unit = require('./unit'); | ||
ValueParser.unit = require("./unit"); | ||
ValueParser.walk = walk; | ||
ValueParser.stringify = stringify; | ||
module.exports = ValueParser; |
"use strict"; | ||
var openParentheses = '('.charCodeAt(0); | ||
var closeParentheses = ')'.charCodeAt(0); | ||
var openParentheses = "(".charCodeAt(0); | ||
var closeParentheses = ")".charCodeAt(0); | ||
var singleQuote = "'".charCodeAt(0); | ||
var doubleQuote = '"'.charCodeAt(0); | ||
var backslash = '\\'.charCodeAt(0); | ||
var slash = '/'.charCodeAt(0); | ||
var comma = ','.charCodeAt(0); | ||
var colon = ':'.charCodeAt(0); | ||
var star = '*'.charCodeAt(0); | ||
var uLower = 'u'.charCodeAt(0); | ||
var uUpper = 'U'.charCodeAt(0); | ||
var plus = '+'.charCodeAt(0); | ||
var backslash = "\\".charCodeAt(0); | ||
var slash = "/".charCodeAt(0); | ||
var comma = ",".charCodeAt(0); | ||
var colon = ":".charCodeAt(0); | ||
var star = "*".charCodeAt(0); | ||
var uLower = "u".charCodeAt(0); | ||
var uUpper = "U".charCodeAt(0); | ||
var plus = "+".charCodeAt(0); | ||
var isUnicodeRange = /^[a-f0-9?-]+$/i; | ||
@@ -29,5 +29,5 @@ module.exports = function(input) { | ||
var parent; | ||
var name = ''; | ||
var before = ''; | ||
var after = ''; | ||
var name = ""; | ||
var before = ""; | ||
var after = ""; | ||
while(pos < max){ | ||
@@ -40,3 +40,3 @@ // Whitespaces | ||
code = value.charCodeAt(next); | ||
}while (code <= 32) | ||
}while (code <= 32); | ||
token = value.slice(pos, next); | ||
@@ -46,10 +46,10 @@ prev = tokens[tokens.length - 1]; | ||
after = token; | ||
} else if (prev && prev.type === 'div') { | ||
} else if (prev && prev.type === "div") { | ||
prev.after = token; | ||
prev.sourceEndIndex += token.length; | ||
} else if (code === comma || code === colon || code === slash && value.charCodeAt(next + 1) !== star && (!parent || parent && parent.type === 'function' && false)) { | ||
} else if (code === comma || code === colon || code === slash && value.charCodeAt(next + 1) !== star && (!parent || parent && parent.type === "function" && false)) { | ||
before = token; | ||
} else { | ||
tokens.push({ | ||
type: 'space', | ||
type: "space", | ||
sourceIndex: pos, | ||
@@ -66,3 +66,3 @@ sourceEndIndex: next, | ||
token = { | ||
type: 'string', | ||
type: "string", | ||
sourceIndex: pos, | ||
@@ -85,3 +85,3 @@ quote: quote | ||
} | ||
}while (escape) | ||
}while (escape); | ||
token.value = value.slice(pos + 1, next); | ||
@@ -94,5 +94,5 @@ token.sourceEndIndex = token.unclosed ? next : next + 1; | ||
} else if (code === slash && value.charCodeAt(pos + 1) === star) { | ||
next = value.indexOf('*/', pos); | ||
next = value.indexOf("*/", pos); | ||
token = { | ||
type: 'comment', | ||
type: "comment", | ||
sourceIndex: pos, | ||
@@ -111,6 +111,6 @@ sourceEndIndex: next + 2 | ||
// Operation within calc | ||
} else if ((code === slash || code === star) && parent && parent.type === 'function' && true) { | ||
} else if ((code === slash || code === star) && parent && parent.type === "function" && true) { | ||
token = value[pos]; | ||
tokens.push({ | ||
type: 'word', | ||
type: "word", | ||
sourceIndex: pos - before.length, | ||
@@ -126,3 +126,3 @@ sourceEndIndex: pos + token.length, | ||
tokens.push({ | ||
type: 'div', | ||
type: "div", | ||
sourceIndex: pos - before.length, | ||
@@ -132,5 +132,5 @@ sourceEndIndex: pos + token.length, | ||
before: before, | ||
after: '' | ||
after: "" | ||
}); | ||
before = ''; | ||
before = ""; | ||
pos += 1; | ||
@@ -145,6 +145,6 @@ code = value.charCodeAt(pos); | ||
code = value.charCodeAt(next); | ||
}while (code <= 32) | ||
}while (code <= 32); | ||
parenthesesOpenPos = pos; | ||
token = { | ||
type: 'function', | ||
type: "function", | ||
sourceIndex: pos - name.length, | ||
@@ -155,7 +155,7 @@ value: name, | ||
pos = next; | ||
if (name === 'url' && code !== singleQuote && code !== doubleQuote) { | ||
if (name === "url" && code !== singleQuote && code !== doubleQuote) { | ||
next -= 1; | ||
do { | ||
escape = false; | ||
next = value.indexOf(')', next + 1); | ||
next = value.indexOf(")", next + 1); | ||
if (~next) { | ||
@@ -168,7 +168,7 @@ escapePos = next; | ||
} else { | ||
value += ')'; | ||
value += ")"; | ||
next = value.length - 1; | ||
token.unclosed = true; | ||
} | ||
}while (escape) | ||
}while (escape); | ||
// Whitespaces before closed | ||
@@ -179,3 +179,3 @@ whitespacePos = next; | ||
code = value.charCodeAt(whitespacePos); | ||
}while (code <= 32) | ||
}while (code <= 32); | ||
if (parenthesesOpenPos < whitespacePos) { | ||
@@ -185,3 +185,3 @@ if (pos !== whitespacePos + 1) { | ||
{ | ||
type: 'word', | ||
type: "word", | ||
sourceIndex: pos, | ||
@@ -196,5 +196,5 @@ sourceEndIndex: whitespacePos + 1, | ||
if (token.unclosed && whitespacePos + 1 !== next) { | ||
token.after = ''; | ||
token.after = ""; | ||
token.nodes.push({ | ||
type: 'space', | ||
type: "space", | ||
sourceIndex: whitespacePos + 1, | ||
@@ -209,3 +209,3 @@ sourceEndIndex: next, | ||
} else { | ||
token.after = ''; | ||
token.after = ""; | ||
token.nodes = []; | ||
@@ -219,3 +219,3 @@ } | ||
balanced += 1; | ||
token.after = ''; | ||
token.after = ""; | ||
token.sourceEndIndex = pos + 1; | ||
@@ -227,3 +227,3 @@ tokens.push(token); | ||
} | ||
name = ''; | ||
name = ""; | ||
// Close parentheses | ||
@@ -235,3 +235,3 @@ } else if (closeParentheses === code && balanced) { | ||
parent.sourceEndIndex += after.length; | ||
after = ''; | ||
after = ""; | ||
balanced -= 1; | ||
@@ -251,3 +251,3 @@ stack[stack.length - 1].sourceEndIndex = pos; | ||
code = value.charCodeAt(next); | ||
}while (next < max && !(code <= 32 || code === singleQuote || code === doubleQuote || code === comma || code === colon || code === slash || code === openParentheses || code === star && parent && parent.type === 'function' && true || code === slash && parent.type === 'function' && true || code === closeParentheses && balanced)) | ||
}while (next < max && !(code <= 32 || code === singleQuote || code === doubleQuote || code === comma || code === colon || code === slash || code === openParentheses || code === star && parent && parent.type === "function" && true || code === slash && parent.type === "function" && true || code === closeParentheses && balanced)); | ||
token = value.slice(pos, next); | ||
@@ -258,3 +258,3 @@ if (openParentheses === code) { | ||
tokens.push({ | ||
type: 'unicode-range', | ||
type: "unicode-range", | ||
sourceIndex: pos, | ||
@@ -266,3 +266,3 @@ sourceEndIndex: next, | ||
tokens.push({ | ||
type: 'word', | ||
type: "word", | ||
sourceIndex: pos, | ||
@@ -269,0 +269,0 @@ sourceEndIndex: next, |
@@ -9,17 +9,17 @@ "use strict"; | ||
return customResult; | ||
} else if (type === 'word' || type === 'space') { | ||
} else if (type === "word" || type === "space") { | ||
return value; | ||
} else if (type === 'string') { | ||
buf = node.quote || ''; | ||
return buf + value + (node.unclosed ? '' : buf); | ||
} else if (type === 'comment') { | ||
return '/*' + value + (node.unclosed ? '' : '*/'); | ||
} else if (type === 'div') { | ||
return (node.before || '') + value + (node.after || ''); | ||
} else if (type === "string") { | ||
buf = node.quote || ""; | ||
return buf + value + (node.unclosed ? "" : buf); | ||
} else if (type === "comment") { | ||
return "/*" + value + (node.unclosed ? "" : "*/"); | ||
} else if (type === "div") { | ||
return (node.before || "") + value + (node.after || ""); | ||
} else if (Array.isArray(node.nodes)) { | ||
buf = stringify(node.nodes, custom); | ||
if (type !== 'function') { | ||
if (type !== "function") { | ||
return buf; | ||
} | ||
return value + '(' + (node.before || '') + buf + (node.after || '') + (node.unclosed ? '' : ')'); | ||
return value + "(" + (node.before || "") + buf + (node.after || "") + (node.unclosed ? "" : ")"); | ||
} | ||
@@ -31,3 +31,3 @@ return value; | ||
if (Array.isArray(nodes)) { | ||
result = ''; | ||
result = ""; | ||
for(i = nodes.length - 1; ~i; i -= 1){ | ||
@@ -34,0 +34,0 @@ result = stringifyNode(nodes[i], custom) + result; |
"use strict"; | ||
var minus = '-'.charCodeAt(0); | ||
var plus = '+'.charCodeAt(0); | ||
var dot = '.'.charCodeAt(0); | ||
var exp = 'e'.charCodeAt(0); | ||
var EXP = 'E'.charCodeAt(0); | ||
var minus = "-".charCodeAt(0); | ||
var plus = "+".charCodeAt(0); | ||
var dot = ".".charCodeAt(0); | ||
var exp = "e".charCodeAt(0); | ||
var EXP = "E".charCodeAt(0); | ||
// Check if three code points would start a number | ||
@@ -8,0 +8,0 @@ // https://www.w3.org/TR/css-syntax-3/#starts-with-a-number |
@@ -9,3 +9,3 @@ "use strict"; | ||
} | ||
if (result !== false && node.type === 'function' && Array.isArray(node.nodes)) { | ||
if (result !== false && node.type === "function" && Array.isArray(node.nodes)) { | ||
walk(node.nodes, cb, bubble); | ||
@@ -12,0 +12,0 @@ } |
{ | ||
"name": "tailwindcss", | ||
"version": "0.0.0-insiders.8f788e2", | ||
"version": "0.0.0-insiders.8f91c27", | ||
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", | ||
@@ -15,19 +15,18 @@ "license": "MIT", | ||
}, | ||
"workspaces": [ | ||
"integrations/*", | ||
"oxide/crates/node" | ||
], | ||
"scripts": { | ||
"dev": "concurrently -n tailwind,oxide-node -c green,yellow 'npm run dev:js' 'npm run dev:rust'", | ||
"build": "npm run build:rust && npm run build:js", | ||
"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 .", | ||
"pretest": "npm run generate", | ||
"test": "jest", | ||
"test:integrations": "npm run test -w ./integrations", | ||
"style": "eslint .", | ||
"prepublishOnly": "npm install --force && npm run build && npm run generate:types", | ||
"dev:rust": "npm run --prefix ./oxide dev:node", | ||
"dev:js": "npm run build:js -- --watch", | ||
"build:rust": "npm run --prefix ./oxide build:node", | ||
"build:js": "npm run generate:plugin-list && swc src --out-dir lib --copy-files --delete-dir-on-start", | ||
"test:integrations": "npm run test --prefix ./integrations", | ||
"install:integrations": "node scripts/install-integrations.js", | ||
"generate:plugin-list": "node -r @swc/register scripts/create-plugin-list.js", | ||
"generate:types": "node -r @swc/register scripts/generate-types.js" | ||
"generate:types": "node -r @swc/register scripts/generate-types.js", | ||
"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" | ||
}, | ||
@@ -38,2 +37,3 @@ "files": [ | ||
"lib/*", | ||
"peers/*", | ||
"scripts/*.js", | ||
@@ -48,52 +48,54 @@ "stubs/*", | ||
"devDependencies": { | ||
"@swc/cli": "^0.1.62", | ||
"@swc/core": "^1.3.92", | ||
"@swc/jest": "^0.2.29", | ||
"@swc/register": "^0.1.10", | ||
"concurrently": "^8.0.1", | ||
"eslint": "^8.51.0", | ||
"eslint-config-prettier": "^9.0.0", | ||
"@swc/cli": "0.1.62", | ||
"@swc/core": "1.3.55", | ||
"@swc/jest": "0.2.26", | ||
"@swc/register": "0.1.10", | ||
"autoprefixer": "^10.4.20", | ||
"browserslist": "^4.24.0", | ||
"concurrently": "^8.2.2", | ||
"cssnano": "^6.1.2", | ||
"esbuild": "^0.24.0", | ||
"eslint": "^8.57.1", | ||
"eslint-config-prettier": "^8.10.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"jest": "^29.7.0", | ||
"jest-diff": "^29.7.0", | ||
"lightningcss": "1.27.0", | ||
"prettier": "^2.8.8", | ||
"rimraf": "^5.0.0", | ||
"source-map-js": "^1.0.2", | ||
"turbo": "^1.10.15" | ||
"rimraf": "^5.0.10", | ||
"source-map-js": "^1.2.1", | ||
"turbo": "^1.13.4" | ||
}, | ||
"dependencies": { | ||
"@alloc/quick-lru": "^5.2.0", | ||
"@tailwindcss/oxide": "0.0.0-insiders.8f788e2", | ||
"arg": "^5.0.2", | ||
"browserslist": "^4.22.1", | ||
"chokidar": "^3.5.3", | ||
"chokidar": "^3.6.0", | ||
"didyoumean": "^1.2.2", | ||
"dlv": "^1.1.3", | ||
"fast-glob": "^3.3.1", | ||
"fast-glob": "^3.3.2", | ||
"glob-parent": "^6.0.2", | ||
"is-glob": "^4.0.3", | ||
"jiti": "^1.20.0", | ||
"lightningcss": "^1.22.0", | ||
"lilconfig": "^2.1.0", | ||
"micromatch": "^4.0.5", | ||
"jiti": "^1.21.6", | ||
"lilconfig": "^3.1.3", | ||
"micromatch": "^4.0.8", | ||
"normalize-path": "^3.0.0", | ||
"object-hash": "^3.0.0", | ||
"picocolors": "^1.0.0", | ||
"postcss": "^8.4.31", | ||
"picocolors": "^1.1.1", | ||
"postcss": "^8.4.47", | ||
"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.12", | ||
"postcss-value-parser": "^4.2.0", | ||
"postcss-load-config": "^4.0.2", | ||
"postcss-nested": "^6.2.0", | ||
"postcss-selector-parser": "^6.1.2", | ||
"resolve": "^1.22.8", | ||
"sucrase": "^3.34.0" | ||
"sucrase": "^3.35.0" | ||
}, | ||
"browserslist": [ | ||
"defaults and supports css-variables and supports css-matches-pseudo", | ||
"safari >= 14" | ||
"> 1%", | ||
"not edge <= 18", | ||
"not ie 11", | ||
"not op_mini all" | ||
], | ||
"jest": { | ||
"testTimeout": 30000, | ||
"globalSetup": "<rootDir>/jest/global-setup.js", | ||
"setupFilesAfterEnv": [ | ||
@@ -108,2 +110,5 @@ "<rootDir>/jest/customMatchers.js" | ||
], | ||
"transformIgnorePatterns": [ | ||
"node_modules/(?!lightningcss)" | ||
], | ||
"transform": { | ||
@@ -115,4 +120,4 @@ "\\.js$": "@swc/jest", | ||
"engines": { | ||
"node": ">=16.0.0" | ||
"node": ">=14.0.0" | ||
} | ||
} |
@@ -15,11 +15,10 @@ <p align="center"> | ||
<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://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/actions/workflow/status/tailwindlabs/tailwindcss/ci.yml?branch=main" 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> | ||
<a href="https://github.com/tailwindcss/tailwindcss/releases"><img src="https://img.shields.io/npm/v/tailwindcss.svg" alt="Latest Release"></a> | ||
<a href="https://github.com/tailwindcss/tailwindcss/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/tailwindcss.svg" alt="License"></a> | ||
<a href="https://github.com/tailwindcss/tailwindcss/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/tailwindcss.svg" alt="License"></a> | ||
</p> | ||
------ | ||
--- | ||
@@ -42,2 +41,2 @@ ## Documentation | ||
If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md) **before submitting a pull request**. | ||
If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md) **before submitting a pull request**. |
// Given a version, figure out what the release notes are so that we can use this to pre-fill the | ||
// release notes on a GitHub release for the current version. | ||
// relase notes on a GitHub release for the current version. | ||
@@ -4,0 +4,0 @@ let path = require('path') |
@@ -28,6 +28,2 @@ // @ts-check | ||
if (args['--no-autoprefixer']) { | ||
console.error('[deprecation] The --no-autoprefixer flag is deprecated and has no effect.') | ||
} | ||
// TODO: Reference the @config path here if exists | ||
@@ -34,0 +30,0 @@ let configPath = args['--config'] ? args['--config'] : resolveDefaultConfigPath() |
// @ts-check | ||
import pkg from '../../../package.json' | ||
import path from 'path' | ||
import fs from 'fs' | ||
import postcss from 'postcss' | ||
import postcssrc from 'postcss-load-config' | ||
import browserslist from 'browserslist' | ||
import lightning, { Features } from 'lightningcss' | ||
import { lilconfig } from 'lilconfig' | ||
@@ -15,6 +11,7 @@ import loadPlugins from 'postcss-load-config/src/plugins' // Little bit scary, looking at private/internal API | ||
import tailwind from '../../processTailwindFeatures' | ||
import { loadAutoprefixer, loadCssNano, loadPostcss, loadPostcssImport } from './deps' | ||
import { formatNodes, drainStdin, outputFile } from './utils' | ||
import { env } from '../../lib/sharedState' | ||
import resolveConfig from '../../../resolveConfig.js' | ||
import { parseCandidateFiles } from '../../lib/content.js' | ||
import { createBroadPatternCheck, parseCandidateFiles } from '../../lib/content.js' | ||
import { createWatcher } from './watching.js' | ||
@@ -26,47 +23,3 @@ import fastGlob from 'fast-glob' | ||
import getModuleDependencies from '../../lib/getModuleDependencies' | ||
import { validateConfig } from '../../util/validateConfig' | ||
import { handleImportAtRules } from '../../lib/handleImportAtRules' | ||
import { flagEnabled } from '../../featureFlags' | ||
function license() { | ||
return `/* ! tailwindcss v${pkg.version} | MIT License | https://tailwindcss.com */\n` | ||
} | ||
async function lightningcss(result, { map = true, minify = true } = {}) { | ||
try { | ||
let resolvedBrowsersListConfig = browserslist.findConfig( | ||
result.opts.from ?? process.cwd() | ||
)?.defaults | ||
let defaultBrowsersListConfig = pkg.browserslist | ||
let browsersListConfig = resolvedBrowsersListConfig ?? defaultBrowsersListConfig | ||
let transformed = lightning.transform({ | ||
filename: result.opts.from || 'input.css', | ||
code: Buffer.from(result.css, 'utf-8'), | ||
minify, | ||
sourceMap: result.map === undefined ? map : !!result.map, | ||
inputSourceMap: result.map ? result.map.toString() : undefined, | ||
targets: lightning.browserslistToTargets(browserslist(browsersListConfig)), | ||
include: Features.Nesting, | ||
exclude: Features.LogicalProperties, | ||
}) | ||
return Object.assign(result, { | ||
css: transformed.code.toString(), | ||
map: result.map | ||
? Object.assign(result.map, { | ||
toString() { | ||
return transformed.map?.toString() | ||
}, | ||
}) | ||
: result.map, | ||
}) | ||
} catch (err) { | ||
console.error('Unable to use Lightning CSS. Using raw version instead.') | ||
console.error(err) | ||
return result | ||
} | ||
} | ||
/** | ||
@@ -127,2 +80,35 @@ * | ||
function loadBuiltinPostcssPlugins() { | ||
let postcss = loadPostcss() | ||
let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: ' | ||
return [ | ||
[ | ||
(root) => { | ||
root.walkAtRules('import', (rule) => { | ||
if (rule.params.slice(1).startsWith('tailwindcss/')) { | ||
rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params })) | ||
rule.remove() | ||
} | ||
}) | ||
}, | ||
loadPostcssImport(), | ||
(root) => { | ||
root.walkComments((rule) => { | ||
if (rule.text.startsWith(IMPORT_COMMENT)) { | ||
rule.after( | ||
postcss.atRule({ | ||
name: 'import', | ||
params: rule.text.replace(IMPORT_COMMENT, ''), | ||
}) | ||
) | ||
rule.remove() | ||
} | ||
}) | ||
}, | ||
], | ||
[], | ||
{}, | ||
] | ||
} | ||
let state = { | ||
@@ -138,3 +124,3 @@ /** @type {any} */ | ||
/** @type {{config: import('../../../types').Config, dependencies: Set<string>, dispose: Function } | null} */ | ||
/** @type {ReturnType<typeof load> | null} */ | ||
configBag: null, | ||
@@ -181,3 +167,4 @@ | ||
this.configBag.config = validateConfig(resolveConfig(this.configBag.config)) | ||
// @ts-ignore | ||
this.configBag.config = resolveConfig(this.configBag.config, { content: { files: [] } }) | ||
@@ -205,14 +192,11 @@ // Override content files if `--content` has been passed explicitly | ||
let checkBroadPattern = createBroadPatternCheck(this.contentPatterns.all) | ||
for (let file of files) { | ||
if (flagEnabled(this.config, 'oxideParser')) { | ||
content.push({ | ||
file, | ||
extension: path.extname(file).slice(1), | ||
}) | ||
} else { | ||
content.push({ | ||
content: fs.readFileSync(path.resolve(file), 'utf8'), | ||
extension: path.extname(file).slice(1), | ||
}) | ||
} | ||
checkBroadPattern(file) | ||
content.push({ | ||
content: fs.readFileSync(path.resolve(file), 'utf8'), | ||
extension: path.extname(file).slice(1), | ||
}) | ||
} | ||
@@ -233,2 +217,6 @@ | ||
getContext({ createContext, cliConfigPath, root, result, content }) { | ||
env.DEBUG && console.time('Searching for config') | ||
let configPath = findAtConfigPath(root, result) ?? cliConfigPath | ||
env.DEBUG && console.timeEnd('Searching for config') | ||
if (this.context) { | ||
@@ -240,6 +228,2 @@ this.context.changedContent = this.changedContent.splice(0) | ||
env.DEBUG && console.time('Searching for config') | ||
let configPath = findAtConfigPath(root, result) ?? cliConfigPath | ||
env.DEBUG && console.timeEnd('Searching for config') | ||
env.DEBUG && console.time('Loading config') | ||
@@ -275,2 +259,4 @@ let config = this.loadConfig(configPath, content) | ||
export async function createProcessor(args, cliConfigPath) { | ||
let postcss = loadPostcss() | ||
let input = args['--input'] | ||
@@ -283,6 +269,4 @@ let output = args['--output'] | ||
? await loadPostCssPlugins(customPostCssPath) | ||
: [[], [], {}] | ||
: loadBuiltinPostcssPlugins() | ||
beforePlugins.unshift(...handleImportAtRules()) | ||
if (args['--purge']) { | ||
@@ -332,2 +316,4 @@ log.warn('purge-flag-deprecated', [ | ||
...afterPlugins, | ||
!args['--no-autoprefixer'] && loadAutoprefixer(), | ||
args['--minify'] && loadCssNano(), | ||
].filter(Boolean) | ||
@@ -350,3 +336,3 @@ | ||
// No input file provided, fallback to default atrules | ||
// No input file provided, fallback to default at-rules | ||
return '@tailwind base; @tailwind components; @tailwind utilities' | ||
@@ -357,16 +343,5 @@ } | ||
let start = process.hrtime.bigint() | ||
let options = { | ||
...postcssOptions, | ||
from: input, | ||
to: output, | ||
} | ||
return readInput() | ||
.then((css) => processor.process(css, options)) | ||
.then((result) => | ||
lightningcss(result, { | ||
...options, | ||
minify: !!args['--minify'], | ||
}) | ||
) | ||
.then((css) => processor.process(css, { ...postcssOptions, from: input, to: output })) | ||
.then((result) => { | ||
@@ -394,3 +369,3 @@ if (!state.watcher) { | ||
if (!output) { | ||
process.stdout.write(license() + result.css) | ||
process.stdout.write(result.css) | ||
return | ||
@@ -400,3 +375,3 @@ } | ||
return Promise.all([ | ||
outputFile(result.opts.to, license() + result.css), | ||
outputFile(result.opts.to, result.css), | ||
result.map && outputFile(result.opts.to + '.map', result.map.toString()), | ||
@@ -403,0 +378,0 @@ ]) |
@@ -73,3 +73,2 @@ #!/usr/bin/env node | ||
'--no-autoprefixer': { | ||
deprecated: true, | ||
type: Boolean, | ||
@@ -76,0 +75,0 @@ description: 'Disable autoprefixer', |
@@ -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","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","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,9 +6,8 @@ import colors from 'picocolors' | ||
optimizeUniversalDefaults: false, | ||
generalizedModifiers: true, | ||
disableColorOpacityUtilitiesByDefault: false, | ||
relativeContentPathsByDefault: false, | ||
oxideParser: true, | ||
logicalSiblingUtilities: false, | ||
} | ||
export let featureFlags = { | ||
let featureFlags = { | ||
future: [ | ||
@@ -19,5 +18,4 @@ 'hoverOnlyWhenSupported', | ||
'relativeContentPathsByDefault', | ||
'logicalSiblingUtilities', | ||
], | ||
experimental: ['optimizeUniversalDefaults', 'oxideParser'], | ||
experimental: ['optimizeUniversalDefaults', 'generalizedModifiers'], | ||
} | ||
@@ -24,0 +22,0 @@ |
@@ -10,3 +10,4 @@ // @ts-check | ||
import { env } from './sharedState' | ||
import { resolveContentPaths } from '@tailwindcss/oxide' | ||
import log from '../util/log' | ||
import micromatch from 'micromatch' | ||
@@ -16,31 +17,2 @@ /** @typedef {import('../../types/config.js').RawFile} RawFile */ | ||
/* | ||
* @param {import('tailwindcss').Config} tailwindConfig | ||
* @param {{skip:string[]}} options | ||
* @returns {ContentPath[]} | ||
*/ | ||
function resolveContentFiles(tailwindConfig, { skip = [] } = {}) { | ||
if ( | ||
Array.isArray(tailwindConfig.content.files) && | ||
tailwindConfig.content.files.includes('auto') | ||
) { | ||
let idx = tailwindConfig.content.files.indexOf('auto') | ||
if (idx !== -1) { | ||
env.DEBUG && console.time('Calculating resolve content paths') | ||
let resolved = resolveContentPaths({ base: process.cwd() }) | ||
env.DEBUG && console.timeEnd('Calculating resolve content paths') | ||
tailwindConfig.content.files.splice(idx, 1, ...resolved) | ||
} | ||
} | ||
if (skip.length > 0) { | ||
tailwindConfig.content.files = tailwindConfig.content.files.filter( | ||
(filePath) => !skip.includes(filePath) | ||
) | ||
} | ||
return tailwindConfig.content.files | ||
} | ||
/** | ||
@@ -67,5 +39,3 @@ * @typedef {object} ContentPath | ||
export function parseCandidateFiles(context, tailwindConfig) { | ||
let files = resolveContentFiles(tailwindConfig, { | ||
skip: [context.userConfigPath], | ||
}) | ||
let files = tailwindConfig.content.files | ||
@@ -219,3 +189,84 @@ // Normalize the file globs | ||
const LARGE_DIRECTORIES = [ | ||
'node_modules', // Node | ||
] | ||
// Ensures that `node_modules` has to match as-is, otherwise `mynode_modules` | ||
// would match as well, but that is not a known large directory. | ||
const LARGE_DIRECTORIES_REGEX = new RegExp( | ||
`(${LARGE_DIRECTORIES.map((dir) => String.raw`\b${dir}\b`).join('|')})` | ||
) | ||
/** | ||
* @param {string[]} paths | ||
*/ | ||
export function createBroadPatternCheck(paths) { | ||
// Detect whether a glob pattern might be too broad. This means that it: | ||
// - Includes `**` | ||
// - Does not include any of the known large directories (e.g.: node_modules) | ||
let maybeBroadPattern = paths.some( | ||
(path) => path.includes('**') && !LARGE_DIRECTORIES_REGEX.test(path) | ||
) | ||
// Didn't detect any potentially broad patterns, so we can skip further | ||
// checks. | ||
if (!maybeBroadPattern) { | ||
return () => {} | ||
} | ||
// All glob matchers | ||
let matchers = [] | ||
// All glob matchers that explicitly contain any of the known large | ||
// directories (e.g.: node_modules). | ||
let explicitMatchers = [] | ||
// Create matchers for all paths | ||
for (let path of paths) { | ||
let matcher = micromatch.matcher(path) | ||
if (LARGE_DIRECTORIES_REGEX.test(path)) { | ||
explicitMatchers.push(matcher) | ||
} | ||
matchers.push(matcher) | ||
} | ||
// Keep track of whether we already warned about the broad pattern issue or | ||
// not. The `log.warn` function already does something similar where we only | ||
// output the log once. However, with this we can also skip the other checks | ||
// when we already warned about the broad pattern. | ||
let warned = false | ||
/** | ||
* @param {string} file | ||
*/ | ||
return (file) => { | ||
if (warned) return // Already warned about the broad pattern | ||
if (explicitMatchers.some((matcher) => matcher(file))) return // Explicitly included, so we can skip further checks | ||
// When a broad pattern is used, we have to double check that the file was | ||
// not explicitly included in the globs. | ||
let matchingGlobIndex = matchers.findIndex((matcher) => matcher(file)) | ||
if (matchingGlobIndex === -1) return // This should never happen | ||
let matchingGlob = paths[matchingGlobIndex] | ||
// Create relative paths to make the output a bit more readable. | ||
let relativeMatchingGlob = path.relative(process.cwd(), matchingGlob) | ||
if (relativeMatchingGlob[0] !== '.') relativeMatchingGlob = `./${relativeMatchingGlob}` | ||
let largeDirectory = LARGE_DIRECTORIES.find((directory) => file.includes(directory)) | ||
if (largeDirectory) { | ||
warned = true | ||
log.warn('broad-content-glob-pattern', [ | ||
`Your \`content\` configuration includes a pattern which looks like it's accidentally matching all of \`${largeDirectory}\` and can cause serious performance issues.`, | ||
`Pattern: \`${relativeMatchingGlob}\``, | ||
`See our documentation for recommendations:`, | ||
'https://tailwindcss.com/docs/content-configuration#pattern-recommendations', | ||
]) | ||
} | ||
} | ||
} | ||
/** | ||
* | ||
@@ -230,2 +281,4 @@ * @param {ContentPath[]} candidateFiles | ||
let checkBroadPattern = createBroadPatternCheck(paths) | ||
let changedFiles = new Set() | ||
@@ -235,2 +288,4 @@ env.DEBUG && console.time('Finding changed files') | ||
for (let file of files) { | ||
checkBroadPattern(file) | ||
let prevModified = fileModifiedMap.get(file) || -Infinity | ||
@@ -237,0 +292,0 @@ let modified = fs.statSync(file).mtimeMs |
import * as regex from './regex' | ||
import { splitAtTopLevelOnly } from '../util/splitAtTopLevelOnly' | ||
@@ -19,2 +20,26 @@ export function defaultExtractor(context) { | ||
// 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 | ||
@@ -44,4 +69,9 @@ } | ||
// Utility Name / Group Name | ||
/-?(?:\w+)/, | ||
regex.any([ | ||
/-?(?:\w+)/, | ||
// This is here to make sure @container supports everything that other utilities do | ||
/@(?:\w+)/, | ||
]), | ||
// Normal/Arbitrary values | ||
@@ -52,3 +82,8 @@ regex.optional( | ||
// Arbitrary values | ||
/-(?:\w+-)*\[[^\s:]+\]/, | ||
regex.any([ | ||
/-(?:\w+-)*\['[^\s]+'\]/, | ||
/-(?:\w+-)*\["[^\s]+"\]/, | ||
/-(?:\w+-)*\[`[^\s]+`\]/, | ||
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/, | ||
]), | ||
@@ -64,3 +99,8 @@ // Not immediately followed by an `{[(` | ||
// Arbitrary values | ||
/-(?:\w+-)*\[[^\s]+\]/, | ||
regex.any([ | ||
/-(?:\w+-)*\['[^\s]+'\]/, | ||
/-(?:\w+-)*\["[^\s]+"\]/, | ||
/-(?:\w+-)*\[`[^\s]+`\]/, | ||
/-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/, | ||
]), | ||
@@ -88,3 +128,3 @@ // Not immediately followed by an `{[(` | ||
// With variant modifier (e.g.: group-[..]/modifier) | ||
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/\w+/, separator]), | ||
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/, separator]), | ||
@@ -98,3 +138,3 @@ regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]), | ||
// With variant modifier (e.g.: group-[..]/modifier) | ||
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/\w+/, separator]), | ||
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/, separator]), | ||
@@ -123,3 +163,3 @@ regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]), | ||
// 5. Inner matches | ||
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g | ||
yield /[^<>"'`\s.(){}[\]#=%$][^<>"'`\s(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g | ||
} | ||
@@ -126,0 +166,0 @@ |
@@ -435,2 +435,19 @@ import postcss from 'postcss' | ||
// 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]) | ||
@@ -437,0 +454,0 @@ } |
import fs from 'fs' | ||
import LRU from '@alloc/quick-lru' | ||
import { parseCandidateStrings, IO, Parsing } from '@tailwindcss/oxide' | ||
import * as sharedState from './sharedState' | ||
@@ -9,3 +8,2 @@ import { generateRules } from './generateRules' | ||
import { defaultExtractor } from './defaultExtractor' | ||
import { flagEnabled } from '../featureFlags' | ||
@@ -30,6 +28,3 @@ let env = sharedState.env | ||
builtInExtractors[fileExtension] || | ||
// Because we call `DEFAULT(context)`, the returning function is always a new function without a | ||
// stable identity. Marking it with `DEFAULT_EXTRACTOR` allows us to check if it is the default | ||
// extractor without relying on the function identity. | ||
Object.assign(builtInExtractors.DEFAULT(context), { DEFAULT_EXTRACTOR: true }) | ||
builtInExtractors.DEFAULT(context) | ||
) | ||
@@ -143,33 +138,8 @@ } | ||
/** @type {{file?: string, content?: string}[]} */ | ||
let rustParserContent = [] | ||
for (let item of context.changedContent) { | ||
let transformer = getTransformer(context.tailwindConfig, item.extension) | ||
let extractor = getExtractor(context, item.extension) | ||
if ( | ||
flagEnabled(context.tailwindConfig, 'oxideParser') && | ||
transformer === builtInTransformers.DEFAULT && | ||
extractor?.DEFAULT_EXTRACTOR === true | ||
) { | ||
rustParserContent.push(item) | ||
} else { | ||
regexParserContent.push([item, { transformer, extractor }]) | ||
} | ||
regexParserContent.push([item, { transformer, extractor }]) | ||
} | ||
// Read files using our newer, faster parser when: | ||
// - Oxide is enabled; AND | ||
// - The file is using default transfomers and extractors | ||
if (rustParserContent.length > 0) { | ||
for (let candidate of parseCandidateStrings( | ||
rustParserContent, | ||
IO.Parallel | Parsing.Parallel | ||
)) { | ||
candidates.add(candidate) | ||
} | ||
} | ||
// Otherwise, read any files in node and parse with regexes | ||
const BATCH_SIZE = 500 | ||
@@ -179,3 +149,2 @@ | ||
let batch = regexParserContent.slice(i, i + BATCH_SIZE) | ||
await Promise.all( | ||
@@ -198,5 +167,2 @@ batch.map(async ([{ file, content }, { transformer, extractor }]) => { | ||
env.DEBUG && console.time('Sorting candidates') | ||
// TODO: only sort if we are not using the oxide parser (flagEnabled(context.tailwindConfig, | ||
// 'oxideParser')) AND if we got all the candidates form the oxideParser alone. This will not | ||
// be the case currently if you have custom transformers / extractors. | ||
let sortedCandidates = new Set( | ||
@@ -234,3 +200,3 @@ [...candidates].sort((a, z) => { | ||
layerNodes.base.before( | ||
cloneNodes([...baseNodes, ...defaultNodes], layerNodes.base.source, { | ||
cloneNodes([...defaultNodes, ...baseNodes], layerNodes.base.source, { | ||
layer: 'base', | ||
@@ -283,19 +249,12 @@ }) | ||
} else if (variantNodes.length > 0) { | ||
let cloned = cloneNodes(variantNodes, undefined, { | ||
layer: 'variants', | ||
}) | ||
cloned.forEach((node) => { | ||
let parentLayer = node.raws.tailwind?.parentLayer ?? null | ||
node.walk((n) => { | ||
if (!n.source) { | ||
n.source = layerNodes[parentLayer].source | ||
} | ||
root.append( | ||
cloneNodes(variantNodes, root.source, { | ||
layer: 'variants', | ||
}) | ||
}) | ||
root.append(cloned) | ||
) | ||
} | ||
// 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 | ||
@@ -302,0 +261,0 @@ const hasUtilityVariants = variantNodes.some( |
@@ -19,2 +19,3 @@ import postcss from 'postcss' | ||
import { splitAtTopLevelOnly } from '../util/splitAtTopLevelOnly.js' | ||
import { flagEnabled } from '../featureFlags' | ||
import { applyImportantSelector } from '../util/applyImportantSelector' | ||
@@ -48,3 +49,3 @@ | ||
// If character before `[` isn't a dash or a slash, this isn't a dynamic class | ||
// e.g. string[] | ||
// eg. string[] | ||
if (candidate[bracketIdx - 1] === '-') { | ||
@@ -123,2 +124,6 @@ dashIdx = bracketIdx - 1 | ||
function isInKeyframes(rule) { | ||
return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes' | ||
} | ||
for (let [meta, rule] of matches) { | ||
@@ -128,2 +133,8 @@ let container = postcss.root({ nodes: [rule.clone()] }) | ||
container.walkRules((r) => { | ||
// 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) | ||
@@ -181,2 +192,6 @@ | ||
args.modifier = modifiers[0] | ||
if (!flagEnabled(context.tailwindConfig, 'generalizedModifiers')) { | ||
return [] | ||
} | ||
} | ||
@@ -469,5 +484,5 @@ } | ||
function isParsableCssValue(property, value) { | ||
// We don't want to treat [https://example.com] as a custom property | ||
// We don't want to to treat [https://example.com] as a custom property | ||
// Even though, according to the CSS grammar, it's a totally valid CSS declaration | ||
// So we short-circuit here by checking if the custom property looks like a URL | ||
// So we short-circuit here by checking if the custom property looks like a url | ||
if (looksLikeUri(`${property}:${value}`)) { | ||
@@ -506,7 +521,7 @@ return false | ||
let sort = context.offsets.arbitraryProperty() | ||
let sort = context.offsets.arbitraryProperty(classCandidate) | ||
return [ | ||
[ | ||
{ sort, layer: 'utilities' }, | ||
{ sort, layer: 'utilities', options: { respectImportant: true } }, | ||
() => ({ | ||
@@ -850,2 +865,7 @@ [asClass(classCandidate)]: { | ||
// If all rules have been eliminated we can skip this candidate entirely | ||
if (container.nodes.length === 0) { | ||
return null | ||
} | ||
match[1] = container.nodes[0] | ||
@@ -852,0 +872,0 @@ |
@@ -7,2 +7,10 @@ import jitiFactory from 'jiti' | ||
let jiti: ReturnType<typeof jitiFactory> | null = null | ||
// @internal | ||
// This WILL be removed in some future release | ||
// If you rely on this your stuff WILL break | ||
export function useCustomJiti(_jiti: () => ReturnType<typeof jitiFactory>) { | ||
jiti = _jiti() | ||
} | ||
function lazyJiti() { | ||
@@ -14,2 +22,7 @@ return ( | ||
transform: (opts) => { | ||
// Sucrase can't transform import.meta so we have to use Babel | ||
if (opts.source.includes('import.meta')) { | ||
return require('jiti/dist/babel.js')(opts) | ||
} | ||
return transform(opts.source, { | ||
@@ -25,2 +38,13 @@ transforms: ['typescript', 'imports'], | ||
let config = (function () { | ||
// Always use jiti for ESM or TS files | ||
if ( | ||
path && | ||
(path.endsWith('.mjs') || | ||
path.endsWith('.ts') || | ||
path.endsWith('.cts') || | ||
path.endsWith('.mts')) | ||
) { | ||
return lazyJiti()(path) | ||
} | ||
try { | ||
@@ -27,0 +51,0 @@ return path ? require(path) : {} |
@@ -13,2 +13,29 @@ import log from '../util/log' | ||
if (atRule.name === 'import') { | ||
if (atRule.params === '"tailwindcss/base"' || atRule.params === "'tailwindcss/base'") { | ||
atRule.name = 'tailwind' | ||
atRule.params = 'base' | ||
} else if ( | ||
atRule.params === '"tailwindcss/components"' || | ||
atRule.params === "'tailwindcss/components'" | ||
) { | ||
atRule.name = 'tailwind' | ||
atRule.params = 'components' | ||
} else if ( | ||
atRule.params === '"tailwindcss/utilities"' || | ||
atRule.params === "'tailwindcss/utilities'" | ||
) { | ||
atRule.name = 'tailwind' | ||
atRule.params = 'utilities' | ||
} else if ( | ||
atRule.params === '"tailwindcss/screens"' || | ||
atRule.params === "'tailwindcss/screens'" || | ||
atRule.params === '"tailwindcss/variants"' || | ||
atRule.params === "'tailwindcss/variants'" | ||
) { | ||
atRule.name = 'tailwind' | ||
atRule.params = 'variants' | ||
} | ||
} | ||
if (atRule.name === 'tailwind') { | ||
@@ -15,0 +42,0 @@ if (atRule.params === 'screens') { |
@@ -27,2 +27,4 @@ // @ts-check | ||
* @property {bigint} index Index of the rule / utility in its given *parent* layer. Monotonically increasing. | ||
* @property {bigint} propertyOffset Offset for the arbitrary property. Only valid after sorting. | ||
* @property {string} property Name/Value of the arbitrary property. | ||
* @property {VariantOption[]} options Some information on how we can sort arbitrary variants | ||
@@ -92,2 +94,4 @@ */ | ||
index: this.offsets[layer]++, | ||
propertyOffset: 0n, | ||
property: '', | ||
options: [], | ||
@@ -98,8 +102,10 @@ } | ||
/** | ||
* @param {string} name | ||
* @returns {RuleOffset} | ||
*/ | ||
arbitraryProperty() { | ||
arbitraryProperty(name) { | ||
return { | ||
...this.create('utilities'), | ||
arbitrary: 1n, | ||
property: name, | ||
} | ||
@@ -268,2 +274,7 @@ } | ||
// Always sort arbitrary properties alphabetically | ||
if (a.propertyOffset !== b.propertyOffset) { | ||
return a.propertyOffset - b.propertyOffset | ||
} | ||
// Sort utilities, components, etc… in the order they were registered | ||
@@ -309,3 +320,3 @@ return a.index - b.index | ||
// No arbitrary variants? Nothing to do. | ||
// Everything already in order? Nothing to do. | ||
// Everyhing already in order? Nothing to do. | ||
if (mapping.length === 0) { | ||
@@ -333,5 +344,53 @@ return list | ||
*/ | ||
sortArbitraryProperties(list) { | ||
// Collect all known arbitrary properties | ||
let known = new Set() | ||
for (let [offset] of list) { | ||
if (offset.arbitrary === 1n) { | ||
known.add(offset.property) | ||
} | ||
} | ||
// No arbitrary properties? Nothing to do. | ||
if (known.size === 0) { | ||
return list | ||
} | ||
// Sort the properties alphabetically | ||
let properties = Array.from(known).sort() | ||
// Create a map from the property name to its offset | ||
let offsets = new Map() | ||
let offset = 1n | ||
for (let property of properties) { | ||
offsets.set(property, offset++) | ||
} | ||
// Apply the sorted offsets to the list | ||
return list.map((item) => { | ||
let [offset, rule] = item | ||
offset = { | ||
...offset, | ||
propertyOffset: offsets.get(offset.property) ?? 0n, | ||
} | ||
return [offset, rule] | ||
}) | ||
} | ||
/** | ||
* @template T | ||
* @param {[RuleOffset, T][]} list | ||
* @returns {[RuleOffset, T][]} | ||
*/ | ||
sort(list) { | ||
// Sort arbitrary variants so they're in alphabetical order | ||
list = this.remapArbitraryVariantOffsets(list) | ||
// Sort arbitrary properties so they're in alphabetical order | ||
list = this.sortArbitraryProperties(list) | ||
return list.sort(([a], [b]) => bigSign(this.compare(a, b))) | ||
@@ -363,3 +422,3 @@ } | ||
* only strings. If you're sorting strings inside objects | ||
* or arrays, you need to use a custom compare function. | ||
* or arrays, you need must use a custom compare function. | ||
* | ||
@@ -366,0 +425,0 @@ * @param {string} a |
@@ -107,4 +107,8 @@ import postcss from 'postcss' | ||
// 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 : '__DEFAULT__' | ||
selector.includes(':-') || selector.includes('::-') || selector.includes(':has') | ||
? selector | ||
: '__DEFAULT__' | ||
@@ -118,18 +122,16 @@ let selectors = selectorGroups.get(selectorGroupName) ?? new Set() | ||
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) { | ||
if (selectorGroups.size === 0) { | ||
universal.remove() | ||
continue | ||
} | ||
if (selectorGroups.size === 0) { | ||
universal.remove() | ||
continue | ||
} | ||
for (let [, selectors] of selectorGroups) { | ||
let universalRule = postcss.rule({ | ||
source: universal.source, | ||
}) | ||
for (let [, selectors] of selectorGroups) { | ||
let universalRule = postcss.rule({ | ||
source: universal.source, | ||
}) | ||
universalRule.selectors = [...selectors] | ||
universalRule.selectors = [...selectors] | ||
universalRule.append(universal.nodes.map((node) => node.clone())) | ||
universal.before(universalRule) | ||
} | ||
universalRule.append(universal.nodes.map((node) => node.clone())) | ||
universal.before(universalRule) | ||
} | ||
@@ -136,0 +138,0 @@ |
@@ -24,2 +24,3 @@ import fs from 'fs' | ||
import { Offsets } from './offsets.js' | ||
import { flagEnabled } from '../featureFlags.js' | ||
import { finalizeSelector, formatVariantSelector } from '../util/formatVariantSelector' | ||
@@ -441,4 +442,6 @@ | ||
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers') | ||
let ruleSets = [] | ||
.concat(rule(value, extras)) | ||
.concat(modifiersEnabled ? rule(value, extras) : rule(value)) | ||
.filter(Boolean) | ||
@@ -520,4 +523,6 @@ .map((declaration) => ({ | ||
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers') | ||
let ruleSets = [] | ||
.concat(rule(value, extras)) | ||
.concat(modifiersEnabled ? rule(value, extras) : rule(value)) | ||
.filter(Boolean) | ||
@@ -590,2 +595,4 @@ .map((declaration) => ({ | ||
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers') | ||
for (let [key, value] of Object.entries(options?.values ?? {})) { | ||
@@ -597,3 +604,6 @@ if (key === 'DEFAULT') continue | ||
({ args, container }) => { | ||
return variantFn(value, { modifier: args?.modifier, container }) | ||
return variantFn( | ||
value, | ||
modifiersEnabled ? { modifier: args?.modifier, container } : { container } | ||
) | ||
}, | ||
@@ -626,3 +636,3 @@ | ||
args?.value ?? (typeof args === 'string' ? args : ''), | ||
{ modifier: args?.modifier, container } | ||
modifiersEnabled ? { modifier: args?.modifier, container } : { container } | ||
) | ||
@@ -732,3 +742,3 @@ }, | ||
function resolvePlugins(context, root) { | ||
let corePluginList = Object.entries(corePlugins) | ||
let corePluginList = Object.entries({ ...variantPlugins, ...corePlugins }) | ||
.map(([name, plugin]) => { | ||
@@ -756,2 +766,3 @@ if (!context.tailwindConfig.corePlugins.includes(name)) { | ||
let beforeVariants = [ | ||
variantPlugins['childVariant'], | ||
variantPlugins['pseudoElementVariants'], | ||
@@ -765,11 +776,33 @@ variantPlugins['pseudoClassVariants'], | ||
variantPlugins['supportsVariants'], | ||
variantPlugins['directionVariants'], | ||
variantPlugins['reducedMotionVariants'], | ||
variantPlugins['prefersContrastVariants'], | ||
variantPlugins['screenVariants'], | ||
variantPlugins['orientationVariants'], | ||
variantPlugins['directionVariants'], | ||
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] | ||
@@ -1023,2 +1056,7 @@ } | ||
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 = [] | ||
@@ -1034,3 +1072,3 @@ for (let [name, options] of context.variantOptions.entries()) { | ||
selectors({ modifier, value } = {}) { | ||
let candidate = '__TAILWIND_PLACEHOLDER__' | ||
let candidate = `TAILWINDPLACEHOLDER${id}` | ||
@@ -1037,0 +1075,0 @@ let rule = postcss.rule({ selector: `.${candidate}` }) |
@@ -1,4 +0,1 @@ | ||
import postcss from 'postcss' | ||
import lightningcss, { Features } from 'lightningcss' | ||
import browserslist from 'browserslist' | ||
import setupTrackingContext from './lib/setupTrackingContext' | ||
@@ -8,9 +5,3 @@ import processTailwindFeatures from './processTailwindFeatures' | ||
import { findAtConfigPath } from './lib/findAtConfigPath' | ||
import { handleImportAtRules } from './lib/handleImportAtRules' | ||
import { version as tailwindVersion } from '../package.json' | ||
function license() { | ||
return `/* ! tailwindcss v${tailwindVersion} | MIT License | https://tailwindcss.com */\n` | ||
} | ||
module.exports = function tailwindcss(configOrPath) { | ||
@@ -26,3 +17,2 @@ return { | ||
}, | ||
...handleImportAtRules(), | ||
async function (root, result) { | ||
@@ -49,78 +39,2 @@ // Use the path for the `@config` directive if it exists, otherwise use the | ||
}, | ||
function lightningCssPlugin(_root, result) { | ||
let map = result.map ?? result.opts.map | ||
let intermediateResult = result.root.toResult({ | ||
map: map ? { inline: true } : false, | ||
}) | ||
let intermediateMap = intermediateResult.map?.toJSON?.() ?? map | ||
try { | ||
let resolvedBrowsersListConfig = browserslist.findConfig( | ||
result.opts.from ?? process.cwd() | ||
)?.defaults | ||
let defaultBrowsersListConfig = require('../package.json').browserslist | ||
let browsersListConfig = resolvedBrowsersListConfig ?? defaultBrowsersListConfig | ||
let transformed = lightningcss.transform({ | ||
filename: result.opts.from, | ||
code: Buffer.from(intermediateResult.css), | ||
minify: false, | ||
sourceMap: !!intermediateMap, | ||
targets: lightningcss.browserslistToTargets(browserslist(browsersListConfig)), | ||
errorRecovery: true, | ||
drafts: { | ||
customMedia: true, | ||
}, | ||
nonStandard: { | ||
deepSelectorCombinator: true, | ||
}, | ||
include: Features.Nesting, | ||
exclude: Features.LogicalProperties, | ||
}) | ||
let code = transformed.code.toString() | ||
// https://postcss.org/api/#sourcemapoptions | ||
if (intermediateMap && transformed.map != null) { | ||
let prev = transformed.map.toString() | ||
if (typeof intermediateMap === 'object') { | ||
intermediateMap.prev = prev | ||
} else { | ||
code = `${code}\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from( | ||
prev | ||
).toString('base64')} */` | ||
} | ||
} | ||
result.root = postcss.parse(license() + code, { | ||
...result.opts, | ||
map: intermediateMap, | ||
}) | ||
} catch (err) { | ||
if (err.source && typeof process !== 'undefined' && process.env.JEST_WORKER_ID) { | ||
let lines = err.source.split('\n') | ||
err = new Error( | ||
[ | ||
'Error formatting using Lightning CSS:', | ||
'', | ||
...[ | ||
'```css', | ||
...lines.slice(Math.max(err.loc.line - 3, 0), err.loc.line), | ||
' '.repeat(err.loc.column - 1) + '^-- ' + err.toString(), | ||
...lines.slice(err.loc.line, err.loc.line + 2), | ||
'```', | ||
], | ||
].join('\n') | ||
) | ||
} | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(err, lightningCssPlugin) | ||
} | ||
throw err | ||
} | ||
}, | ||
env.DEBUG && | ||
@@ -127,0 +41,0 @@ function (root) { |
@@ -10,3 +10,2 @@ import normalizeTailwindDirectives from './lib/normalizeTailwindDirectives' | ||
import partitionApplyAtRules from './lib/partitionApplyAtRules' | ||
import detectNesting from './lib/detectNesting' | ||
import { createContext } from './lib/setupContextUtils' | ||
@@ -19,4 +18,2 @@ import { issueFlagNotices } from './featureFlags' | ||
detectNesting()(root, result) | ||
// Partition apply rules that are found in the css | ||
@@ -23,0 +20,0 @@ // itself. |
@@ -8,9 +8,8 @@ import parser from 'postcss-selector-parser' | ||
sel.each((sel) => { | ||
// Wrap with :is if it's not already wrapped | ||
let isWrapped = | ||
sel.nodes[0].type === 'pseudo' && | ||
sel.nodes[0].value === ':is' && | ||
sel.nodes.every((node) => node.type !== 'combinator') | ||
// For nesting, we only need to wrap a selector with :is() if it has a top-level combinator, | ||
// e.g. `.dark .text-white`, to be independent of DOM order. Any other selector, including | ||
// combinators inside of pseudos like `:where()`, are ok to nest. | ||
let shouldWrap = sel.nodes.some((node) => node.type === 'combinator') | ||
if (!isWrapped) { | ||
if (shouldWrap) { | ||
sel.nodes = [ | ||
@@ -17,0 +16,0 @@ parser.pseudo({ |
@@ -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,16 +11,2 @@ return nodes.map((node) => { | ||
// We always want override the source map | ||
// except when explicitly told not to | ||
let shouldOverwriteSource = node.raws.tailwind?.preserveSource !== true || !cloned.source | ||
if (source !== undefined && shouldOverwriteSource) { | ||
cloned.source = source | ||
if ('walk' in cloned) { | ||
cloned.walk((child) => { | ||
child.source = source | ||
}) | ||
} | ||
} | ||
if (raws !== undefined) { | ||
@@ -27,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)) | ||
} | ||
} |
@@ -6,3 +6,2 @@ import { parseColor } from './color' | ||
let cssFunctions = ['min', 'max', 'clamp', 'calc'] | ||
let IS_CSS_FN = new RegExp(`^(${cssFunctions.join('|')})\\(.*\\)`) | ||
@@ -12,3 +11,3 @@ // Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types | ||
function isCSSFunction(value) { | ||
return IS_CSS_FN.test(value) | ||
return cssFunctions.some((fn) => new RegExp(`^${fn}\\(.*\\)`).test(value)) | ||
} | ||
@@ -25,2 +24,3 @@ | ||
// - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident | ||
// - https://www.w3.org/TR/css-anchor-position-1 | ||
// | ||
@@ -33,2 +33,6 @@ const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([ | ||
'font-palette', | ||
'anchor-name', | ||
'anchor-scope', | ||
'position-anchor', | ||
'position-try-options', | ||
@@ -39,2 +43,3 @@ // Shorthand properties | ||
'view-timeline', | ||
'position-try', | ||
]) | ||
@@ -84,5 +89,33 @@ | ||
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 '('. | ||
* like calc() that do not follow an operator, '(', or `,`. | ||
* | ||
@@ -116,2 +149,11 @@ * @param {string} value | ||
'keyboard-inset-height', | ||
'radial-gradient', | ||
'linear-gradient', | ||
'conic-gradient', | ||
'repeating-radial-gradient', | ||
'repeating-linear-gradient', | ||
'repeating-conic-gradient', | ||
'anchor-size', | ||
] | ||
@@ -172,6 +214,11 @@ | ||
// Don't break CSS grid track names | ||
else if (peek('[')) { | ||
result += consumeUntil([']']) | ||
} | ||
// Handle operators | ||
else if ( | ||
['+', '-', '*', '/'].includes(char) && | ||
!['(', '+', '-', '*', '/'].includes(lastChar()) | ||
!['(', '+', '-', '*', '/', ','].includes(lastChar()) | ||
) { | ||
@@ -238,5 +285,8 @@ result += ` ${char} ` | ||
let lengthUnitsPattern = `(?:${lengthUnits.join('|')})` | ||
let lengthRegExp = new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`) | ||
export function length(value) { | ||
return value === '0' || lengthRegExp.test(value) || isCSSFunction(value) | ||
return ( | ||
value === '0' || | ||
new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`).test(value) || | ||
isCSSFunction(value) | ||
) | ||
} | ||
@@ -391,3 +441,3 @@ | ||
'x-large', | ||
'x-large', | ||
'xx-large', | ||
'xxx-large', | ||
@@ -394,0 +444,0 @@ ]) |
@@ -189,3 +189,3 @@ import selectorParser from 'postcss-selector-parser' | ||
// If after eliminating irrelevant selectors, we end up with nothing | ||
// If ffter eliminating irrelevant selectors, we end up with nothing | ||
// Then the whole "rule" this is associated with does not need to exist | ||
@@ -192,0 +192,0 @@ // We use `null` as a marker value for that case |
@@ -20,26 +20,2 @@ import colors from 'picocolors' | ||
export default { | ||
group(key, cb) { | ||
if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) return | ||
if (key && alreadyShown.has(key)) return | ||
if (key) alreadyShown.add(key) | ||
console.warn('') | ||
cb({ | ||
info(messages) { | ||
messages.forEach((message) => console.warn(colors.bold(colors.cyan('info')), '-', message)) | ||
}, | ||
warn(messages) { | ||
messages.forEach((message) => | ||
console.warn(colors.bold(colors.yellow('warn')), '-', message) | ||
) | ||
}, | ||
risk(messages) { | ||
messages.forEach((message) => | ||
console.warn(colors.bold(colors.magenta('risk')), '-', message) | ||
) | ||
}, | ||
}) | ||
}, | ||
info(key, messages) { | ||
@@ -46,0 +22,0 @@ log(colors.bold(colors.cyan('info')), ...(Array.isArray(key) ? [key] : [messages, key])) |
@@ -1,2 +0,2 @@ | ||
import { flagEnabled, featureFlags } from '../featureFlags' | ||
import { flagEnabled } from '../featureFlags' | ||
import log, { dim } from './log' | ||
@@ -21,6 +21,2 @@ | ||
let valid = (() => { | ||
if (config.content === 'auto') { | ||
return true | ||
} | ||
// `config.purge` should not exist anymore | ||
@@ -204,13 +200,7 @@ if (config.purge) { | ||
if (content === undefined && purge === undefined) return [] | ||
if (purge) { | ||
if (Array.isArray(purge)) return purge | ||
if (Array.isArray(purge?.content)) return purge.content | ||
return [] | ||
} | ||
if (Array.isArray(purge)) return purge | ||
if (Array.isArray(purge?.content)) return purge.content | ||
if (Array.isArray(content)) return content | ||
if (Array.isArray(content?.content)) return content.content | ||
if (Array.isArray(content?.files)) return content.files | ||
if (content === 'auto') return ['auto'] | ||
@@ -289,5 +279,3 @@ return [] | ||
transformers.DEFAULT = transform | ||
} | ||
if (typeof transform === 'object' && transform !== null) { | ||
} else if (typeof transform === 'object' && transform !== null) { | ||
Object.assign(transformers, transform) | ||
@@ -300,29 +288,12 @@ } | ||
// Force disable the `oxideParser` feature flag when using unsupported features. | ||
// TODO: Remove once we have prefix or separator support in the oxide parser. | ||
if (config.prefix !== '' || config.separator !== ':') { | ||
if (config.experimental === 'all') { | ||
config.experimental = {} | ||
for (let key of featureFlags.experimental) { | ||
config.experimental[key] = true | ||
} | ||
} else { | ||
config.experimental = config.experimental ?? {} | ||
} | ||
config.experimental.oxideParser = false | ||
} | ||
// Validate globs to prevent bogus globs. | ||
// E.g.: `./src/*.{html}` is invalid, the `{html}` should just be `html` | ||
if (config.content.files !== 'auto') { | ||
for (let file of config.content.files) { | ||
if (typeof file === 'string' && /{([^,]*?)}/g.test(file)) { | ||
log.warn('invalid-glob-braces', [ | ||
`The glob pattern ${dim(file)} in your Tailwind CSS configuration is invalid.`, | ||
`Update it to ${dim(file.replace(/{([^,]*?)}/g, '$1'))} to silence this warning.`, | ||
// TODO: Add https://tw.wtf/invalid-glob-braces | ||
]) | ||
break | ||
} | ||
for (let file of config.content.files) { | ||
if (typeof file === 'string' && /{([^,]*?)}/g.test(file)) { | ||
log.warn('invalid-glob-braces', [ | ||
`The glob pattern ${dim(file)} in your Tailwind CSS configuration is invalid.`, | ||
`Update it to ${dim(file.replace(/{([^,]*?)}/g, '$1'))} to silence this warning.`, | ||
// TODO: Add https://tw.wtf/invalid-glob-braces | ||
]) | ||
break | ||
} | ||
@@ -329,0 +300,0 @@ } |
@@ -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)$/ |
@@ -18,4 +18,3 @@ import globParent from 'glob-parent' | ||
glob = glob.substr(2) | ||
} | ||
if (glob.charAt(0) === '/') { | ||
} else if (glob.charAt(0) === '/') { | ||
glob = glob.substr(1) | ||
@@ -22,0 +21,0 @@ } |
@@ -21,2 +21,3 @@ import escapeCommas from './escapeCommas' | ||
import { backgroundSize } from './validateFormalSyntax' | ||
import { flagEnabled } from '../featureFlags.js' | ||
@@ -91,2 +92,18 @@ /** | ||
// 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) { | ||
@@ -112,3 +129,3 @@ return [modifier, undefined] | ||
return ({ opacityValue = 1 }) => oldValue.replace('<alpha-value>', opacityValue) | ||
return ({ opacityValue = 1 }) => oldValue.replace(/<alpha-value>/g, opacityValue) | ||
} | ||
@@ -248,5 +265,8 @@ | ||
export function* getMatchingTypes(types, rawModifier, options, tailwindConfig) { | ||
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers') | ||
let [modifier, utilityModifier] = splitUtilityModifier(rawModifier) | ||
let canUseUtilityModifier = | ||
modifiersEnabled && | ||
options.modifiers != null && | ||
@@ -253,0 +273,0 @@ (options.modifiers === 'any' || |
@@ -63,2 +63,6 @@ /** @typedef {import('postcss-selector-parser').Root} Root */ | ||
':where': [], | ||
':is': [], | ||
':has': [], | ||
// The default value is used when the pseudo-element is not recognized | ||
@@ -65,0 +69,0 @@ // Because it's not recognized, we don't know if it's terminal or not |
@@ -21,2 +21,4 @@ /** | ||
decl.value = decl.value.replace(`/ var(${varName})`, '') | ||
} else if (decl.value.includes(`/ var(${varName}, 1)`)) { | ||
decl.value = decl.value.replace(`/ var(${varName}, 1)`, '') | ||
} | ||
@@ -23,0 +25,0 @@ } |
@@ -213,47 +213,23 @@ import negateValue from './negateValue' | ||
function resolvePlugins(configs) { | ||
let pluginGroups = [] | ||
function extractPluginConfigs(configs) { | ||
let allConfigs = [] | ||
for (let config of configs) { | ||
allConfigs.push(config) | ||
configs.forEach((config) => { | ||
allConfigs = [...allConfigs, config] | ||
let plugins = [] | ||
const plugins = config?.plugins ?? [] | ||
for (let plugin of config?.plugins ?? []) { | ||
// TODO: If we want to support ESM plugins then a handful of things will have to become async | ||
if (typeof plugin === 'string') { | ||
// If the plugin is specified as a string then it's just the package name | ||
plugin = require(plugin) | ||
plugin = plugin.default ?? plugin | ||
} else if (Array.isArray(plugin)) { | ||
// If the plugin is specified as an array then it's a package name and optional options object | ||
// [name] or [name, options] | ||
let [pkg, options = undefined] = plugin | ||
plugin = require(pkg) | ||
plugin = plugin.default ?? plugin | ||
plugin = plugin(options) | ||
} | ||
if (plugins.length === 0) { | ||
return | ||
} | ||
plugins.forEach((plugin) => { | ||
if (plugin.__isOptionsFunction) { | ||
plugin = plugin() | ||
} | ||
allConfigs = [...allConfigs, ...extractPluginConfigs([plugin?.config ?? {}])] | ||
}) | ||
}) | ||
// We're explicitly skipping registering child plugins | ||
// This will change in v4 | ||
let [, childConfigs] = resolvePlugins([plugin?.config ?? {}]) | ||
plugins.push(plugin) | ||
allConfigs.push(...childConfigs) | ||
} | ||
pluginGroups.push(plugins) | ||
} | ||
// Reverse the order of the plugin groups | ||
// This matches the old `reduceRight` behavior of the old `resolvePluginLists` | ||
// Why? No idea. | ||
let plugins = pluginGroups.reverse().flat() | ||
return [plugins, allConfigs] | ||
return allConfigs | ||
} | ||
@@ -272,7 +248,13 @@ | ||
function resolvePluginLists(pluginLists) { | ||
const result = [...pluginLists].reduceRight((resolved, pluginList) => { | ||
return [...resolved, ...pluginList] | ||
}, []) | ||
return result | ||
} | ||
export default function resolveConfig(configs) { | ||
let [plugins, pluginConfigs] = resolvePlugins(configs) | ||
let allConfigs = [ | ||
...pluginConfigs, | ||
...extractPluginConfigs(configs), | ||
{ | ||
@@ -292,3 +274,3 @@ prefix: '', | ||
corePlugins: resolveCorePlugins(allConfigs.map((c) => c.corePlugins)), | ||
plugins, | ||
plugins: resolvePluginLists(configs.map((c) => c?.plugins ?? [])), | ||
}, | ||
@@ -295,0 +277,0 @@ ...allConfigs |
@@ -9,2 +9,4 @@ import fs from 'fs' | ||
'./tailwind.config.ts', | ||
'./tailwind.config.cts', | ||
'./tailwind.config.mts', | ||
] | ||
@@ -11,0 +13,0 @@ |
@@ -32,7 +32,3 @@ /** | ||
if (isEscaped) { | ||
isEscaped = false | ||
} else if (char === '\\') { | ||
isEscaped = true | ||
} | ||
isEscaped = isEscaped ? false : char === '\\' | ||
@@ -39,0 +35,0 @@ if (char === '(' || char === '[' || char === '{') { |
@@ -1,2 +0,1 @@ | ||
import pc from 'picocolors' | ||
import log from './log' | ||
@@ -13,11 +12,2 @@ | ||
if (config.content.files.includes('auto')) { | ||
log.group('auto-content-experimental', (log) => { | ||
log.info([pc.bold('Automatically detecting Tailwind CSS content sources...')]) | ||
log.warn([ | ||
'Automatic content detection is experimental, and the behavior may change at any time.', | ||
]) | ||
}) | ||
} | ||
// Warn if the line-clamp plugin is installed | ||
@@ -24,0 +14,0 @@ try { |
@@ -24,3 +24,3 @@ import { parseColor, formatColor } from './color' | ||
properties.map((p) => { | ||
return [p, color({ opacityVariable: variable, opacityValue: `var(${variable})` })] | ||
return [p, color({ opacityVariable: variable, opacityValue: `var(${variable}, 1)` })] | ||
}) | ||
@@ -46,3 +46,3 @@ ), | ||
properties.map((p) => { | ||
return [p, formatColor({ ...parsed, alpha: `var(${variable})` })] | ||
return [p, formatColor({ ...parsed, alpha: `var(${variable}, 1)` })] | ||
}) | ||
@@ -49,0 +49,0 @@ ), |
module.exports = { | ||
content: ['auto'], | ||
content: [], | ||
presets: [], | ||
@@ -73,3 +73,3 @@ darkMode: 'media', // or 'class' | ||
0: '0', | ||
none: '0', | ||
none: '', | ||
sm: '4px', | ||
@@ -76,0 +76,0 @@ DEFAULT: '8px', |
module.exports = { | ||
content: ['auto'], | ||
content: [], | ||
theme: { | ||
@@ -4,0 +4,0 @@ extend: {}, |
export default { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
}, | ||
} |
@@ -63,7 +63,6 @@ import type { CorePluginList } from './generated/corePluginList' | ||
| 'relativeContentPathsByDefault' | ||
| 'logicalSiblingUtilities' | ||
type FutureConfig = Expand<'all' | Partial<Record<FutureConfigValues, boolean>>> | [] | ||
// Experimental related config | ||
type ExperimentalConfigValues = 'optimizeUniversalDefaults' | 'oxideParser' | ||
type ExperimentalConfigValues = 'optimizeUniversalDefaults' | 'matchVariant' | ||
type ExperimentalConfig = Expand<'all' | Partial<Record<ExperimentalConfigValues, boolean>>> | [] | ||
@@ -79,2 +78,9 @@ | ||
| ['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[]] | ||
@@ -206,3 +212,3 @@ type Screen = { raw: string } | { min: string } | { max: string } | { min: string; max: string } | ||
opacity: ResolvableTo<KeyValuePair> | ||
boxShadow: ResolvableTo<KeyValuePair> | ||
boxShadow: ResolvableTo<KeyValuePair<string, string | string[]>> | ||
boxShadowColor: ThemeConfig['colors'] | ||
@@ -344,9 +350,10 @@ outlineWidth: ResolvableTo<KeyValuePair> | ||
| PluginCreator | ||
| { handler: PluginCreator; config?: Partial<Config> } | ||
| { handler: PluginCreator; config?: Partial<Config> | undefined } | ||
| { | ||
(options: any): { handler: PluginCreator; config?: Partial<Config> } | ||
(options: any): { | ||
handler: PluginCreator; | ||
config?: Partial<Config> | undefined; | ||
}; | ||
__isOptionsFunction: true | ||
} | ||
| string | ||
| [string, Record<string, any>] | ||
)[] | ||
@@ -353,0 +360,0 @@ |
@@ -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' | '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' | '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' |
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 not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
5585125
22
32815
43
19
41
- Removedbrowserslist@^4.22.1
- Removedlightningcss@^1.22.0
- Removedpostcss-value-parser@^4.2.0
- Removed@tailwindcss/oxide@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-darwin-arm64@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-darwin-x64@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-freebsd-x64@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-linux-arm-gnueabihf@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-linux-arm64-gnu@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-linux-arm64-musl@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-linux-x64-gnu@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-linux-x64-musl@0.0.0-insiders.8f788e2(transitive)
- Removed@tailwindcss/oxide-win32-x64-msvc@0.0.0-insiders.8f788e2(transitive)
- Removedbrowserslist@4.24.4(transitive)
- Removedcaniuse-lite@1.0.30001697(transitive)
- Removeddetect-libc@1.0.3(transitive)
- Removedelectron-to-chromium@1.5.92(transitive)
- Removedescalade@3.2.0(transitive)
- Removedlightningcss@1.29.1(transitive)
- Removedlightningcss-darwin-arm64@1.29.1(transitive)
- Removedlightningcss-darwin-x64@1.29.1(transitive)
- Removedlightningcss-freebsd-x64@1.29.1(transitive)
- Removedlightningcss-linux-arm-gnueabihf@1.29.1(transitive)
- Removedlightningcss-linux-arm64-gnu@1.29.1(transitive)
- Removedlightningcss-linux-arm64-musl@1.29.1(transitive)
- Removedlightningcss-linux-x64-gnu@1.29.1(transitive)
- Removedlightningcss-linux-x64-musl@1.29.1(transitive)
- Removedlightningcss-win32-arm64-msvc@1.29.1(transitive)
- Removedlightningcss-win32-x64-msvc@1.29.1(transitive)
- Removedlilconfig@2.1.0(transitive)
- Removednode-releases@2.0.19(transitive)
- Removedupdate-browserslist-db@1.1.2(transitive)
Updatedchokidar@^3.6.0
Updatedfast-glob@^3.3.2
Updatedjiti@^1.21.6
Updatedlilconfig@^3.1.3
Updatedmicromatch@^4.0.8
Updatedpicocolors@^1.1.1
Updatedpostcss@^8.4.47
Updatedpostcss-load-config@^4.0.2
Updatedpostcss-nested@^6.2.0
Updatedsucrase@^3.35.0