tailwindcss 0.0.0-insiders.ca1dfd6 → 0.0.0-insiders.cb6e45a

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.
Files changed (190) hide show
  1. package/CHANGELOG.md +526 -2
  2. package/LICENSE +1 -2
  3. package/README.md +13 -6
  4. package/colors.d.ts +3 -0
  5. package/colors.js +2 -1
  6. package/defaultConfig.d.ts +3 -0
  7. package/defaultConfig.js +2 -1
  8. package/defaultTheme.d.ts +4 -0
  9. package/defaultTheme.js +2 -1
  10. package/lib/cli/build/deps.js +54 -0
  11. package/lib/cli/build/index.js +44 -0
  12. package/lib/cli/build/plugin.js +335 -0
  13. package/lib/cli/build/utils.js +78 -0
  14. package/lib/cli/build/watching.js +113 -0
  15. package/lib/cli/help/index.js +71 -0
  16. package/lib/cli/index.js +18 -0
  17. package/lib/cli/init/index.js +46 -0
  18. package/lib/cli/shared.js +12 -0
  19. package/lib/cli-peer-dependencies.js +20 -7
  20. package/lib/cli.js +91 -569
  21. package/lib/constants.js +27 -20
  22. package/lib/corePluginList.js +16 -4
  23. package/lib/corePlugins.js +2247 -1873
  24. package/lib/css/preflight.css +20 -9
  25. package/lib/featureFlags.js +37 -23
  26. package/lib/index.js +28 -12
  27. package/lib/lib/cacheInvalidation.js +90 -0
  28. package/lib/lib/collapseAdjacentRules.js +27 -9
  29. package/lib/lib/collapseDuplicateDeclarations.js +83 -0
  30. package/lib/lib/content.js +167 -0
  31. package/lib/lib/defaultExtractor.js +236 -0
  32. package/lib/lib/detectNesting.js +21 -3
  33. package/lib/lib/evaluateTailwindFunctions.js +117 -50
  34. package/lib/lib/expandApplyAtRules.js +439 -160
  35. package/lib/lib/expandTailwindAtRules.js +141 -151
  36. package/lib/lib/findAtConfigPath.js +44 -0
  37. package/lib/lib/generateRules.js +572 -105
  38. package/lib/lib/getModuleDependencies.js +11 -8
  39. package/lib/lib/normalizeTailwindDirectives.js +45 -33
  40. package/lib/lib/offsets.js +217 -0
  41. package/lib/lib/partitionApplyAtRules.js +56 -0
  42. package/lib/lib/regex.js +60 -0
  43. package/lib/lib/resolveDefaultsAtRules.js +114 -81
  44. package/lib/lib/setupContextUtils.js +777 -385
  45. package/lib/lib/setupTrackingContext.js +43 -71
  46. package/lib/lib/sharedState.js +49 -18
  47. package/lib/lib/substituteScreenAtRules.js +13 -8
  48. package/{nesting → lib/postcss-plugins/nesting}/README.md +2 -2
  49. package/lib/postcss-plugins/nesting/index.js +19 -0
  50. package/lib/postcss-plugins/nesting/plugin.js +87 -0
  51. package/lib/processTailwindFeatures.js +36 -21
  52. package/lib/public/colors.js +250 -252
  53. package/lib/public/create-plugin.js +6 -4
  54. package/lib/public/default-config.js +7 -5
  55. package/lib/public/default-theme.js +7 -5
  56. package/lib/public/resolve-config.js +8 -5
  57. package/lib/util/bigSign.js +4 -1
  58. package/lib/util/buildMediaQuery.js +18 -24
  59. package/lib/util/cloneDeep.js +7 -6
  60. package/lib/util/cloneNodes.js +21 -3
  61. package/lib/util/color.js +54 -40
  62. package/lib/util/configurePlugins.js +5 -2
  63. package/lib/util/createPlugin.js +6 -6
  64. package/lib/util/createUtilityPlugin.js +11 -13
  65. package/lib/util/dataTypes.js +137 -100
  66. package/lib/util/defaults.js +10 -1
  67. package/lib/util/escapeClassName.js +7 -4
  68. package/lib/util/escapeCommas.js +5 -2
  69. package/lib/util/flattenColorPalette.js +9 -12
  70. package/lib/util/formatVariantSelector.js +285 -0
  71. package/lib/util/getAllConfigs.js +27 -8
  72. package/lib/util/hashConfig.js +6 -3
  73. package/lib/util/isKeyframeRule.js +5 -2
  74. package/lib/util/isPlainObject.js +5 -2
  75. package/lib/util/isValidArbitraryValue.js +72 -0
  76. package/lib/util/log.js +44 -22
  77. package/lib/util/nameClass.js +20 -8
  78. package/lib/util/negateValue.js +23 -6
  79. package/lib/util/normalizeConfig.js +267 -0
  80. package/lib/util/normalizeScreens.js +170 -0
  81. package/lib/util/parseAnimationValue.js +42 -40
  82. package/lib/util/parseBoxShadowValue.js +84 -0
  83. package/lib/util/parseDependency.js +38 -56
  84. package/lib/util/parseGlob.js +34 -0
  85. package/lib/util/parseObjectStyles.js +11 -8
  86. package/lib/util/pluginUtils.js +171 -189
  87. package/lib/util/prefixSelector.js +10 -10
  88. package/lib/util/removeAlphaVariables.js +29 -0
  89. package/lib/util/resolveConfig.js +92 -126
  90. package/lib/util/resolveConfigPath.js +11 -9
  91. package/lib/util/responsive.js +8 -5
  92. package/lib/util/splitAtTopLevelOnly.js +43 -0
  93. package/lib/util/tap.js +4 -1
  94. package/lib/util/toColorValue.js +5 -3
  95. package/lib/util/toPath.js +24 -3
  96. package/lib/util/transformThemeValue.js +49 -31
  97. package/lib/util/validateConfig.js +24 -0
  98. package/lib/util/validateFormalSyntax.js +24 -0
  99. package/lib/util/withAlphaVariable.js +23 -15
  100. package/nesting/index.js +2 -12
  101. package/package.json +48 -46
  102. package/peers/index.js +14817 -12471
  103. package/plugin.d.ts +11 -0
  104. package/plugin.js +2 -1
  105. package/resolveConfig.d.ts +3 -0
  106. package/resolveConfig.js +2 -1
  107. package/scripts/create-plugin-list.js +2 -2
  108. package/scripts/generate-types.js +105 -0
  109. package/scripts/release-channel.js +18 -0
  110. package/scripts/release-notes.js +21 -0
  111. package/scripts/type-utils.js +27 -0
  112. package/src/cli/build/deps.js +56 -0
  113. package/src/cli/build/index.js +45 -0
  114. package/src/cli/build/plugin.js +397 -0
  115. package/src/cli/build/utils.js +76 -0
  116. package/src/cli/build/watching.js +134 -0
  117. package/src/cli/help/index.js +70 -0
  118. package/src/cli/index.js +3 -0
  119. package/src/cli/init/index.js +50 -0
  120. package/src/cli/shared.js +5 -0
  121. package/src/cli-peer-dependencies.js +7 -1
  122. package/src/cli.js +26 -565
  123. package/src/corePluginList.js +1 -1
  124. package/src/corePlugins.js +905 -615
  125. package/src/css/preflight.css +20 -9
  126. package/src/featureFlags.js +26 -10
  127. package/src/index.js +19 -6
  128. package/src/lib/cacheInvalidation.js +52 -0
  129. package/src/lib/collapseAdjacentRules.js +21 -2
  130. package/src/lib/collapseDuplicateDeclarations.js +93 -0
  131. package/src/lib/content.js +205 -0
  132. package/src/lib/defaultExtractor.js +211 -0
  133. package/src/lib/detectNesting.js +22 -3
  134. package/src/lib/evaluateTailwindFunctions.js +84 -10
  135. package/src/lib/expandApplyAtRules.js +488 -153
  136. package/src/lib/expandTailwindAtRules.js +94 -106
  137. package/src/lib/findAtConfigPath.js +50 -0
  138. package/src/lib/generateRules.js +589 -67
  139. package/src/lib/normalizeTailwindDirectives.js +10 -3
  140. package/src/lib/offsets.js +270 -0
  141. package/src/lib/partitionApplyAtRules.js +52 -0
  142. package/src/lib/regex.js +74 -0
  143. package/src/lib/resolveDefaultsAtRules.js +98 -60
  144. package/src/lib/setupContextUtils.js +737 -246
  145. package/src/lib/setupTrackingContext.js +16 -54
  146. package/src/lib/sharedState.js +44 -7
  147. package/src/lib/substituteScreenAtRules.js +6 -3
  148. package/src/postcss-plugins/nesting/README.md +42 -0
  149. package/src/postcss-plugins/nesting/index.js +13 -0
  150. package/src/postcss-plugins/nesting/plugin.js +80 -0
  151. package/src/processTailwindFeatures.js +17 -2
  152. package/src/public/colors.js +4 -9
  153. package/src/util/buildMediaQuery.js +14 -16
  154. package/src/util/cloneNodes.js +19 -2
  155. package/src/util/color.js +31 -14
  156. package/src/util/createUtilityPlugin.js +2 -2
  157. package/src/util/dataTypes.js +57 -21
  158. package/src/util/defaults.js +6 -0
  159. package/src/util/formatVariantSelector.js +319 -0
  160. package/src/util/getAllConfigs.js +19 -0
  161. package/src/util/isValidArbitraryValue.js +61 -0
  162. package/src/util/log.js +23 -22
  163. package/src/util/nameClass.js +6 -2
  164. package/src/util/negateValue.js +14 -4
  165. package/src/util/normalizeConfig.js +282 -0
  166. package/src/util/normalizeScreens.js +140 -0
  167. package/src/util/parseBoxShadowValue.js +72 -0
  168. package/src/util/parseDependency.js +37 -42
  169. package/src/util/parseGlob.js +24 -0
  170. package/src/util/pluginUtils.js +144 -152
  171. package/src/util/prefixSelector.js +7 -8
  172. package/src/util/removeAlphaVariables.js +24 -0
  173. package/src/util/resolveConfig.js +82 -81
  174. package/src/util/splitAtTopLevelOnly.js +45 -0
  175. package/src/util/toPath.js +23 -1
  176. package/src/util/transformThemeValue.js +33 -8
  177. package/src/util/validateConfig.js +13 -0
  178. package/src/util/validateFormalSyntax.js +34 -0
  179. package/src/util/withAlphaVariable.js +1 -1
  180. package/stubs/defaultConfig.stub.js +173 -93
  181. package/stubs/simpleConfig.stub.js +1 -1
  182. package/types/config.d.ts +361 -0
  183. package/types/generated/.gitkeep +0 -0
  184. package/types/generated/colors.d.ts +276 -0
  185. package/types/generated/corePluginList.d.ts +1 -0
  186. package/types/generated/default-theme.d.ts +342 -0
  187. package/types/index.d.ts +7 -0
  188. package/lib/lib/setupWatchingContext.js +0 -284
  189. package/nesting/plugin.js +0 -41
  190. package/src/lib/setupWatchingContext.js +0 -306
