(ts, onNode)
| 2515 | * @returns {{ decls: Declaration[], rules: Rule[] }} consumed decls + rules (both empty when `onNode` is given; stops at the enclosing `}` / EOF, left in the stream) |
| 2516 | */ |
| 2517 | const consumeABlocksContents = (ts, onNode) => { |
| 2518 | /** @type {Declaration[]} */ |
| 2519 | const decls = []; |
| 2520 | /** @type {Rule[]} */ |
| 2521 | const rules = []; |
| 2522 | |
| 2523 | // Process input: |
| 2524 | for (;;) { |
| 2525 | const t = ts.next(); |
| 2526 | |
| 2527 | // <whitespace-token> / <semicolon-token> |
| 2528 | // Discard a token from input. |
| 2529 | if (t.type === TT_WHITESPACE || t.type === TT_SEMICOLON) { |
| 2530 | ts.discard(); |
| 2531 | } |
| 2532 | // <EOF-token> / <}-token> |
| 2533 | // Return decls and rules. |
| 2534 | else if (t.type === TT_EOF || t.type === TT_RIGHT_CURLY_BRACKET) { |
| 2535 | return { decls, rules }; |
| 2536 | } |
| 2537 | // <at-keyword-token> |
| 2538 | // Consume an at-rule from input, with nested set to true. If a rule was returned, append it to rules. |
| 2539 | else if (t.type === TT_AT_KEYWORD) { |
| 2540 | const atRule = consumeAnAtRule(ts, true); |
| 2541 | if (atRule) { |
| 2542 | if (onNode) onNode(atRule); |
| 2543 | else rules.push(atRule); |
| 2544 | } |
| 2545 | } |
| 2546 | // anything else |
| 2547 | // Mark input. Consume a declaration from input, with nested set to true. |
| 2548 | // If a declaration was returned, append it to decls, and discard a mark from input. |
| 2549 | // Otherwise, restore a mark from input, then consume a qualified rule from input, with nested set to true, and <semicolon-token> as the stop token. If a rule was returned, append it to rules. |
| 2550 | else { |
| 2551 | // 2-token peek: consume-a-declaration's steps 1 / 3 require `<ident> <colon>`; if absent it would call consume-the-remnants-of-a-bad-declaration (potentially the rest of the enclosing block) only for the restoreMark to undo it (O(N²) on flat blocks of qualified rules). Skip straight to consume-a-qualified-rule — same observable result. |
| 2552 | if (declarationStartLikely(ts)) { |
| 2553 | ts.mark(); |
| 2554 | const decl = consumeADeclaration(ts, true); |
| 2555 | if (decl) { |
| 2556 | if (onNode) onNode(decl); |
| 2557 | else decls.push(decl); |
| 2558 | ts.discardMark(); |
| 2559 | continue; |
| 2560 | } |
| 2561 | ts.restoreMark(); |
| 2562 | } |
| 2563 | const rule = consumeAQualifiedRule(ts, TT_SEMICOLON, true); |
| 2564 | if (rule) { |
| 2565 | if (onNode) onNode(rule); |
| 2566 | else rules.push(rule); |
| 2567 | } |
| 2568 | } |
| 2569 | } |
| 2570 | }; |
| 2571 | |
| 2572 | /** |
| 2573 | * Consume the remnants of a bad declaration, CSS Syntax Level 3 [§5.4.11](https://drafts.csswg.org/css-syntax/#consume-the-remnants-of-a-bad-declaration). Advances the stream past a malformed declaration's tail so the caller (`consumeABlocksContents`) can resume cleanly. |
no test coverage detected