tailwindcss/src/util/dataTypes.js

363 lines
8.1 KiB
JavaScript
Raw Normal View History

Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
import { parseColor } from './color'
import { parseBoxShadowValue } from './parseBoxShadowValue'
Improve data type analyses for arbitrary values (#9320) * improve split logic by delimiter The original RegEx did mostly what we want, the idea is that we wanted to split by a `,` but one that was not within `()`. This is useful when you define multiple background colors for example: ```html <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> ``` In this case splitting by the regex would result in the proper result: ```js let result = [ 'rgb(0,0,0)', 'rgb(255,255,255)' ] ``` Visually, you can think of it like: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> · ──┬── ┬ ─────┬───── · │ │ ╰─────── Guarded by parens · │ ╰───────────────── We will split here · ╰───────────────────── Guarded by parens │ └─ ``` We properly split by `,` not inside a `()`. However, this RegEx fails the moment you have deeply nested RegEx values. Visually, this is what's happening: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha))]"></div> · ┬ ┬ ┬ · ╰─┴─┴── We accidentally split here │ └─ ``` This is because on the right of the `,`, the first paren is an opening paren `(` instead of a closing one `)`. I'm not 100% sure how we can improve the RegEx to handle that case as well, instead I wrote a small `splitBy` function that allows you to split the string by a character (just like you could do before) but ignores the ones inside the given exceptions. This keeps track of a stack to know whether we are within parens or not. Visually, the fix looks like this: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha)),rgb(255,255,255,var(--alpha))]"></div> · ┬ ┬ ┬ ┬ ┬ ┬ ┬ · │ │ │ │ ╰───┴───┴── Guarded by parens · │ │ │ ╰────────────────── We will split here · ╰─┴─┴──────────────────────────────── Guarded by parens │ └─ ``` * use already existing `splitAtTopLevelOnly` function * add faster implemetation for `splitAtTopLevelOnly` However, the faster version can't handle separators with multiple characters right now. So instead of using buggy code or only using the "slower" code, we've added a fast path where we use the faster code wherever we can. * use `splitAtTopLevelOnly` directly * make split go brrrrrrr * update changelog * remove unncessary array.from call Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2022-09-14 14:08:56 +02:00
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
let cssFunctions = ['min', 'max', 'clamp', 'calc']
let IS_CSS_FN = new RegExp(`^(${cssFunctions.join('|')})\\(.*\\)`)
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
// Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types
function isCSSFunction(value) {
return IS_CSS_FN.test(value)
}
// These properties accept a `<dashed-ident>` as one of the values. This means that you can use them
// as: `timeline-scope: --tl;`
//
// Without the `var(--tl)`, in these cases we don't want to normalize the value, and you should add
// the `var()` yourself.
//
// More info:
// - https://drafts.csswg.org/scroll-animations/#propdef-timeline-scope
// - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident
//
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
// Concrete properties
'scroll-timeline-name',
'timeline-scope',
'view-timeline-name',
'font-palette',
// Shorthand properties
'scroll-timeline',
'animation-timeline',
'view-timeline',
])
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
// This is not a data type, but rather a function that can normalize the
// correct values.
export function normalize(value, context = null, isRoot = true) {
let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property)
if (value.startsWith('--') && !isVarException) {
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, context, false)
})
.join('')
}
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
// 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()
}
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
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) {
let preventFormattingInFunctions = ['theme']
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
let result = ''
function lastChar() {
let char = result.trimEnd()
return char[char.length - 1]
}
for (let i = 0; i < match.length; i++) {
function peek(word) {
return word.split('').every((char, j) => match[i + j] === char)
}
function consumeUntil(chars) {
let minIndex = Infinity
for (let char of chars) {
let index = match.indexOf(char, i)
if (index !== -1 && index < minIndex) {
minIndex = index
}
}
let result = match.slice(i, minIndex)
i += result.length - 1
return result
}
let char = match[i]
// Handle `var(--variable)`
if (peek('var')) {
// When we consume until `)`, then we are dealing with this scenario:
// `var(--example)`
//
// When we consume until `,`, then we are dealing with this scenario:
// `var(--example, 1rem)`
//
// In this case we do want to "format", the default value as well
result += consumeUntil([')', ','])
}
// Skip formatting inside known functions
else if (preventFormattingInFunctions.some((fn) => peek(fn))) {
result += consumeUntil([')'])
}
// Handle operators
else if (
['+', '-', '*', '/'].includes(char) &&
!['(', '+', '-', '*', '/'].includes(lastChar())
) {
result += ` ${char} `
} else {
result += char
}
}
// Simplify multiple spaces
return result.replace(/\s+/g, ' ')
})
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
}
export function url(value) {
return value.startsWith('url(')
}
export function number(value) {
return !isNaN(Number(value)) || isCSSFunction(value)
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
}
export function percentage(value) {
return (value.endsWith('%') && number(value.slice(0, -1))) || isCSSFunction(value)
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
}
// 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
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
let lengthUnits = [
'cm',
'mm',
'Q',
'in',
'pc',
'pt',
'px',
'em',
'ex',
'ch',
'rem',
'lh',
'rlh',
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
'vw',
'vh',
'vmin',
'vmax',
'vb',
'vi',
'svw',
'svh',
'lvw',
'lvh',
'dvw',
'dvh',
'cqw',
'cqh',
'cqi',
'cqb',
'cqmin',
'cqmax',
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
]
let lengthUnitsPattern = `(?:${lengthUnits.join('|')})`
let lengthRegExp = new RegExp(`^[+-]?[0-9]*\.?[0-9]+(?:[eE][+-]?[0-9]+)?${lengthUnitsPattern}$`)
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
export function length(value) {
return value === '0' || lengthRegExp.test(value) || isCSSFunction(value)
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
}
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
}
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
export function color(value) {
let colors = 0
Improve data type analyses for arbitrary values (#9320) * improve split logic by delimiter The original RegEx did mostly what we want, the idea is that we wanted to split by a `,` but one that was not within `()`. This is useful when you define multiple background colors for example: ```html <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> ``` In this case splitting by the regex would result in the proper result: ```js let result = [ 'rgb(0,0,0)', 'rgb(255,255,255)' ] ``` Visually, you can think of it like: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> · ──┬── ┬ ─────┬───── · │ │ ╰─────── Guarded by parens · │ ╰───────────────── We will split here · ╰───────────────────── Guarded by parens │ └─ ``` We properly split by `,` not inside a `()`. However, this RegEx fails the moment you have deeply nested RegEx values. Visually, this is what's happening: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha))]"></div> · ┬ ┬ ┬ · ╰─┴─┴── We accidentally split here │ └─ ``` This is because on the right of the `,`, the first paren is an opening paren `(` instead of a closing one `)`. I'm not 100% sure how we can improve the RegEx to handle that case as well, instead I wrote a small `splitBy` function that allows you to split the string by a character (just like you could do before) but ignores the ones inside the given exceptions. This keeps track of a stack to know whether we are within parens or not. Visually, the fix looks like this: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha)),rgb(255,255,255,var(--alpha))]"></div> · ┬ ┬ ┬ ┬ ┬ ┬ ┬ · │ │ │ │ ╰───┴───┴── Guarded by parens · │ │ │ ╰────────────────── We will split here · ╰─┴─┴──────────────────────────────── Guarded by parens │ └─ ``` * use already existing `splitAtTopLevelOnly` function * add faster implemetation for `splitAtTopLevelOnly` However, the faster version can't handle separators with multiple characters right now. So instead of using buggy code or only using the "slower" code, we've added a fast path where we use the faster code wherever we can. * use `splitAtTopLevelOnly` directly * make split go brrrrrrr * update changelog * remove unncessary array.from call Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2022-09-14 14:08:56 +02:00
let result = splitAtTopLevelOnly(value, '_').every((part) => {
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
part = normalize(part)
if (part.startsWith('var(')) return true
if (parseColor(part, { loose: true }) !== null) return colors++, true
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
return false
})
if (!result) return false
return colors > 0
}
export function image(value) {
let images = 0
Improve data type analyses for arbitrary values (#9320) * improve split logic by delimiter The original RegEx did mostly what we want, the idea is that we wanted to split by a `,` but one that was not within `()`. This is useful when you define multiple background colors for example: ```html <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> ``` In this case splitting by the regex would result in the proper result: ```js let result = [ 'rgb(0,0,0)', 'rgb(255,255,255)' ] ``` Visually, you can think of it like: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> · ──┬── ┬ ─────┬───── · │ │ ╰─────── Guarded by parens · │ ╰───────────────── We will split here · ╰───────────────────── Guarded by parens │ └─ ``` We properly split by `,` not inside a `()`. However, this RegEx fails the moment you have deeply nested RegEx values. Visually, this is what's happening: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha))]"></div> · ┬ ┬ ┬ · ╰─┴─┴── We accidentally split here │ └─ ``` This is because on the right of the `,`, the first paren is an opening paren `(` instead of a closing one `)`. I'm not 100% sure how we can improve the RegEx to handle that case as well, instead I wrote a small `splitBy` function that allows you to split the string by a character (just like you could do before) but ignores the ones inside the given exceptions. This keeps track of a stack to know whether we are within parens or not. Visually, the fix looks like this: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha)),rgb(255,255,255,var(--alpha))]"></div> · ┬ ┬ ┬ ┬ ┬ ┬ ┬ · │ │ │ │ ╰───┴───┴── Guarded by parens · │ │ │ ╰────────────────── We will split here · ╰─┴─┴──────────────────────────────── Guarded by parens │ └─ ``` * use already existing `splitAtTopLevelOnly` function * add faster implemetation for `splitAtTopLevelOnly` However, the faster version can't handle separators with multiple characters right now. So instead of using buggy code or only using the "slower" code, we've added a fast path where we use the faster code wherever we can. * use `splitAtTopLevelOnly` directly * make split go brrrrrrr * update changelog * remove unncessary array.from call Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2022-09-14 14:08:56 +02:00
let result = splitAtTopLevelOnly(value, ',').every((part) => {
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
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',
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
'linear-gradient',
'radial-gradient',
'repeating-conic-gradient',
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
'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
Improve data type analyses for arbitrary values (#9320) * improve split logic by delimiter The original RegEx did mostly what we want, the idea is that we wanted to split by a `,` but one that was not within `()`. This is useful when you define multiple background colors for example: ```html <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> ``` In this case splitting by the regex would result in the proper result: ```js let result = [ 'rgb(0,0,0)', 'rgb(255,255,255)' ] ``` Visually, you can think of it like: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> · ──┬── ┬ ─────┬───── · │ │ ╰─────── Guarded by parens · │ ╰───────────────── We will split here · ╰───────────────────── Guarded by parens │ └─ ``` We properly split by `,` not inside a `()`. However, this RegEx fails the moment you have deeply nested RegEx values. Visually, this is what's happening: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha))]"></div> · ┬ ┬ ┬ · ╰─┴─┴── We accidentally split here │ └─ ``` This is because on the right of the `,`, the first paren is an opening paren `(` instead of a closing one `)`. I'm not 100% sure how we can improve the RegEx to handle that case as well, instead I wrote a small `splitBy` function that allows you to split the string by a character (just like you could do before) but ignores the ones inside the given exceptions. This keeps track of a stack to know whether we are within parens or not. Visually, the fix looks like this: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha)),rgb(255,255,255,var(--alpha))]"></div> · ┬ ┬ ┬ ┬ ┬ ┬ ┬ · │ │ │ │ ╰───┴───┴── Guarded by parens · │ │ │ ╰────────────────── We will split here · ╰─┴─┴──────────────────────────────── Guarded by parens │ └─ ``` * use already existing `splitAtTopLevelOnly` function * add faster implemetation for `splitAtTopLevelOnly` However, the faster version can't handle separators with multiple characters right now. So instead of using buggy code or only using the "slower" code, we've added a fast path where we use the faster code wherever we can. * use `splitAtTopLevelOnly` directly * make split go brrrrrrr * update changelog * remove unncessary array.from call Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2022-09-14 14:08:56 +02:00
let result = splitAtTopLevelOnly(value, '_').every((part) => {
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
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
Improve data type analyses for arbitrary values (#9320) * improve split logic by delimiter The original RegEx did mostly what we want, the idea is that we wanted to split by a `,` but one that was not within `()`. This is useful when you define multiple background colors for example: ```html <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> ``` In this case splitting by the regex would result in the proper result: ```js let result = [ 'rgb(0,0,0)', 'rgb(255,255,255)' ] ``` Visually, you can think of it like: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgb(0,0,0),rgb(255,255,255)]"></div> · ──┬── ┬ ─────┬───── · │ │ ╰─────── Guarded by parens · │ ╰───────────────── We will split here · ╰───────────────────── Guarded by parens │ └─ ``` We properly split by `,` not inside a `()`. However, this RegEx fails the moment you have deeply nested RegEx values. Visually, this is what's happening: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha))]"></div> · ┬ ┬ ┬ · ╰─┴─┴── We accidentally split here │ └─ ``` This is because on the right of the `,`, the first paren is an opening paren `(` instead of a closing one `)`. I'm not 100% sure how we can improve the RegEx to handle that case as well, instead I wrote a small `splitBy` function that allows you to split the string by a character (just like you could do before) but ignores the ones inside the given exceptions. This keeps track of a stack to know whether we are within parens or not. Visually, the fix looks like this: ``` ┌─[./example.html] │ ∙ 1 │ <div class="bg-[rgba(0,0,0,var(--alpha)),rgb(255,255,255,var(--alpha))]"></div> · ┬ ┬ ┬ ┬ ┬ ┬ ┬ · │ │ │ │ ╰───┴───┴── Guarded by parens · │ │ │ ╰────────────────── We will split here · ╰─┴─┴──────────────────────────────── Guarded by parens │ └─ ``` * use already existing `splitAtTopLevelOnly` function * add faster implemetation for `splitAtTopLevelOnly` However, the faster version can't handle separators with multiple characters right now. So instead of using buggy code or only using the "slower" code, we've added a fast path where we use the faster code wherever we can. * use `splitAtTopLevelOnly` directly * make split go brrrrrrr * update changelog * remove unncessary array.from call Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2022-09-14 14:08:56 +02:00
let result = splitAtTopLevelOnly(value, ',').every((part) => {
Improve arbitrary value support (#5568) * simplify `inset` plugin * run `prettier` on stub file * simplify `align` utility * improve arbitrary support for outline This will allow us to use `outline-[OUTLINE,OPTIONAL_OFFSET]` Input: ```html outline-[2px_solid_black] ``` Output: ```css .outline-\[2px_solid_black\] { outline: 2px solid black; outline-offset: 0; } ``` --- Input: ```html outline-[2px_solid_black,2px] ``` Output: ```css .outline-\[2px_solid_black\2c 2px\] { outline: 2px solid black; outline-offset: 2px; } ``` * remove default `type` * simplify createUtilityPlugin, use types directly * find first matching type when coercing the value * introduce css data types Ref: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Types These data types will be used to "guess" the type of an arbitrary value if there is some ambiguity going on. For example: ``` bg-[#0088cc] -> This is a `color` -> `background-color` bg-[url('...')] -> This is a `url` -> `background-image` ``` If you are using css variables, then there is no way of knowing which type it is referring to, in that case you can be explicit: ``` bg-[color:var(--value)] -> This is a `color` -> `background-color` bg-[url:var(--value)] -> This is a `url` -> `background-image` ``` When you explicitly pass a data type, then we bypass the type system and assume you are right. This is nice in a way because now we don't have to run all of the guessing type code. On the other hand, you can introduce runtime issues that we are not able to detect: ``` :root { --value: 12px; } /* Later... */ bg-[color:var(--value)] -> Assumes `color` -> *eventually* -> `background-color: 12px` ``` * add a bunch of new tests for advanced arbitrary values
2021-09-24 18:45:42 +02:00
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)
}