Skip to content

Commit 0399afa

Browse files
committed
Merge branch 'simplify-options'
BREAKING CHANGE: Several types relating to options and configuration are removed/renamed. The options code was some of the first I wrote for this project and it was awkward to use. A lot of APIs expected a concrete options reader instead of just the options interface in a read-only state. This change introduces the term "configuration" to mean a set of complete configuration options and "options" to mean a partial configuration. The act of turning options into configuration is called "resolving" the options. The options reader is no longer exported, the new resolveConfiguration function should be used to get a read-only configuration object populated with default values where necessary. Because configurations are assignable to options, if a resolved configuration is ever passed to resolveConfiguration, is it efficiently passed through, so, when in doubt, an API should accept options and resolve them. Where user-supplied options are accepted, the Options type is accepted and then resolved to a ResolvedConfiguration. This merge also re-organizes the project a bit, two new directories are added to `css-blocks/src`: configuration and importing. The importing.ts file has been broken up into constituent parts. This enabled making the css-blocks configuration no longer need to be augmented from different modules in the project. Configuration and options related code is now found in the configuration module directory.
2 parents 0ec1b45 + c6fd6c5 commit 0399afa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1033
-1112
lines changed

Diff for: packages/css-blocks/src/Block/AttrValue.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import {
77
import { assertNever, assertNeverCalled } from "@opticss/util";
88

99
import { ATTR_PRESENT } from "../BlockSyntax";
10-
import { OptionsReader } from "../OptionsReader";
11-
import { OutputMode } from "../OutputMode";
10+
import { OutputMode,
11+
ResolvedConfiguration } from "../configuration";
1212

1313
import { Attribute } from "./Attribute";
1414
import { Block } from "./Block";
@@ -78,12 +78,12 @@ export class AttrValue extends Style<AttrValue, Block, Attribute, never> {
7878
return this.parent.asSource(this.value);
7979
}
8080

81-
public cssClass(opts: OptionsReader): string {
82-
switch (opts.outputMode) {
81+
public cssClass(config: ResolvedConfiguration): string {
82+
switch (config.outputMode) {
8383
case OutputMode.BEM:
84-
return `${this.parent.cssClass(opts)}${ this.isPresenceRule ? "" : `-${this.value}`}`;
84+
return `${this.parent.cssClass(config)}${ this.isPresenceRule ? "" : `-${this.value}`}`;
8585
default:
86-
return assertNever(opts.outputMode);
86+
return assertNever(config.outputMode);
8787
}
8888
}
8989

Diff for: packages/css-blocks/src/Block/Attribute.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import {
99
import { assertNever, ObjectDictionary } from "@opticss/util";
1010

1111
import { ATTR_PRESENT, IAttrToken as AttrToken } from "../BlockSyntax";
12-
import { OptionsReader } from "../OptionsReader";
13-
import { OutputMode } from "../OutputMode";
12+
import { OutputMode, ResolvedConfiguration } from "../configuration";
1413

1514
import { AttrValue } from "./AttrValue";
1615
import { Block } from "./Block";
@@ -174,16 +173,16 @@ export class Attribute extends Inheritable<Attribute, Block, BlockClass, AttrVal
174173

175174
/**
176175
* Export as new class name.
177-
* @param opts Option hash configuring output mode.
176+
* @param config Option hash configuring output mode.
178177
* @returns String representing output class.
179178
*/
180-
cssClass(opts: OptionsReader) {
181-
switch (opts.outputMode) {
179+
cssClass(config: ResolvedConfiguration) {
180+
switch (config.outputMode) {
182181
case OutputMode.BEM:
183-
let cssClassName = this.blockClass.cssClass(opts);
182+
let cssClassName = this.blockClass.cssClass(config);
184183
return `${cssClassName}--${this.token.name}`;
185184
default:
186-
return assertNever(opts.outputMode);
185+
return assertNever(config.outputMode);
187186
}
188187
}
189188

Diff for: packages/css-blocks/src/Block/Block.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import {
1616
} from "../BlockParser";
1717
import { isRootNode, toAttrToken } from "../BlockParser";
1818
import { BlockPath, CLASS_NAME_IDENT, ROOT_CLASS } from "../BlockSyntax";
19-
import { OptionsReader } from "../OptionsReader";
2019
import { SourceLocation } from "../SourceLocation";
20+
import { ResolvedConfiguration } from "../configuration";
2121
import { CssBlockError, InvalidBlockSyntax } from "../errors";
2222
import { FileIdentifier } from "../importing";
2323

@@ -367,28 +367,28 @@ export class Block
367367
return null;
368368
}
369369

370-
rewriteSelectorNodes(nodes: selectorParser.Node[], opts: OptionsReader): selectorParser.Node[] {
370+
rewriteSelectorNodes(nodes: selectorParser.Node[], config: ResolvedConfiguration): selectorParser.Node[] {
371371
let newNodes: selectorParser.Node[] = [];
372372
for (let i = 0; i < nodes.length; i++) {
373373
let node = nodes[i];
374374
let result = this.nodeAsStyle(node);
375375
if (result === null) {
376376
newNodes.push(node);
377377
} else {
378-
newNodes.push(selectorParser.className({ value: result[0].cssClass(opts) }));
378+
newNodes.push(selectorParser.className({ value: result[0].cssClass(config) }));
379379
i += result[1];
380380
}
381381
}
382382
return newNodes;
383383
}
384384

385-
rewriteSelectorToString(selector: ParsedSelector, opts: OptionsReader): string {
385+
rewriteSelectorToString(selector: ParsedSelector, config: ResolvedConfiguration): string {
386386
let firstNewSelector = new CompoundSelector();
387387
let newSelector = firstNewSelector;
388388
let newCurrentSelector = newSelector;
389389
let currentSelector: CompoundSelector | undefined = selector.selector;
390390
do {
391-
newCurrentSelector.nodes = this.rewriteSelectorNodes(currentSelector.nodes, opts);
391+
newCurrentSelector.nodes = this.rewriteSelectorNodes(currentSelector.nodes, config);
392392
newCurrentSelector.pseudoelement = currentSelector.pseudoelement;
393393
if (currentSelector.next !== undefined) {
394394
let tempSel = newCurrentSelector;
@@ -402,21 +402,21 @@ export class Block
402402
return firstNewSelector.toString();
403403
}
404404

405-
rewriteSelector(selector: ParsedSelector, opts: OptionsReader): ParsedSelector {
405+
rewriteSelector(selector: ParsedSelector, config: ResolvedConfiguration): ParsedSelector {
406406
// generating a string and re-parsing ensures the internal structure is consistent
407407
// otherwise the parent/next/prev relationships will be wonky with the new nodes.
408-
let s = this.rewriteSelectorToString(selector, opts);
408+
let s = this.rewriteSelectorToString(selector, config);
409409
return parseSelector(s)[0];
410410
}
411411

412-
debug(opts: OptionsReader): string[] {
413-
let result: string[] = [`Source: ${this.identifier}`, this.rootClass.asDebug(opts)];
412+
debug(config: ResolvedConfiguration): string[] {
413+
let result: string[] = [`Source: ${this.identifier}`, this.rootClass.asDebug(config)];
414414
let sourceNames = new Set<string>(this.all().map(s => s.asSource()));
415415
let sortedNames = [...sourceNames].sort();
416416
for (let n of sortedNames) {
417417
if (n !== ROOT_CLASS) {
418418
let o = this.find(n) as Styles;
419-
result.push(o.asDebug(opts));
419+
result.push(o.asDebug(config));
420420
}
421421
}
422422
return result;

Diff for: packages/css-blocks/src/Block/BlockClass.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Attribute as Attr, AttributeValue, attrValues } from "@opticss/element-analysis";
2+
import { assertNever } from "@opticss/util";
23
import { isString } from "util";
34

45
import { ATTR_PRESENT, IAttrToken as AttrToken, ROOT_CLASS } from "../BlockSyntax";
56
import { BlockPath } from "../BlockSyntax";
6-
import { OptionsReader } from "../OptionsReader";
7-
import { OutputMode } from "../OutputMode";
7+
import { OutputMode, ResolvedConfiguration } from "../configuration";
88

99
import { AttrValue } from "./AttrValue";
1010
import { Attribute } from "./Attribute";
@@ -181,19 +181,19 @@ export class BlockClass extends Style<BlockClass, Block, Block, Attribute> {
181181

182182
/**
183183
* Export as new class name.
184-
* @param opts Option hash configuring output mode.
184+
* @param config Option hash configuring output mode.
185185
* @returns String representing output class.
186186
*/
187-
public cssClass(opts: OptionsReader): string {
188-
switch (opts.outputMode) {
187+
public cssClass(config: ResolvedConfiguration): string {
188+
switch (config.outputMode) {
189189
case OutputMode.BEM:
190190
if (this.isRoot) {
191191
return `${this.block.name}`;
192192
} else {
193193
return `${this.block.name}__${this.name}`;
194194
}
195195
default:
196-
throw new Error("this never happens");
196+
return assertNever(config.outputMode);
197197
}
198198
}
199199

@@ -219,10 +219,10 @@ export class BlockClass extends Style<BlockClass, Block, Block, Attribute> {
219219
* @param options Options to pass to BlockClass' asDebug method.
220220
* @return Array of debug strings for this BlockClass
221221
*/
222-
debug(opts: OptionsReader): string[] {
222+
debug(config: ResolvedConfiguration): string[] {
223223
let result: string[] = [];
224224
for (let style of this.all()) {
225-
result.push(style.asDebug(opts));
225+
result.push(style.asDebug(config));
226226
}
227227
return result;
228228
}

Diff for: packages/css-blocks/src/Block/Style.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Attr } from "@opticss/element-analysis";
22

3-
import { OptionsReader } from "../OptionsReader";
3+
import { ResolvedConfiguration } from "../configuration";
44
import { unionInto } from "../util/unionInto";
55

66
import { AnyNode, Inheritable } from "./Inheritable";
@@ -38,10 +38,10 @@ export abstract class Style<
3838

3939
/**
4040
* Return the css selector for this `Style`.
41-
* @param opts Option hash configuring output mode.
41+
* @param config Option hash configuring output mode.
4242
* @returns The CSS class.
4343
*/
44-
public abstract cssClass(opts: OptionsReader): string;
44+
public abstract cssClass(config: ResolvedConfiguration): string;
4545

4646
/**
4747
* Return the source selector this `Style` was read from.
@@ -59,10 +59,10 @@ export abstract class Style<
5959
* including inherited classes.
6060
* @returns this object's css class and all inherited classes.
6161
*/
62-
cssClasses(opts: OptionsReader): string[] {
62+
cssClasses(config: ResolvedConfiguration): string[] {
6363
let classes: string[] = [];
6464
for (let style of this.resolveStyles()) {
65-
classes.push(style.cssClass(opts));
65+
classes.push(style.cssClass(config));
6666
}
6767
return classes;
6868
}
@@ -107,11 +107,11 @@ export abstract class Style<
107107

108108
/**
109109
* Debug utility to help log Styles
110-
* @param opts Options for rendering cssClass.
110+
* @param config Options for rendering cssClass.
111111
* @returns A debug string.
112112
*/
113-
asDebug(opts: OptionsReader) {
114-
return `${this.asSource()} => ${this.cssClasses(opts).map(n => `.${n}`).join(" ")}`;
113+
asDebug(config: ResolvedConfiguration) {
114+
return `${this.asSource()} => ${this.cssClasses(config).map(n => `.${n}`).join(" ")}`;
115115
}
116116

117117
// TypeScript can't figure out that `this` is the `StyleType` so this private

Diff for: packages/css-blocks/src/BlockCompiler/ConflictResolver.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import selectorParser = require("postcss-selector-parser");
66
import { Block, Style } from "../Block";
77
import { getBlockNode } from "../BlockParser";
88
import { RESOLVE_RE } from "../BlockSyntax";
9-
import { OptionsReader } from "../OptionsReader";
109
import { SourceLocation, sourceLocation } from "../SourceLocation";
10+
import { ResolvedConfiguration } from "../configuration";
1111
import * as errors from "../errors";
1212
import { QueryKeySelector } from "../query";
1313

@@ -61,10 +61,10 @@ function updateConflict(t1: ConflictType, t2: ConflictType): ConflictType {
6161
* resolves property values accordingly.
6262
*/
6363
export class ConflictResolver {
64-
readonly opts: OptionsReader;
64+
readonly config: ResolvedConfiguration;
6565

66-
constructor(opts: OptionsReader) {
67-
this.opts = opts;
66+
constructor(config: ResolvedConfiguration) {
67+
this.config = config;
6868
}
6969

7070
/**
@@ -242,7 +242,7 @@ export class ConflictResolver {
242242
// we reverse the selectors because otherwise the insertion order causes them to be backwards from the
243243
// source order of the target selector
244244
resultSelectors.reverse().forEach((s) => {
245-
let newSelectors = this.mergeKeySelectors(other.block.rewriteSelector(s.parsedSelector, this.opts), cs);
245+
let newSelectors = this.mergeKeySelectors(other.block.rewriteSelector(s.parsedSelector, this.config), cs);
246246
if (newSelectors === null) return;
247247
let newSelStr = newSelectors.join(",\n");
248248
// avoid duplicate selector via permutation
@@ -416,7 +416,7 @@ export class ConflictResolver {
416416
return mergedSelectors.map(sel => new ParsedSelector(sel));
417417
}
418418
sourceLocation(block: Block, node: postcss.Node): SourceLocation | undefined {
419-
let blockPath = this.opts.importer.debugIdentifier(block.identifier, this.opts);
419+
let blockPath = this.config.importer.debugIdentifier(block.identifier, this.config);
420420
return sourceLocation(blockPath, node);
421421
}
422422
}

Diff for: packages/css-blocks/src/BlockCompiler/index.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,33 @@ import {
88
parseBlockDebug,
99
ROOT_CLASS,
1010
} from "../BlockSyntax";
11-
import { OptionsReader } from "../OptionsReader";
1211
import { StyleAnalysis } from "../TemplateAnalysis/StyleAnalysis";
13-
import { PluginOptions } from "../options";
12+
import {
13+
Options,
14+
resolveConfiguration,
15+
ResolvedConfiguration,
16+
} from "../configuration";
1417

1518
import { ConflictResolver } from "./ConflictResolver";
1619
/**
1720
* Compiler that, given a Block will return a transformed AST
1821
* interface is `BlockParser.parse`.
1922
*/
2023
export class BlockCompiler {
21-
private opts: OptionsReader;
24+
private config: ResolvedConfiguration;
2225
private postcss: typeof postcss;
2326

24-
constructor(postcssImpl: typeof postcss, opts?: PluginOptions) {
25-
this.opts = new OptionsReader(opts);
27+
constructor(postcssImpl: typeof postcss, opts?: Options) {
28+
this.config = resolveConfiguration(opts);
2629
this.postcss = postcssImpl;
2730
}
2831

2932
compile(block: Block, root: postcss.Root, analysis?: StyleAnalysis): postcss.Root {
3033
if (analysis) {
3134
// console.log("Got an analysis for compilation. I should use it probably.", analysis);
3235
}
33-
let resolver = new ConflictResolver(this.opts);
34-
let filename = this.opts.importer.debugIdentifier(block.identifier, this.opts);
36+
let resolver = new ConflictResolver(this.config);
37+
let filename = this.config.importer.debugIdentifier(block.identifier, this.config);
3538

3639
// Process all debug statements for this block.
3740
this.processDebugStatements(filename, root, block);
@@ -53,7 +56,7 @@ export class BlockCompiler {
5356
resolver.resolveInheritance(root, block);
5457
root.walkRules((rule) => {
5558
let parsedSelectors = block.getParsedSelectors(rule);
56-
rule.selector = parsedSelectors.map(s => block.rewriteSelectorToString(s, this.opts)).join(",\n");
59+
rule.selector = parsedSelectors.map(s => block.rewriteSelectorToString(s, this.config)).join(",\n");
5760
});
5861

5962
resolver.resolve(root, block);
@@ -71,7 +74,7 @@ export class BlockCompiler {
7174
root.walkAtRules(BLOCK_DEBUG, (atRule) => {
7275
let {block: ref, channel} = parseBlockDebug(atRule, sourceFile, block);
7376
if (channel === "comment") {
74-
let debugStr = ref.debug(this.opts);
77+
let debugStr = ref.debug(this.config);
7578
atRule.replaceWith(this.postcss.comment({text: debugStr.join("\n ")}));
7679
} else {
7780
// stderr/stdout are emitted during parse.

0 commit comments

Comments
 (0)