Replace underscore with space in arbitrary values (#5460)
* refactor dropShadow plugin, use `matchUtilities` * replace `_` with ` ` for arbitrary values * remove custom `asList` function * do not replace escaped underscores with spaces
This commit is contained in:
parent
4919cbfbb8
commit
9daebe43b9
5 changed files with 128 additions and 54 deletions
|
|
@ -9,7 +9,6 @@ import withAlphaVariable, { withAlphaValue } from './util/withAlphaVariable'
|
|||
import toColorValue from './util/toColorValue'
|
||||
import isPlainObject from './util/isPlainObject'
|
||||
import transformThemeValue from './util/transformThemeValue'
|
||||
import nameClass from './util/nameClass'
|
||||
import {
|
||||
applyPseudoToMarker,
|
||||
updateLastClasses,
|
||||
|
|
@ -17,7 +16,6 @@ import {
|
|||
transformAllSelectors,
|
||||
transformAllClasses,
|
||||
transformLastClasses,
|
||||
asList,
|
||||
asLength,
|
||||
asLookupValue,
|
||||
} from './util/pluginUtils'
|
||||
|
|
@ -829,16 +827,12 @@ export let gridAutoFlow = ({ addUtilities }) => {
|
|||
}
|
||||
|
||||
export let gridAutoRows = createUtilityPlugin('gridAutoRows', [['auto-rows', ['gridAutoRows']]])
|
||||
export let gridTemplateColumns = createUtilityPlugin(
|
||||
'gridTemplateColumns',
|
||||
[['grid-cols', ['gridTemplateColumns']]],
|
||||
{ resolveArbitraryValue: asList }
|
||||
)
|
||||
export let gridTemplateRows = createUtilityPlugin(
|
||||
'gridTemplateRows',
|
||||
[['grid-rows', ['gridTemplateRows']]],
|
||||
{ resolveArbitraryValue: asList }
|
||||
)
|
||||
export let gridTemplateColumns = createUtilityPlugin('gridTemplateColumns', [
|
||||
['grid-cols', ['gridTemplateColumns']],
|
||||
])
|
||||
export let gridTemplateRows = createUtilityPlugin('gridTemplateRows', [
|
||||
['grid-rows', ['gridTemplateRows']],
|
||||
])
|
||||
|
||||
export let flexDirection = ({ addUtilities }) => {
|
||||
addUtilities({
|
||||
|
|
@ -1431,12 +1425,8 @@ export let objectFit = ({ addUtilities }) => {
|
|||
'.object-scale-down': { 'object-fit': 'scale-down' },
|
||||
})
|
||||
}
|
||||
export let objectPosition = createUtilityPlugin('objectPosition', [['object', ['object-position']]])
|
||||
|
||||
export let objectPosition = createUtilityPlugin(
|
||||
'objectPosition',
|
||||
[['object', ['object-position']]],
|
||||
{ resolveArbitraryValue: asList }
|
||||
)
|
||||
export let padding = createUtilityPlugin('padding', [
|
||||
['p', ['padding']],
|
||||
[
|
||||
|
|
@ -1715,7 +1705,7 @@ export let boxShadow = (() => {
|
|||
}
|
||||
},
|
||||
},
|
||||
{ values: theme('boxShadow'), type: 'lookup' }
|
||||
{ values: theme('boxShadow') }
|
||||
)
|
||||
}
|
||||
})()
|
||||
|
|
@ -1867,23 +1857,21 @@ export let contrast = ({ matchUtilities, theme }) => {
|
|||
)
|
||||
}
|
||||
|
||||
export let dropShadow = ({ addUtilities, theme }) => {
|
||||
let utilities = Object.fromEntries(
|
||||
Object.entries(theme('dropShadow') ?? {}).map(([modifier, value]) => {
|
||||
return [
|
||||
nameClass('drop-shadow', modifier),
|
||||
{
|
||||
export let dropShadow = ({ matchUtilities, theme }) => {
|
||||
matchUtilities(
|
||||
{
|
||||
'drop-shadow': (value) => {
|
||||
return {
|
||||
'--tw-drop-shadow': Array.isArray(value)
|
||||
? value.map((v) => `drop-shadow(${v})`).join(' ')
|
||||
: `drop-shadow(${value})`,
|
||||
'@defaults filter': {},
|
||||
filter: 'var(--tw-filter)',
|
||||
},
|
||||
]
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
{ values: theme('dropShadow') }
|
||||
)
|
||||
|
||||
addUtilities(utilities)
|
||||
}
|
||||
|
||||
export let grayscale = ({ matchUtilities, theme }) => {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import transformThemeValue from './transformThemeValue'
|
||||
import { asValue, asList, asColor, asAngle, asLength, asLookupValue } from '../util/pluginUtils'
|
||||
import { asValue, asColor, asAngle, asLength, asLookupValue } from '../util/pluginUtils'
|
||||
|
||||
let asMap = new Map([
|
||||
[asValue, 'any'],
|
||||
[asList, 'list'],
|
||||
[asColor, 'color'],
|
||||
[asAngle, 'angle'],
|
||||
[asLength, 'length'],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import selectorParser from 'postcss-selector-parser'
|
||||
import postcss from 'postcss'
|
||||
import escapeCommas from './escapeCommas'
|
||||
import { withAlphaValue } from './withAlphaVariable'
|
||||
import isKeyframeRule from './isKeyframeRule'
|
||||
|
|
@ -153,11 +152,7 @@ export function transformLastClasses(transformClass, { wrap, withRule } = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
export function asValue(
|
||||
modifier,
|
||||
lookup = {},
|
||||
{ validate = () => true, transform = (v) => v } = {}
|
||||
) {
|
||||
export function asValue(modifier, lookup = {}, { validate = () => true } = {}) {
|
||||
let value = lookup[modifier]
|
||||
|
||||
if (value !== undefined) {
|
||||
|
|
@ -174,8 +169,14 @@ export function asValue(
|
|||
return undefined
|
||||
}
|
||||
|
||||
// convert `_` to ` `, escept for escaped underscores `\_`
|
||||
value = value
|
||||
.replace(/([^\\])_/g, '$1 ')
|
||||
.replace(/^_/g, ' ')
|
||||
.replace(/\\_/g, '_')
|
||||
|
||||
// add spaces around operators inside calc() that do not follow an operator or (
|
||||
return transform(value).replace(
|
||||
return value.replace(
|
||||
/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
|
||||
'$1 $2 '
|
||||
)
|
||||
|
|
@ -190,20 +191,6 @@ export function asUnit(modifier, units, lookup = {}) {
|
|||
new RegExp(`^calc\\(.+?${unitsPattern}`).test(value)
|
||||
)
|
||||
},
|
||||
transform: (value) => {
|
||||
return value
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function asList(modifier, lookup = {}) {
|
||||
return asValue(modifier, lookup, {
|
||||
transform: (value) => {
|
||||
return postcss.list
|
||||
.comma(value)
|
||||
.map((v) => v.replace(/,/g, ', '))
|
||||
.join(' ')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +268,6 @@ export function asLookupValue(modifier, lookup = {}) {
|
|||
|
||||
let typeMap = {
|
||||
any: asValue,
|
||||
list: asList,
|
||||
color: asColor,
|
||||
angle: asAngle,
|
||||
length: asLength,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import postcss from 'postcss'
|
||||
|
||||
export default function transformThemeValue(themeSection) {
|
||||
if (['fontSize', 'outline'].includes(themeSection)) {
|
||||
return (value) => (Array.isArray(value) ? value[0] : value)
|
||||
|
|
@ -21,6 +23,12 @@ export default function transformThemeValue(themeSection) {
|
|||
return (value) => (Array.isArray(value) ? value.join(', ') : value)
|
||||
}
|
||||
|
||||
// For backwards compatibility reasons, before we switched to underscores
|
||||
// instead of commas for arbitrary values.
|
||||
if (['gridTemplateColumns', 'gridTemplateRows', 'objectPosition'].includes(themeSection)) {
|
||||
return (value) => (typeof value === 'string' ? postcss.list.comma(value).join(' ') : value)
|
||||
}
|
||||
|
||||
if (themeSection === 'colors') {
|
||||
return (value) => (typeof value === 'function' ? value({}) : value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { run } from './util/run'
|
||||
import { run, html, css } from './util/run'
|
||||
|
||||
test('arbitrary values', () => {
|
||||
let config = {
|
||||
|
|
@ -15,3 +15,96 @@ test('arbitrary values', () => {
|
|||
expect(result.css).toMatchFormattedCss(expected)
|
||||
})
|
||||
})
|
||||
|
||||
it('should convert _ to spaces', () => {
|
||||
let config = {
|
||||
content: [
|
||||
{
|
||||
raw: html`
|
||||
<div class="grid-cols-[200px_repeat(auto-fill,minmax(15%,100px))_300px]"></div>
|
||||
<div class="grid-rows-[200px_repeat(auto-fill,minmax(15%,100px))_300px]"></div>
|
||||
<div class="shadow-[0px_0px_4px_black]"></div>
|
||||
<div class="rounded-[0px_4px_4px_0px]"></div>
|
||||
<div class="m-[8px_4px]"></div>
|
||||
<div class="p-[8px_4px]"></div>
|
||||
<div class="flex-[1_1_100%]"></div>
|
||||
<div class="col-[span_3_/_span_8]"></div>
|
||||
<div class="row-[span_3_/_span_8]"></div>
|
||||
<div class="auto-cols-[minmax(0,_1fr)]"></div>
|
||||
<div class="drop-shadow-[0px_1px_3px_black]"></div>
|
||||
<div class="content-[_hello_world_]"></div>
|
||||
`,
|
||||
},
|
||||
],
|
||||
corePlugins: { preflight: false },
|
||||
}
|
||||
|
||||
return run('@tailwind utilities', config).then((result) => {
|
||||
return expect(result.css).toMatchFormattedCss(css`
|
||||
.col-\\[span_3_\\/_span_8\\] {
|
||||
grid-column: span 3 / span 8;
|
||||
}
|
||||
|
||||
.row-\\[span_3_\\/_span_8\\] {
|
||||
grid-row: span 3 / span 8;
|
||||
}
|
||||
|
||||
.m-\\[8px_4px\\] {
|
||||
margin: 8px 4px;
|
||||
}
|
||||
|
||||
.flex-\\[1_1_100\\%\\] {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.auto-cols-\\[minmax\\(0\\2c _1fr\\)\\] {
|
||||
grid-auto-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.grid-cols-\\[200px_repeat\\(auto-fill\\2c minmax\\(15\\%\\2c 100px\\)\\)_300px\\] {
|
||||
grid-template-columns: 200px repeat(auto-fill, minmax(15%, 100px)) 300px;
|
||||
}
|
||||
|
||||
.grid-rows-\\[200px_repeat\\(auto-fill\\2c minmax\\(15\\%\\2c 100px\\)\\)_300px\\] {
|
||||
grid-template-rows: 200px repeat(auto-fill, minmax(15%, 100px)) 300px;
|
||||
}
|
||||
|
||||
.rounded-\\[0px_4px_4px_0px\\] {
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
|
||||
.p-\\[8px_4px\\] {
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
.shadow-\\[0px_0px_4px_black\\] {
|
||||
--tw-shadow: 0px 0px 4px black;
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
|
||||
.drop-shadow-\\[0px_1px_3px_black\\] {
|
||||
--tw-drop-shadow: drop-shadow(0px 1px 3px black);
|
||||
filter: var(--tw-filter);
|
||||
}
|
||||
.content-\\[_hello_world_\\] {
|
||||
content: hello world;
|
||||
}
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
it('should not convert escaped underscores with spaces', () => {
|
||||
let config = {
|
||||
content: [{ raw: html` <div class="content-['snake\\_case']"></div> ` }],
|
||||
corePlugins: { preflight: false },
|
||||
}
|
||||
|
||||
return run('@tailwind utilities', config).then((result) => {
|
||||
return expect(result.css).toMatchFormattedCss(css`
|
||||
.content-\\[\\'snake\\\\_case\\'\\] {
|
||||
content: 'snake_case';
|
||||
}
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue