|
1 |
| -import { assertNever } from "@opticss/util"; |
2 | 1 | import { CompoundSelector, ParsedSelector, postcss, postcssSelectorParser as selectorParser } from "opticss";
|
3 | 2 |
|
4 |
| -import { Block, Style } from "../../BlockTree"; |
| 3 | +import { Block, BlockClass, Style } from "../../BlockTree"; |
5 | 4 | import * as errors from "../../errors";
|
6 | 5 | import { selectorSourceLocation as loc, sourceLocation } from "../../SourceLocation";
|
7 | 6 | import {
|
8 | 7 | BlockNodeAndType,
|
9 | 8 | BlockType,
|
10 | 9 | NodeAndType,
|
11 | 10 | blockTypeName,
|
12 |
| - getBlockNode, |
13 | 11 | isAttributeNode,
|
14 | 12 | isClassLevelObject,
|
15 | 13 | isClassNode,
|
@@ -71,53 +69,32 @@ export async function constructBlock(root: postcss.Root, block: Block, file: str
|
71 | 69 | // For each `CompoundSelector` in this rule, configure the `Block` object
|
72 | 70 | // depending on the BlockType.
|
73 | 71 | while (currentCompoundSel) {
|
| 72 | + |
74 | 73 | let isKey = (keySel === currentCompoundSel);
|
75 |
| - let obj = getBlockNode(currentCompoundSel); |
76 |
| - if (obj) { |
77 |
| - switch (obj.blockType) { |
78 |
| - |
79 |
| - // If type `block`, track all property concerns on the block object |
80 |
| - // itself, excluding any inheritance properties. Make sure to |
81 |
| - // process any inheritance properties present in this ruleset. |
82 |
| - case BlockType.root: |
83 |
| - if (!isKey) { break; } |
84 |
| - styleRuleTuples.add([block.rootClass, rule]); |
85 |
| - break; |
86 |
| - |
87 |
| - // If a local attribute selector, ensure the attribute is registered with |
88 |
| - // the parent block and track add all property concerns from this |
89 |
| - // ruleset. If a foreign attribute, do nothing (validation happened earlier). |
90 |
| - case BlockType.attribute: |
91 |
| - if (obj.blockName) { break; } |
92 |
| - let attr = block.rootClass.ensureAttributeValue(toAttrToken(obj.node)); |
93 |
| - if (!isKey) { break; } |
94 |
| - styleRuleTuples.add([attr, rule]); |
95 |
| - break; |
96 |
| - |
97 |
| - // If a class selector, ensure this class is registered with the |
98 |
| - // parent block and track all property concerns from this ruleset. |
99 |
| - case BlockType.class: |
100 |
| - let blockClass = block.ensureClass(obj.node.value); |
101 |
| - if (!isKey) { break; } |
102 |
| - styleRuleTuples.add([blockClass, rule]); |
103 |
| - break; |
104 |
| - |
105 |
| - // If a classAttribute selector, ensure the class is registered with |
106 |
| - // the parent block, and the attribute is registered with this class. |
107 |
| - // Track all property concerns from this ruleset. |
108 |
| - case BlockType.classAttribute: |
109 |
| - let classNode = obj.node.prev(); |
110 |
| - let classObj = block.ensureClass(classNode.value!); |
111 |
| - let classAttr = classObj.ensureAttributeValue(toAttrToken(obj.node)); |
112 |
| - if (!isKey) { break; } |
113 |
| - styleRuleTuples.add([classAttr, rule]); |
114 |
| - break; |
115 |
| - default: |
116 |
| - assertNever(obj); |
| 74 | + let blockClass: BlockClass | undefined = undefined; |
| 75 | + let foundStyles: Style[] = []; |
| 76 | + |
| 77 | + for (let node of currentCompoundSel.nodes) { |
| 78 | + if (isRootNode(node)){ |
| 79 | + blockClass = block.rootClass; |
| 80 | + } |
| 81 | + else if (isClassNode(node)){ |
| 82 | + blockClass = block.ensureClass(node.value); |
| 83 | + } |
| 84 | + else if (isAttributeNode(node)){ |
| 85 | + // The fact that a base class exists for all state selectors is validated elsewhere |
| 86 | + foundStyles.push(blockClass!.ensureAttributeValue(toAttrToken(node))); |
117 | 87 | }
|
| 88 | + |
118 | 89 | }
|
| 90 | + // If we haven't found any terminating states, we're targeting the discovered Block class. |
| 91 | + if (blockClass && !foundStyles.length) { foundStyles.push(blockClass); } |
| 92 | + |
| 93 | + // If this is the key selector, save this ruleset on the created style. |
| 94 | + if (isKey) { |
| 95 | + foundStyles.map(s => styleRuleTuples.add([s, rule])); |
| 96 | + } |
119 | 97 |
|
120 |
| - // Move on to the next compound selector. |
121 | 98 | currentCompoundSel = currentCompoundSel.next && currentCompoundSel.next.selector;
|
122 | 99 | }
|
123 | 100 | });
|
@@ -325,14 +302,14 @@ function assertBlockObject(block: Block, sel: CompoundSelector, rule: postcss.Ru
|
325 | 302 | );
|
326 | 303 | }
|
327 | 304 | if (!found) {
|
328 |
| - found = { node: n, blockType: BlockType.attribute }; |
329 |
| - } else if (found.blockType === BlockType.class) { |
330 |
| - found = { node: n, blockType: BlockType.classAttribute }; |
331 |
| - } else if (found.blockType === BlockType.root) { |
332 | 305 | throw new errors.InvalidBlockSyntax(
|
333 |
| - `It's redundant to specify a state with an explicit .root: ${rule.selector}`, |
334 |
| - loc(file, rule, found.node), |
| 306 | + `States without an explicit :scope or class selector are not yet supported: ${rule.selector}`, |
| 307 | + loc(file, rule, n), |
335 | 308 | );
|
| 309 | + } else if (found.blockType === BlockType.class || found.blockType === BlockType.classAttribute) { |
| 310 | + found = { node: n, blockType: BlockType.classAttribute }; |
| 311 | + } else if (found.blockType === BlockType.root || found.blockType === BlockType.attribute) { |
| 312 | + found = { node: n, blockType: BlockType.attribute }; |
336 | 313 | }
|
337 | 314 | }
|
338 | 315 |
|
|
0 commit comments