(ts, stopToken, nested = false)
| 2366 | * @returns {QualifiedRule | undefined} parsed qualified rule, or `undefined` on a parse error |
| 2367 | */ |
| 2368 | const consumeAQualifiedRule = (ts, stopToken, nested = false) => { |
| 2369 | const start = ts.next().start; |
| 2370 | // Let rule be a new qualified rule with its prelude, declarations, and child rules all initially set to empty lists. |
| 2371 | const rule = /** @type {QualifiedRule} */ ( |
| 2372 | _mkContainer(T_QUALIFIED_RULE, start, start) |
| 2373 | ); |
| 2374 | const prelude = _list(); |
| 2375 | _setPrelude(rule, prelude); |
| 2376 | // declarations / childRules / blockStart (-1) / blockEnd (-1) keep their |
| 2377 | // defaults (no block until a `{` is reached). |
| 2378 | |
| 2379 | // Process input |
| 2380 | for (;;) { |
| 2381 | const t = ts.next(); |
| 2382 | // <EOF-token> |
| 2383 | // stop token (if passed) |
| 2384 | // This is a parse error. Return nothing. |
| 2385 | if (t.type === TT_EOF || t.type === stopToken) { |
| 2386 | return undefined; |
| 2387 | } |
| 2388 | // <}-token> |
| 2389 | // This is a parse error. If nested is true, return nothing. Otherwise, consume a token and append the result to rule’s prelude. |
| 2390 | else if (t.type === TT_RIGHT_CURLY_BRACKET) { |
| 2391 | if (nested) return undefined; |
| 2392 | prelude.push(consumeATokenAsNode(ts)); |
| 2393 | continue; |
| 2394 | } |
| 2395 | // <{-token> |
| 2396 | // If the first two non-<whitespace-token> values of rule's prelude are an <ident-token> whose value starts with "--" followed by a <colon-token>, then: |
| 2397 | // - If nested is true, consume the remnants of a bad declaration from input, with nested set to true, and return nothing. |
| 2398 | // - If nested is false, consume a block from input, and return nothing. |
| 2399 | // (This disambiguates custom-property declarations from nested qualified rules — `--foo: { … }` at top level of a block is a declaration, not a rule.) |
| 2400 | // Otherwise, consume a block from input, and let child rules be the result. |
| 2401 | else if (t.type === TT_LEFT_CURLY_BRACKET) { |
| 2402 | let firstIdx = 0; |
| 2403 | /* istanbul ignore next -- @preserve: leading whitespace is discarded before the rule, so the prelude never starts with it */ |
| 2404 | while ( |
| 2405 | firstIdx < prelude.length && |
| 2406 | _nType(prelude[firstIdx]) === T_WHITESPACE |
| 2407 | ) { |
| 2408 | firstIdx++; |
| 2409 | } |
| 2410 | let secondIdx = firstIdx + 1; |
| 2411 | while ( |
| 2412 | secondIdx < prelude.length && |
| 2413 | _nType(prelude[secondIdx]) === T_WHITESPACE |
| 2414 | ) { |
| 2415 | secondIdx++; |
| 2416 | } |
| 2417 | const first = prelude[firstIdx]; |
| 2418 | const second = prelude[secondIdx]; |
| 2419 | if ( |
| 2420 | first && |
| 2421 | _nType(first) === T_IDENT && |
| 2422 | // Test the source bytes directly — avoids forcing the lazy `value` |
| 2423 | // slice just to check the `--` custom-property prefix. |
| 2424 | ts.input.startsWith("--", _nStart(first)) && |
| 2425 | second && |
no test coverage detected