mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-02 18:49:30 +08:00
944 lines
38 KiB
Text
944 lines
38 KiB
Text
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
function _export(target, all) {
|
|
for(var name in all)Object.defineProperty(target, name, {
|
|
enumerable: true,
|
|
get: all[name]
|
|
});
|
|
}
|
|
_export(exports, {
|
|
isValidVariantFormatString: ()=>isValidVariantFormatString,
|
|
parseVariant: ()=>parseVariant,
|
|
getFileModifiedMap: ()=>getFileModifiedMap,
|
|
createContext: ()=>createContext,
|
|
getContext: ()=>getContext
|
|
});
|
|
const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
|
|
const _url = /*#__PURE__*/ _interopRequireDefault(require("url"));
|
|
const _postcss = /*#__PURE__*/ _interopRequireDefault(require("postcss"));
|
|
const _dlv = /*#__PURE__*/ _interopRequireDefault(require("dlv"));
|
|
const _postcssSelectorParser = /*#__PURE__*/ _interopRequireDefault(require("postcss-selector-parser"));
|
|
const _featureFlagsJs = require("../featureFlags.js");
|
|
const _transformThemeValue = /*#__PURE__*/ _interopRequireDefault(require("../util/transformThemeValue"));
|
|
const _parseObjectStyles = /*#__PURE__*/ _interopRequireDefault(require("../util/parseObjectStyles"));
|
|
const _prefixSelector = /*#__PURE__*/ _interopRequireDefault(require("../util/prefixSelector"));
|
|
const _isPlainObject = /*#__PURE__*/ _interopRequireDefault(require("../util/isPlainObject"));
|
|
const _escapeClassName = /*#__PURE__*/ _interopRequireDefault(require("../util/escapeClassName"));
|
|
const _nameClass = /*#__PURE__*/ _interopRequireWildcard(require("../util/nameClass"));
|
|
const _pluginUtils = require("../util/pluginUtils");
|
|
const _bigSign = /*#__PURE__*/ _interopRequireDefault(require("../util/bigSign"));
|
|
const _corePlugins = require("../corePlugins");
|
|
const _sharedState = /*#__PURE__*/ _interopRequireWildcard(require("./sharedState"));
|
|
const _toPath = require("../util/toPath");
|
|
const _log = /*#__PURE__*/ _interopRequireDefault(require("../util/log"));
|
|
const _negateValue = /*#__PURE__*/ _interopRequireDefault(require("../util/negateValue"));
|
|
const _isValidArbitraryValue = /*#__PURE__*/ _interopRequireDefault(require("../util/isValidArbitraryValue"));
|
|
const _generateRules = require("./generateRules");
|
|
const _cacheInvalidationJs = require("./cacheInvalidation.js");
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _getRequireWildcardCache(nodeInterop) {
|
|
if (typeof WeakMap !== "function") return null;
|
|
var cacheBabelInterop = new WeakMap();
|
|
var cacheNodeInterop = new WeakMap();
|
|
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
})(nodeInterop);
|
|
}
|
|
function _interopRequireWildcard(obj, nodeInterop) {
|
|
if (!nodeInterop && obj && obj.__esModule) {
|
|
return obj;
|
|
}
|
|
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
return {
|
|
default: obj
|
|
};
|
|
}
|
|
var cache = _getRequireWildcardCache(nodeInterop);
|
|
if (cache && cache.has(obj)) {
|
|
return cache.get(obj);
|
|
}
|
|
var newObj = {};
|
|
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
for(var key in obj){
|
|
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
if (desc && (desc.get || desc.set)) {
|
|
Object.defineProperty(newObj, key, desc);
|
|
} else {
|
|
newObj[key] = obj[key];
|
|
}
|
|
}
|
|
}
|
|
newObj.default = obj;
|
|
if (cache) {
|
|
cache.set(obj, newObj);
|
|
}
|
|
return newObj;
|
|
}
|
|
let MATCH_VARIANT = Symbol();
|
|
function prefix(context, selector) {
|
|
let prefix = context.tailwindConfig.prefix;
|
|
return typeof prefix === "function" ? prefix(selector) : prefix + selector;
|
|
}
|
|
function parseVariantFormatString(input) {
|
|
if (input.includes("{")) {
|
|
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`);
|
|
return input.split(/{(.*)}/gim).flatMap((line)=>parseVariantFormatString(line)).filter(Boolean);
|
|
}
|
|
return [
|
|
input.trim()
|
|
];
|
|
}
|
|
function isBalanced(input) {
|
|
let count = 0;
|
|
for (let char of input){
|
|
if (char === "{") {
|
|
count++;
|
|
} else if (char === "}") {
|
|
if (--count < 0) {
|
|
return false // unbalanced
|
|
;
|
|
}
|
|
}
|
|
}
|
|
return count === 0;
|
|
}
|
|
function insertInto(list, value, { before =[] } = {}) {
|
|
before = [].concat(before);
|
|
if (before.length <= 0) {
|
|
list.push(value);
|
|
return;
|
|
}
|
|
let idx = list.length - 1;
|
|
for (let other of before){
|
|
let iidx = list.indexOf(other);
|
|
if (iidx === -1) continue;
|
|
idx = Math.min(idx, iidx);
|
|
}
|
|
list.splice(idx, 0, value);
|
|
}
|
|
function parseStyles(styles) {
|
|
if (!Array.isArray(styles)) {
|
|
return parseStyles([
|
|
styles
|
|
]);
|
|
}
|
|
return styles.flatMap((style)=>{
|
|
let isNode = !Array.isArray(style) && !(0, _isPlainObject.default)(style);
|
|
return isNode ? style : (0, _parseObjectStyles.default)(style);
|
|
});
|
|
}
|
|
function getClasses(selector, mutate) {
|
|
let parser = (0, _postcssSelectorParser.default)((selectors)=>{
|
|
let allClasses = [];
|
|
if (mutate) {
|
|
mutate(selectors);
|
|
}
|
|
selectors.walkClasses((classNode)=>{
|
|
allClasses.push(classNode.value);
|
|
});
|
|
return allClasses;
|
|
});
|
|
return parser.transformSync(selector);
|
|
}
|
|
function extractCandidates(node, state = {
|
|
containsNonOnDemandable: false
|
|
}, depth = 0) {
|
|
let classes = [];
|
|
// Handle normal rules
|
|
if (node.type === "rule") {
|
|
// Ignore everything inside a :not(...). This allows you to write code like
|
|
// `div:not(.foo)`. If `.foo` is never found in your code, then we used to
|
|
// not generated it. But now we will ignore everything inside a `:not`, so
|
|
// that it still gets generated.
|
|
function ignoreNot(selectors) {
|
|
selectors.walkPseudos((pseudo)=>{
|
|
if (pseudo.value === ":not") {
|
|
pseudo.remove();
|
|
}
|
|
});
|
|
}
|
|
for (let selector of node.selectors){
|
|
let classCandidates = getClasses(selector, ignoreNot);
|
|
// At least one of the selectors contains non-"on-demandable" candidates.
|
|
if (classCandidates.length === 0) {
|
|
state.containsNonOnDemandable = true;
|
|
}
|
|
for (let classCandidate of classCandidates){
|
|
classes.push(classCandidate);
|
|
}
|
|
}
|
|
} else if (node.type === "atrule") {
|
|
node.walkRules((rule)=>{
|
|
for (let classCandidate of rule.selectors.flatMap((selector)=>getClasses(selector))){
|
|
classes.push(classCandidate);
|
|
}
|
|
});
|
|
}
|
|
if (depth === 0) {
|
|
return [
|
|
state.containsNonOnDemandable || classes.length === 0,
|
|
classes
|
|
];
|
|
}
|
|
return classes;
|
|
}
|
|
function withIdentifiers(styles) {
|
|
return parseStyles(styles).flatMap((node)=>{
|
|
let nodeMap = new Map();
|
|
let [containsNonOnDemandableSelectors, candidates] = extractCandidates(node);
|
|
// If this isn't "on-demandable", assign it a universal candidate to always include it.
|
|
if (containsNonOnDemandableSelectors) {
|
|
candidates.unshift(_sharedState.NOT_ON_DEMAND);
|
|
}
|
|
// However, it could be that it also contains "on-demandable" candidates.
|
|
// E.g.: `span, .foo {}`, in that case it should still be possible to use
|
|
// `@apply foo` for example.
|
|
return candidates.map((c)=>{
|
|
if (!nodeMap.has(node)) {
|
|
nodeMap.set(node, node);
|
|
}
|
|
return [
|
|
c,
|
|
nodeMap.get(node)
|
|
];
|
|
});
|
|
});
|
|
}
|
|
function isValidVariantFormatString(format) {
|
|
return format.startsWith("@") || format.includes("&");
|
|
}
|
|
function parseVariant(variant) {
|
|
variant = variant.replace(/\n+/g, "").replace(/\s{1,}/g, " ").trim();
|
|
let fns = parseVariantFormatString(variant).map((str)=>{
|
|
if (!str.startsWith("@")) {
|
|
return ({ format })=>format(str);
|
|
}
|
|
let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(str);
|
|
return ({ wrap })=>wrap(_postcss.default.atRule({
|
|
name,
|
|
params: params.trim()
|
|
}));
|
|
}).reverse();
|
|
return (api)=>{
|
|
for (let fn of fns){
|
|
fn(api);
|
|
}
|
|
};
|
|
}
|
|
function buildPluginApi(tailwindConfig, context, { variantList , variantMap , offsets , classList }) {
|
|
function getConfigValue(path, defaultValue) {
|
|
return path ? (0, _dlv.default)(tailwindConfig, path, defaultValue) : tailwindConfig;
|
|
}
|
|
function applyConfiguredPrefix(selector) {
|
|
return (0, _prefixSelector.default)(tailwindConfig.prefix, selector);
|
|
}
|
|
function prefixIdentifier(identifier, options) {
|
|
if (identifier === _sharedState.NOT_ON_DEMAND) {
|
|
return _sharedState.NOT_ON_DEMAND;
|
|
}
|
|
if (!options.respectPrefix) {
|
|
return identifier;
|
|
}
|
|
return context.tailwindConfig.prefix + identifier;
|
|
}
|
|
function resolveThemeValue(path, defaultValue, opts = {}) {
|
|
const [pathRoot, ...subPaths] = (0, _toPath.toPath)(path);
|
|
const value = getConfigValue([
|
|
"theme",
|
|
pathRoot,
|
|
...subPaths
|
|
], defaultValue);
|
|
return (0, _transformThemeValue.default)(pathRoot)(value, opts);
|
|
}
|
|
const theme = Object.assign((path, defaultValue = undefined)=>resolveThemeValue(path, defaultValue), {
|
|
withAlpha: (path, opacityValue)=>resolveThemeValue(path, undefined, {
|
|
opacityValue
|
|
})
|
|
});
|
|
let api = {
|
|
postcss: _postcss.default,
|
|
prefix: applyConfiguredPrefix,
|
|
e: _escapeClassName.default,
|
|
config: getConfigValue,
|
|
theme,
|
|
corePlugins: (path)=>{
|
|
if (Array.isArray(tailwindConfig.corePlugins)) {
|
|
return tailwindConfig.corePlugins.includes(path);
|
|
}
|
|
return getConfigValue([
|
|
"corePlugins",
|
|
path
|
|
], true);
|
|
},
|
|
variants: ()=>{
|
|
// Preserved for backwards compatibility but not used in v3.0+
|
|
return [];
|
|
},
|
|
addBase (base) {
|
|
for (let [identifier, rule] of withIdentifiers(base)){
|
|
let prefixedIdentifier = prefixIdentifier(identifier, {});
|
|
let offset = offsets.base++;
|
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
context.candidateRuleMap.set(prefixedIdentifier, []);
|
|
}
|
|
context.candidateRuleMap.get(prefixedIdentifier).push([
|
|
{
|
|
sort: offset,
|
|
layer: "base"
|
|
},
|
|
rule
|
|
]);
|
|
}
|
|
},
|
|
/**
|
|
* @param {string} group
|
|
* @param {Record<string, string | string[]>} declarations
|
|
*/ addDefaults (group, declarations) {
|
|
const groups = {
|
|
[`@defaults ${group}`]: declarations
|
|
};
|
|
for (let [identifier, rule] of withIdentifiers(groups)){
|
|
let prefixedIdentifier = prefixIdentifier(identifier, {});
|
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
context.candidateRuleMap.set(prefixedIdentifier, []);
|
|
}
|
|
context.candidateRuleMap.get(prefixedIdentifier).push([
|
|
{
|
|
sort: offsets.base++,
|
|
layer: "defaults"
|
|
},
|
|
rule
|
|
]);
|
|
}
|
|
},
|
|
addComponents (components, options) {
|
|
let defaultOptions = {
|
|
preserveSource: false,
|
|
respectPrefix: true,
|
|
respectImportant: false
|
|
};
|
|
options = Object.assign({}, defaultOptions, Array.isArray(options) ? {} : options);
|
|
for (let [identifier, rule] of withIdentifiers(components)){
|
|
let prefixedIdentifier = prefixIdentifier(identifier, options);
|
|
classList.add(prefixedIdentifier);
|
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
context.candidateRuleMap.set(prefixedIdentifier, []);
|
|
}
|
|
context.candidateRuleMap.get(prefixedIdentifier).push([
|
|
{
|
|
sort: offsets.components++,
|
|
layer: "components",
|
|
options
|
|
},
|
|
rule
|
|
]);
|
|
}
|
|
},
|
|
addUtilities (utilities, options) {
|
|
let defaultOptions = {
|
|
preserveSource: false,
|
|
respectPrefix: true,
|
|
respectImportant: true
|
|
};
|
|
options = Object.assign({}, defaultOptions, Array.isArray(options) ? {} : options);
|
|
for (let [identifier, rule] of withIdentifiers(utilities)){
|
|
let prefixedIdentifier = prefixIdentifier(identifier, options);
|
|
classList.add(prefixedIdentifier);
|
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
context.candidateRuleMap.set(prefixedIdentifier, []);
|
|
}
|
|
context.candidateRuleMap.get(prefixedIdentifier).push([
|
|
{
|
|
sort: offsets.utilities++,
|
|
layer: "utilities",
|
|
options
|
|
},
|
|
rule
|
|
]);
|
|
}
|
|
},
|
|
matchUtilities: function(utilities, options) {
|
|
let defaultOptions = {
|
|
respectPrefix: true,
|
|
respectImportant: true
|
|
};
|
|
options = {
|
|
...defaultOptions,
|
|
...options
|
|
};
|
|
let offset = offsets.utilities++;
|
|
for(let identifier in utilities){
|
|
let prefixedIdentifier = prefixIdentifier(identifier, options);
|
|
let rule = utilities[identifier];
|
|
classList.add([
|
|
prefixedIdentifier,
|
|
options
|
|
]);
|
|
function wrapped(modifier, { isOnlyPlugin }) {
|
|
let { type ="any" } = options;
|
|
type = [].concat(type);
|
|
let [value, coercedType] = (0, _pluginUtils.coerceValue)(type, modifier, options, tailwindConfig);
|
|
if (value === undefined) {
|
|
return [];
|
|
}
|
|
if (!type.includes(coercedType) && !isOnlyPlugin) {
|
|
return [];
|
|
}
|
|
if (!(0, _isValidArbitraryValue.default)(value)) {
|
|
return [];
|
|
}
|
|
let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
|
|
[(0, _nameClass.default)(identifier, modifier)]: declaration
|
|
}));
|
|
return ruleSets;
|
|
}
|
|
let withOffsets = [
|
|
{
|
|
sort: offset,
|
|
layer: "utilities",
|
|
options
|
|
},
|
|
wrapped
|
|
];
|
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
context.candidateRuleMap.set(prefixedIdentifier, []);
|
|
}
|
|
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets);
|
|
}
|
|
},
|
|
matchComponents: function(components, options) {
|
|
let defaultOptions = {
|
|
respectPrefix: true,
|
|
respectImportant: false
|
|
};
|
|
options = {
|
|
...defaultOptions,
|
|
...options
|
|
};
|
|
let offset = offsets.components++;
|
|
for(let identifier in components){
|
|
let prefixedIdentifier = prefixIdentifier(identifier, options);
|
|
let rule = components[identifier];
|
|
classList.add([
|
|
prefixedIdentifier,
|
|
options
|
|
]);
|
|
function wrapped(modifier, { isOnlyPlugin }) {
|
|
let { type ="any" } = options;
|
|
type = [].concat(type);
|
|
let [value, coercedType] = (0, _pluginUtils.coerceValue)(type, modifier, options, tailwindConfig);
|
|
if (value === undefined) {
|
|
return [];
|
|
}
|
|
if (!type.includes(coercedType)) {
|
|
if (isOnlyPlugin) {
|
|
_log.default.warn([
|
|
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
|
|
`You can safely update it to \`${identifier}-${modifier.replace(coercedType + ":", "")}\`.`,
|
|
]);
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
if (!(0, _isValidArbitraryValue.default)(value)) {
|
|
return [];
|
|
}
|
|
let ruleSets = [].concat(rule(value)).filter(Boolean).map((declaration)=>({
|
|
[(0, _nameClass.default)(identifier, modifier)]: declaration
|
|
}));
|
|
return ruleSets;
|
|
}
|
|
let withOffsets = [
|
|
{
|
|
sort: offset,
|
|
layer: "components",
|
|
options
|
|
},
|
|
wrapped
|
|
];
|
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
context.candidateRuleMap.set(prefixedIdentifier, []);
|
|
}
|
|
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets);
|
|
}
|
|
},
|
|
addVariant (variantName, variantFunctions, options = {}) {
|
|
variantFunctions = [].concat(variantFunctions).map((variantFunction)=>{
|
|
if (typeof variantFunction !== "string") {
|
|
// Safelist public API functions
|
|
return (api)=>{
|
|
let { args , modifySelectors , container , separator , wrap , format } = api;
|
|
let result = variantFunction(Object.assign({
|
|
modifySelectors,
|
|
container,
|
|
separator
|
|
}, variantFunction[MATCH_VARIANT] && {
|
|
args,
|
|
wrap,
|
|
format
|
|
}));
|
|
if (typeof result === "string" && !isValidVariantFormatString(result)) {
|
|
throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
|
|
}
|
|
if (Array.isArray(result)) {
|
|
return result.filter((variant)=>typeof variant === "string").map((variant)=>parseVariant(variant));
|
|
}
|
|
// result may be undefined with legacy variants that use APIs like `modifySelectors`
|
|
// result may also be a postcss node if someone was returning the result from `modifySelectors`
|
|
return result && typeof result === "string" && parseVariant(result)(api);
|
|
};
|
|
}
|
|
if (!isValidVariantFormatString(variantFunction)) {
|
|
throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
|
|
}
|
|
return parseVariant(variantFunction);
|
|
});
|
|
insertInto(variantList, variantName, options);
|
|
variantMap.set(variantName, variantFunctions);
|
|
}
|
|
};
|
|
if ((0, _featureFlagsJs.flagEnabled)(tailwindConfig, "matchVariant")) {
|
|
api.matchVariant = function(variants, options) {
|
|
for(let variant in variants){
|
|
var ref;
|
|
for (let [k, v] of Object.entries((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {})){
|
|
api.addVariant(`${variant}-${k}`, variants[variant](v));
|
|
}
|
|
api.addVariant(variant, Object.assign(({ args })=>variants[variant](args), {
|
|
[MATCH_VARIANT]: true
|
|
}), options);
|
|
}
|
|
};
|
|
}
|
|
return api;
|
|
}
|
|
let fileModifiedMapCache = new WeakMap();
|
|
function getFileModifiedMap(context) {
|
|
if (!fileModifiedMapCache.has(context)) {
|
|
fileModifiedMapCache.set(context, new Map());
|
|
}
|
|
return fileModifiedMapCache.get(context);
|
|
}
|
|
function trackModified(files, fileModifiedMap) {
|
|
let changed = false;
|
|
for (let file of files){
|
|
var ref;
|
|
if (!file) continue;
|
|
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 newModified = (ref = _fs.default.statSync(decodeURIComponent(pathname), {
|
|
throwIfNoEntry: false
|
|
})) === null || ref === void 0 ? void 0 : ref.mtimeMs;
|
|
if (!newModified) {
|
|
continue;
|
|
}
|
|
if (!fileModifiedMap.has(file) || newModified > fileModifiedMap.get(file)) {
|
|
changed = true;
|
|
}
|
|
fileModifiedMap.set(file, newModified);
|
|
}
|
|
return changed;
|
|
}
|
|
function extractVariantAtRules(node) {
|
|
node.walkAtRules((atRule)=>{
|
|
if ([
|
|
"responsive",
|
|
"variants"
|
|
].includes(atRule.name)) {
|
|
extractVariantAtRules(atRule);
|
|
atRule.before(atRule.nodes);
|
|
atRule.remove();
|
|
}
|
|
});
|
|
}
|
|
function collectLayerPlugins(root) {
|
|
let layerPlugins = [];
|
|
root.each((node)=>{
|
|
if (node.type === "atrule" && [
|
|
"responsive",
|
|
"variants"
|
|
].includes(node.name)) {
|
|
node.name = "layer";
|
|
node.params = "utilities";
|
|
}
|
|
});
|
|
// Walk @layer rules and treat them like plugins
|
|
root.walkAtRules("layer", (layerRule)=>{
|
|
extractVariantAtRules(layerRule);
|
|
if (layerRule.params === "base") {
|
|
for (let node of layerRule.nodes){
|
|
layerPlugins.push(function({ addBase }) {
|
|
addBase(node, {
|
|
respectPrefix: false
|
|
});
|
|
});
|
|
}
|
|
layerRule.remove();
|
|
} else if (layerRule.params === "components") {
|
|
for (let node1 of layerRule.nodes){
|
|
layerPlugins.push(function({ addComponents }) {
|
|
addComponents(node1, {
|
|
respectPrefix: false,
|
|
preserveSource: true
|
|
});
|
|
});
|
|
}
|
|
layerRule.remove();
|
|
} else if (layerRule.params === "utilities") {
|
|
for (let node2 of layerRule.nodes){
|
|
layerPlugins.push(function({ addUtilities }) {
|
|
addUtilities(node2, {
|
|
respectPrefix: false,
|
|
preserveSource: true
|
|
});
|
|
});
|
|
}
|
|
layerRule.remove();
|
|
}
|
|
});
|
|
return layerPlugins;
|
|
}
|
|
function resolvePlugins(context, root) {
|
|
let corePluginList = Object.entries({
|
|
..._corePlugins.variantPlugins,
|
|
..._corePlugins.corePlugins
|
|
}).map(([name, plugin])=>{
|
|
if (!context.tailwindConfig.corePlugins.includes(name)) {
|
|
return null;
|
|
}
|
|
return plugin;
|
|
}).filter(Boolean);
|
|
let userPlugins = context.tailwindConfig.plugins.map((plugin)=>{
|
|
if (plugin.__isOptionsFunction) {
|
|
plugin = plugin();
|
|
}
|
|
return typeof plugin === "function" ? plugin : plugin.handler;
|
|
});
|
|
let layerPlugins = collectLayerPlugins(root);
|
|
// TODO: This is a workaround for backwards compatibility, since custom variants
|
|
// were historically sorted before screen/stackable variants.
|
|
let beforeVariants = [
|
|
_corePlugins.variantPlugins["pseudoElementVariants"],
|
|
_corePlugins.variantPlugins["pseudoClassVariants"],
|
|
];
|
|
let afterVariants = [
|
|
_corePlugins.variantPlugins["directionVariants"],
|
|
_corePlugins.variantPlugins["reducedMotionVariants"],
|
|
_corePlugins.variantPlugins["prefersContrastVariants"],
|
|
_corePlugins.variantPlugins["darkVariants"],
|
|
_corePlugins.variantPlugins["printVariant"],
|
|
_corePlugins.variantPlugins["screenVariants"],
|
|
_corePlugins.variantPlugins["orientationVariants"],
|
|
];
|
|
return [
|
|
...corePluginList,
|
|
...beforeVariants,
|
|
...userPlugins,
|
|
...afterVariants,
|
|
...layerPlugins
|
|
];
|
|
}
|
|
function registerPlugins(plugins, context) {
|
|
let variantList = [];
|
|
let variantMap = new Map();
|
|
let offsets = {
|
|
defaults: 0n,
|
|
base: 0n,
|
|
components: 0n,
|
|
utilities: 0n,
|
|
user: 0n
|
|
};
|
|
let classList = new Set();
|
|
let pluginApi = buildPluginApi(context.tailwindConfig, context, {
|
|
variantList,
|
|
variantMap,
|
|
offsets,
|
|
classList
|
|
});
|
|
for (let plugin of plugins){
|
|
if (Array.isArray(plugin)) {
|
|
for (let pluginItem of plugin){
|
|
pluginItem(pluginApi);
|
|
}
|
|
} else {
|
|
plugin === null || plugin === void 0 ? void 0 : plugin(pluginApi);
|
|
}
|
|
}
|
|
let highestOffset = ((args)=>args.reduce((m, e)=>e > m ? e : m))([
|
|
offsets.base,
|
|
offsets.defaults,
|
|
offsets.components,
|
|
offsets.utilities,
|
|
offsets.user,
|
|
]);
|
|
let reservedBits = BigInt(highestOffset.toString(2).length);
|
|
// A number one less than the top range of the highest offset area
|
|
// so arbitrary properties are always sorted at the end.
|
|
context.arbitraryPropertiesSort = (1n << reservedBits << 0n) - 1n;
|
|
context.layerOrder = {
|
|
defaults: 1n << reservedBits << 0n,
|
|
base: 1n << reservedBits << 1n,
|
|
components: 1n << reservedBits << 2n,
|
|
utilities: 1n << reservedBits << 3n,
|
|
user: 1n << reservedBits << 4n
|
|
};
|
|
reservedBits += 5n;
|
|
let offset = 0;
|
|
context.variantOrder = new Map(variantList.map((variant, i)=>{
|
|
let variantFunctions = variantMap.get(variant).length;
|
|
let bits = 1n << BigInt(i + offset) << reservedBits;
|
|
offset += variantFunctions - 1;
|
|
return [
|
|
variant,
|
|
bits
|
|
];
|
|
}).sort(([, a], [, z])=>(0, _bigSign.default)(a - z)));
|
|
context.minimumScreen = [
|
|
...context.variantOrder.values()
|
|
].shift();
|
|
// Build variantMap
|
|
for (let [variantName, variantFunctions] of variantMap.entries()){
|
|
let sort = context.variantOrder.get(variantName);
|
|
context.variantMap.set(variantName, variantFunctions.map((variantFunction, idx)=>[
|
|
sort << BigInt(idx),
|
|
variantFunction
|
|
]));
|
|
}
|
|
var _safelist;
|
|
let safelist = ((_safelist = context.tailwindConfig.safelist) !== null && _safelist !== void 0 ? _safelist : []).filter(Boolean);
|
|
if (safelist.length > 0) {
|
|
let checks = [];
|
|
for (let value of safelist){
|
|
if (typeof value === "string") {
|
|
context.changedContent.push({
|
|
content: value,
|
|
extension: "html"
|
|
});
|
|
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",
|
|
]);
|
|
continue;
|
|
}
|
|
checks.push(value);
|
|
}
|
|
if (checks.length > 0) {
|
|
let patternMatchingCount = new Map();
|
|
let prefixLength = context.tailwindConfig.prefix.length;
|
|
for (let util of classList){
|
|
let utils = Array.isArray(util) ? (()=>{
|
|
let [utilName, options] = util;
|
|
var ref;
|
|
let values = Object.keys((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {});
|
|
let classes = values.map((value)=>(0, _nameClass.formatClass)(utilName, value));
|
|
if (options === null || options === void 0 ? void 0 : options.supportsNegativeValues) {
|
|
// This is the normal negated version
|
|
// e.g. `-inset-1` or `-tw-inset-1`
|
|
classes = [
|
|
...classes,
|
|
...classes.map((cls)=>"-" + cls)
|
|
];
|
|
// This is the negated version *after* the prefix
|
|
// e.g. `tw--inset-1`
|
|
// The prefix is already attached to util name
|
|
// So we add the negative after the prefix
|
|
classes = [
|
|
...classes,
|
|
...classes.map((cls)=>cls.slice(0, prefixLength) + "-" + cls.slice(prefixLength)),
|
|
];
|
|
}
|
|
if ([].concat(options === null || options === void 0 ? void 0 : options.type).includes("color")) {
|
|
classes = [
|
|
...classes,
|
|
...classes.flatMap((cls)=>Object.keys(context.tailwindConfig.theme.opacity).map((opacity)=>`${cls}/${opacity}`)),
|
|
];
|
|
}
|
|
return classes;
|
|
})() : [
|
|
util
|
|
];
|
|
for (let util1 of utils){
|
|
for (let { pattern , variants =[] } of checks){
|
|
// RegExp with the /g flag are stateful, so let's reset the last
|
|
// index pointer to reset the state.
|
|
pattern.lastIndex = 0;
|
|
if (!patternMatchingCount.has(pattern)) {
|
|
patternMatchingCount.set(pattern, 0);
|
|
}
|
|
if (!pattern.test(util1)) continue;
|
|
patternMatchingCount.set(pattern, patternMatchingCount.get(pattern) + 1);
|
|
context.changedContent.push({
|
|
content: util1,
|
|
extension: "html"
|
|
});
|
|
for (let variant of variants){
|
|
context.changedContent.push({
|
|
content: variant + context.tailwindConfig.separator + util1,
|
|
extension: "html"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let [regex, count] of patternMatchingCount.entries()){
|
|
if (count !== 0) continue;
|
|
_log.default.warn([
|
|
`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",
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
// A list of utilities that are used by certain Tailwind CSS utilities but
|
|
// that don't exist on their own. This will result in them "not existing" and
|
|
// sorting could be weird since you still require them in order to make the
|
|
// host utitlies work properly. (Thanks Biology)
|
|
let parasiteUtilities = new Set([
|
|
prefix(context, "group"),
|
|
prefix(context, "peer")
|
|
]);
|
|
context.getClassOrder = function getClassOrder(classes) {
|
|
let sortedClassNames = new Map();
|
|
for (let [sort, rule] of (0, _generateRules.generateRules)(new Set(classes), context)){
|
|
if (sortedClassNames.has(rule.raws.tailwind.candidate)) continue;
|
|
sortedClassNames.set(rule.raws.tailwind.candidate, sort);
|
|
}
|
|
return classes.map((className)=>{
|
|
var ref;
|
|
let order = (ref = sortedClassNames.get(className)) !== null && ref !== void 0 ? ref : null;
|
|
if (order === null && parasiteUtilities.has(className)) {
|
|
// This will make sure that it is at the very beginning of the
|
|
// `components` layer which technically means 'before any
|
|
// components'.
|
|
order = context.layerOrder.components;
|
|
}
|
|
return [
|
|
className,
|
|
order
|
|
];
|
|
});
|
|
};
|
|
// Generate a list of strings for autocompletion purposes, e.g.
|
|
// ['uppercase', 'lowercase', ...]
|
|
context.getClassList = function getClassList() {
|
|
let output = [];
|
|
for (let util of classList){
|
|
if (Array.isArray(util)) {
|
|
let [utilName, options] = util;
|
|
let negativeClasses = [];
|
|
var ref;
|
|
for (let [key, value] of Object.entries((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {})){
|
|
output.push((0, _nameClass.formatClass)(utilName, key));
|
|
if ((options === null || options === void 0 ? void 0 : options.supportsNegativeValues) && (0, _negateValue.default)(value)) {
|
|
negativeClasses.push((0, _nameClass.formatClass)(utilName, `-${key}`));
|
|
}
|
|
}
|
|
output.push(...negativeClasses);
|
|
} else {
|
|
output.push(util);
|
|
}
|
|
}
|
|
return output;
|
|
};
|
|
}
|
|
function createContext(tailwindConfig, changedContent = [], root = _postcss.default.root()) {
|
|
let context = {
|
|
disposables: [],
|
|
ruleCache: new Set(),
|
|
classCache: new Map(),
|
|
applyClassCache: new Map(),
|
|
notClassCache: new Set(),
|
|
postCssNodeCache: new Map(),
|
|
candidateRuleMap: new Map(),
|
|
tailwindConfig,
|
|
changedContent: changedContent,
|
|
variantMap: new Map(),
|
|
stylesheetCache: null
|
|
};
|
|
let resolvedPlugins = resolvePlugins(context, root);
|
|
registerPlugins(resolvedPlugins, context);
|
|
return context;
|
|
}
|
|
let contextMap = _sharedState.contextMap;
|
|
let configContextMap = _sharedState.configContextMap;
|
|
let contextSourcesMap = _sharedState.contextSourcesMap;
|
|
function getContext(root, result, tailwindConfig, userConfigPath, tailwindConfigHash, contextDependencies) {
|
|
let sourcePath = result.opts.from;
|
|
let isConfigFile = userConfigPath !== null;
|
|
_sharedState.env.DEBUG && console.log("Source path:", sourcePath);
|
|
let existingContext;
|
|
if (isConfigFile && contextMap.has(sourcePath)) {
|
|
existingContext = contextMap.get(sourcePath);
|
|
} else if (configContextMap.has(tailwindConfigHash)) {
|
|
let context = configContextMap.get(tailwindConfigHash);
|
|
contextSourcesMap.get(context).add(sourcePath);
|
|
contextMap.set(sourcePath, context);
|
|
existingContext = context;
|
|
}
|
|
let cssDidChange = (0, _cacheInvalidationJs.hasContentChanged)(sourcePath, root);
|
|
// If there's already a context in the cache and we don't need to
|
|
// reset the context, return the cached context.
|
|
if (existingContext) {
|
|
let contextDependenciesChanged = trackModified([
|
|
...contextDependencies
|
|
], getFileModifiedMap(existingContext));
|
|
if (!contextDependenciesChanged && !cssDidChange) {
|
|
return [
|
|
existingContext,
|
|
false
|
|
];
|
|
}
|
|
}
|
|
// If this source is in the context map, get the old context.
|
|
// Remove this source from the context sources for the old context,
|
|
// and clean up that context if no one else is using it. This can be
|
|
// called by many processes in rapid succession, so we check for presence
|
|
// first because the first process to run this code will wipe it out first.
|
|
if (contextMap.has(sourcePath)) {
|
|
let oldContext = contextMap.get(sourcePath);
|
|
if (contextSourcesMap.has(oldContext)) {
|
|
contextSourcesMap.get(oldContext).delete(sourcePath);
|
|
if (contextSourcesMap.get(oldContext).size === 0) {
|
|
contextSourcesMap.delete(oldContext);
|
|
for (let [tailwindConfigHash1, context1] of configContextMap){
|
|
if (context1 === oldContext) {
|
|
configContextMap.delete(tailwindConfigHash1);
|
|
}
|
|
}
|
|
for (let disposable of oldContext.disposables.splice(0)){
|
|
disposable(oldContext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_sharedState.env.DEBUG && console.log("Setting up new context...");
|
|
let context2 = createContext(tailwindConfig, [], root);
|
|
trackModified([
|
|
...contextDependencies
|
|
], getFileModifiedMap(context2));
|
|
// ---
|
|
// Update all context tracking state
|
|
configContextMap.set(tailwindConfigHash, context2);
|
|
contextMap.set(sourcePath, context2);
|
|
if (!contextSourcesMap.has(context2)) {
|
|
contextSourcesMap.set(context2, new Set());
|
|
}
|
|
contextSourcesMap.get(context2).add(sourcePath);
|
|
return [
|
|
context2,
|
|
true
|
|
];
|
|
}
|