You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
8.9 KiB
JavaScript
244 lines
8.9 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "defaultExtractor", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return defaultExtractor;
|
|
}
|
|
});
|
|
const _featureFlags = require("../featureFlags");
|
|
const _regex = /*#__PURE__*/ _interop_require_wildcard(require("./regex"));
|
|
function _getRequireWildcardCache(nodeInterop) {
|
|
if (typeof WeakMap !== "function") return null;
|
|
var cacheBabelInterop = new WeakMap();
|
|
var cacheNodeInterop = new WeakMap();
|
|
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
})(nodeInterop);
|
|
}
|
|
function _interop_require_wildcard(obj, nodeInterop) {
|
|
if (!nodeInterop && obj && obj.__esModule) {
|
|
return obj;
|
|
}
|
|
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
return {
|
|
default: obj
|
|
};
|
|
}
|
|
var cache = _getRequireWildcardCache(nodeInterop);
|
|
if (cache && cache.has(obj)) {
|
|
return cache.get(obj);
|
|
}
|
|
var newObj = {};
|
|
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
for(var key in obj){
|
|
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
if (desc && (desc.get || desc.set)) {
|
|
Object.defineProperty(newObj, key, desc);
|
|
} else {
|
|
newObj[key] = obj[key];
|
|
}
|
|
}
|
|
}
|
|
newObj.default = obj;
|
|
if (cache) {
|
|
cache.set(obj, newObj);
|
|
}
|
|
return newObj;
|
|
}
|
|
function defaultExtractor(context) {
|
|
let patterns = Array.from(buildRegExps(context));
|
|
/**
|
|
* @param {string} content
|
|
*/ return (content)=>{
|
|
/** @type {(string|string)[]} */ let results = [];
|
|
for (let pattern of patterns){
|
|
var _content_match;
|
|
results = [
|
|
...results,
|
|
...(_content_match = content.match(pattern)) !== null && _content_match !== void 0 ? _content_match : []
|
|
];
|
|
}
|
|
return results.filter((v)=>v !== undefined).map(clipAtBalancedParens);
|
|
};
|
|
}
|
|
function* buildRegExps(context) {
|
|
let separator = context.tailwindConfig.separator;
|
|
let variantGroupingEnabled = (0, _featureFlags.flagEnabled)(context.tailwindConfig, "variantGrouping");
|
|
let prefix = context.tailwindConfig.prefix !== "" ? _regex.optional(_regex.pattern([
|
|
/-?/,
|
|
_regex.escape(context.tailwindConfig.prefix)
|
|
])) : "";
|
|
let utility = _regex.any([
|
|
// Arbitrary properties (without square brackets)
|
|
/\[[^\s:'"`]+:[^\s\[\]]+\]/,
|
|
// Arbitrary properties with balanced square brackets
|
|
// This is a targeted fix to continue to allow theme()
|
|
// with square brackets to work in arbitrary properties
|
|
// while fixing a problem with the regex matching too much
|
|
/\[[^\s:'"`]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
|
|
// Utilities
|
|
_regex.pattern([
|
|
// Utility Name / Group Name
|
|
/-?(?:\w+)/,
|
|
// Normal/Arbitrary values
|
|
_regex.optional(_regex.any([
|
|
_regex.pattern([
|
|
// Arbitrary values
|
|
/-(?:\w+-)*\[[^\s:]+\]/,
|
|
// Not immediately followed by an `{[(`
|
|
/(?![{([]])/,
|
|
// optionally followed by an opacity modifier
|
|
/(?:\/[^\s'"`\\><$]*)?/
|
|
]),
|
|
_regex.pattern([
|
|
// Arbitrary values
|
|
/-(?:\w+-)*\[[^\s]+\]/,
|
|
// Not immediately followed by an `{[(`
|
|
/(?![{([]])/,
|
|
// optionally followed by an opacity modifier
|
|
/(?:\/[^\s'"`\\$]*)?/
|
|
]),
|
|
// Normal values w/o quotes — may include an opacity modifier
|
|
/[-\/][^\s'"`\\$={><]*/
|
|
]))
|
|
])
|
|
]);
|
|
let variantPatterns = [
|
|
// Without quotes
|
|
_regex.any([
|
|
// This is here to provide special support for the `@` variant
|
|
_regex.pattern([
|
|
/@\[[^\s"'`]+\](\/[^\s"'`]+)?/,
|
|
separator
|
|
]),
|
|
_regex.pattern([
|
|
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,
|
|
separator
|
|
]),
|
|
_regex.pattern([
|
|
/[^\s"'`\[\\]+/,
|
|
separator
|
|
])
|
|
]),
|
|
// With quotes allowed
|
|
_regex.any([
|
|
_regex.pattern([
|
|
/([^\s"'`\[\\]+-)?\[[^\s`]+\]/,
|
|
separator
|
|
]),
|
|
_regex.pattern([
|
|
/[^\s`\[\\]+/,
|
|
separator
|
|
])
|
|
])
|
|
];
|
|
for (const variantPattern of variantPatterns){
|
|
yield _regex.pattern([
|
|
// Variants
|
|
"((?=((",
|
|
variantPattern,
|
|
")+))\\2)?",
|
|
// Important (optional)
|
|
/!?/,
|
|
prefix,
|
|
variantGroupingEnabled ? _regex.any([
|
|
// Or any of those things but grouped separated by commas
|
|
_regex.pattern([
|
|
/\(/,
|
|
utility,
|
|
_regex.zeroOrMore([
|
|
/,/,
|
|
utility
|
|
]),
|
|
/\)/
|
|
]),
|
|
// Arbitrary properties, constrained utilities, arbitrary values, etc…
|
|
utility
|
|
]) : utility
|
|
]);
|
|
}
|
|
// 5. Inner matches
|
|
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
|
|
}
|
|
// We want to capture any "special" characters
|
|
// AND the characters immediately following them (if there is one)
|
|
let SPECIALS = /([\[\]'"`])([^\[\]'"`])?/g;
|
|
let ALLOWED_CLASS_CHARACTERS = /[^"'`\s<>\]]+/;
|
|
/**
|
|
* Clips a string ensuring that parentheses, quotes, etc… are balanced
|
|
* Used for arbitrary values only
|
|
*
|
|
* We will go past the end of the balanced parens until we find a non-class character
|
|
*
|
|
* Depth matching behavior:
|
|
* w-[calc(100%-theme('spacing[some_key][1.5]'))]']
|
|
* ┬ ┬ ┬┬ ┬ ┬┬ ┬┬┬┬┬┬┬
|
|
* 1 2 3 4 34 3 210 END
|
|
* ╰────┴──────────┴────────┴────────┴┴───┴─┴┴┴
|
|
*
|
|
* @param {string} input
|
|
*/ function clipAtBalancedParens(input) {
|
|
// We are care about this for arbitrary values
|
|
if (!input.includes("-[")) {
|
|
return input;
|
|
}
|
|
let depth = 0;
|
|
let openStringTypes = [];
|
|
// Find all parens, brackets, quotes, etc
|
|
// Stop when we end at a balanced pair
|
|
// This is naive and will treat mismatched parens as balanced
|
|
// This shouldn't be a problem in practice though
|
|
let matches = input.matchAll(SPECIALS);
|
|
// We can't use lookbehind assertions because we have to support Safari
|
|
// So, instead, we've emulated it using capture groups and we'll re-work the matches to accommodate
|
|
matches = Array.from(matches).flatMap((match)=>{
|
|
const [, ...groups] = match;
|
|
return groups.map((group, idx)=>Object.assign([], match, {
|
|
index: match.index + idx,
|
|
0: group
|
|
}));
|
|
});
|
|
for (let match of matches){
|
|
let char = match[0];
|
|
let inStringType = openStringTypes[openStringTypes.length - 1];
|
|
if (char === inStringType) {
|
|
openStringTypes.pop();
|
|
} else if (char === "'" || char === '"' || char === "`") {
|
|
openStringTypes.push(char);
|
|
}
|
|
if (inStringType) {
|
|
continue;
|
|
} else if (char === "[") {
|
|
depth++;
|
|
continue;
|
|
} else if (char === "]") {
|
|
depth--;
|
|
continue;
|
|
}
|
|
// We've gone one character past the point where we should stop
|
|
// This means that there was an extra closing `]`
|
|
// We'll clip to just before it
|
|
if (depth < 0) {
|
|
return input.substring(0, match.index - 1);
|
|
}
|
|
// We've finished balancing the brackets but there still may be characters that can be included
|
|
// For example in the class `text-[#336699]/[.35]`
|
|
// The depth goes to `0` at the closing `]` but goes up again at the `[`
|
|
// If we're at zero and encounter a non-class character then we clip the class there
|
|
if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
|
|
return input.substring(0, match.index);
|
|
}
|
|
}
|
|
return input;
|
|
} // Regular utilities
|
|
// {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
|
|
// Arbitrary values
|
|
// {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
|
|
// arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
|
|
// Arbitrary properties
|
|
// {{modifier}:}*[{validCssPropertyName}:{arbitraryValue}]
|