@@ -0,0 +1,282 @@
1
+ import log, { dim } from './log'
2
+
3
+ export function normalizeConfig(config) {
4
+ // Quick structure validation
5
+ /**
6
+ * type FilePath = string
7
+ * type RawFile = { raw: string, extension?: string }
8
+ * type ExtractorFn = (content: string) => Array<string>
9
+ * type TransformerFn = (content: string) => string
10
+ *
11
+ * type Content =
12
+ * | Array<FilePath | RawFile>
13
+ * | {
14
+ * files: Array<FilePath | RawFile>,
15
+ * extract?: ExtractorFn | { [extension: string]: ExtractorFn }
16
+ * transform?: TransformerFn | { [extension: string]: TransformerFn }
17
+ * }
18
+ */
19
+ let valid = (() => {
20
+ // `config.purge` should not exist anymore
21
+ if (config.purge) {
22
+ return false
23
+ }
24
+
25
+ // `config.content` should exist
26
+ if (!config.content) {
27
+ return false
28
+ }
29
+
30
+ // `config.content` should be an object or an array
31
+ if (
32
+ !Array.isArray(config.content) &&
33
+ !(typeof config.content === 'object' && config.content !== null)
34
+ ) {
35
+ return false
36
+ }
37
+
38
+ // When `config.content` is an array, it should consist of FilePaths or RawFiles
39
+ if (Array.isArray(config.content)) {
40
+ return config.content.every((path) => {
41
+ // `path` can be a string
42
+ if (typeof path === 'string') return true
43
+
44
+ // `path` can be an object { raw: string, extension?: string }
45
+ // `raw` must be a string
46
+ if (typeof path?.raw !== 'string') return false
47
+
48
+ // `extension` (if provided) should also be a string
49
+ if (path?.extension && typeof path?.extension !== 'string') {
50
+ return false
51
+ }
52
+
53
+ return true
54
+ })
55
+ }
56
+
57
+ // When `config.content` is an object
58
+ if (typeof config.content === 'object' && config.content !== null) {
59
+ // Only `files`, `relative`, `extract`, and `transform` can exist in `config.content`
60
+ if (
61
+ Object.keys(config.content).some(
62
+ (key) => !['files', 'relative', 'extract', 'transform'].includes(key)
63
+ )
64
+ ) {
65
+ return false
66
+ }
67
+
68
+ // `config.content.files` should exist of FilePaths or RawFiles
69
+ if (Array.isArray(config.content.files)) {
70
+ if (
71
+ !config.content.files.every((path) => {
72
+ // `path` can be a string
73
+ if (typeof path === 'string') return true
74
+
75
+ // `path` can be an object { raw: string, extension?: string }
76
+ // `raw` must be a string
77
+ if (typeof path?.raw !== 'string') return false
78
+
79
+ // `extension` (if provided) should also be a string
80
+ if (path?.extension && typeof path?.extension !== 'string') {
81
+ return false
82
+ }
83
+
84
+ return true
85
+ })
86
+ ) {
87
+ return false
88
+ }
89
+
90
+ // `config.content.extract` is optional, and can be a Function or a Record<String, Function>
91
+ if (typeof config.content.extract === 'object') {
92
+ for (let value of Object.values(config.content.extract)) {
93
+ if (typeof value !== 'function') {
94
+ return false
95
+ }
96
+ }
97
+ } else if (
98
+ !(config.content.extract === undefined || typeof config.content.extract === 'function')
99
+ ) {
100
+ return false
101
+ }
102
+
103
+ // `config.content.transform` is optional, and can be a Function or a Record<String, Function>
104
+ if (typeof config.content.transform === 'object') {
105
+ for (let value of Object.values(config.content.transform)) {
106
+ if (typeof value !== 'function') {
107
+ return false
108
+ }
109
+ }
110
+ } else if (
111
+ !(
112
+ config.content.transform === undefined || typeof config.content.transform === 'function'
113
+ )
114
+ ) {
115
+ return false
116
+ }
117
+
118
+ // `config.content.relative` is optional and can be a boolean
119
+ if (
120
+ typeof config.content.relative !== 'boolean' &&
121
+ typeof config.content.relative !== 'undefined'
122
+ ) {
123
+ return false
124
+ }
125
+ }
126
+
127
+ return true
128
+ }
129
+
130
+ return false
131
+ })()
132
+
133
+ if (!valid) {
134
+ log.warn('purge-deprecation', [
135
+ 'The `purge`/`content` options have changed in Tailwind CSS v3.0.',
136
+ 'Update your configuration file to eliminate this warning.',
137
+ 'https://tailwindcss.com/docs/upgrade-guide#configure-content-sources',
138
+ ])
139
+ }
140
+
141
+ // Normalize the `safelist`
142
+ config.safelist = (() => {
143
+ let { content, purge, safelist } = config
144
+
145
+ if (Array.isArray(safelist)) return safelist
146
+ if (Array.isArray(content?.safelist)) return content.safelist
147
+ if (Array.isArray(purge?.safelist)) return purge.safelist
148
+ if (Array.isArray(purge?.options?.safelist)) return purge.options.safelist
149
+
150
+ return []
151
+ })()
152
+
153
+ // Normalize prefix option
154
+ if (typeof config.prefix === 'function') {
155
+ log.warn('prefix-function', [
156
+ 'As of Tailwind CSS v3.0, `prefix` cannot be a function.',
157
+ 'Update `prefix` in your configuration to be a string to eliminate this warning.',
158
+ 'https://tailwindcss.com/docs/upgrade-guide#prefix-cannot-be-a-function',
159
+ ])
160
+ config.prefix = ''
161
+ } else {
162
+ config.prefix = config.prefix ?? ''
163
+ }
164
+
165
+ // Normalize the `content`
166
+ config.content = {
167
+ relative: (() => {
168
+ let { content } = config
169
+
170
+ if (content?.relative) {
171
+ return content.relative
172
+ }
173
+
174
+ return config.future?.relativeContentPathsByDefault ?? false
175
+ })(),
176
+
177
+ files: (() => {
178
+ let { content, purge } = config
179
+
180
+ if (Array.isArray(purge)) return purge
181
+ if (Array.isArray(purge?.content)) return purge.content
182
+ if (Array.isArray(content)) return content
183
+ if (Array.isArray(content?.content)) return content.content
184
+ if (Array.isArray(content?.files)) return content.files
185
+
186
+ return []
187
+ })(),
188
+
189
+ extract: (() => {
190
+ let extract = (() => {
191
+ if (config.purge?.extract) return config.purge.extract
192
+ if (config.content?.extract) return config.content.extract
193
+
194
+ if (config.purge?.extract?.DEFAULT) return config.purge.extract.DEFAULT
195
+ if (config.content?.extract?.DEFAULT) return config.content.extract.DEFAULT
196
+
197
+ if (config.purge?.options?.extractors) return config.purge.options.extractors
198
+ if (config.content?.options?.extractors) return config.content.options.extractors
199
+
200
+ return {}
201
+ })()
202
+
203
+ let extractors = {}
204
+
205
+ let defaultExtractor = (() => {
206
+ if (config.purge?.options?.defaultExtractor) {
207
+ return config.purge.options.defaultExtractor
208
+ }
209
+
210
+ if (config.content?.options?.defaultExtractor) {
211
+ return config.content.options.defaultExtractor
212
+ }
213
+
214
+ return undefined
215
+ })()
216
+
217
+ if (defaultExtractor !== undefined) {
218
+ extractors.DEFAULT = defaultExtractor
219
+ }
220
+
221
+ // Functions
222
+ if (typeof extract === 'function') {
223
+ extractors.DEFAULT = extract
224
+ }
225
+
226
+ // Arrays
227
+ else if (Array.isArray(extract)) {
228
+ for (let { extensions, extractor } of extract ?? []) {
229
+ for (let extension of extensions) {
230
+ extractors[extension] = extractor
231
+ }
232
+ }
233
+ }
234
+
235
+ // Objects
236
+ else if (typeof extract === 'object' && extract !== null) {
237
+ Object.assign(extractors, extract)
238
+ }
239
+
240
+ return extractors
241
+ })(),
242
+
243
+ transform: (() => {
244
+ let transform = (() => {
245
+ if (config.purge?.transform) return config.purge.transform
246
+ if (config.content?.transform) return config.content.transform
247
+
248
+ if (config.purge?.transform?.DEFAULT) return config.purge.transform.DEFAULT
249
+ if (config.content?.transform?.DEFAULT) return config.content.transform.DEFAULT
250
+
251
+ return {}
252
+ })()
253
+
254
+ let transformers = {}
255
+
256
+ if (typeof transform === 'function') {
257
+ transformers.DEFAULT = transform
258
+ }
259
+
260
+ if (typeof transform === 'object' && transform !== null) {
261
+ Object.assign(transformers, transform)
262
+ }
263
+
264
+ return transformers
265
+ })(),
266
+ }
267
+
268
+ // Validate globs to prevent bogus globs.
269
+ // E.g.: `./src/*.{html}` is invalid, the `{html}` should just be `html`
270
+ for (let file of config.content.files) {
271
+ if (typeof file === 'string' && /{([^,]*?)}/g.test(file)) {
272
+ log.warn('invalid-glob-braces', [
273
+ `The glob pattern ${dim(file)} in your Tailwind CSS configuration is invalid.`,
274
+ `Update it to ${dim(file.replace(/{([^,]*?)}/g, '$1'))} to silence this warning.`,
275
+ // TODO: Add https://tw.wtf/invalid-glob-braces
276
+ ])
277
+ break
278
+ }
279
+ }
280
+
281
+ return config
282
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @typedef {object} ScreenValue
3
+ * @property {number|undefined} min
4
+ * @property {number|undefined} max
5
+ * @property {string|undefined} raw
6
+ */
7
+
8
+ /**
9
+ * @typedef {object} Screen
10
+ * @property {string} name
11
+ * @property {boolean} not
12
+ * @property {ScreenValue[]} values
13
+ */
14
+
15
+ /**
16
+ * A function that normalizes the various forms that the screens object can be
17
+ * provided in.
18
+ *
19
+ * Input(s):
20
+ * - ['100px', '200px'] // Raw strings
21
+ * - { sm: '100px', md: '200px' } // Object with string values
22
+ * - { sm: { min: '100px' }, md: { max: '100px' } } // Object with object values
23
+ * - { sm: [{ min: '100px' }, { max: '200px' }] } // Object with object array (multiple values)
24
+ *
25
+ * Output(s):
26
+ * - [{ name: 'sm', values: [{ min: '100px', max: '200px' }] }] // List of objects, that contains multiple values
27
+ *
28
+ * @returns {Screen[]}
29
+ */
30
+ export function normalizeScreens(screens, root = true) {
31
+ if (Array.isArray(screens)) {
32
+ return screens.map((screen) => {
33
+ if (root && Array.isArray(screen)) {
34
+ throw new Error('The tuple syntax is not supported for `screens`.')
35
+ }
36
+
37
+ if (typeof screen === 'string') {
38
+ return { name: screen.toString(), not: false, values: [{ min: screen, max: undefined }] }
39
+ }
40
+
41
+ let [name, options] = screen
42
+ name = name.toString()
43
+
44
+ if (typeof options === 'string') {
45
+ return { name, not: false, values: [{ min: options, max: undefined }] }
46
+ }
47
+
48
+ if (Array.isArray(options)) {
49
+ return { name, not: false, values: options.map((option) => resolveValue(option)) }
50
+ }
51
+
52
+ return { name, not: false, values: [resolveValue(options)] }
53
+ })
54
+ }
55
+
56
+ return normalizeScreens(Object.entries(screens ?? {}), false)
57
+ }
58
+
59
+ /**
60
+ * @param {Screen} screen
61
+ * @returns {{result: false, reason: string} | {result: true, reason: null}}
62
+ */
63
+ export function isScreenSortable(screen) {
64
+ if (screen.values.length !== 1) {
65
+ return { result: false, reason: 'multiple-values' }
66
+ } else if (screen.values[0].raw !== undefined) {
67
+ return { result: false, reason: 'raw-values' }
68
+ } else if (screen.values[0].min !== undefined && screen.values[0].max !== undefined) {
69
+ return { result: false, reason: 'min-and-max' }
70
+ }
71
+
72
+ return { result: true, reason: null }
73
+ }
74
+
75
+ /**
76
+ * @param {'min' | 'max'} type
77
+ * @param {Screen | 'string'} a
78
+ * @param {Screen | 'string'} z
79
+ * @returns {number}
80
+ */
81
+ export function compareScreens(type, a, z) {
82
+ let aScreen = toScreen(a, type)
83
+ let zScreen = toScreen(z, type)
84
+
85
+ let aSorting = isScreenSortable(aScreen)
86
+ let bSorting = isScreenSortable(zScreen)
87
+
88
+ // These cases should never happen and indicate a bug in Tailwind CSS itself
89
+ if (aSorting.reason === 'multiple-values' || bSorting.reason === 'multiple-values') {
90
+ throw new Error(
91
+ 'Attempted to sort a screen with multiple values. This should never happen. Please open a bug report.'
92
+ )
93
+ } else if (aSorting.reason === 'raw-values' || bSorting.reason === 'raw-values') {
94
+ throw new Error(
95
+ 'Attempted to sort a screen with raw values. This should never happen. Please open a bug report.'
96
+ )
97
+ } else if (aSorting.reason === 'min-and-max' || bSorting.reason === 'min-and-max') {
98
+ throw new Error(
99
+ 'Attempted to sort a screen with both min and max values. This should never happen. Please open a bug report.'
100
+ )
101
+ }
102
+
103
+ // Let the sorting begin
104
+ let { min: aMin, max: aMax } = aScreen.values[0]
105
+ let { min: zMin, max: zMax } = zScreen.values[0]
106
+
107
+ // Negating screens flip their behavior. Basically `not min-width` is `max-width`
108
+ if (a.not) [aMin, aMax] = [aMax, aMin]
109
+ if (z.not) [zMin, zMax] = [zMax, zMin]
110
+
111
+ aMin = aMin === undefined ? aMin : parseFloat(aMin)
112
+ aMax = aMax === undefined ? aMax : parseFloat(aMax)
113
+ zMin = zMin === undefined ? zMin : parseFloat(zMin)
114
+ zMax = zMax === undefined ? zMax : parseFloat(zMax)
115
+
116
+ let [aValue, zValue] = type === 'min' ? [aMin, zMin] : [zMax, aMax]
117
+
118
+ return aValue - zValue
119
+ }
120
+
121
+ /**
122
+ *
123
+ * @param {PartialScreen> | string} value
124
+ * @param {'min' | 'max'} type
125
+ * @returns {Screen}
126
+ */
127
+ export function toScreen(value, type) {
128
+ if (typeof value === 'object') {
129
+ return value
130
+ }
131
+
132
+ return {
133
+ name: 'arbitrary-screen',
134
+ values: [{ [type]: value }],
135
+ }
136
+ }
137
+
138
+ function resolveValue({ 'min-width': _minWidth, min = _minWidth, max, raw } = {}) {
139
+ return { min, max, raw }
140
+ }
@@ -0,0 +1,72 @@
1
+ import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
2
+
3
+ let KEYWORDS = new Set(['inset', 'inherit', 'initial', 'revert', 'unset'])
4
+ let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
5
+ let LENGTH = /^-?(\d+|\.\d+)(.*?)$/g
6
+
7
+ export function parseBoxShadowValue(input) {
8
+ let shadows = splitAtTopLevelOnly(input, ',')
9
+ return shadows.map((shadow) => {
10
+ let value = shadow.trim()
11
+ let result = { raw: value }
12
+ let parts = value.split(SPACE)
13
+ let seen = new Set()
14
+
15
+ for (let part of parts) {
16
+ // Reset index, since the regex is stateful.
17
+ LENGTH.lastIndex = 0
18
+
19
+ // Keyword
20
+ if (!seen.has('KEYWORD') && KEYWORDS.has(part)) {
21
+ result.keyword = part
22
+ seen.add('KEYWORD')
23
+ }
24
+
25
+ // Length value
26
+ else if (LENGTH.test(part)) {
27
+ if (!seen.has('X')) {
28
+ result.x = part
29
+ seen.add('X')
30
+ } else if (!seen.has('Y')) {
31
+ result.y = part
32
+ seen.add('Y')
33
+ } else if (!seen.has('BLUR')) {
34
+ result.blur = part
35
+ seen.add('BLUR')
36
+ } else if (!seen.has('SPREAD')) {
37
+ result.spread = part
38
+ seen.add('SPREAD')
39
+ }
40
+ }
41
+
42
+ // Color or unknown
43
+ else {
44
+ if (!result.color) {
45
+ result.color = part
46
+ } else {
47
+ if (!result.unknown) result.unknown = []
48
+ result.unknown.push(part)
49
+ }
50
+ }
51
+ }
52
+
53
+ // Check if valid
54
+ result.valid = result.x !== undefined && result.y !== undefined
55
+
56
+ return result
57
+ })
58
+ }
59
+
60
+ export function formatBoxShadowValue(shadows) {
61
+ return shadows
62
+ .map((shadow) => {
63
+ if (!shadow.valid) {
64
+ return shadow.raw
65
+ }
66
+
67
+ return [shadow.keyword, shadow.x, shadow.y, shadow.blur, shadow.spread, shadow.color]
68
+ .filter(Boolean)
69
+ .join(' ')
70
+ })
71
+ .join(', ')
72
+ }
@@ -1,49 +1,44 @@
1
- import isGlob from 'is-glob'
2
- import globParent from 'glob-parent'
3
- import path from 'path'
4
-
5
- // Based on `glob-base`
6
- // https://github.com/micromatch/glob-base/blob/master/index.js
7
- function parseGlob(pattern) {
8
- let glob = pattern
9
- let base = globParent(pattern)
10
-
11
- if (base !== '.') {
12
- glob = pattern.substr(base.length)
13
- if (glob.charAt(0) === '/') {
14
- glob = glob.substr(1)
15
- }
16
- }
17
-
18
- if (glob.substr(0, 2) === './') {
19
- glob = glob.substr(2)
20
- }
21
- if (glob.charAt(0) === '/') {
22
- glob = glob.substr(1)
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {{type: 'dependency', file: string} | {type: 'dir-dependency', dir: string, glob: string}} Dependency
5
+ */
6
+
7
+ /**
8
+ *
9
+ * @param {import('../lib/content.js').ContentPath} contentPath
10
+ * @returns {Dependency[]}
11
+ */
12
+ export default function parseDependency(contentPath) {
13
+ if (contentPath.ignore) {
14
+ return []
23
15
  }
24
16
 
25
- return { base, glob }
26
- }
27
-
28
- export default function parseDependency(normalizedFileOrGlob) {
29
- if (normalizedFileOrGlob.startsWith('!')) {
30
- return null
31
- }
32
-
33
- let message
34
-
35
- if (isGlob(normalizedFileOrGlob)) {
36
- let { base, glob } = parseGlob(normalizedFileOrGlob)
37
- message = { type: 'dir-dependency', dir: path.resolve(base), glob }
38
- } else {
39
- message = { type: 'dependency', file: path.resolve(normalizedFileOrGlob) }
17
+ if (!contentPath.glob) {
18
+ return [
19
+ {
20
+ type: 'dependency',
21
+ file: contentPath.base,
22
+ },
23
+ ]
40
24
  }
41
25
 
42
- // rollup-plugin-postcss does not support dir-dependency messages
43
- // but directories can be watched in the same way as files
44
- if (message.type === 'dir-dependency' && process.env.ROLLUP_WATCH === 'true') {
45
- message = { type: 'dependency', file: message.dir }
26
+ if (process.env.ROLLUP_WATCH === 'true') {
27
+ // rollup-plugin-postcss does not support dir-dependency messages
28
+ // but directories can be watched in the same way as files
29
+ return [
30
+ {
31
+ type: 'dependency',
32
+ file: contentPath.base,
33
+ },
34
+ ]
46
35
  }
47
36
 
48
- return message
37
+ return [
38
+ {
39
+ type: 'dir-dependency',
40
+ dir: contentPath.base,
41
+ glob: contentPath.glob,
42
+ },
43
+ ]
49
44
  }
@@ -0,0 +1,24 @@
1
+ import globParent from 'glob-parent'
2
+
3
+ // Based on `glob-base`
4
+ // https://github.com/micromatch/glob-base/blob/master/index.js
5
+ export function parseGlob(pattern) {
6
+ let glob = pattern
7
+ let base = globParent(pattern)
8
+
9
+ if (base !== '.') {
10
+ glob = pattern.substr(base.length)
11
+ if (glob.charAt(0) === '/') {
12
+ glob = glob.substr(1)
13
+ }
14
+ }
15
+
16
+ if (glob.substr(0, 2) === './') {
17
+ glob = glob.substr(2)
18
+ }
19
+ if (glob.charAt(0) === '/') {
20
+ glob = glob.substr(1)
21
+ }
22
+
23
+ return { base, glob }
24
+ }