Updated node modules
This commit is contained in:
27
node_modules/tailwindcss/src/util/applyImportantSelector.js
generated
vendored
Normal file
27
node_modules/tailwindcss/src/util/applyImportantSelector.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import parser from 'postcss-selector-parser'
|
||||
import { movePseudos } from './pseudoElements'
|
||||
|
||||
export function applyImportantSelector(selector, important) {
|
||||
let sel = parser().astSync(selector)
|
||||
|
||||
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) {
|
||||
sel.nodes = [
|
||||
parser.pseudo({
|
||||
value: ':is',
|
||||
nodes: [sel.clone()],
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
movePseudos(sel)
|
||||
})
|
||||
|
||||
return `${important} ${sel.toString()}`
|
||||
}
|
||||
3
node_modules/tailwindcss/src/util/bigSign.js
generated
vendored
Normal file
3
node_modules/tailwindcss/src/util/bigSign.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function bigSign(bigIntValue) {
|
||||
return (bigIntValue > 0n) - (bigIntValue < 0n)
|
||||
}
|
||||
22
node_modules/tailwindcss/src/util/buildMediaQuery.js
generated
vendored
Normal file
22
node_modules/tailwindcss/src/util/buildMediaQuery.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
export default function buildMediaQuery(screens) {
|
||||
screens = Array.isArray(screens) ? screens : [screens]
|
||||
|
||||
return screens
|
||||
.map((screen) => {
|
||||
let values = screen.values.map((screen) => {
|
||||
if (screen.raw !== undefined) {
|
||||
return screen.raw
|
||||
}
|
||||
|
||||
return [
|
||||
screen.min && `(min-width: ${screen.min})`,
|
||||
screen.max && `(max-width: ${screen.max})`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' and ')
|
||||
})
|
||||
|
||||
return screen.not ? `not all and ${values}` : values
|
||||
})
|
||||
.join(', ')
|
||||
}
|
||||
11
node_modules/tailwindcss/src/util/cloneDeep.js
generated
vendored
Normal file
11
node_modules/tailwindcss/src/util/cloneDeep.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
export function cloneDeep(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((child) => cloneDeep(child))
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, cloneDeep(v)]))
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
28
node_modules/tailwindcss/src/util/cloneNodes.js
generated
vendored
Normal file
28
node_modules/tailwindcss/src/util/cloneNodes.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
export default function cloneNodes(nodes, source = undefined, raws = undefined) {
|
||||
return nodes.map((node) => {
|
||||
let cloned = node.clone()
|
||||
|
||||
// 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) {
|
||||
cloned.raws.tailwind = {
|
||||
...cloned.raws.tailwind,
|
||||
...raws,
|
||||
}
|
||||
}
|
||||
|
||||
return cloned
|
||||
})
|
||||
}
|
||||
88
node_modules/tailwindcss/src/util/color.js
generated
vendored
Normal file
88
node_modules/tailwindcss/src/util/color.js
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
import namedColors from './colorNames'
|
||||
|
||||
let HEX = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i
|
||||
let SHORT_HEX = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i
|
||||
let VALUE = /(?:\d+|\d*\.\d+)%?/
|
||||
let SEP = /(?:\s*,\s*|\s+)/
|
||||
let ALPHA_SEP = /\s*[,/]\s*/
|
||||
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/
|
||||
|
||||
let RGB = new RegExp(
|
||||
`^(rgba?)\\(\\s*(${VALUE.source}|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`
|
||||
)
|
||||
let HSL = new RegExp(
|
||||
`^(hsla?)\\(\\s*((?:${VALUE.source})(?:deg|rad|grad|turn)?|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`
|
||||
)
|
||||
|
||||
// In "loose" mode the color may contain fewer than 3 parts, as long as at least
|
||||
// one of the parts is variable.
|
||||
export function parseColor(value, { loose = false } = {}) {
|
||||
if (typeof value !== 'string') {
|
||||
return null
|
||||
}
|
||||
|
||||
value = value.trim()
|
||||
if (value === 'transparent') {
|
||||
return { mode: 'rgb', color: ['0', '0', '0'], alpha: '0' }
|
||||
}
|
||||
|
||||
if (value in namedColors) {
|
||||
return { mode: 'rgb', color: namedColors[value].map((v) => v.toString()) }
|
||||
}
|
||||
|
||||
let hex = value
|
||||
.replace(SHORT_HEX, (_, r, g, b, a) => ['#', r, r, g, g, b, b, a ? a + a : ''].join(''))
|
||||
.match(HEX)
|
||||
|
||||
if (hex !== null) {
|
||||
return {
|
||||
mode: 'rgb',
|
||||
color: [parseInt(hex[1], 16), parseInt(hex[2], 16), parseInt(hex[3], 16)].map((v) =>
|
||||
v.toString()
|
||||
),
|
||||
alpha: hex[4] ? (parseInt(hex[4], 16) / 255).toString() : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
let match = value.match(RGB) ?? value.match(HSL)
|
||||
|
||||
if (match === null) {
|
||||
return null
|
||||
}
|
||||
|
||||
let color = [match[2], match[3], match[4]].filter(Boolean).map((v) => v.toString())
|
||||
|
||||
// rgba(var(--my-color), 0.1)
|
||||
// hsla(var(--my-color), 0.1)
|
||||
if (color.length === 2 && color[0].startsWith('var(')) {
|
||||
return {
|
||||
mode: match[1],
|
||||
color: [color[0]],
|
||||
alpha: color[1],
|
||||
}
|
||||
}
|
||||
|
||||
if (!loose && color.length !== 3) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (color.length < 3 && !color.some((part) => /^var\(.*?\)$/.test(part))) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
mode: match[1],
|
||||
color,
|
||||
alpha: match[5]?.toString?.(),
|
||||
}
|
||||
}
|
||||
|
||||
export function formatColor({ mode, color, alpha }) {
|
||||
let hasAlpha = alpha !== undefined
|
||||
|
||||
if (mode === 'rgba' || mode === 'hsla') {
|
||||
return `${mode}(${color.join(', ')}${hasAlpha ? `, ${alpha}` : ''})`
|
||||
}
|
||||
|
||||
return `${mode}(${color.join(' ')}${hasAlpha ? ` / ${alpha}` : ''})`
|
||||
}
|
||||
150
node_modules/tailwindcss/src/util/colorNames.js
generated
vendored
Normal file
150
node_modules/tailwindcss/src/util/colorNames.js
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
export default {
|
||||
aliceblue: [240, 248, 255],
|
||||
antiquewhite: [250, 235, 215],
|
||||
aqua: [0, 255, 255],
|
||||
aquamarine: [127, 255, 212],
|
||||
azure: [240, 255, 255],
|
||||
beige: [245, 245, 220],
|
||||
bisque: [255, 228, 196],
|
||||
black: [0, 0, 0],
|
||||
blanchedalmond: [255, 235, 205],
|
||||
blue: [0, 0, 255],
|
||||
blueviolet: [138, 43, 226],
|
||||
brown: [165, 42, 42],
|
||||
burlywood: [222, 184, 135],
|
||||
cadetblue: [95, 158, 160],
|
||||
chartreuse: [127, 255, 0],
|
||||
chocolate: [210, 105, 30],
|
||||
coral: [255, 127, 80],
|
||||
cornflowerblue: [100, 149, 237],
|
||||
cornsilk: [255, 248, 220],
|
||||
crimson: [220, 20, 60],
|
||||
cyan: [0, 255, 255],
|
||||
darkblue: [0, 0, 139],
|
||||
darkcyan: [0, 139, 139],
|
||||
darkgoldenrod: [184, 134, 11],
|
||||
darkgray: [169, 169, 169],
|
||||
darkgreen: [0, 100, 0],
|
||||
darkgrey: [169, 169, 169],
|
||||
darkkhaki: [189, 183, 107],
|
||||
darkmagenta: [139, 0, 139],
|
||||
darkolivegreen: [85, 107, 47],
|
||||
darkorange: [255, 140, 0],
|
||||
darkorchid: [153, 50, 204],
|
||||
darkred: [139, 0, 0],
|
||||
darksalmon: [233, 150, 122],
|
||||
darkseagreen: [143, 188, 143],
|
||||
darkslateblue: [72, 61, 139],
|
||||
darkslategray: [47, 79, 79],
|
||||
darkslategrey: [47, 79, 79],
|
||||
darkturquoise: [0, 206, 209],
|
||||
darkviolet: [148, 0, 211],
|
||||
deeppink: [255, 20, 147],
|
||||
deepskyblue: [0, 191, 255],
|
||||
dimgray: [105, 105, 105],
|
||||
dimgrey: [105, 105, 105],
|
||||
dodgerblue: [30, 144, 255],
|
||||
firebrick: [178, 34, 34],
|
||||
floralwhite: [255, 250, 240],
|
||||
forestgreen: [34, 139, 34],
|
||||
fuchsia: [255, 0, 255],
|
||||
gainsboro: [220, 220, 220],
|
||||
ghostwhite: [248, 248, 255],
|
||||
gold: [255, 215, 0],
|
||||
goldenrod: [218, 165, 32],
|
||||
gray: [128, 128, 128],
|
||||
green: [0, 128, 0],
|
||||
greenyellow: [173, 255, 47],
|
||||
grey: [128, 128, 128],
|
||||
honeydew: [240, 255, 240],
|
||||
hotpink: [255, 105, 180],
|
||||
indianred: [205, 92, 92],
|
||||
indigo: [75, 0, 130],
|
||||
ivory: [255, 255, 240],
|
||||
khaki: [240, 230, 140],
|
||||
lavender: [230, 230, 250],
|
||||
lavenderblush: [255, 240, 245],
|
||||
lawngreen: [124, 252, 0],
|
||||
lemonchiffon: [255, 250, 205],
|
||||
lightblue: [173, 216, 230],
|
||||
lightcoral: [240, 128, 128],
|
||||
lightcyan: [224, 255, 255],
|
||||
lightgoldenrodyellow: [250, 250, 210],
|
||||
lightgray: [211, 211, 211],
|
||||
lightgreen: [144, 238, 144],
|
||||
lightgrey: [211, 211, 211],
|
||||
lightpink: [255, 182, 193],
|
||||
lightsalmon: [255, 160, 122],
|
||||
lightseagreen: [32, 178, 170],
|
||||
lightskyblue: [135, 206, 250],
|
||||
lightslategray: [119, 136, 153],
|
||||
lightslategrey: [119, 136, 153],
|
||||
lightsteelblue: [176, 196, 222],
|
||||
lightyellow: [255, 255, 224],
|
||||
lime: [0, 255, 0],
|
||||
limegreen: [50, 205, 50],
|
||||
linen: [250, 240, 230],
|
||||
magenta: [255, 0, 255],
|
||||
maroon: [128, 0, 0],
|
||||
mediumaquamarine: [102, 205, 170],
|
||||
mediumblue: [0, 0, 205],
|
||||
mediumorchid: [186, 85, 211],
|
||||
mediumpurple: [147, 112, 219],
|
||||
mediumseagreen: [60, 179, 113],
|
||||
mediumslateblue: [123, 104, 238],
|
||||
mediumspringgreen: [0, 250, 154],
|
||||
mediumturquoise: [72, 209, 204],
|
||||
mediumvioletred: [199, 21, 133],
|
||||
midnightblue: [25, 25, 112],
|
||||
mintcream: [245, 255, 250],
|
||||
mistyrose: [255, 228, 225],
|
||||
moccasin: [255, 228, 181],
|
||||
navajowhite: [255, 222, 173],
|
||||
navy: [0, 0, 128],
|
||||
oldlace: [253, 245, 230],
|
||||
olive: [128, 128, 0],
|
||||
olivedrab: [107, 142, 35],
|
||||
orange: [255, 165, 0],
|
||||
orangered: [255, 69, 0],
|
||||
orchid: [218, 112, 214],
|
||||
palegoldenrod: [238, 232, 170],
|
||||
palegreen: [152, 251, 152],
|
||||
paleturquoise: [175, 238, 238],
|
||||
palevioletred: [219, 112, 147],
|
||||
papayawhip: [255, 239, 213],
|
||||
peachpuff: [255, 218, 185],
|
||||
peru: [205, 133, 63],
|
||||
pink: [255, 192, 203],
|
||||
plum: [221, 160, 221],
|
||||
powderblue: [176, 224, 230],
|
||||
purple: [128, 0, 128],
|
||||
rebeccapurple: [102, 51, 153],
|
||||
red: [255, 0, 0],
|
||||
rosybrown: [188, 143, 143],
|
||||
royalblue: [65, 105, 225],
|
||||
saddlebrown: [139, 69, 19],
|
||||
salmon: [250, 128, 114],
|
||||
sandybrown: [244, 164, 96],
|
||||
seagreen: [46, 139, 87],
|
||||
seashell: [255, 245, 238],
|
||||
sienna: [160, 82, 45],
|
||||
silver: [192, 192, 192],
|
||||
skyblue: [135, 206, 235],
|
||||
slateblue: [106, 90, 205],
|
||||
slategray: [112, 128, 144],
|
||||
slategrey: [112, 128, 144],
|
||||
snow: [255, 250, 250],
|
||||
springgreen: [0, 255, 127],
|
||||
steelblue: [70, 130, 180],
|
||||
tan: [210, 180, 140],
|
||||
teal: [0, 128, 128],
|
||||
thistle: [216, 191, 216],
|
||||
tomato: [255, 99, 71],
|
||||
turquoise: [64, 224, 208],
|
||||
violet: [238, 130, 238],
|
||||
wheat: [245, 222, 179],
|
||||
white: [255, 255, 255],
|
||||
whitesmoke: [245, 245, 245],
|
||||
yellow: [255, 255, 0],
|
||||
yellowgreen: [154, 205, 50],
|
||||
}
|
||||
23
node_modules/tailwindcss/src/util/configurePlugins.js
generated
vendored
Normal file
23
node_modules/tailwindcss/src/util/configurePlugins.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export default function (pluginConfig, plugins) {
|
||||
if (pluginConfig === undefined) {
|
||||
return plugins
|
||||
}
|
||||
|
||||
const pluginNames = Array.isArray(pluginConfig)
|
||||
? pluginConfig
|
||||
: [
|
||||
...new Set(
|
||||
plugins
|
||||
.filter((pluginName) => {
|
||||
return pluginConfig !== false && pluginConfig[pluginName] !== false
|
||||
})
|
||||
.concat(
|
||||
Object.keys(pluginConfig).filter((pluginName) => {
|
||||
return pluginConfig[pluginName] !== false
|
||||
})
|
||||
)
|
||||
),
|
||||
]
|
||||
|
||||
return pluginNames
|
||||
}
|
||||
27
node_modules/tailwindcss/src/util/createPlugin.js
generated
vendored
Normal file
27
node_modules/tailwindcss/src/util/createPlugin.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
function createPlugin(plugin, config) {
|
||||
return {
|
||||
handler: plugin,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
createPlugin.withOptions = function (pluginFunction, configFunction = () => ({})) {
|
||||
const optionsFunction = function (options) {
|
||||
return {
|
||||
__options: options,
|
||||
handler: pluginFunction(options),
|
||||
config: configFunction(options),
|
||||
}
|
||||
}
|
||||
|
||||
optionsFunction.__isOptionsFunction = true
|
||||
|
||||
// Expose plugin dependencies so that `object-hash` returns a different
|
||||
// value if anything here changes, to ensure a rebuild is triggered.
|
||||
optionsFunction.__pluginFunction = pluginFunction
|
||||
optionsFunction.__configFunction = configFunction
|
||||
|
||||
return optionsFunction
|
||||
}
|
||||
|
||||
export default createPlugin
|
||||
37
node_modules/tailwindcss/src/util/createUtilityPlugin.js
generated
vendored
Normal file
37
node_modules/tailwindcss/src/util/createUtilityPlugin.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import transformThemeValue from './transformThemeValue'
|
||||
|
||||
export default function createUtilityPlugin(
|
||||
themeKey,
|
||||
utilityVariations = [[themeKey, [themeKey]]],
|
||||
{ filterDefault = false, ...options } = {}
|
||||
) {
|
||||
let transformValue = transformThemeValue(themeKey)
|
||||
return function ({ matchUtilities, theme }) {
|
||||
for (let utilityVariation of utilityVariations) {
|
||||
let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [utilityVariation]
|
||||
|
||||
matchUtilities(
|
||||
group.reduce((obj, [classPrefix, properties]) => {
|
||||
return Object.assign(obj, {
|
||||
[classPrefix]: (value) => {
|
||||
return properties.reduce((obj, name) => {
|
||||
if (Array.isArray(name)) {
|
||||
return Object.assign(obj, { [name[0]]: name[1] })
|
||||
}
|
||||
return Object.assign(obj, { [name]: transformValue(value) })
|
||||
}, {})
|
||||
},
|
||||
})
|
||||
}, {}),
|
||||
{
|
||||
...options,
|
||||
values: filterDefault
|
||||
? Object.fromEntries(
|
||||
Object.entries(theme(themeKey) ?? {}).filter(([modifier]) => modifier !== 'DEFAULT')
|
||||
)
|
||||
: theme(themeKey),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
292
node_modules/tailwindcss/src/util/dataTypes.js
generated
vendored
Normal file
292
node_modules/tailwindcss/src/util/dataTypes.js
generated
vendored
Normal file
@@ -0,0 +1,292 @@
|
||||
import { parseColor } from './color'
|
||||
import { parseBoxShadowValue } from './parseBoxShadowValue'
|
||||
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
|
||||
|
||||
let cssFunctions = ['min', 'max', 'clamp', 'calc']
|
||||
|
||||
// Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types
|
||||
|
||||
function isCSSFunction(value) {
|
||||
return cssFunctions.some((fn) => new RegExp(`^${fn}\\(.*\\)`).test(value))
|
||||
}
|
||||
|
||||
const placeholder = '--tw-placeholder'
|
||||
const placeholderRe = new RegExp(placeholder, 'g')
|
||||
|
||||
// This is not a data type, but rather a function that can normalize the
|
||||
// correct values.
|
||||
export function normalize(value, isRoot = true) {
|
||||
if (value.startsWith('--')) {
|
||||
return `var(${value})`
|
||||
}
|
||||
|
||||
// Keep raw strings if it starts with `url(`
|
||||
if (value.includes('url(')) {
|
||||
return value
|
||||
.split(/(url\(.*?\))/g)
|
||||
.filter(Boolean)
|
||||
.map((part) => {
|
||||
if (/^url\(.*?\)$/.test(part)) {
|
||||
return part
|
||||
}
|
||||
|
||||
return normalize(part, false)
|
||||
})
|
||||
.join('')
|
||||
}
|
||||
|
||||
// Convert `_` to ` `, except for escaped underscores `\_`
|
||||
value = value
|
||||
.replace(
|
||||
/([^\\])_+/g,
|
||||
(fullMatch, characterBefore) => characterBefore + ' '.repeat(fullMatch.length - 1)
|
||||
)
|
||||
.replace(/^_/g, ' ')
|
||||
.replace(/\\_/g, '_')
|
||||
|
||||
// Remove leftover whitespace
|
||||
if (isRoot) {
|
||||
value = value.trim()
|
||||
}
|
||||
|
||||
value = normalizeMathOperatorSpacing(value)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Add spaces around operators inside math functions
|
||||
* like calc() that do not follow an operator or '('.
|
||||
*
|
||||
* @param {string} value
|
||||
* @returns {string}
|
||||
*/
|
||||
function normalizeMathOperatorSpacing(value) {
|
||||
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
|
||||
let vars = []
|
||||
|
||||
return match
|
||||
.replace(/var\((--.+?)[,)]/g, (match, g1) => {
|
||||
vars.push(g1)
|
||||
return match.replace(g1, placeholder)
|
||||
})
|
||||
.replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ')
|
||||
.replace(placeholderRe, () => vars.shift())
|
||||
})
|
||||
}
|
||||
|
||||
export function url(value) {
|
||||
return value.startsWith('url(')
|
||||
}
|
||||
|
||||
export function number(value) {
|
||||
return !isNaN(Number(value)) || isCSSFunction(value)
|
||||
}
|
||||
|
||||
export function percentage(value) {
|
||||
return (value.endsWith('%') && number(value.slice(0, -1))) || isCSSFunction(value)
|
||||
}
|
||||
|
||||
// Please refer to MDN when updating this list:
|
||||
// https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries#container_query_length_units
|
||||
let lengthUnits = [
|
||||
'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('|')})`
|
||||
export function length(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'])
|
||||
export function lineWidth(value) {
|
||||
return lineWidths.has(value)
|
||||
}
|
||||
|
||||
export function shadow(value) {
|
||||
let parsedShadows = parseBoxShadowValue(normalize(value))
|
||||
|
||||
for (let parsedShadow of parsedShadows) {
|
||||
if (!parsedShadow.valid) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export function color(value) {
|
||||
let colors = 0
|
||||
|
||||
let result = splitAtTopLevelOnly(value, '_').every((part) => {
|
||||
part = normalize(part)
|
||||
|
||||
if (part.startsWith('var(')) return true
|
||||
if (parseColor(part, { loose: true }) !== null) return colors++, true
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if (!result) return false
|
||||
return colors > 0
|
||||
}
|
||||
|
||||
export function image(value) {
|
||||
let images = 0
|
||||
let result = splitAtTopLevelOnly(value, ',').every((part) => {
|
||||
part = normalize(part)
|
||||
|
||||
if (part.startsWith('var(')) return true
|
||||
if (
|
||||
url(part) ||
|
||||
gradient(part) ||
|
||||
['element(', 'image(', 'cross-fade(', 'image-set('].some((fn) => part.startsWith(fn))
|
||||
) {
|
||||
images++
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if (!result) return false
|
||||
return images > 0
|
||||
}
|
||||
|
||||
let gradientTypes = new Set([
|
||||
'conic-gradient',
|
||||
'linear-gradient',
|
||||
'radial-gradient',
|
||||
'repeating-conic-gradient',
|
||||
'repeating-linear-gradient',
|
||||
'repeating-radial-gradient',
|
||||
])
|
||||
export function gradient(value) {
|
||||
value = normalize(value)
|
||||
|
||||
for (let type of gradientTypes) {
|
||||
if (value.startsWith(`${type}(`)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
let validPositions = new Set(['center', 'top', 'right', 'bottom', 'left'])
|
||||
export function position(value) {
|
||||
let positions = 0
|
||||
let result = splitAtTopLevelOnly(value, '_').every((part) => {
|
||||
part = normalize(part)
|
||||
|
||||
if (part.startsWith('var(')) return true
|
||||
if (validPositions.has(part) || length(part) || percentage(part)) {
|
||||
positions++
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if (!result) return false
|
||||
return positions > 0
|
||||
}
|
||||
|
||||
export function familyName(value) {
|
||||
let fonts = 0
|
||||
let result = splitAtTopLevelOnly(value, ',').every((part) => {
|
||||
part = normalize(part)
|
||||
|
||||
if (part.startsWith('var(')) return true
|
||||
|
||||
// If it contains spaces, then it should be quoted
|
||||
if (part.includes(' ')) {
|
||||
if (!/(['"])([^"']+)\1/g.test(part)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// If it starts with a number, it's invalid
|
||||
if (/^\d/g.test(part)) {
|
||||
return false
|
||||
}
|
||||
|
||||
fonts++
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if (!result) return false
|
||||
return fonts > 0
|
||||
}
|
||||
|
||||
let genericNames = new Set([
|
||||
'serif',
|
||||
'sans-serif',
|
||||
'monospace',
|
||||
'cursive',
|
||||
'fantasy',
|
||||
'system-ui',
|
||||
'ui-serif',
|
||||
'ui-sans-serif',
|
||||
'ui-monospace',
|
||||
'ui-rounded',
|
||||
'math',
|
||||
'emoji',
|
||||
'fangsong',
|
||||
])
|
||||
export function genericName(value) {
|
||||
return genericNames.has(value)
|
||||
}
|
||||
|
||||
let absoluteSizes = new Set([
|
||||
'xx-small',
|
||||
'x-small',
|
||||
'small',
|
||||
'medium',
|
||||
'large',
|
||||
'x-large',
|
||||
'x-large',
|
||||
'xxx-large',
|
||||
])
|
||||
export function absoluteSize(value) {
|
||||
return absoluteSizes.has(value)
|
||||
}
|
||||
|
||||
let relativeSizes = new Set(['larger', 'smaller'])
|
||||
export function relativeSize(value) {
|
||||
return relativeSizes.has(value)
|
||||
}
|
||||
17
node_modules/tailwindcss/src/util/defaults.js
generated
vendored
Normal file
17
node_modules/tailwindcss/src/util/defaults.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export function defaults(target, ...sources) {
|
||||
for (let source of sources) {
|
||||
for (let k in source) {
|
||||
if (!target?.hasOwnProperty?.(k)) {
|
||||
target[k] = source[k]
|
||||
}
|
||||
}
|
||||
|
||||
for (let k of Object.getOwnPropertySymbols(source)) {
|
||||
if (!target?.hasOwnProperty?.(k)) {
|
||||
target[k] = source[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
8
node_modules/tailwindcss/src/util/escapeClassName.js
generated
vendored
Normal file
8
node_modules/tailwindcss/src/util/escapeClassName.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import parser from 'postcss-selector-parser'
|
||||
import escapeCommas from './escapeCommas'
|
||||
|
||||
export default function escapeClassName(className) {
|
||||
let node = parser.className()
|
||||
node.value = className
|
||||
return escapeCommas(node?.raws?.value ?? node.value)
|
||||
}
|
||||
3
node_modules/tailwindcss/src/util/escapeCommas.js
generated
vendored
Normal file
3
node_modules/tailwindcss/src/util/escapeCommas.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function escapeCommas(className) {
|
||||
return className.replace(/\\,/g, '\\2c ')
|
||||
}
|
||||
13
node_modules/tailwindcss/src/util/flattenColorPalette.js
generated
vendored
Normal file
13
node_modules/tailwindcss/src/util/flattenColorPalette.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
const flattenColorPalette = (colors) =>
|
||||
Object.assign(
|
||||
{},
|
||||
...Object.entries(colors ?? {}).flatMap(([color, values]) =>
|
||||
typeof values == 'object'
|
||||
? Object.entries(flattenColorPalette(values)).map(([number, hex]) => ({
|
||||
[color + (number === 'DEFAULT' ? '' : `-${number}`)]: hex,
|
||||
}))
|
||||
: [{ [`${color}`]: values }]
|
||||
)
|
||||
)
|
||||
|
||||
export default flattenColorPalette
|
||||
316
node_modules/tailwindcss/src/util/formatVariantSelector.js
generated
vendored
Normal file
316
node_modules/tailwindcss/src/util/formatVariantSelector.js
generated
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
import selectorParser from 'postcss-selector-parser'
|
||||
import unescape from 'postcss-selector-parser/dist/util/unesc'
|
||||
import escapeClassName from '../util/escapeClassName'
|
||||
import prefixSelector from '../util/prefixSelector'
|
||||
import { movePseudos } from './pseudoElements'
|
||||
|
||||
/** @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'
|
||||
|
||||
/**
|
||||
* @param {RawFormats} formats
|
||||
* @param {{context: any, candidate: string, base: string | null}} options
|
||||
* @returns {ParsedFormats | null}
|
||||
*/
|
||||
export function formatVariantSelector(formats, { context, candidate }) {
|
||||
let prefix = context?.tailwindConfig.prefix ?? ''
|
||||
|
||||
// Parse the format selector into an AST
|
||||
let parsedFormats = formats.map((format) => {
|
||||
let ast = selectorParser().astSync(format.format)
|
||||
|
||||
return {
|
||||
...format,
|
||||
ast: format.respectPrefix ? prefixSelector(prefix, ast) : ast,
|
||||
}
|
||||
})
|
||||
|
||||
// We start with the candidate selector
|
||||
let formatAst = selectorParser.root({
|
||||
nodes: [
|
||||
selectorParser.selector({
|
||||
nodes: [selectorParser.className({ value: escapeClassName(candidate) })],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
// And iteratively merge each format selector into the candidate selector
|
||||
for (let { ast } of parsedFormats) {
|
||||
// 1. Handle :merge() special pseudo-class
|
||||
;[formatAst, ast] = handleMergePseudo(formatAst, ast)
|
||||
|
||||
// 2. Merge the format selector into the current selector AST
|
||||
ast.walkNesting((nesting) => nesting.replaceWith(...formatAst.nodes[0].nodes))
|
||||
|
||||
// 3. Keep going!
|
||||
formatAst = ast
|
||||
}
|
||||
|
||||
return formatAst
|
||||
}
|
||||
|
||||
/**
|
||||
* Given any node in a selector this gets the "simple" selector it's a part of
|
||||
* A simple selector is just a list of nodes without any combinators
|
||||
* Technically :is(), :not(), :has(), etc… can have combinators but those are nested
|
||||
* inside the relevant node and won't be picked up so they're fine to ignore
|
||||
*
|
||||
* @param {Node} node
|
||||
* @returns {Node[]}
|
||||
**/
|
||||
function simpleSelectorForNode(node) {
|
||||
/** @type {Node[]} */
|
||||
let nodes = []
|
||||
|
||||
// Walk backwards until we hit a combinator node (or the start)
|
||||
while (node.prev() && node.prev().type !== 'combinator') {
|
||||
node = node.prev()
|
||||
}
|
||||
|
||||
// Now record all non-combinator nodes until we hit one (or the end)
|
||||
while (node && node.type !== 'combinator') {
|
||||
nodes.push(node)
|
||||
node = node.next()
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
/**
|
||||
* Resorts the nodes in a selector to ensure they're in the correct order
|
||||
* Tags go before classes, and pseudo classes go after classes
|
||||
*
|
||||
* @param {Selector} sel
|
||||
* @returns {Selector}
|
||||
**/
|
||||
function resortSelector(sel) {
|
||||
sel.sort((a, b) => {
|
||||
if (a.type === 'tag' && b.type === 'class') {
|
||||
return -1
|
||||
} else if (a.type === 'class' && b.type === 'tag') {
|
||||
return 1
|
||||
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) {
|
||||
return -1
|
||||
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') {
|
||||
return 1
|
||||
}
|
||||
|
||||
return sel.index(a) - sel.index(b)
|
||||
})
|
||||
|
||||
return sel
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove extraneous selectors that do not include the base class/candidate
|
||||
*
|
||||
* Example:
|
||||
* Given the utility `.a, .b { color: red}`
|
||||
* Given the candidate `sm:b`
|
||||
*
|
||||
* The final selector should be `.sm\:b` and not `.a, .sm\:b`
|
||||
*
|
||||
* @param {Selector} ast
|
||||
* @param {string} base
|
||||
*/
|
||||
export function eliminateIrrelevantSelectors(sel, base) {
|
||||
let hasClassesMatchingCandidate = false
|
||||
|
||||
sel.walk((child) => {
|
||||
if (child.type === 'class' && child.value === base) {
|
||||
hasClassesMatchingCandidate = true
|
||||
return false // Stop walking
|
||||
}
|
||||
})
|
||||
|
||||
if (!hasClassesMatchingCandidate) {
|
||||
sel.remove()
|
||||
}
|
||||
|
||||
// We do NOT recursively eliminate sub selectors that don't have the base class
|
||||
// as this is NOT a safe operation. For example, if we have:
|
||||
// `.space-x-2 > :not([hidden]) ~ :not([hidden])`
|
||||
// We cannot remove the [hidden] from the :not() because it would change the
|
||||
// meaning of the selector.
|
||||
|
||||
// TODO: Can we do this for :matches, :is, and :where?
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} current
|
||||
* @param {AcceptedFormats} formats
|
||||
* @param {{context: any, candidate: string, base: string | null}} options
|
||||
* @returns {string}
|
||||
*/
|
||||
export function finalizeSelector(current, formats, { context, candidate, base }) {
|
||||
let separator = context?.tailwindConfig?.separator ?? ':'
|
||||
|
||||
// Split by the separator, but ignore the separator inside square brackets:
|
||||
//
|
||||
// E.g.: dark:lg:hover:[paint-order:markers]
|
||||
// ┬ ┬ ┬ ┬
|
||||
// │ │ │ ╰── We will not split here
|
||||
// ╰──┴─────┴─────────────── We will split here
|
||||
//
|
||||
base = base ?? candidate.split(new RegExp(`\\${separator}(?![^[]*\\])`)).pop()
|
||||
|
||||
// Parse the selector into an AST
|
||||
let selector = selectorParser().astSync(current)
|
||||
|
||||
// Normalize escaped classes, e.g.:
|
||||
//
|
||||
// The idea would be to replace the escaped `base` in the selector with the
|
||||
// `format`. However, in css you can escape the same selector in a few
|
||||
// different ways. This would result in different strings and therefore we
|
||||
// can't replace it properly.
|
||||
//
|
||||
// base: bg-[rgb(255,0,0)]
|
||||
// base in selector: bg-\\[rgb\\(255\\,0\\,0\\)\\]
|
||||
// escaped base: bg-\\[rgb\\(255\\2c 0\\2c 0\\)\\]
|
||||
//
|
||||
selector.walkClasses((node) => {
|
||||
if (node.raws && node.value.includes(base)) {
|
||||
node.raws.value = escapeClassName(unescape(node.raws.value))
|
||||
}
|
||||
})
|
||||
|
||||
// Remove extraneous selectors that do not include the base candidate
|
||||
selector.each((sel) => eliminateIrrelevantSelectors(sel, base))
|
||||
|
||||
// If there are no formats that means there were no variants added to the candidate
|
||||
// so we can just return the selector as-is
|
||||
let formatAst = Array.isArray(formats)
|
||||
? formatVariantSelector(formats, { context, candidate })
|
||||
: formats
|
||||
|
||||
if (formatAst === null) {
|
||||
return selector.toString()
|
||||
}
|
||||
|
||||
let simpleStart = selectorParser.comment({ value: '/*__simple__*/' })
|
||||
let simpleEnd = selectorParser.comment({ value: '/*__simple__*/' })
|
||||
|
||||
// We can safely replace the escaped base now, since the `base` section is
|
||||
// now in a normalized escaped value.
|
||||
selector.walkClasses((node) => {
|
||||
if (node.value !== base) {
|
||||
return
|
||||
}
|
||||
|
||||
let parent = node.parent
|
||||
let formatNodes = formatAst.nodes[0].nodes
|
||||
|
||||
// Perf optimization: if the parent is a single class we can just replace it and be done
|
||||
if (parent.nodes.length === 1) {
|
||||
node.replaceWith(...formatNodes)
|
||||
return
|
||||
}
|
||||
|
||||
let simpleSelector = simpleSelectorForNode(node)
|
||||
parent.insertBefore(simpleSelector[0], simpleStart)
|
||||
parent.insertAfter(simpleSelector[simpleSelector.length - 1], simpleEnd)
|
||||
|
||||
for (let child of formatNodes) {
|
||||
parent.insertBefore(simpleSelector[0], child.clone())
|
||||
}
|
||||
|
||||
node.remove()
|
||||
|
||||
// Re-sort the simple selector to ensure it's in the correct order
|
||||
simpleSelector = simpleSelectorForNode(simpleStart)
|
||||
let firstNode = parent.index(simpleStart)
|
||||
|
||||
parent.nodes.splice(
|
||||
firstNode,
|
||||
simpleSelector.length,
|
||||
...resortSelector(selectorParser.selector({ nodes: simpleSelector })).nodes
|
||||
)
|
||||
|
||||
simpleStart.remove()
|
||||
simpleEnd.remove()
|
||||
})
|
||||
|
||||
// Remove unnecessary pseudo selectors that we used as placeholders
|
||||
selector.walkPseudos((p) => {
|
||||
if (p.value === MERGE) {
|
||||
p.replaceWith(p.nodes)
|
||||
}
|
||||
})
|
||||
|
||||
// Move pseudo elements to the end of the selector (if necessary)
|
||||
selector.each((sel) => movePseudos(sel))
|
||||
|
||||
return selector.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Selector} selector
|
||||
* @param {Selector} format
|
||||
*/
|
||||
export function handleMergePseudo(selector, format) {
|
||||
/** @type {{pseudo: Pseudo, value: string}[]} */
|
||||
let merges = []
|
||||
|
||||
// Find all :merge() pseudo-classes in `selector`
|
||||
selector.walkPseudos((pseudo) => {
|
||||
if (pseudo.value === MERGE) {
|
||||
merges.push({
|
||||
pseudo,
|
||||
value: pseudo.nodes[0].toString(),
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Find all :merge() "attachments" in `format` and attach them to the matching selector in `selector`
|
||||
format.walkPseudos((pseudo) => {
|
||||
if (pseudo.value !== MERGE) {
|
||||
return
|
||||
}
|
||||
|
||||
let value = pseudo.nodes[0].toString()
|
||||
|
||||
// Does `selector` contain a :merge() pseudo-class with the same value?
|
||||
let existing = merges.find((merge) => merge.value === value)
|
||||
|
||||
// Nope so there's nothing to do
|
||||
if (!existing) {
|
||||
return
|
||||
}
|
||||
|
||||
// Everything after `:merge()` up to the next combinator is what is attached to the merged selector
|
||||
let attachments = []
|
||||
let next = pseudo.next()
|
||||
while (next && next.type !== 'combinator') {
|
||||
attachments.push(next)
|
||||
next = next.next()
|
||||
}
|
||||
|
||||
let combinator = next
|
||||
|
||||
existing.pseudo.parent.insertAfter(
|
||||
existing.pseudo,
|
||||
selectorParser.selector({ nodes: attachments.map((node) => node.clone()) })
|
||||
)
|
||||
|
||||
pseudo.remove()
|
||||
attachments.forEach((node) => node.remove())
|
||||
|
||||
// What about this case:
|
||||
// :merge(.group):focus > &
|
||||
// :merge(.group):hover &
|
||||
if (combinator && combinator.type === 'combinator') {
|
||||
combinator.remove()
|
||||
}
|
||||
})
|
||||
|
||||
return [selector, format]
|
||||
}
|
||||
38
node_modules/tailwindcss/src/util/getAllConfigs.js
generated
vendored
Normal file
38
node_modules/tailwindcss/src/util/getAllConfigs.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import defaultFullConfig from '../../stubs/config.full.js'
|
||||
import { flagEnabled } from '../featureFlags'
|
||||
|
||||
export default function getAllConfigs(config) {
|
||||
const configs = (config?.presets ?? [defaultFullConfig])
|
||||
.slice()
|
||||
.reverse()
|
||||
.flatMap((preset) => getAllConfigs(preset instanceof Function ? preset() : preset))
|
||||
|
||||
const features = {
|
||||
// Add experimental configs here...
|
||||
respectDefaultRingColorOpacity: {
|
||||
theme: {
|
||||
ringColor: ({ theme }) => ({
|
||||
DEFAULT: '#3b82f67f',
|
||||
...theme('colors'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
disableColorOpacityUtilitiesByDefault: {
|
||||
corePlugins: {
|
||||
backgroundOpacity: false,
|
||||
borderOpacity: false,
|
||||
divideOpacity: false,
|
||||
placeholderOpacity: false,
|
||||
ringOpacity: false,
|
||||
textOpacity: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const experimentals = Object.keys(features)
|
||||
.filter((feature) => flagEnabled(config, feature))
|
||||
.map((feature) => features[feature])
|
||||
|
||||
return [config, ...experimentals, ...configs]
|
||||
}
|
||||
5
node_modules/tailwindcss/src/util/hashConfig.js
generated
vendored
Normal file
5
node_modules/tailwindcss/src/util/hashConfig.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import hash from 'object-hash'
|
||||
|
||||
export default function hashConfig(config) {
|
||||
return hash(config, { ignoreUnknown: true })
|
||||
}
|
||||
3
node_modules/tailwindcss/src/util/isKeyframeRule.js
generated
vendored
Normal file
3
node_modules/tailwindcss/src/util/isKeyframeRule.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function isKeyframeRule(rule) {
|
||||
return rule.parent && rule.parent.type === 'atrule' && /keyframes$/.test(rule.parent.name)
|
||||
}
|
||||
8
node_modules/tailwindcss/src/util/isPlainObject.js
generated
vendored
Normal file
8
node_modules/tailwindcss/src/util/isPlainObject.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export default function isPlainObject(value) {
|
||||
if (Object.prototype.toString.call(value) !== '[object Object]') {
|
||||
return false
|
||||
}
|
||||
|
||||
const prototype = Object.getPrototypeOf(value)
|
||||
return prototype === null || prototype === Object.prototype
|
||||
}
|
||||
61
node_modules/tailwindcss/src/util/isSyntacticallyValidPropertyValue.js
generated
vendored
Normal file
61
node_modules/tailwindcss/src/util/isSyntacticallyValidPropertyValue.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
let matchingBrackets = new Map([
|
||||
['{', '}'],
|
||||
['[', ']'],
|
||||
['(', ')'],
|
||||
])
|
||||
let inverseMatchingBrackets = new Map(
|
||||
Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
|
||||
)
|
||||
|
||||
let quotes = new Set(['"', "'", '`'])
|
||||
|
||||
// Arbitrary values must contain balanced brackets (), [] and {}. Escaped
|
||||
// values don't count, and brackets inside quotes also don't count.
|
||||
//
|
||||
// E.g.: w-[this-is]w-[weird-and-invalid]
|
||||
// E.g.: w-[this-is\\]w-\\[weird-but-valid]
|
||||
// E.g.: content-['this-is-also-valid]-weirdly-enough']
|
||||
export default function isSyntacticallyValidPropertyValue(value) {
|
||||
let stack = []
|
||||
let inQuotes = false
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
let char = value[i]
|
||||
|
||||
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] !== '\\') {
|
||||
inQuotes = !inQuotes
|
||||
}
|
||||
|
||||
if (inQuotes) continue
|
||||
if (value[i - 1] === '\\') continue // Escaped
|
||||
|
||||
if (matchingBrackets.has(char)) {
|
||||
stack.push(char)
|
||||
} else if (inverseMatchingBrackets.has(char)) {
|
||||
let inverse = inverseMatchingBrackets.get(char)
|
||||
|
||||
// Nothing to pop from, therefore it is unbalanced
|
||||
if (stack.length <= 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Popped value must match the inverse value, otherwise it is unbalanced
|
||||
if (stack.pop() !== inverse) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is still something on the stack, it is also unbalanced
|
||||
if (stack.length > 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
// All good, totally balanced!
|
||||
return true
|
||||
}
|
||||
29
node_modules/tailwindcss/src/util/log.js
generated
vendored
Normal file
29
node_modules/tailwindcss/src/util/log.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import colors from 'picocolors'
|
||||
|
||||
let alreadyShown = new Set()
|
||||
|
||||
function log(type, messages, key) {
|
||||
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))
|
||||
}
|
||||
|
||||
export function dim(input) {
|
||||
return colors.dim(input)
|
||||
}
|
||||
|
||||
export default {
|
||||
info(key, messages) {
|
||||
log(colors.bold(colors.cyan('info')), ...(Array.isArray(key) ? [key] : [messages, key]))
|
||||
},
|
||||
warn(key, messages) {
|
||||
log(colors.bold(colors.yellow('warn')), ...(Array.isArray(key) ? [key] : [messages, key]))
|
||||
},
|
||||
risk(key, messages) {
|
||||
log(colors.bold(colors.magenta('risk')), ...(Array.isArray(key) ? [key] : [messages, key]))
|
||||
},
|
||||
}
|
||||
30
node_modules/tailwindcss/src/util/nameClass.js
generated
vendored
Normal file
30
node_modules/tailwindcss/src/util/nameClass.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import escapeClassName from './escapeClassName'
|
||||
import escapeCommas from './escapeCommas'
|
||||
|
||||
export function asClass(name) {
|
||||
return escapeCommas(`.${escapeClassName(name)}`)
|
||||
}
|
||||
|
||||
export default function nameClass(classPrefix, key) {
|
||||
return asClass(formatClass(classPrefix, key))
|
||||
}
|
||||
|
||||
export function formatClass(classPrefix, key) {
|
||||
if (key === 'DEFAULT') {
|
||||
return classPrefix
|
||||
}
|
||||
|
||||
if (key === '-' || key === '-DEFAULT') {
|
||||
return `-${classPrefix}`
|
||||
}
|
||||
|
||||
if (key.startsWith('-')) {
|
||||
return `-${classPrefix}${key}`
|
||||
}
|
||||
|
||||
if (key.startsWith('/')) {
|
||||
return `${classPrefix}${key}`
|
||||
}
|
||||
|
||||
return `${classPrefix}-${key}`
|
||||
}
|
||||
24
node_modules/tailwindcss/src/util/negateValue.js
generated
vendored
Normal file
24
node_modules/tailwindcss/src/util/negateValue.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
export default function negateValue(value) {
|
||||
value = `${value}`
|
||||
|
||||
if (value === '0') {
|
||||
return '0'
|
||||
}
|
||||
|
||||
// Flip sign of numbers
|
||||
if (/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(value)) {
|
||||
return value.replace(/^[+-]?/, (sign) => (sign === '-' ? '' : '-'))
|
||||
}
|
||||
|
||||
// What functions we support negating numeric values for
|
||||
// var() isn't inherently a numeric function but we support it anyway
|
||||
// The trigonometric functions are omitted because you'll need to use calc(…) with them _anyway_
|
||||
// to produce generally useful results and that will be covered already
|
||||
let numericFunctions = ['var', 'calc', 'min', 'max', 'clamp']
|
||||
|
||||
for (const fn of numericFunctions) {
|
||||
if (value.includes(`${fn}(`)) {
|
||||
return `calc(${value} * -1)`
|
||||
}
|
||||
}
|
||||
}
|
||||
301
node_modules/tailwindcss/src/util/normalizeConfig.js
generated
vendored
Normal file
301
node_modules/tailwindcss/src/util/normalizeConfig.js
generated
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
import { flagEnabled } from '../featureFlags'
|
||||
import log, { dim } from './log'
|
||||
|
||||
export function normalizeConfig(config) {
|
||||
// Quick structure validation
|
||||
/**
|
||||
* type FilePath = string
|
||||
* type RawFile = { raw: string, extension?: string }
|
||||
* type ExtractorFn = (content: string) => Array<string>
|
||||
* type TransformerFn = (content: string) => string
|
||||
*
|
||||
* type Content =
|
||||
* | Array<FilePath | RawFile>
|
||||
* | {
|
||||
* files: Array<FilePath | RawFile>,
|
||||
* extract?: ExtractorFn | { [extension: string]: ExtractorFn }
|
||||
* transform?: TransformerFn | { [extension: string]: TransformerFn }
|
||||
* }
|
||||
*/
|
||||
let valid = (() => {
|
||||
// `config.purge` should not exist anymore
|
||||
if (config.purge) {
|
||||
return false
|
||||
}
|
||||
|
||||
// `config.content` should exist
|
||||
if (!config.content) {
|
||||
return false
|
||||
}
|
||||
|
||||
// `config.content` should be an object or an array
|
||||
if (
|
||||
!Array.isArray(config.content) &&
|
||||
!(typeof config.content === 'object' && config.content !== null)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
// When `config.content` is an array, it should consist of FilePaths or RawFiles
|
||||
if (Array.isArray(config.content)) {
|
||||
return config.content.every((path) => {
|
||||
// `path` can be a string
|
||||
if (typeof path === 'string') return true
|
||||
|
||||
// `path` can be an object { raw: string, extension?: string }
|
||||
// `raw` must be a string
|
||||
if (typeof path?.raw !== 'string') return false
|
||||
|
||||
// `extension` (if provided) should also be a string
|
||||
if (path?.extension && typeof path?.extension !== 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// When `config.content` is an object
|
||||
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'].includes(key)
|
||||
)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
// `config.content.files` should exist of FilePaths or RawFiles
|
||||
if (Array.isArray(config.content.files)) {
|
||||
if (
|
||||
!config.content.files.every((path) => {
|
||||
// `path` can be a string
|
||||
if (typeof path === 'string') return true
|
||||
|
||||
// `path` can be an object { raw: string, extension?: string }
|
||||
// `raw` must be a string
|
||||
if (typeof path?.raw !== 'string') return false
|
||||
|
||||
// `extension` (if provided) should also be a string
|
||||
if (path?.extension && typeof path?.extension !== 'string') {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
// `config.content.extract` is optional, and can be a Function or a Record<String, Function>
|
||||
if (typeof config.content.extract === 'object') {
|
||||
for (let value of Object.values(config.content.extract)) {
|
||||
if (typeof value !== 'function') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} 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') {
|
||||
for (let value of Object.values(config.content.transform)) {
|
||||
if (typeof value !== 'function') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} 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'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})()
|
||||
|
||||
if (!valid) {
|
||||
log.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',
|
||||
])
|
||||
}
|
||||
|
||||
// Normalize the `safelist`
|
||||
config.safelist = (() => {
|
||||
let { content, purge, safelist } = config
|
||||
|
||||
if (Array.isArray(safelist)) return safelist
|
||||
if (Array.isArray(content?.safelist)) return content.safelist
|
||||
if (Array.isArray(purge?.safelist)) return purge.safelist
|
||||
if (Array.isArray(purge?.options?.safelist)) return purge.options.safelist
|
||||
|
||||
return []
|
||||
})()
|
||||
|
||||
// Normalize the `blocklist`
|
||||
config.blocklist = (() => {
|
||||
let { blocklist } = config
|
||||
|
||||
if (Array.isArray(blocklist)) {
|
||||
if (blocklist.every((item) => typeof item === 'string')) {
|
||||
return blocklist
|
||||
}
|
||||
|
||||
log.warn('blocklist-invalid', [
|
||||
'The `blocklist` option must be an array of strings.',
|
||||
'https://tailwindcss.com/docs/content-configuration#discarding-classes',
|
||||
])
|
||||
}
|
||||
|
||||
return []
|
||||
})()
|
||||
|
||||
// Normalize prefix option
|
||||
if (typeof config.prefix === 'function') {
|
||||
log.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 = ''
|
||||
} else {
|
||||
config.prefix = config.prefix ?? ''
|
||||
}
|
||||
|
||||
// Normalize the `content`
|
||||
config.content = {
|
||||
relative: (() => {
|
||||
let { content } = config
|
||||
|
||||
if (content?.relative) {
|
||||
return content.relative
|
||||
}
|
||||
|
||||
return flagEnabled(config, 'relativeContentPathsByDefault')
|
||||
})(),
|
||||
|
||||
files: (() => {
|
||||
let { content, purge } = config
|
||||
|
||||
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
|
||||
|
||||
return []
|
||||
})(),
|
||||
|
||||
extract: (() => {
|
||||
let extract = (() => {
|
||||
if (config.purge?.extract) return config.purge.extract
|
||||
if (config.content?.extract) return config.content.extract
|
||||
|
||||
if (config.purge?.extract?.DEFAULT) return config.purge.extract.DEFAULT
|
||||
if (config.content?.extract?.DEFAULT) return config.content.extract.DEFAULT
|
||||
|
||||
if (config.purge?.options?.extractors) return config.purge.options.extractors
|
||||
if (config.content?.options?.extractors) return config.content.options.extractors
|
||||
|
||||
return {}
|
||||
})()
|
||||
|
||||
let extractors = {}
|
||||
|
||||
let defaultExtractor = (() => {
|
||||
if (config.purge?.options?.defaultExtractor) {
|
||||
return config.purge.options.defaultExtractor
|
||||
}
|
||||
|
||||
if (config.content?.options?.defaultExtractor) {
|
||||
return config.content.options.defaultExtractor
|
||||
}
|
||||
|
||||
return undefined
|
||||
})()
|
||||
|
||||
if (defaultExtractor !== undefined) {
|
||||
extractors.DEFAULT = defaultExtractor
|
||||
}
|
||||
|
||||
// Functions
|
||||
if (typeof extract === 'function') {
|
||||
extractors.DEFAULT = extract
|
||||
}
|
||||
|
||||
// Arrays
|
||||
else if (Array.isArray(extract)) {
|
||||
for (let { extensions, extractor } of extract ?? []) {
|
||||
for (let extension of extensions) {
|
||||
extractors[extension] = extractor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Objects
|
||||
else if (typeof extract === 'object' && extract !== null) {
|
||||
Object.assign(extractors, extract)
|
||||
}
|
||||
|
||||
return extractors
|
||||
})(),
|
||||
|
||||
transform: (() => {
|
||||
let transform = (() => {
|
||||
if (config.purge?.transform) return config.purge.transform
|
||||
if (config.content?.transform) return config.content.transform
|
||||
|
||||
if (config.purge?.transform?.DEFAULT) return config.purge.transform.DEFAULT
|
||||
if (config.content?.transform?.DEFAULT) return config.content.transform.DEFAULT
|
||||
|
||||
return {}
|
||||
})()
|
||||
|
||||
let transformers = {}
|
||||
|
||||
if (typeof transform === 'function') {
|
||||
transformers.DEFAULT = transform
|
||||
}
|
||||
|
||||
if (typeof transform === 'object' && transform !== null) {
|
||||
Object.assign(transformers, transform)
|
||||
}
|
||||
|
||||
return transformers
|
||||
})(),
|
||||
}
|
||||
|
||||
// Validate globs to prevent bogus globs.
|
||||
// E.g.: `./src/*.{html}` is invalid, the `{html}` should just be `html`
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
140
node_modules/tailwindcss/src/util/normalizeScreens.js
generated
vendored
Normal file
140
node_modules/tailwindcss/src/util/normalizeScreens.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* @typedef {object} ScreenValue
|
||||
* @property {number|undefined} min
|
||||
* @property {number|undefined} max
|
||||
* @property {string|undefined} raw
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {object} Screen
|
||||
* @property {string} name
|
||||
* @property {boolean} not
|
||||
* @property {ScreenValue[]} values
|
||||
*/
|
||||
|
||||
/**
|
||||
* A function that normalizes the various forms that the screens object can be
|
||||
* provided in.
|
||||
*
|
||||
* Input(s):
|
||||
* - ['100px', '200px'] // Raw strings
|
||||
* - { sm: '100px', md: '200px' } // Object with string values
|
||||
* - { sm: { min: '100px' }, md: { max: '100px' } } // Object with object values
|
||||
* - { sm: [{ min: '100px' }, { max: '200px' }] } // Object with object array (multiple values)
|
||||
*
|
||||
* Output(s):
|
||||
* - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
|
||||
*
|
||||
* @returns {Screen[]}
|
||||
*/
|
||||
export function normalizeScreens(screens, root = true) {
|
||||
if (Array.isArray(screens)) {
|
||||
return screens.map((screen) => {
|
||||
if (root && Array.isArray(screen)) {
|
||||
throw new Error('The tuple syntax is not supported for `screens`.')
|
||||
}
|
||||
|
||||
if (typeof screen === 'string') {
|
||||
return { name: screen.toString(), not: false, values: [{ min: screen, max: undefined }] }
|
||||
}
|
||||
|
||||
let [name, options] = screen
|
||||
name = name.toString()
|
||||
|
||||
if (typeof options === 'string') {
|
||||
return { name, not: false, values: [{ min: options, max: undefined }] }
|
||||
}
|
||||
|
||||
if (Array.isArray(options)) {
|
||||
return { name, not: false, values: options.map((option) => resolveValue(option)) }
|
||||
}
|
||||
|
||||
return { name, not: false, values: [resolveValue(options)] }
|
||||
})
|
||||
}
|
||||
|
||||
return normalizeScreens(Object.entries(screens ?? {}), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Screen} screen
|
||||
* @returns {{result: false, reason: string} | {result: true, reason: null}}
|
||||
*/
|
||||
export function isScreenSortable(screen) {
|
||||
if (screen.values.length !== 1) {
|
||||
return { result: false, reason: 'multiple-values' }
|
||||
} else if (screen.values[0].raw !== undefined) {
|
||||
return { result: false, reason: 'raw-values' }
|
||||
} else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) {
|
||||
return { result: false, reason: 'min-and-max' }
|
||||
}
|
||||
|
||||
return { result: true, reason: null }
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {'min' | 'max'} type
|
||||
* @param {Screen | 'string'} a
|
||||
* @param {Screen | 'string'} z
|
||||
* @returns {number}
|
||||
*/
|
||||
export function compareScreens(type, a, z) {
|
||||
let aScreen = toScreen(a, type)
|
||||
let zScreen = toScreen(z, type)
|
||||
|
||||
let aSorting = isScreenSortable(aScreen)
|
||||
let bSorting = isScreenSortable(zScreen)
|
||||
|
||||
// These cases should never happen and indicate a bug in Tailwind CSS itself
|
||||
if (aSorting.reason === 'multiple-values' || bSorting.reason === 'multiple-values') {
|
||||
throw new Error(
|
||||
'Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.'
|
||||
)
|
||||
} else if (aSorting.reason === 'raw-values' || bSorting.reason === 'raw-values') {
|
||||
throw new Error(
|
||||
'Attempted to sort a screen with raw values. This should never happen. Please open a bug report.'
|
||||
)
|
||||
} else if (aSorting.reason === 'min-and-max' || bSorting.reason === 'min-and-max') {
|
||||
throw new Error(
|
||||
'Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.'
|
||||
)
|
||||
}
|
||||
|
||||
// Let the sorting begin
|
||||
let { min: aMin, max: aMax } = aScreen.values[0]
|
||||
let { min: zMin, max: zMax } = zScreen.values[0]
|
||||
|
||||
// Negating screens flip their behavior. Basically `not min-width` is `max-width`
|
||||
if (a.not) [aMin, aMax] = [aMax, aMin]
|
||||
if (z.not) [zMin, zMax] = [zMax, zMin]
|
||||
|
||||
aMin = aMin === undefined ? aMin : parseFloat(aMin)
|
||||
aMax = aMax === undefined ? aMax : parseFloat(aMax)
|
||||
zMin = zMin === undefined ? zMin : parseFloat(zMin)
|
||||
zMax = zMax === undefined ? zMax : parseFloat(zMax)
|
||||
|
||||
let [aValue, zValue] = type === 'min' ? [aMin, zMin] : [zMax, aMax]
|
||||
|
||||
return aValue - zValue
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PartialScreen> | string} value
|
||||
* @param {'min' | 'max'} type
|
||||
* @returns {Screen}
|
||||
*/
|
||||
export function toScreen(value, type) {
|
||||
if (typeof value === 'object') {
|
||||
return value
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'arbitrary-screen',
|
||||
values: [{ [type]: value }],
|
||||
}
|
||||
}
|
||||
|
||||
function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) {
|
||||
return { min, max, raw }
|
||||
}
|
||||
68
node_modules/tailwindcss/src/util/parseAnimationValue.js
generated
vendored
Normal file
68
node_modules/tailwindcss/src/util/parseAnimationValue.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
const DIRECTIONS = new Set(['normal', 'reverse', 'alternate', 'alternate-reverse'])
|
||||
const PLAY_STATES = new Set(['running', 'paused'])
|
||||
const FILL_MODES = new Set(['none', 'forwards', 'backwards', 'both'])
|
||||
const ITERATION_COUNTS = new Set(['infinite'])
|
||||
const TIMINGS = new Set([
|
||||
'linear',
|
||||
'ease',
|
||||
'ease-in',
|
||||
'ease-out',
|
||||
'ease-in-out',
|
||||
'step-start',
|
||||
'step-end',
|
||||
])
|
||||
const TIMING_FNS = ['cubic-bezier', 'steps']
|
||||
|
||||
const COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
|
||||
const SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
|
||||
const TIME = /^(-?[\d.]+m?s)$/
|
||||
const DIGIT = /^(\d+)$/
|
||||
|
||||
export default function parseAnimationValue(input) {
|
||||
let animations = input.split(COMMA)
|
||||
return animations.map((animation) => {
|
||||
let value = animation.trim()
|
||||
let result = { value }
|
||||
let parts = value.split(SPACE)
|
||||
let seen = new Set()
|
||||
|
||||
for (let part of parts) {
|
||||
if (!seen.has('DIRECTIONS') && DIRECTIONS.has(part)) {
|
||||
result.direction = 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)) {
|
||||
result.fillMode = 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)) {
|
||||
result.timingFunction = part
|
||||
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)) {
|
||||
result.duration = part
|
||||
seen.add('DURATION')
|
||||
} else if (!seen.has('DELAY') && TIME.test(part)) {
|
||||
result.delay = part
|
||||
seen.add('DELAY')
|
||||
} else if (!seen.has('NAME')) {
|
||||
result.name = part
|
||||
seen.add('NAME')
|
||||
} else {
|
||||
if (!result.unknown) result.unknown = []
|
||||
result.unknown.push(part)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
72
node_modules/tailwindcss/src/util/parseBoxShadowValue.js
generated
vendored
Normal file
72
node_modules/tailwindcss/src/util/parseBoxShadowValue.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
|
||||
|
||||
let KEYWORDS = new Set(['inset', 'inherit', 'initial', 'revert', 'unset'])
|
||||
let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
|
||||
let LENGTH = /^-?(\d+|\.\d+)(.*?)$/g
|
||||
|
||||
export function parseBoxShadowValue(input) {
|
||||
let shadows = splitAtTopLevelOnly(input, ',')
|
||||
return shadows.map((shadow) => {
|
||||
let value = shadow.trim()
|
||||
let result = { raw: value }
|
||||
let parts = value.split(SPACE)
|
||||
let seen = new Set()
|
||||
|
||||
for (let part of parts) {
|
||||
// Reset index, since the regex is stateful.
|
||||
LENGTH.lastIndex = 0
|
||||
|
||||
// Keyword
|
||||
if (!seen.has('KEYWORD') && KEYWORDS.has(part)) {
|
||||
result.keyword = part
|
||||
seen.add('KEYWORD')
|
||||
}
|
||||
|
||||
// Length value
|
||||
else if (LENGTH.test(part)) {
|
||||
if (!seen.has('X')) {
|
||||
result.x = part
|
||||
seen.add('X')
|
||||
} else if (!seen.has('Y')) {
|
||||
result.y = part
|
||||
seen.add('Y')
|
||||
} else if (!seen.has('BLUR')) {
|
||||
result.blur = part
|
||||
seen.add('BLUR')
|
||||
} else if (!seen.has('SPREAD')) {
|
||||
result.spread = part
|
||||
seen.add('SPREAD')
|
||||
}
|
||||
}
|
||||
|
||||
// Color or unknown
|
||||
else {
|
||||
if (!result.color) {
|
||||
result.color = part
|
||||
} else {
|
||||
if (!result.unknown) result.unknown = []
|
||||
result.unknown.push(part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if valid
|
||||
result.valid = result.x !== undefined && result.y !== undefined
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
export function formatBoxShadowValue(shadows) {
|
||||
return shadows
|
||||
.map((shadow) => {
|
||||
if (!shadow.valid) {
|
||||
return shadow.raw
|
||||
}
|
||||
|
||||
return [shadow.keyword, shadow.x, shadow.y, shadow.blur, shadow.spread, shadow.color]
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
})
|
||||
.join(', ')
|
||||
}
|
||||
44
node_modules/tailwindcss/src/util/parseDependency.js
generated
vendored
Normal file
44
node_modules/tailwindcss/src/util/parseDependency.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* @typedef {{type: 'dependency', file: string} | {type: 'dir-dependency', dir: string, glob: string}} Dependency
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('../lib/content.js').ContentPath} contentPath
|
||||
* @returns {Dependency[]}
|
||||
*/
|
||||
export default function parseDependency(contentPath) {
|
||||
if (contentPath.ignore) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (!contentPath.glob) {
|
||||
return [
|
||||
{
|
||||
type: 'dependency',
|
||||
file: contentPath.base,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
if (process.env.ROLLUP_WATCH === 'true') {
|
||||
// rollup-plugin-postcss does not support dir-dependency messages
|
||||
// but directories can be watched in the same way as files
|
||||
return [
|
||||
{
|
||||
type: 'dependency',
|
||||
file: contentPath.base,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
type: 'dir-dependency',
|
||||
dir: contentPath.base,
|
||||
glob: contentPath.glob,
|
||||
},
|
||||
]
|
||||
}
|
||||
24
node_modules/tailwindcss/src/util/parseGlob.js
generated
vendored
Normal file
24
node_modules/tailwindcss/src/util/parseGlob.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import globParent from 'glob-parent'
|
||||
|
||||
// Based on `glob-base`
|
||||
// https://github.com/micromatch/glob-base/blob/master/index.js
|
||||
export function parseGlob(pattern) {
|
||||
let glob = pattern
|
||||
let base = globParent(pattern)
|
||||
|
||||
if (base !== '.') {
|
||||
glob = pattern.substr(base.length)
|
||||
if (glob.charAt(0) === '/') {
|
||||
glob = glob.substr(1)
|
||||
}
|
||||
}
|
||||
|
||||
if (glob.substr(0, 2) === './') {
|
||||
glob = glob.substr(2)
|
||||
}
|
||||
if (glob.charAt(0) === '/') {
|
||||
glob = glob.substr(1)
|
||||
}
|
||||
|
||||
return { base, glob }
|
||||
}
|
||||
19
node_modules/tailwindcss/src/util/parseObjectStyles.js
generated
vendored
Normal file
19
node_modules/tailwindcss/src/util/parseObjectStyles.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import postcss from 'postcss'
|
||||
import postcssNested from 'postcss-nested'
|
||||
import postcssJs from 'postcss-js'
|
||||
|
||||
export default function parseObjectStyles(styles) {
|
||||
if (!Array.isArray(styles)) {
|
||||
return parseObjectStyles([styles])
|
||||
}
|
||||
|
||||
return styles.flatMap((style) => {
|
||||
return postcss([
|
||||
postcssNested({
|
||||
bubble: ['screen'],
|
||||
}),
|
||||
]).process(style, {
|
||||
parser: postcssJs,
|
||||
}).root.nodes
|
||||
})
|
||||
}
|
||||
291
node_modules/tailwindcss/src/util/pluginUtils.js
generated
vendored
Normal file
291
node_modules/tailwindcss/src/util/pluginUtils.js
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
import escapeCommas from './escapeCommas'
|
||||
import { withAlphaValue } from './withAlphaVariable'
|
||||
import {
|
||||
normalize,
|
||||
length,
|
||||
number,
|
||||
percentage,
|
||||
url,
|
||||
color as validateColor,
|
||||
genericName,
|
||||
familyName,
|
||||
image,
|
||||
absoluteSize,
|
||||
relativeSize,
|
||||
position,
|
||||
lineWidth,
|
||||
shadow,
|
||||
} from './dataTypes'
|
||||
import negateValue from './negateValue'
|
||||
import { backgroundSize } from './validateFormalSyntax'
|
||||
import { flagEnabled } from '../featureFlags.js'
|
||||
|
||||
/**
|
||||
* @param {import('postcss-selector-parser').Container} selectors
|
||||
* @param {(className: string) => string} updateClass
|
||||
* @returns {string}
|
||||
*/
|
||||
export function updateAllClasses(selectors, updateClass) {
|
||||
selectors.walkClasses((sel) => {
|
||||
sel.value = updateClass(sel.value)
|
||||
|
||||
if (sel.raws && sel.raws.value) {
|
||||
sel.raws.value = escapeCommas(sel.raws.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function resolveArbitraryValue(modifier, validate) {
|
||||
if (!isArbitraryValue(modifier)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
let value = modifier.slice(1, -1)
|
||||
|
||||
if (!validate(value)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return normalize(value)
|
||||
}
|
||||
|
||||
function asNegativeValue(modifier, lookup = {}, validate) {
|
||||
let positiveValue = lookup[modifier]
|
||||
|
||||
if (positiveValue !== undefined) {
|
||||
return negateValue(positiveValue)
|
||||
}
|
||||
|
||||
if (isArbitraryValue(modifier)) {
|
||||
let resolved = resolveArbitraryValue(modifier, validate)
|
||||
|
||||
if (resolved === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return negateValue(resolved)
|
||||
}
|
||||
}
|
||||
|
||||
export function asValue(modifier, options = {}, { validate = () => true } = {}) {
|
||||
let value = options.values?.[modifier]
|
||||
|
||||
if (value !== undefined) {
|
||||
return value
|
||||
}
|
||||
|
||||
if (options.supportsNegativeValues && modifier.startsWith('-')) {
|
||||
return asNegativeValue(modifier.slice(1), options.values, validate)
|
||||
}
|
||||
|
||||
return resolveArbitraryValue(modifier, validate)
|
||||
}
|
||||
|
||||
function isArbitraryValue(input) {
|
||||
return input.startsWith('[') && input.endsWith(']')
|
||||
}
|
||||
|
||||
function splitUtilityModifier(modifier) {
|
||||
let slashIdx = modifier.lastIndexOf('/')
|
||||
|
||||
if (slashIdx === -1 || slashIdx === modifier.length - 1) {
|
||||
return [modifier, undefined]
|
||||
}
|
||||
|
||||
let arbitrary = isArbitraryValue(modifier)
|
||||
|
||||
// The modifier could be of the form `[foo]/[bar]`
|
||||
// We want to handle this case properly
|
||||
// without affecting `[foo/bar]`
|
||||
if (arbitrary && !modifier.includes(']/[')) {
|
||||
return [modifier, undefined]
|
||||
}
|
||||
|
||||
return [modifier.slice(0, slashIdx), modifier.slice(slashIdx + 1)]
|
||||
}
|
||||
|
||||
export function parseColorFormat(value) {
|
||||
if (typeof value === 'string' && value.includes('<alpha-value>')) {
|
||||
let oldValue = value
|
||||
|
||||
return ({ opacityValue = 1 }) => oldValue.replace('<alpha-value>', opacityValue)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
function unwrapArbitraryModifier(modifier) {
|
||||
return normalize(modifier.slice(1, -1))
|
||||
}
|
||||
|
||||
export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
|
||||
if (options.values?.[modifier] !== undefined) {
|
||||
return parseColorFormat(options.values?.[modifier])
|
||||
}
|
||||
|
||||
// TODO: Hoist this up to getMatchingTypes or something
|
||||
// We do this here because we need the alpha value (if any)
|
||||
let [color, alpha] = splitUtilityModifier(modifier)
|
||||
|
||||
if (alpha !== undefined) {
|
||||
let normalizedColor =
|
||||
options.values?.[color] ?? (isArbitraryValue(color) ? color.slice(1, -1) : undefined)
|
||||
|
||||
if (normalizedColor === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
normalizedColor = parseColorFormat(normalizedColor)
|
||||
|
||||
if (isArbitraryValue(alpha)) {
|
||||
return withAlphaValue(normalizedColor, unwrapArbitraryModifier(alpha))
|
||||
}
|
||||
|
||||
if (tailwindConfig.theme?.opacity?.[alpha] === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return withAlphaValue(normalizedColor, tailwindConfig.theme.opacity[alpha])
|
||||
}
|
||||
|
||||
return asValue(modifier, options, { validate: validateColor })
|
||||
}
|
||||
|
||||
export function asLookupValue(modifier, options = {}) {
|
||||
return options.values?.[modifier]
|
||||
}
|
||||
|
||||
function guess(validate) {
|
||||
return (modifier, options) => {
|
||||
return asValue(modifier, options, { validate })
|
||||
}
|
||||
}
|
||||
|
||||
export let typeMap = {
|
||||
any: asValue,
|
||||
color: asColor,
|
||||
url: guess(url),
|
||||
image: guess(image),
|
||||
length: guess(length),
|
||||
percentage: guess(percentage),
|
||||
position: guess(position),
|
||||
lookup: asLookupValue,
|
||||
'generic-name': guess(genericName),
|
||||
'family-name': guess(familyName),
|
||||
number: guess(number),
|
||||
'line-width': guess(lineWidth),
|
||||
'absolute-size': guess(absoluteSize),
|
||||
'relative-size': guess(relativeSize),
|
||||
shadow: guess(shadow),
|
||||
size: guess(backgroundSize),
|
||||
}
|
||||
|
||||
let supportedTypes = Object.keys(typeMap)
|
||||
|
||||
function splitAtFirst(input, delim) {
|
||||
let idx = input.indexOf(delim)
|
||||
if (idx === -1) return [undefined, input]
|
||||
return [input.slice(0, idx), input.slice(idx + 1)]
|
||||
}
|
||||
|
||||
export function coerceValue(types, modifier, options, tailwindConfig) {
|
||||
if (options.values && modifier in options.values) {
|
||||
for (let { type } of types ?? []) {
|
||||
let result = typeMap[type](modifier, options, {
|
||||
tailwindConfig,
|
||||
})
|
||||
|
||||
if (result === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
return [result, type, null]
|
||||
}
|
||||
}
|
||||
|
||||
if (isArbitraryValue(modifier)) {
|
||||
let arbitraryValue = modifier.slice(1, -1)
|
||||
let [explicitType, value] = splitAtFirst(arbitraryValue, ':')
|
||||
|
||||
// It could be that this resolves to `url(https` which is not a valid
|
||||
// identifier. We currently only support "simple" words with dashes or
|
||||
// underscores. E.g.: family-name
|
||||
if (!/^[\w-_]+$/g.test(explicitType)) {
|
||||
value = arbitraryValue
|
||||
}
|
||||
|
||||
//
|
||||
else if (explicitType !== undefined && !supportedTypes.includes(explicitType)) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (value.length > 0 && supportedTypes.includes(explicitType)) {
|
||||
return [asValue(`[${value}]`, options), explicitType, null]
|
||||
}
|
||||
}
|
||||
|
||||
let matches = getMatchingTypes(types, modifier, options, tailwindConfig)
|
||||
|
||||
// Find first matching type
|
||||
for (let match of matches) {
|
||||
return match
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{type: string}[]} types
|
||||
* @param {string} rawModifier
|
||||
* @param {any} options
|
||||
* @param {any} tailwindConfig
|
||||
* @returns {Iterator<[value: string, type: string, modifier: string | null]>}
|
||||
*/
|
||||
export function* getMatchingTypes(types, rawModifier, options, tailwindConfig) {
|
||||
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
||||
|
||||
let [modifier, utilityModifier] = splitUtilityModifier(rawModifier)
|
||||
|
||||
let canUseUtilityModifier =
|
||||
modifiersEnabled &&
|
||||
options.modifiers != null &&
|
||||
(options.modifiers === 'any' ||
|
||||
(typeof options.modifiers === 'object' &&
|
||||
((utilityModifier && isArbitraryValue(utilityModifier)) ||
|
||||
utilityModifier in options.modifiers)))
|
||||
|
||||
if (!canUseUtilityModifier) {
|
||||
modifier = rawModifier
|
||||
utilityModifier = undefined
|
||||
}
|
||||
|
||||
if (utilityModifier !== undefined && modifier === '') {
|
||||
modifier = 'DEFAULT'
|
||||
}
|
||||
|
||||
// Check the full value first
|
||||
// TODO: Move to asValue… somehow
|
||||
if (utilityModifier !== undefined) {
|
||||
if (typeof options.modifiers === 'object') {
|
||||
let configValue = options.modifiers?.[utilityModifier] ?? null
|
||||
if (configValue !== null) {
|
||||
utilityModifier = configValue
|
||||
} else if (isArbitraryValue(utilityModifier)) {
|
||||
utilityModifier = unwrapArbitraryModifier(utilityModifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let { type } of types ?? []) {
|
||||
let result = typeMap[type](modifier, options, {
|
||||
tailwindConfig,
|
||||
})
|
||||
|
||||
if (result === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
yield [result, type, utilityModifier ?? null]
|
||||
}
|
||||
}
|
||||
33
node_modules/tailwindcss/src/util/prefixSelector.js
generated
vendored
Normal file
33
node_modules/tailwindcss/src/util/prefixSelector.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import parser from 'postcss-selector-parser'
|
||||
|
||||
/**
|
||||
* @template {string | import('postcss-selector-parser').Root} T
|
||||
*
|
||||
* Prefix all classes in the selector with the given prefix
|
||||
*
|
||||
* It can take either a string or a selector AST and will return the same type
|
||||
*
|
||||
* @param {string} prefix
|
||||
* @param {T} selector
|
||||
* @param {boolean} prependNegative
|
||||
* @returns {T}
|
||||
*/
|
||||
export default function (prefix, selector, prependNegative = false) {
|
||||
if (prefix === '') {
|
||||
return selector
|
||||
}
|
||||
|
||||
/** @type {import('postcss-selector-parser').Root} */
|
||||
let ast = typeof selector === 'string' ? parser().astSync(selector) : selector
|
||||
|
||||
ast.walkClasses((classSelector) => {
|
||||
let baseClass = classSelector.value
|
||||
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith('-')
|
||||
|
||||
classSelector.value = shouldPlaceNegativeBeforePrefix
|
||||
? `-${prefix}${baseClass.slice(1)}`
|
||||
: `${prefix}${baseClass}`
|
||||
})
|
||||
|
||||
return typeof selector === 'string' ? ast.toString() : ast
|
||||
}
|
||||
167
node_modules/tailwindcss/src/util/pseudoElements.js
generated
vendored
Normal file
167
node_modules/tailwindcss/src/util/pseudoElements.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
/** @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:
|
||||
|
||||
// **Actionable**
|
||||
// Zero or more user-action pseudo-classes may be attached to the pseudo-element itself
|
||||
// structural-pseudo-classes are NOT allowed but we don't make
|
||||
// The spec is not clear on whether this is allowed or not — but in practice it is.
|
||||
|
||||
// **Terminal**
|
||||
// It MUST be placed at the end of a selector
|
||||
//
|
||||
// This is the required in the spec. However, some pseudo elements are not "terminal" because
|
||||
// they represent a "boundary piercing" that is compiled out by a build step.
|
||||
|
||||
// **Jumpable**
|
||||
// Any terminal element may "jump" over combinators when moving to the end of the selector
|
||||
//
|
||||
// This is a backwards-compat quirk of pseudo element variants from earlier versions of Tailwind CSS.
|
||||
|
||||
/** @typedef {'terminal' | 'actionable' | 'jumpable'} PseudoProperty */
|
||||
|
||||
/** @type {Record<string, PseudoProperty[]>} */
|
||||
let elementProperties = {
|
||||
// Pseudo elements from the spec
|
||||
'::after': ['terminal', 'jumpable'],
|
||||
'::backdrop': ['terminal', 'jumpable'],
|
||||
'::before': ['terminal', 'jumpable'],
|
||||
'::cue': ['terminal'],
|
||||
'::cue-region': ['terminal'],
|
||||
'::first-letter': ['terminal', 'jumpable'],
|
||||
'::first-line': ['terminal', 'jumpable'],
|
||||
'::grammar-error': ['terminal'],
|
||||
'::marker': ['terminal', 'jumpable'],
|
||||
'::part': ['terminal', 'actionable'],
|
||||
'::placeholder': ['terminal', 'jumpable'],
|
||||
'::selection': ['terminal', 'jumpable'],
|
||||
'::slotted': ['terminal'],
|
||||
'::spelling-error': ['terminal'],
|
||||
'::target-text': ['terminal'],
|
||||
|
||||
// Pseudo elements from the spec with special rules
|
||||
'::file-selector-button': ['terminal', 'actionable'],
|
||||
|
||||
// Library-specific pseudo elements used by component libraries
|
||||
// These are Shadow DOM-like
|
||||
'::deep': ['actionable'],
|
||||
'::v-deep': ['actionable'],
|
||||
'::ng-deep': ['actionable'],
|
||||
|
||||
// Note: As a rule, double colons (::) should be used instead of a single colon
|
||||
// (:). This distinguishes pseudo-classes from pseudo-elements. However, since
|
||||
// this distinction was not present in older versions of the W3C spec, most
|
||||
// browsers support both syntaxes for the original pseudo-elements.
|
||||
':after': ['terminal', 'jumpable'],
|
||||
':before': ['terminal', 'jumpable'],
|
||||
':first-letter': ['terminal', 'jumpable'],
|
||||
':first-line': ['terminal', 'jumpable'],
|
||||
|
||||
// The default value is used when the pseudo-element is not recognized
|
||||
// Because it's not recognized, we don't know if it's terminal or not
|
||||
// So we assume it can be moved AND can have user-action pseudo classes attached to it
|
||||
__default__: ['terminal', 'actionable'],
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Selector} sel
|
||||
* @returns {Selector}
|
||||
*/
|
||||
export function movePseudos(sel) {
|
||||
let [pseudos] = movablePseudos(sel)
|
||||
|
||||
// Remove all pseudo elements from their respective selectors
|
||||
pseudos.forEach(([sel, pseudo]) => sel.removeChild(pseudo))
|
||||
|
||||
// Re-add them to the end of the selector in the correct order.
|
||||
// This moves terminal pseudo elements to the end of the
|
||||
// selector otherwise the selector will not be valid.
|
||||
//
|
||||
// Examples:
|
||||
// - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
|
||||
// - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
|
||||
//
|
||||
// The selector `::before:hover` does not work but we
|
||||
// can make it work for you by flipping the order.
|
||||
sel.nodes.push(...pseudos.map(([, pseudo]) => pseudo))
|
||||
|
||||
return sel
|
||||
}
|
||||
|
||||
/** @typedef {[sel: Selector, pseudo: Pseudo, attachedTo: Pseudo | null]} MovablePseudo */
|
||||
/** @typedef {[pseudos: MovablePseudo[], lastSeenElement: Pseudo | null]} MovablePseudosResult */
|
||||
|
||||
/**
|
||||
* @param {Selector} sel
|
||||
* @returns {MovablePseudosResult}
|
||||
*/
|
||||
function movablePseudos(sel) {
|
||||
/** @type {MovablePseudo[]} */
|
||||
let buffer = []
|
||||
|
||||
/** @type {Pseudo | null} */
|
||||
let lastSeenElement = null
|
||||
|
||||
for (let node of sel.nodes) {
|
||||
if (node.type === 'combinator') {
|
||||
buffer = buffer.filter(([, node]) => propertiesForPseudo(node).includes('jumpable'))
|
||||
lastSeenElement = null
|
||||
} else if (node.type === 'pseudo') {
|
||||
if (isMovablePseudoElement(node)) {
|
||||
lastSeenElement = node
|
||||
buffer.push([sel, node, null])
|
||||
} else if (lastSeenElement && isAttachablePseudoClass(node, lastSeenElement)) {
|
||||
buffer.push([sel, node, lastSeenElement])
|
||||
} else {
|
||||
lastSeenElement = null
|
||||
}
|
||||
|
||||
for (let sub of node.nodes ?? []) {
|
||||
let [movable, lastSeenElementInSub] = movablePseudos(sub)
|
||||
lastSeenElement = lastSeenElementInSub || lastSeenElement
|
||||
buffer.push(...movable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [buffer, lastSeenElement]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isPseudoElement(node) {
|
||||
return node.value.startsWith('::') || elementProperties[node.value] !== undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isMovablePseudoElement(node) {
|
||||
return isPseudoElement(node) && propertiesForPseudo(node).includes('terminal')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @param {Pseudo} pseudo
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isAttachablePseudoClass(node, pseudo) {
|
||||
if (node.type !== 'pseudo') return false
|
||||
if (isPseudoElement(node)) return false
|
||||
|
||||
return propertiesForPseudo(pseudo).includes('actionable')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Pseudo} pseudo
|
||||
* @returns {PseudoProperty[]}
|
||||
*/
|
||||
function propertiesForPseudo(pseudo) {
|
||||
return elementProperties[pseudo.value] ?? elementProperties.__default__
|
||||
}
|
||||
24
node_modules/tailwindcss/src/util/removeAlphaVariables.js
generated
vendored
Normal file
24
node_modules/tailwindcss/src/util/removeAlphaVariables.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* This function removes any uses of CSS variables used as an alpha channel
|
||||
*
|
||||
* This is required for selectors like `:visited` which do not allow
|
||||
* changes in opacity or external control using CSS variables.
|
||||
*
|
||||
* @param {import('postcss').Container} container
|
||||
* @param {string[]} toRemove
|
||||
*/
|
||||
export function removeAlphaVariables(container, toRemove) {
|
||||
container.walkDecls((decl) => {
|
||||
if (toRemove.includes(decl.prop)) {
|
||||
decl.remove()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for (let varName of toRemove) {
|
||||
if (decl.value.includes(`/ var(${varName})`)) {
|
||||
decl.value = decl.value.replace(`/ var(${varName})`, '')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
277
node_modules/tailwindcss/src/util/resolveConfig.js
generated
vendored
Normal file
277
node_modules/tailwindcss/src/util/resolveConfig.js
generated
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
import negateValue from './negateValue'
|
||||
import corePluginList from '../corePluginList'
|
||||
import configurePlugins from './configurePlugins'
|
||||
import colors from '../public/colors'
|
||||
import { defaults } from './defaults'
|
||||
import { toPath } from './toPath'
|
||||
import { normalizeConfig } from './normalizeConfig'
|
||||
import isPlainObject from './isPlainObject'
|
||||
import { cloneDeep } from './cloneDeep'
|
||||
import { parseColorFormat } from './pluginUtils'
|
||||
import { withAlphaValue } from './withAlphaVariable'
|
||||
import toColorValue from './toColorValue'
|
||||
|
||||
function isFunction(input) {
|
||||
return typeof input === 'function'
|
||||
}
|
||||
|
||||
function mergeWith(target, ...sources) {
|
||||
let customizer = sources.pop()
|
||||
|
||||
for (let source of sources) {
|
||||
for (let k in source) {
|
||||
let merged = customizer(target[k], source[k])
|
||||
|
||||
if (merged === undefined) {
|
||||
if (isPlainObject(target[k]) && isPlainObject(source[k])) {
|
||||
target[k] = mergeWith({}, target[k], source[k], customizer)
|
||||
} else {
|
||||
target[k] = source[k]
|
||||
}
|
||||
} else {
|
||||
target[k] = merged
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
const configUtils = {
|
||||
colors,
|
||||
negative(scale) {
|
||||
// TODO: Log that this function isn't really needed anymore?
|
||||
return Object.keys(scale)
|
||||
.filter((key) => scale[key] !== '0')
|
||||
.reduce((negativeScale, key) => {
|
||||
let negativeValue = negateValue(scale[key])
|
||||
|
||||
if (negativeValue !== undefined) {
|
||||
negativeScale[`-${key}`] = negativeValue
|
||||
}
|
||||
|
||||
return negativeScale
|
||||
}, {})
|
||||
},
|
||||
breakpoints(screens) {
|
||||
return Object.keys(screens)
|
||||
.filter((key) => typeof screens[key] === 'string')
|
||||
.reduce(
|
||||
(breakpoints, key) => ({
|
||||
...breakpoints,
|
||||
[`screen-${key}`]: screens[key],
|
||||
}),
|
||||
{}
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
function value(valueToResolve, ...args) {
|
||||
return isFunction(valueToResolve) ? valueToResolve(...args) : valueToResolve
|
||||
}
|
||||
|
||||
function collectExtends(items) {
|
||||
return items.reduce((merged, { extend }) => {
|
||||
return mergeWith(merged, extend, (mergedValue, extendValue) => {
|
||||
if (mergedValue === undefined) {
|
||||
return [extendValue]
|
||||
}
|
||||
|
||||
if (Array.isArray(mergedValue)) {
|
||||
return [extendValue, ...mergedValue]
|
||||
}
|
||||
|
||||
return [extendValue, mergedValue]
|
||||
})
|
||||
}, {})
|
||||
}
|
||||
|
||||
function mergeThemes(themes) {
|
||||
return {
|
||||
...themes.reduce((merged, theme) => defaults(merged, theme), {}),
|
||||
|
||||
// In order to resolve n config objects, we combine all of their `extend` properties
|
||||
// into arrays instead of objects so they aren't overridden.
|
||||
extend: collectExtends(themes),
|
||||
}
|
||||
}
|
||||
|
||||
function mergeExtensionCustomizer(merged, value) {
|
||||
// When we have an array of objects, we do want to merge it
|
||||
if (Array.isArray(merged) && isPlainObject(merged[0])) {
|
||||
return merged.concat(value)
|
||||
}
|
||||
|
||||
// When the incoming value is an array, and the existing config is an object, prepend the existing object
|
||||
if (Array.isArray(value) && isPlainObject(value[0]) && isPlainObject(merged)) {
|
||||
return [merged, ...value]
|
||||
}
|
||||
|
||||
// Override arrays (for example for font-families, box-shadows, ...)
|
||||
if (Array.isArray(value)) {
|
||||
return value
|
||||
}
|
||||
|
||||
// Execute default behaviour
|
||||
return undefined
|
||||
}
|
||||
|
||||
function mergeExtensions({ extend, ...theme }) {
|
||||
return mergeWith(theme, extend, (themeValue, extensions) => {
|
||||
// The `extend` property is an array, so we need to check if it contains any functions
|
||||
if (!isFunction(themeValue) && !extensions.some(isFunction)) {
|
||||
return mergeWith({}, themeValue, ...extensions, mergeExtensionCustomizer)
|
||||
}
|
||||
|
||||
return (resolveThemePath, utils) =>
|
||||
mergeWith(
|
||||
{},
|
||||
...[themeValue, ...extensions].map((e) => value(e, resolveThemePath, utils)),
|
||||
mergeExtensionCustomizer
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} key
|
||||
* @return {Iterable<string[] & {alpha: string | undefined}>}
|
||||
*/
|
||||
function* toPaths(key) {
|
||||
let path = toPath(key)
|
||||
|
||||
if (path.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
yield path
|
||||
|
||||
if (Array.isArray(key)) {
|
||||
return
|
||||
}
|
||||
|
||||
let pattern = /^(.*?)\s*\/\s*([^/]+)$/
|
||||
let matches = key.match(pattern)
|
||||
|
||||
if (matches !== null) {
|
||||
let [, prefix, alpha] = matches
|
||||
|
||||
let newPath = toPath(prefix)
|
||||
newPath.alpha = alpha
|
||||
|
||||
yield newPath
|
||||
}
|
||||
}
|
||||
|
||||
function resolveFunctionKeys(object) {
|
||||
// theme('colors.red.500 / 0.5') -> ['colors', 'red', '500 / 0', '5]
|
||||
|
||||
const resolvePath = (key, defaultValue) => {
|
||||
for (const path of toPaths(key)) {
|
||||
let index = 0
|
||||
let val = object
|
||||
|
||||
while (val !== undefined && val !== null && index < path.length) {
|
||||
val = val[path[index++]]
|
||||
|
||||
let shouldResolveAsFn =
|
||||
isFunction(val) && (path.alpha === undefined || index <= path.length - 1)
|
||||
|
||||
val = shouldResolveAsFn ? val(resolvePath, configUtils) : val
|
||||
}
|
||||
|
||||
if (val !== undefined) {
|
||||
if (path.alpha !== undefined) {
|
||||
let normalized = parseColorFormat(val)
|
||||
|
||||
return withAlphaValue(normalized, path.alpha, toColorValue(normalized))
|
||||
}
|
||||
|
||||
if (isPlainObject(val)) {
|
||||
return cloneDeep(val)
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
Object.assign(resolvePath, {
|
||||
theme: resolvePath,
|
||||
...configUtils,
|
||||
})
|
||||
|
||||
return Object.keys(object).reduce((resolved, key) => {
|
||||
resolved[key] = isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key]
|
||||
|
||||
return resolved
|
||||
}, {})
|
||||
}
|
||||
|
||||
function extractPluginConfigs(configs) {
|
||||
let allConfigs = []
|
||||
|
||||
configs.forEach((config) => {
|
||||
allConfigs = [...allConfigs, config]
|
||||
|
||||
const plugins = config?.plugins ?? []
|
||||
|
||||
if (plugins.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
plugins.forEach((plugin) => {
|
||||
if (plugin.__isOptionsFunction) {
|
||||
plugin = plugin()
|
||||
}
|
||||
allConfigs = [...allConfigs, ...extractPluginConfigs([plugin?.config ?? {}])]
|
||||
})
|
||||
})
|
||||
|
||||
return allConfigs
|
||||
}
|
||||
|
||||
function resolveCorePlugins(corePluginConfigs) {
|
||||
const result = [...corePluginConfigs].reduceRight((resolved, corePluginConfig) => {
|
||||
if (isFunction(corePluginConfig)) {
|
||||
return corePluginConfig({ corePlugins: resolved })
|
||||
}
|
||||
return configurePlugins(corePluginConfig, resolved)
|
||||
}, corePluginList)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function resolvePluginLists(pluginLists) {
|
||||
const result = [...pluginLists].reduceRight((resolved, pluginList) => {
|
||||
return [...resolved, ...pluginList]
|
||||
}, [])
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export default function resolveConfig(configs) {
|
||||
let allConfigs = [
|
||||
...extractPluginConfigs(configs),
|
||||
{
|
||||
prefix: '',
|
||||
important: false,
|
||||
separator: ':',
|
||||
},
|
||||
]
|
||||
|
||||
return normalizeConfig(
|
||||
defaults(
|
||||
{
|
||||
theme: resolveFunctionKeys(
|
||||
mergeExtensions(mergeThemes(allConfigs.map((t) => t?.theme ?? {})))
|
||||
),
|
||||
corePlugins: resolveCorePlugins(allConfigs.map((c) => c.corePlugins)),
|
||||
plugins: resolvePluginLists(configs.map((c) => c?.plugins ?? [])),
|
||||
},
|
||||
...allConfigs
|
||||
)
|
||||
)
|
||||
}
|
||||
66
node_modules/tailwindcss/src/util/resolveConfigPath.js
generated
vendored
Normal file
66
node_modules/tailwindcss/src/util/resolveConfigPath.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
const defaultConfigFiles = [
|
||||
'./tailwind.config.js',
|
||||
'./tailwind.config.cjs',
|
||||
'./tailwind.config.mjs',
|
||||
'./tailwind.config.ts',
|
||||
]
|
||||
|
||||
function isObject(value) {
|
||||
return typeof value === 'object' && value !== null
|
||||
}
|
||||
|
||||
function isEmpty(obj) {
|
||||
return Object.keys(obj).length === 0
|
||||
}
|
||||
|
||||
function isString(value) {
|
||||
return typeof value === 'string' || value instanceof String
|
||||
}
|
||||
|
||||
export default function resolveConfigPath(pathOrConfig) {
|
||||
// require('tailwindcss')({ theme: ..., variants: ... })
|
||||
if (isObject(pathOrConfig) && pathOrConfig.config === undefined && !isEmpty(pathOrConfig)) {
|
||||
return null
|
||||
}
|
||||
|
||||
// require('tailwindcss')({ config: 'custom-config.js' })
|
||||
if (
|
||||
isObject(pathOrConfig) &&
|
||||
pathOrConfig.config !== undefined &&
|
||||
isString(pathOrConfig.config)
|
||||
) {
|
||||
return path.resolve(pathOrConfig.config)
|
||||
}
|
||||
|
||||
// require('tailwindcss')({ config: { theme: ..., variants: ... } })
|
||||
if (
|
||||
isObject(pathOrConfig) &&
|
||||
pathOrConfig.config !== undefined &&
|
||||
isObject(pathOrConfig.config)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
// require('tailwindcss')('custom-config.js')
|
||||
if (isString(pathOrConfig)) {
|
||||
return path.resolve(pathOrConfig)
|
||||
}
|
||||
|
||||
// require('tailwindcss')
|
||||
return resolveDefaultConfigPath()
|
||||
}
|
||||
|
||||
export function resolveDefaultConfigPath() {
|
||||
for (const configFile of defaultConfigFiles) {
|
||||
try {
|
||||
const configPath = path.resolve(configFile)
|
||||
fs.accessSync(configPath)
|
||||
return configPath
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
10
node_modules/tailwindcss/src/util/responsive.js
generated
vendored
Normal file
10
node_modules/tailwindcss/src/util/responsive.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import postcss from 'postcss'
|
||||
import cloneNodes from './cloneNodes'
|
||||
|
||||
export default function responsive(rules) {
|
||||
return postcss
|
||||
.atRule({
|
||||
name: 'responsive',
|
||||
})
|
||||
.append(cloneNodes(Array.isArray(rules) ? rules : [rules]))
|
||||
}
|
||||
52
node_modules/tailwindcss/src/util/splitAtTopLevelOnly.js
generated
vendored
Normal file
52
node_modules/tailwindcss/src/util/splitAtTopLevelOnly.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* This splits a string on a top-level character.
|
||||
*
|
||||
* Regex doesn't support recursion (at least not the JS-flavored version).
|
||||
* So we have to use a tiny state machine to keep track of paren placement.
|
||||
*
|
||||
* Expected behavior using commas:
|
||||
* var(--a, 0 0 1px rgb(0, 0, 0)), 0 0 1px rgb(0, 0, 0)
|
||||
* ─┬─ ┬ ┬ ┬
|
||||
* x x x ╰──────── Split because top-level
|
||||
* ╰──────────────┴──┴───────────── Ignored b/c inside >= 1 levels of parens
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {string} separator
|
||||
*/
|
||||
export function splitAtTopLevelOnly(input, separator) {
|
||||
let stack = []
|
||||
let parts = []
|
||||
let lastPos = 0
|
||||
let isEscaped = false
|
||||
|
||||
for (let idx = 0; idx < input.length; idx++) {
|
||||
let char = input[idx]
|
||||
|
||||
if (stack.length === 0 && char === separator[0] && !isEscaped) {
|
||||
if (separator.length === 1 || input.slice(idx, idx + separator.length) === separator) {
|
||||
parts.push(input.slice(lastPos, idx))
|
||||
lastPos = idx + separator.length
|
||||
}
|
||||
}
|
||||
|
||||
if (isEscaped) {
|
||||
isEscaped = false
|
||||
} else if (char === '\\') {
|
||||
isEscaped = true
|
||||
}
|
||||
|
||||
if (char === '(' || char === '[' || char === '{') {
|
||||
stack.push(char)
|
||||
} else if (
|
||||
(char === ')' && stack[stack.length - 1] === '(') ||
|
||||
(char === ']' && stack[stack.length - 1] === '[') ||
|
||||
(char === '}' && stack[stack.length - 1] === '{')
|
||||
) {
|
||||
stack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
parts.push(input.slice(lastPos))
|
||||
|
||||
return parts
|
||||
}
|
||||
4
node_modules/tailwindcss/src/util/tap.js
generated
vendored
Normal file
4
node_modules/tailwindcss/src/util/tap.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export function tap(value, mutator) {
|
||||
mutator(value)
|
||||
return value
|
||||
}
|
||||
3
node_modules/tailwindcss/src/util/toColorValue.js
generated
vendored
Normal file
3
node_modules/tailwindcss/src/util/toColorValue.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function toColorValue(maybeFunction) {
|
||||
return typeof maybeFunction === 'function' ? maybeFunction({}) : maybeFunction
|
||||
}
|
||||
26
node_modules/tailwindcss/src/util/toPath.js
generated
vendored
Normal file
26
node_modules/tailwindcss/src/util/toPath.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Parse a path string into an array of path segments.
|
||||
*
|
||||
* Square bracket notation `a[b]` may be used to "escape" dots that would otherwise be interpreted as path separators.
|
||||
*
|
||||
* Example:
|
||||
* a -> ['a']
|
||||
* a.b.c -> ['a', 'b', 'c']
|
||||
* a[b].c -> ['a', 'b', 'c']
|
||||
* a[b.c].e.f -> ['a', 'b.c', 'e', 'f']
|
||||
* a[b][c][d] -> ['a', 'b', 'c', 'd']
|
||||
*
|
||||
* @param {string|string[]} path
|
||||
**/
|
||||
export function toPath(path) {
|
||||
if (Array.isArray(path)) return path
|
||||
|
||||
let openBrackets = path.split('[').length - 1
|
||||
let closedBrackets = path.split(']').length - 1
|
||||
|
||||
if (openBrackets !== closedBrackets) {
|
||||
throw new Error(`Path is invalid. Has unbalanced brackets: ${path}`)
|
||||
}
|
||||
|
||||
return path.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean)
|
||||
}
|
||||
62
node_modules/tailwindcss/src/util/transformThemeValue.js
generated
vendored
Normal file
62
node_modules/tailwindcss/src/util/transformThemeValue.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import postcss from 'postcss'
|
||||
import isPlainObject from './isPlainObject'
|
||||
|
||||
export default function transformThemeValue(themeSection) {
|
||||
if (['fontSize', 'outline'].includes(themeSection)) {
|
||||
return (value) => {
|
||||
if (typeof value === 'function') value = value({})
|
||||
if (Array.isArray(value)) value = value[0]
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
if (themeSection === 'fontFamily') {
|
||||
return (value) => {
|
||||
if (typeof value === 'function') value = value({})
|
||||
let families = Array.isArray(value) && isPlainObject(value[1]) ? value[0] : value
|
||||
return Array.isArray(families) ? families.join(', ') : families
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
'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(', ')
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility reasons, before we switched to underscores
|
||||
// instead of commas for arbitrary values.
|
||||
if (['gridTemplateColumns', 'gridTemplateRows', 'objectPosition'].includes(themeSection)) {
|
||||
return (value) => {
|
||||
if (typeof value === 'function') value = value({})
|
||||
if (typeof value === 'string') value = postcss.list.comma(value).join(' ')
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
return (value, opts = {}) => {
|
||||
if (typeof value === 'function') {
|
||||
value = value(opts)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
26
node_modules/tailwindcss/src/util/validateConfig.js
generated
vendored
Normal file
26
node_modules/tailwindcss/src/util/validateConfig.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import log from './log'
|
||||
|
||||
export function validateConfig(config) {
|
||||
if (config.content.files.length === 0) {
|
||||
log.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',
|
||||
])
|
||||
}
|
||||
|
||||
// Warn if the line-clamp plugin is installed
|
||||
try {
|
||||
let plugin = require('@tailwindcss/line-clamp')
|
||||
if (config.plugins.includes(plugin)) {
|
||||
log.warn('line-clamp-in-core', [
|
||||
'As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.',
|
||||
'Remove it from the `plugins` array in your configuration to eliminate this warning.',
|
||||
])
|
||||
|
||||
config.plugins = config.plugins.filter((p) => p !== plugin)
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return config
|
||||
}
|
||||
34
node_modules/tailwindcss/src/util/validateFormalSyntax.js
generated
vendored
Normal file
34
node_modules/tailwindcss/src/util/validateFormalSyntax.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { length, percentage } from './dataTypes'
|
||||
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
|
||||
|
||||
/**
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/Web/CSS/background-size#formal_syntax
|
||||
*
|
||||
* background-size =
|
||||
* <bg-size>#
|
||||
*
|
||||
* <bg-size> =
|
||||
* [ <length-percentage [0,∞]> | auto ]{1,2} |
|
||||
* cover |
|
||||
* contain
|
||||
*
|
||||
* <length-percentage> =
|
||||
* <length> |
|
||||
* <percentage>
|
||||
*
|
||||
* @param {string} value
|
||||
*/
|
||||
export function backgroundSize(value) {
|
||||
let keywordValues = ['cover', 'contain']
|
||||
// the <length-percentage> type will probably be a css function
|
||||
// so we have to use `splitAtTopLevelOnly`
|
||||
return splitAtTopLevelOnly(value, ',').every((part) => {
|
||||
let sizes = 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) => length(size) || percentage(size) || size === 'auto')
|
||||
})
|
||||
}
|
||||
49
node_modules/tailwindcss/src/util/withAlphaVariable.js
generated
vendored
Normal file
49
node_modules/tailwindcss/src/util/withAlphaVariable.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { parseColor, formatColor } from './color'
|
||||
|
||||
export function withAlphaValue(color, alphaValue, defaultValue) {
|
||||
if (typeof color === 'function') {
|
||||
return color({ opacityValue: alphaValue })
|
||||
}
|
||||
|
||||
let parsed = parseColor(color, { loose: true })
|
||||
|
||||
if (parsed === null) {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
return formatColor({ ...parsed, alpha: alphaValue })
|
||||
}
|
||||
|
||||
export default function withAlphaVariable({ color, property, variable }) {
|
||||
let properties = [].concat(property)
|
||||
if (typeof color === 'function') {
|
||||
return {
|
||||
[variable]: '1',
|
||||
...Object.fromEntries(
|
||||
properties.map((p) => {
|
||||
return [p, color({ opacityVariable: variable, opacityValue: `var(${variable})` })]
|
||||
})
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
const parsed = parseColor(color)
|
||||
|
||||
if (parsed === null) {
|
||||
return Object.fromEntries(properties.map((p) => [p, color]))
|
||||
}
|
||||
|
||||
if (parsed.alpha !== undefined) {
|
||||
// Has an alpha value, return color as-is
|
||||
return Object.fromEntries(properties.map((p) => [p, color]))
|
||||
}
|
||||
|
||||
return {
|
||||
[variable]: '1',
|
||||
...Object.fromEntries(
|
||||
properties.map((p) => {
|
||||
return [p, formatColor({ ...parsed, alpha: `var(${variable})` })]
|
||||
})
|
||||
),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user