Urara-Blog/node_modules/.pnpm-store/v3/files/36/a8856c082c28c7a0ce73c90564c8c502022805b88642978f31fbc0577178678826caed6f8af619ad92992388d292af7a1f3917e542aac3be9971d1ef3c40ca
2022-08-14 01:14:53 +08:00

254 lines
5.4 KiB
Text

import { parseColor } from './color'
import { parseBoxShadowValue } from './parseBoxShadowValue'
let cssFunctions = ['min', 'max', 'clamp', 'calc']
// Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types
let COMMA = /,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
let UNDERSCORE = /_(?![^(]*\))/g // Underscore separator that is not located between brackets. E.g.: `rgba(255,_255,_255)_black` these don't count.
// This is not a data type, but rather a function that can normalize the
// correct values.
export function normalize(value, isRoot = true) {
// 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()
}
// Add spaces around operators inside math functions like calc() that do not follow an operator
// or '('.
value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
return match.replace(
/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
'$1 $2 '
)
})
return value
}
export function url(value) {
return value.startsWith('url(')
}
export function number(value) {
return !isNaN(Number(value)) || cssFunctions.some((fn) => new RegExp(`^${fn}\\(.+?`).test(value))
}
export function percentage(value) {
return value.split(UNDERSCORE).every((part) => {
return /%$/g.test(part) || cssFunctions.some((fn) => new RegExp(`^${fn}\\(.+?%`).test(part))
})
}
let lengthUnits = [
'cm',
'mm',
'Q',
'in',
'pc',
'pt',
'px',
'em',
'ex',
'ch',
'rem',
'lh',
'vw',
'vh',
'vmin',
'vmax',
]
let lengthUnitsPattern = `(?:${lengthUnits.join('|')})`
export function length(value) {
return value.split(UNDERSCORE).every((part) => {
return (
part === '0' ||
new RegExp(`${lengthUnitsPattern}$`).test(part) ||
cssFunctions.some((fn) => new RegExp(`^${fn}\\(.+?${lengthUnitsPattern}`).test(part))
)
})
}
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 = value.split(UNDERSCORE).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 = value.split(COMMA).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([
'linear-gradient',
'radial-gradient',
'repeating-linear-gradient',
'repeating-radial-gradient',
'conic-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 = value.split(UNDERSCORE).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 = value.split(COMMA).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)
}