(ts, nested = false)
| 2605 | * @returns {Declaration | undefined} parsed declaration, or `undefined` on the spec's "return nothing" branches (steps 1, 3, 8) |
| 2606 | */ |
| 2607 | const consumeADeclaration = (ts, nested = false) => { |
| 2608 | const { input } = ts; |
| 2609 | // Let decl be a new declaration, with an initially empty name and a value set to an empty list. |
| 2610 | const start = ts.next().start; |
| 2611 | // name "" / nameStart / nameEnd (= start) / important (false) keep their |
| 2612 | // `Container` defaults; `value` is set unconditionally at step 5 below. |
| 2613 | const decl = /** @type {Declaration} */ ( |
| 2614 | _mkContainer(T_DECLARATION, start, start) |
| 2615 | ); |
| 2616 | |
| 2617 | // 1. If the next token is an <ident-token>, consume a token from input and set decl's name to the returned token's value. |
| 2618 | // Otherwise, consume the remnants of a bad declaration from input, with nested, and return nothing. |
| 2619 | if (ts.next().type === TT_IDENTIFIER) { |
| 2620 | const head = ts.consume(); |
| 2621 | _setName(decl, input.slice(head.start, head.end), head.start, head.end); |
| 2622 | } else { |
| 2623 | consumeTheRemnantsOfABadDeclaration(ts, nested); |
| 2624 | return undefined; |
| 2625 | } |
| 2626 | |
| 2627 | // 2. Discard whitespace from input. |
| 2628 | while (ts.next().type === TT_WHITESPACE) ts.discard(); |
| 2629 | |
| 2630 | // 3. If the next token is a <colon-token>, discard a token from input. |
| 2631 | // Otherwise, consume the remnants of a bad declaration from input, with nested, and return nothing. |
| 2632 | if (ts.next().type === TT_COLON) { |
| 2633 | ts.discard(); |
| 2634 | } else { |
| 2635 | consumeTheRemnantsOfABadDeclaration(ts, nested); |
| 2636 | return undefined; |
| 2637 | } |
| 2638 | |
| 2639 | // 4. Discard whitespace from input. |
| 2640 | while (ts.next().type === TT_WHITESPACE) ts.discard(); |
| 2641 | |
| 2642 | // 5. Consume a list of component values from input, with nested, and with <semicolon-token> as the stop token, and set decl's value to the result. |
| 2643 | const value = consumeAListOfComponentValues(ts, TT_SEMICOLON, nested); |
| 2644 | _setValue(decl, value); |
| 2645 | _setEnd(decl, ts.next().start); |
| 2646 | |
| 2647 | // 6. If the last two non-<whitespace-token>s in decl's value are a <delim-token> with the value "!" followed by an <ident-token> with a value that is an ASCII case-insensitive match for "important", remove them from decl's value and set decl's important flag. |
| 2648 | { |
| 2649 | let last = value.length - 1; |
| 2650 | while (last >= 0 && _nType(value[last]) === T_WHITESPACE) last--; |
| 2651 | let prev = last - 1; |
| 2652 | while (prev >= 0 && _nType(value[prev]) === T_WHITESPACE) prev--; |
| 2653 | if ( |
| 2654 | prev >= 0 && |
| 2655 | _nType(value[last]) === T_IDENT && |
| 2656 | equalsLowerCase(_nValue(value[last]), "important") && |
| 2657 | _nType(value[prev]) === T_DELIM && |
| 2658 | input.charCodeAt(_nStart(value[prev])) === CC_EXCLAMATION |
| 2659 | ) { |
| 2660 | _setImportant(decl); |
| 2661 | value.length = prev; |
| 2662 | } |
| 2663 | } |
| 2664 |
no test coverage detected