| 264 | }, |
| 265 | |
| 266 | addUtilities(utilities) { |
| 267 | utilities = Array.isArray(utilities) ? utilities : [utilities] |
| 268 | |
| 269 | let entries = utilities.flatMap((u) => Object.entries(u)) |
| 270 | |
| 271 | class="cm">// Split multi-selector utilities into individual utilities |
| 272 | entries = entries.flatMap(([name, css]) => |
| 273 | segment(name, class="st">',').map((selector) => [selector.trim(), css] as [string, CssInJs]), |
| 274 | ) |
| 275 | |
| 276 | class="cm">// Merge entries for the same class |
| 277 | let utils = new DefaultMap<string, AstNode[]>(() => []) |
| 278 | |
| 279 | for (let [name, css] of entries) { |
| 280 | if (name.startsWith(class="st">'@keyframes ')) { |
| 281 | if (!referenceMode) { |
| 282 | let keyframes = rule(name, objectToAst(css)) |
| 283 | walk([keyframes], (node) => { |
| 284 | node.src = src |
| 285 | }) |
| 286 | ast.push(keyframes) |
| 287 | } |
| 288 | continue |
| 289 | } |
| 290 | |
| 291 | let selectorAst = SelectorParser.parse(name) |
| 292 | let foundValidUtility = false |
| 293 | |
| 294 | walk(selectorAst, (node) => { |
| 295 | if ( |
| 296 | node.kind === class="st">'selector' && |
| 297 | node.value[0] === class="st">'.' && |
| 298 | IS_VALID_UTILITY_NAME.test(node.value.slice(1)) |
| 299 | ) { |
| 300 | let value = node.value |
| 301 | node.value = class="st">'&' |
| 302 | let selector = SelectorParser.toCss(selectorAst) |
| 303 | |
| 304 | let className = value.slice(1) |
| 305 | let contents = selector === class="st">'&' ? objectToAst(css) : [rule(selector, objectToAst(css))] |
| 306 | utils.get(className).push(...contents) |
| 307 | foundValidUtility = true |
| 308 | |
| 309 | node.value = value |
| 310 | return |
| 311 | } |
| 312 | |
| 313 | if (node.kind === class="st">'function' && node.value === class="st">':not') { |
| 314 | return WalkAction.Skip |
| 315 | } |
| 316 | }) |
| 317 | |
| 318 | if (!foundValidUtility) { |
| 319 | throw new Error( |
| 320 | `\`addUtilities({ class="st">'${name}' : … })\` defines an invalid utility selector. Utilities must be a single class name and start with a lowercase letter, eg. \`.scrollbar-none\`.`, |
| 321 | ) |
| 322 | } |
| 323 | } |