tailwindcss 0.0.0-insiders.a8836eb → 0.0.0-insiders.ab17c6c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
24
24
  - Add `border-hidden` utility ([#5485](https://github.com/tailwindlabs/tailwindcss/pull/5485))
25
25
  - Add `align-sub` and `align-super` utilities by default ([#5486](https://github.com/tailwindlabs/tailwindcss/pull/5486))
26
26
  - Add `break-before`, `break-inside` and `break-after` utilities ([#5530](https://github.com/tailwindlabs/tailwindcss/pull/5530))
27
+ - Add `file` variant for `::file-selector-button` pseudo element ([#4936](https://github.com/tailwindlabs/tailwindcss/pull/4936))
27
28
 
28
29
  ### Fixed
29
30
 
@@ -83,6 +83,13 @@ let pseudoElementVariants = ({
83
83
  return withPseudo(`selection${config('separator')}${className}`, '::selection');
84
84
  });
85
85
  })]);
86
+ addVariant('file', (0, _pluginUtils.transformAllSelectors)(selector => {
87
+ return (0, _pluginUtils.updateAllClasses)(selector, (className, {
88
+ withPseudo
89
+ }) => {
90
+ return withPseudo(`file${config('separator')}${className}`, '::file-selector-button');
91
+ });
92
+ }));
86
93
  addVariant('before', (0, _pluginUtils.transformAllSelectors)(selector => {
87
94
  return (0, _pluginUtils.updateAllClasses)(selector, (className, {
88
95
  withPseudo
@@ -1790,7 +1797,7 @@ exports.backgroundColor = backgroundColor;
1790
1797
  let backgroundOpacity = (0, _createUtilityPlugin.default)('backgroundOpacity', [['bg-opacity', ['--tw-bg-opacity']]]);
1791
1798
  exports.backgroundOpacity = backgroundOpacity;
1792
1799
  let backgroundImage = (0, _createUtilityPlugin.default)('backgroundImage', [['bg', ['background-image']]], {
1793
- resolveArbitraryValue: _pluginUtils.asLookupValue
1800
+ resolveArbitraryValue: [_pluginUtils.asLookupValue, _pluginUtils.asURL]
1794
1801
  });
1795
1802
  exports.backgroundImage = backgroundImage;
1796
1803
 
@@ -1977,7 +1984,7 @@ let stroke = ({
1977
1984
 
1978
1985
  exports.stroke = stroke;
1979
1986
  let strokeWidth = (0, _createUtilityPlugin.default)('strokeWidth', [['stroke', ['stroke-width']]], {
1980
- resolveArbitraryValue: _pluginUtils.asLength
1987
+ resolveArbitraryValue: [_pluginUtils.asLength, _pluginUtils.asURL]
1981
1988
  });
1982
1989
  exports.strokeWidth = strokeWidth;
1983
1990
 
@@ -21,10 +21,12 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
21
21
 
22
22
  let env = sharedState.env;
23
23
  let contentMatchCache = sharedState.contentMatchCache;
24
- const PATTERNS = ["([^<>\"'`\\s]*\\['[^<>\"'`\\s]*'\\])", // `content-['hello']` but not `content-['hello']']`
25
- '([^<>"\'`\\s]*\\["[^<>"\'`\\s]*"\\])', // `content-["hello"]` but not `content-["hello"]"]`
26
- '([^<>"\'`\\s]*\\[[^<>"\'`\\s]+\\])', // `fill-[#bada55]`
27
- '([^<>"\'`\\s]*[^<>"\'`\\s:])' // `px-1.5`, `uppercase` but not `uppercase:`
24
+ const PATTERNS = [/([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source, // bg-[url('...')]
25
+ /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source, // bg-[url("...")]
26
+ /([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
27
+ /([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
28
+ /([^<>"'`\s]*\[[^"'`\s]+\])/.source, // `fill-[#bada55]`
29
+ /([^<>"'`\s]*[^"'`\s:])/.source // `px-1.5`, `uppercase` but not `uppercase:`].join('|')
28
30
  ].join('|');
29
31
  const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
30
32
  const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g;
@@ -254,10 +254,13 @@ function* resolveMatches(candidate, context) {
254
254
  for (let matchedPlugins of resolveMatchedPlugins(classCandidate, context)) {
255
255
  let matches = [];
256
256
  let [plugins, modifier] = matchedPlugins;
257
+ let isOnlyPlugin = plugins.length === 1;
257
258
 
258
259
  for (let [sort, plugin] of plugins) {
259
260
  if (typeof plugin === 'function') {
260
- for (let ruleSet of [].concat(plugin(modifier))) {
261
+ for (let ruleSet of [].concat(plugin(modifier, {
262
+ isOnlyPlugin
263
+ }))) {
261
264
  let [rules, options] = parseRules(ruleSet, context.postCssNodeCache);
262
265
 
263
266
  for (let rule of rules) {
@@ -333,17 +333,27 @@ function buildPluginApi(tailwindConfig, context, {
333
333
  let rule = utilities[identifier];
334
334
  classList.add([prefixedIdentifier, options]);
335
335
 
336
- function wrapped(modifier) {
336
+ function wrapped(modifier, {
337
+ isOnlyPlugin
338
+ }) {
337
339
  let {
338
340
  type = 'any'
339
341
  } = options;
340
342
  type = [].concat(type);
341
343
  let [value, coercedType] = (0, _pluginUtils.coerceValue)(type, modifier, options.values, tailwindConfig);
342
344
 
343
- if (!type.includes(coercedType) || value === undefined) {
345
+ if (value === undefined) {
344
346
  return [];
345
347
  }
346
348
 
349
+ if (!type.includes(coercedType)) {
350
+ if (isOnlyPlugin) {
351
+ _log.default.warn([`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`, `You can safely update it to \`${identifier}-${modifier.replace(coercedType + ':', '')}\`.`]);
352
+ } else {
353
+ return [];
354
+ }
355
+ }
356
+
347
357
  if (!isValidArbitraryValue(value)) {
348
358
  return [];
349
359
  }
@@ -11,7 +11,7 @@ var _pluginUtils = require("../util/pluginUtils");
11
11
 
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
 
14
- let asMap = new Map([[_pluginUtils.asValue, 'any'], [_pluginUtils.asColor, 'color'], [_pluginUtils.asAngle, 'angle'], [_pluginUtils.asLength, 'length'], [_pluginUtils.asLookupValue, 'lookup']]);
14
+ let asMap = new Map([[_pluginUtils.asValue, 'any'], [_pluginUtils.asColor, 'color'], [_pluginUtils.asAngle, 'angle'], [_pluginUtils.asLength, 'length'], [_pluginUtils.asURL, 'url'], [_pluginUtils.asLookupValue, 'lookup']]);
15
15
 
16
16
  function createUtilityPlugin(themeKey, utilityVariations = [[themeKey, [themeKey]]], {
17
17
  filterDefault = false,
@@ -23,7 +23,7 @@ function createUtilityPlugin(themeKey, utilityVariations = [[themeKey, [themeKey
23
23
  theme
24
24
  }) {
25
25
  for (let utilityVariation of utilityVariations) {
26
- var _theme, _asMap$get;
26
+ var _theme, _asMap$get2;
27
27
 
28
28
  let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [utilityVariation];
29
29
  matchUtilities(group.reduce((obj, [classPrefix, properties]) => {
@@ -44,7 +44,11 @@ function createUtilityPlugin(themeKey, utilityVariations = [[themeKey, [themeKey
44
44
  });
45
45
  }, {}), {
46
46
  values: filterDefault ? Object.fromEntries(Object.entries((_theme = theme(themeKey)) !== null && _theme !== void 0 ? _theme : {}).filter(([modifier]) => modifier !== 'DEFAULT')) : theme(themeKey),
47
- type: (_asMap$get = asMap.get(resolveArbitraryValue)) !== null && _asMap$get !== void 0 ? _asMap$get : 'any'
47
+ type: Array.isArray(resolveArbitraryValue) ? resolveArbitraryValue.map(typeResolver => {
48
+ var _asMap$get;
49
+
50
+ return (_asMap$get = asMap.get(typeResolver)) !== null && _asMap$get !== void 0 ? _asMap$get : 'any';
51
+ }) : (_asMap$get2 = asMap.get(resolveArbitraryValue)) !== null && _asMap$get2 !== void 0 ? _asMap$get2 : 'any'
48
52
  });
49
53
  }
50
54
  };
@@ -13,6 +13,7 @@ exports.asValue = asValue;
13
13
  exports.asUnit = asUnit;
14
14
  exports.asColor = asColor;
15
15
  exports.asAngle = asAngle;
16
+ exports.asURL = asURL;
16
17
  exports.asLength = asLength;
17
18
  exports.asLookupValue = asLookupValue;
18
19
  exports.coerceValue = coerceValue;
@@ -223,7 +224,9 @@ function asValue(modifier, lookup = {}, {
223
224
  } // convert `_` to ` `, escept for escaped underscores `\_`
224
225
 
225
226
 
226
- value = value.replace(/([^\\])_/g, '$1 ').replace(/^_/g, ' ').replace(/\\_/g, '_'); // add spaces around operators inside calc() that do not follow an operator or (
227
+ value = value.replace(/([^\\])_/g, '$1 ').replace(/^_/g, ' ').replace(/\\_/g, '_'); // Keep raw strings if it starts with `url(`
228
+
229
+ if (value.startsWith('url(')) return value; // add spaces around operators inside calc() that do not follow an operator or (
227
230
 
228
231
  return value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ');
229
232
  }
@@ -281,6 +284,12 @@ function asAngle(modifier, lookup = {}) {
281
284
  return asUnit(modifier, ['deg', 'grad', 'rad', 'turn'], lookup);
282
285
  }
283
286
 
287
+ function asURL(modifier, lookup = {}) {
288
+ return asValue(modifier, lookup, {
289
+ validate: value => value.startsWith('url(')
290
+ });
291
+ }
292
+
284
293
  function asLength(modifier, lookup = {}) {
285
294
  return asUnit(modifier, ['cm', 'mm', 'Q', 'in', 'pc', 'pt', 'px', 'em', 'ex', 'ch', 'rem', 'lh', 'vw', 'vh', 'vmin', 'vmax', '%'], lookup);
286
295
  }
@@ -294,11 +303,15 @@ let typeMap = {
294
303
  color: asColor,
295
304
  angle: asAngle,
296
305
  length: asLength,
306
+ url: asURL,
297
307
  lookup: asLookupValue
298
308
  };
309
+ let supportedTypes = Object.keys(typeMap);
299
310
 
300
311
  function splitAtFirst(input, delim) {
301
- return (([first, ...rest]) => [first, rest.join(delim)])(input.split(delim));
312
+ let idx = input.indexOf(delim);
313
+ if (idx === -1) return [undefined, input];
314
+ return [input.slice(0, idx), input.slice(idx + 1)];
302
315
  }
303
316
 
304
317
  function coerceValue(type, modifier, values, tailwindConfig) {
@@ -307,7 +320,11 @@ function coerceValue(type, modifier, values, tailwindConfig) {
307
320
  if (isArbitraryValue(modifier)) {
308
321
  let [explicitType, value] = splitAtFirst(modifier.slice(1, -1), ':');
309
322
 
310
- if (value.length > 0 && Object.keys(typeMap).includes(explicitType)) {
323
+ if (explicitType !== undefined && !supportedTypes.includes(explicitType)) {
324
+ return [];
325
+ }
326
+
327
+ if (value.length > 0 && supportedTypes.includes(explicitType)) {
311
328
  return [asValue(`[${value}]`, values, tailwindConfig), explicitType];
312
329
  }
313
330
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss",
3
- "version": "0.0.0-insiders.a8836eb",
3
+ "version": "0.0.0-insiders.ab17c6c",
4
4
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",
@@ -56,7 +56,7 @@
56
56
  "eslint-config-prettier": "^8.3.0",
57
57
  "eslint-plugin-prettier": "^4.0.0",
58
58
  "jest": "^27.1.0",
59
- "jest-diff": "^27.1.0",
59
+ "jest-diff": "^27.2.0",
60
60
  "postcss": "^8.3.6",
61
61
  "postcss-cli": "^8.3.1",
62
62
  "prettier": "^2.4.1",
@@ -17,6 +17,7 @@ import {
17
17
  transformAllClasses,
18
18
  transformLastClasses,
19
19
  asLength,
20
+ asURL,
20
21
  asLookupValue,
21
22
  } from './util/pluginUtils'
22
23
  import packageJson from '../package.json'
@@ -72,6 +73,15 @@ export let pseudoElementVariants = ({ config, addVariant }) => {
72
73
  }),
73
74
  ])
74
75
 
76
+ addVariant(
77
+ 'file',
78
+ transformAllSelectors((selector) => {
79
+ return updateAllClasses(selector, (className, { withPseudo }) => {
80
+ return withPseudo(`file${config('separator')}${className}`, '::file-selector-button')
81
+ })
82
+ })
83
+ )
84
+
75
85
  addVariant(
76
86
  'before',
77
87
  transformAllSelectors(
@@ -1352,7 +1362,7 @@ export let backgroundOpacity = createUtilityPlugin('backgroundOpacity', [
1352
1362
  export let backgroundImage = createUtilityPlugin(
1353
1363
  'backgroundImage',
1354
1364
  [['bg', ['background-image']]],
1355
- { resolveArbitraryValue: asLookupValue }
1365
+ { resolveArbitraryValue: [asLookupValue, asURL] }
1356
1366
  )
1357
1367
  export let gradientColorStops = (() => {
1358
1368
  function transparentTo(value) {
@@ -1473,7 +1483,7 @@ export let stroke = ({ matchUtilities, theme }) => {
1473
1483
  }
1474
1484
 
1475
1485
  export let strokeWidth = createUtilityPlugin('strokeWidth', [['stroke', ['stroke-width']]], {
1476
- resolveArbitraryValue: asLength,
1486
+ resolveArbitraryValue: [asLength, asURL],
1477
1487
  })
1478
1488
 
1479
1489
  export let objectFit = ({ addUtilities }) => {
@@ -7,10 +7,12 @@ let env = sharedState.env
7
7
  let contentMatchCache = sharedState.contentMatchCache
8
8
 
9
9
  const PATTERNS = [
10
- "([^<>\"'`\\s]*\\['[^<>\"'`\\s]*'\\])", // `content-['hello']` but not `content-['hello']']`
11
- '([^<>"\'`\\s]*\\["[^<>"\'`\\s]*"\\])', // `content-["hello"]` but not `content-["hello"]"]`
12
- '([^<>"\'`\\s]*\\[[^<>"\'`\\s]+\\])', // `fill-[#bada55]`
13
- '([^<>"\'`\\s]*[^<>"\'`\\s:])', // `px-1.5`, `uppercase` but not `uppercase:`
10
+ /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source, // bg-[url('...')]
11
+ /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source, // bg-[url("...")]
12
+ /([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
13
+ /([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
14
+ /([^<>"'`\s]*\[[^"'`\s]+\])/.source, // `fill-[#bada55]`
15
+ /([^<>"'`\s]*[^"'`\s:])/.source, // `px-1.5`, `uppercase` but not `uppercase:`].join('|')
14
16
  ].join('|')
15
17
  const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g')
16
18
  const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g
@@ -226,10 +226,11 @@ function* resolveMatches(candidate, context) {
226
226
  for (let matchedPlugins of resolveMatchedPlugins(classCandidate, context)) {
227
227
  let matches = []
228
228
  let [plugins, modifier] = matchedPlugins
229
+ let isOnlyPlugin = plugins.length === 1
229
230
 
230
231
  for (let [sort, plugin] of plugins) {
231
232
  if (typeof plugin === 'function') {
232
- for (let ruleSet of [].concat(plugin(modifier))) {
233
+ for (let ruleSet of [].concat(plugin(modifier, { isOnlyPlugin }))) {
233
234
  let [rules, options] = parseRules(ruleSet, context.postCssNodeCache)
234
235
  for (let rule of rules) {
235
236
  matches.push([{ ...sort, options: { ...sort.options, ...options } }, rule])
@@ -300,15 +300,29 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
300
300
 
301
301
  classList.add([prefixedIdentifier, options])
302
302
 
303
- function wrapped(modifier) {
303
+ function wrapped(modifier, { isOnlyPlugin }) {
304
304
  let { type = 'any' } = options
305
305
  type = [].concat(type)
306
306
  let [value, coercedType] = coerceValue(type, modifier, options.values, tailwindConfig)
307
307
 
308
- if (!type.includes(coercedType) || value === undefined) {
308
+ if (value === undefined) {
309
309
  return []
310
310
  }
311
311
 
312
+ if (!type.includes(coercedType)) {
313
+ if (isOnlyPlugin) {
314
+ log.warn([
315
+ `Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
316
+ `You can safely update it to \`${identifier}-${modifier.replace(
317
+ coercedType + ':',
318
+ ''
319
+ )}\`.`,
320
+ ])
321
+ } else {
322
+ return []
323
+ }
324
+ }
325
+
312
326
  if (!isValidArbitraryValue(value)) {
313
327
  return []
314
328
  }
@@ -1,11 +1,12 @@
1
1
  import transformThemeValue from './transformThemeValue'
2
- import { asValue, asColor, asAngle, asLength, asLookupValue } from '../util/pluginUtils'
2
+ import { asValue, asColor, asAngle, asLength, asURL, asLookupValue } from '../util/pluginUtils'
3
3
 
4
4
  let asMap = new Map([
5
5
  [asValue, 'any'],
6
6
  [asColor, 'color'],
7
7
  [asAngle, 'angle'],
8
8
  [asLength, 'length'],
9
+ [asURL, 'url'],
9
10
  [asLookupValue, 'lookup'],
10
11
  ])
11
12
 
@@ -38,7 +39,9 @@ export default function createUtilityPlugin(
38
39
  Object.entries(theme(themeKey) ?? {}).filter(([modifier]) => modifier !== 'DEFAULT')
39
40
  )
40
41
  : theme(themeKey),
41
- type: asMap.get(resolveArbitraryValue) ?? 'any',
42
+ type: Array.isArray(resolveArbitraryValue)
43
+ ? resolveArbitraryValue.map((typeResolver) => asMap.get(typeResolver) ?? 'any')
44
+ : asMap.get(resolveArbitraryValue) ?? 'any',
42
45
  }
43
46
  )
44
47
  }
@@ -175,6 +175,9 @@ export function asValue(modifier, lookup = {}, { validate = () => true } = {}) {
175
175
  .replace(/^_/g, ' ')
176
176
  .replace(/\\_/g, '_')
177
177
 
178
+ // Keep raw strings if it starts with `url(`
179
+ if (value.startsWith('url(')) return value
180
+
178
181
  // add spaces around operators inside calc() that do not follow an operator or (
179
182
  return value.replace(
180
183
  /(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
@@ -236,6 +239,12 @@ export function asAngle(modifier, lookup = {}) {
236
239
  return asUnit(modifier, ['deg', 'grad', 'rad', 'turn'], lookup)
237
240
  }
238
241
 
242
+ export function asURL(modifier, lookup = {}) {
243
+ return asValue(modifier, lookup, {
244
+ validate: (value) => value.startsWith('url('),
245
+ })
246
+ }
247
+
239
248
  export function asLength(modifier, lookup = {}) {
240
249
  return asUnit(
241
250
  modifier,
@@ -271,11 +280,16 @@ let typeMap = {
271
280
  color: asColor,
272
281
  angle: asAngle,
273
282
  length: asLength,
283
+ url: asURL,
274
284
  lookup: asLookupValue,
275
285
  }
276
286
 
287
+ let supportedTypes = Object.keys(typeMap)
288
+
277
289
  function splitAtFirst(input, delim) {
278
- return (([first, ...rest]) => [first, rest.join(delim)])(input.split(delim))
290
+ let idx = input.indexOf(delim)
291
+ if (idx === -1) return [undefined, input]
292
+ return [input.slice(0, idx), input.slice(idx + 1)]
279
293
  }
280
294
 
281
295
  export function coerceValue(type, modifier, values, tailwindConfig) {
@@ -284,7 +298,11 @@ export function coerceValue(type, modifier, values, tailwindConfig) {
284
298
  if (isArbitraryValue(modifier)) {
285
299
  let [explicitType, value] = splitAtFirst(modifier.slice(1, -1), ':')
286
300
 
287
- if (value.length > 0 && Object.keys(typeMap).includes(explicitType)) {
301
+ if (explicitType !== undefined && !supportedTypes.includes(explicitType)) {
302
+ return []
303
+ }
304
+
305
+ if (value.length > 0 && supportedTypes.includes(explicitType)) {
288
306
  return [asValue(`[${value}]`, values, tailwindConfig), explicitType]
289
307
  }
290
308