Skip to content

Commit

Permalink
Replace underscore with space in arbitrary values (#5460)
Browse files Browse the repository at this point in the history
* refactor dropShadow plugin, use `matchUtilities`

* replace `_` with ` ` for arbitrary values

* remove custom `asList` function

* do not replace escaped underscores with spaces
  • Loading branch information
RobinMalfait authored Sep 9, 2021
1 parent 4919cbf commit 9daebe4
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 54 deletions.
46 changes: 17 additions & 29 deletions src/corePlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ 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,
updateAllClasses,
transformAllSelectors,
transformAllClasses,
transformLastClasses,
asList,
asLength,
asLookupValue,
} from './util/pluginUtils'
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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']],
[
Expand Down Expand Up @@ -1715,7 +1705,7 @@ export let boxShadow = (() => {
}
},
},
{ values: theme('boxShadow'), type: 'lookup' }
{ values: theme('boxShadow') }
)
}
})()
Expand Down Expand Up @@ -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 }) => {
Expand Down
3 changes: 1 addition & 2 deletions src/util/createUtilityPlugin.js
Original file line number Diff line number Diff line change
@@ -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'],
Expand Down
30 changes: 8 additions & 22 deletions src/util/pluginUtils.js
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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) {
Expand All @@ -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 '
)
Expand All @@ -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(' ')
},
})
}

Expand Down Expand Up @@ -281,7 +268,6 @@ export function asLookupValue(modifier, lookup = {}) {

let typeMap = {
any: asValue,
list: asList,
color: asColor,
angle: asAngle,
length: asLength,
Expand Down
8 changes: 8 additions & 0 deletions src/util/transformThemeValue.js
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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)
}
Expand Down
95 changes: 94 additions & 1 deletion tests/arbitrary-values.test.js
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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';
}
`)
})
})

0 comments on commit 9daebe4

Please sign in to comment.