Skip to content

Commit 5455597

Browse files
ramithachriseppstein
authored andcommitted
feat: Converting composes block errors.
1 parent 29cc368 commit 5455597

File tree

7 files changed

+166
-109
lines changed

7 files changed

+166
-109
lines changed

packages/@css-blocks/core/src/BlockParser/features/composes-block.ts

+21-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { postcss } from "opticss";
1+
import { ParsedSelector, postcss } from "opticss";
22
import { isRule } from "opticss/dist/src/util/cssIntrospection";
33

44
import { COMPOSES } from "../../BlockSyntax";
@@ -18,28 +18,35 @@ import { stripQuotes } from "../utils";
1818
*/
1919
export async function composeBlock(configuration: Configuration, root: postcss.Root, block: Block, sourceFile: string) {
2020
root.walkDecls(COMPOSES, (decl) => {
21-
if (!isRule(decl.parent)) { throw new errors.InvalidBlockSyntax(`The "composes" property may only be used in a rule set.`, sourceRange(configuration, root, sourceFile, decl)); }
21+
if (!isRule(decl.parent)) { block.addError(new errors.InvalidBlockSyntax(`The "composes" property may only be used in a rule set.`, sourceRange(configuration, root, sourceFile, decl))); }
2222
let rule = decl.parent;
2323

2424
// TODO: Move to Block Syntax as parseBlockRefList().
2525
let refNames = decl.value.split(/,\s*/).map(stripQuotes);
2626
for (let refName of refNames) {
2727
let refStyle = block.lookup(refName);
2828
if (!refStyle) {
29-
throw new errors.InvalidBlockSyntax(`No style "${refName}" found.`, sourceRange(configuration, root, sourceFile, decl));
29+
block.addError(new errors.InvalidBlockSyntax(`No style "${refName}" found.`, sourceRange(configuration, root, sourceFile, decl)));
3030
}
31-
if (refStyle.block === block) {
32-
throw new errors.InvalidBlockSyntax(`Styles from the same Block may not be composed together.`, sourceRange(configuration, root, sourceFile, decl));
33-
}
34-
35-
const parsedSel = block.getParsedSelectors(rule);
36-
for (let sel of parsedSel) {
37-
if (sel.selector.next) {
38-
throw new errors.InvalidBlockSyntax(`Style composition is not allowed in rule sets with a scope selector.`, sourceRange(configuration, root, sourceFile, decl));
31+
else {
32+
if (refStyle.block === block) {
33+
block.addError(new errors.InvalidBlockSyntax(`Styles from the same Block may not be composed together.`, sourceRange(configuration, root, sourceFile, decl)));
3934
}
40-
let foundStyles = getStyleTargets(block, sel.selector);
41-
for (let blockClass of foundStyles.blockClasses) {
42-
blockClass.addComposedStyle(refStyle, foundStyles.blockAttrs);
35+
let parsedSel: ParsedSelector[] = [];
36+
try {
37+
parsedSel = block.getParsedSelectors(rule as postcss.Rule);
38+
} catch (e) {
39+
block.addError(new errors.InvalidBlockSyntax(e.message, sourceRange(configuration, block.stylesheet, sourceFile, rule)));
40+
}
41+
42+
for (let sel of parsedSel) {
43+
if (sel.selector.next) {
44+
block.addError(new errors.InvalidBlockSyntax(`Style composition is not allowed in rule sets with a scope selector.`, sourceRange(configuration, root, sourceFile, decl)));
45+
}
46+
let foundStyles = getStyleTargets(block, sel.selector);
47+
for (let blockClass of foundStyles.blockClasses) {
48+
blockClass.addComposedStyle(refStyle, foundStyles.blockAttrs);
49+
}
4350
}
4451
}
4552
}

packages/@css-blocks/core/test/BlockParser/block-attribute-test.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ export class BlockAttributesTest extends BEMProcessor {
1616
let filename = "foo/bar/test-block.css";
1717
let inputCSS = `:scope[scope] { color: red; }`;
1818

19-
return assertMultipleErrors([{
19+
return assertMultipleErrors(
20+
[{
2021
type: InvalidBlockSyntax,
2122
message: `A state cannot be named 'scope'. (foo/bar/test-block.css:1:7)`,
22-
}], this.process(filename, inputCSS, {importer: imports.importer()}));
23+
}],
24+
this.process(filename, inputCSS, {importer: imports.importer()}));
2325
}
2426
}

packages/@css-blocks/core/test/BlockParser/block-composition-test.ts

+24-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { assert } from "chai";
22
import { suite, test } from "mocha-typescript";
33

4-
import { assertError } from "../util/assertError";
4+
import { assertMultipleErrors } from "../util/assertError";
55
import { BEMProcessor } from "../util/BEMProcessor";
66
import { indented } from "../util/indented";
77
import { MockImportRegistry } from "../util/MockImportRegistry";
@@ -22,9 +22,15 @@ export class BlockNames extends BEMProcessor {
2222
let inputCSS = `@block biz from "./biz.css";
2323
@media(max-width: 200px) { composes: biz.baz; }`;
2424

25-
return assertError(
26-
InvalidBlockSyntax,
27-
`The "composes" property may only be used in a rule set. (foo/bar/test-block.css:2:48)`,
25+
return assertMultipleErrors(
26+
[{
27+
type: InvalidBlockSyntax,
28+
message: `The "composes" property may only be used in a rule set. (foo/bar/test-block.css:2:48)`,
29+
},
30+
{
31+
type: InvalidBlockSyntax,
32+
message: `Cannot read property 'valueOf' of undefined (foo/bar/test-block.css:2:21)`,
33+
}],
2834
this.process(filename, inputCSS, {importer: imports.importer()}));
2935
}
3036

@@ -39,9 +45,11 @@ export class BlockNames extends BEMProcessor {
3945
let inputCSS = `@block biz from "./biz.css";
4046
.bar { composes: biz.buz; }`;
4147

42-
return assertError(
43-
InvalidBlockSyntax,
44-
`No style "biz.buz" found. (foo/bar/test-block.css:2:28)`,
48+
return assertMultipleErrors(
49+
[{
50+
type: InvalidBlockSyntax,
51+
message: `No style "biz.buz" found. (foo/bar/test-block.css:2:28)`,
52+
}],
4553
this.process(filename, inputCSS, {importer: imports.importer()}));
4654
}
4755

@@ -57,9 +65,11 @@ export class BlockNames extends BEMProcessor {
5765
.buz { color: green; }
5866
.bar { composes: .buz; }`;
5967

60-
return assertError(
61-
InvalidBlockSyntax,
62-
`Styles from the same Block may not be composed together. (foo/bar/test-block.css:3:28)`,
68+
return assertMultipleErrors(
69+
[{
70+
type: InvalidBlockSyntax,
71+
message: `Styles from the same Block may not be composed together. (foo/bar/test-block.css:3:28)`,
72+
}],
6373
this.process(filename, inputCSS, {importer: imports.importer()}));
6474
}
6575

@@ -74,9 +84,10 @@ export class BlockNames extends BEMProcessor {
7484
let inputCSS = `@block biz from "./biz.css";
7585
:scope[awesome] .bar { composes: biz.baz; }`;
7686

77-
return assertError(
78-
InvalidBlockSyntax,
79-
`Style composition is not allowed in rule sets with a scope selector. (foo/bar/test-block.css:2:44)`,
87+
return assertMultipleErrors(
88+
[{
89+
type: InvalidBlockSyntax,
90+
message: `Style composition is not allowed in rule sets with a scope selector. (foo/bar/test-block.css:2:44)`}],
8091
this.process(filename, inputCSS, {importer: imports.importer()}));
8192
}
8293

packages/@css-blocks/core/test/BlockParser/native-pseudos-test.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,37 @@ export class DisallowedPseudos extends BEMProcessor {
1212
let filename = "foo/bar/illegal-not-pseudoclass.css";
1313
let inputCSS = `:scope {color: #111;}
1414
.another-class:not([foo]) { display: block; }`;
15-
return assertMultipleErrors([{
15+
return assertMultipleErrors(
16+
[{
1617
type: InvalidBlockSyntax,
1718
message: "The :not() pseudoclass cannot be used: .another-class:not([foo])" +
1819
" (foo/bar/illegal-not-pseudoclass.css:2:35)",
1920
}],
20-
this.process(filename, inputCSS));
21+
this.process(filename, inputCSS));
2122
}
2223

2324
@test "disallows the :matches() pseudoclass."() {
2425
let filename = "foo/bar/illegal-not-pseudoclass.css";
2526
let inputCSS = `:scope {color: #111;}
2627
.another-class:matches([foo]) { display: block; }`;
27-
return assertMultipleErrors([{
28+
return assertMultipleErrors(
29+
[{
2830
type: InvalidBlockSyntax,
2931
message: "The :matches() pseudoclass cannot be used: .another-class:matches([foo])" +
30-
" (foo/bar/illegal-not-pseudoclass.css:2:35)"}],
31-
this.process(filename, inputCSS));
32+
" (foo/bar/illegal-not-pseudoclass.css:2:35)",
33+
}],
34+
this.process(filename, inputCSS));
3235
}
3336

3437
@test "disallows pseudos not attached to a block object."() {
3538
let filename = "foo/bar/illegal-class-combinator.css";
3639
let inputCSS = `:scope :hover { display: block; }`;
37-
return assertMultipleErrors([{
40+
return assertMultipleErrors(
41+
[{
3842
type: InvalidBlockSyntax,
3943
message: "Missing block object in selector component ':hover': :scope :hover" +
40-
" (foo/bar/illegal-class-combinator.css:1:8)"}],
41-
this.process(filename, inputCSS));
44+
" (foo/bar/illegal-class-combinator.css:1:8)",
45+
}],
46+
this.process(filename, inputCSS));
4247
}
4348
}

0 commit comments

Comments
 (0)