Skip to content

Commit 81d8853

Browse files
committed
feat: Basic runtime helper build infrastructure and scaffolding.
1 parent 945b2a8 commit 81d8853

File tree

18 files changed

+259
-30
lines changed

18 files changed

+259
-30
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ lerna-debug.log
99
yarn-error.log
1010
package-lock.json
1111
.vscode
12-
jsconfig.json
12+
jsconfig.json
13+
*.tsbuildinfo

packages/@css-blocks/ember-app/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"scripts": {
1515
"test": "yarn run test:runner",
1616
"test:runner": "mocha --opts test/mocha.opts dist/test",
17-
"compile": "tsc --build",
17+
"compile": "tsc --build && tsc --build runtime",
1818
"pretest": "yarn run compile",
1919
"posttest": "yarn run lint",
2020
"prepublish": "rm -rf dist && yarn run compile && yarn run lintall",
@@ -52,10 +52,10 @@
5252
"@opticss/template-api": "^0.6.3",
5353
"@opticss/util": "^0.7.0",
5454
"broccoli-debug": "^0.6.5",
55-
"broccoli-funnel": "^3.0.2",
56-
"broccoli-merge-trees": "^4.0.0",
55+
"broccoli-funnel": "^3.0.3",
56+
"broccoli-merge-trees": "^4.2.0",
5757
"broccoli-output-wrapper": "^3.2.1",
58-
"broccoli-plugin": "^4.0.0",
58+
"broccoli-persistent-filter": "^3.1.0",
5959
"colors": "^1.2.1",
6060
"debug": "^4.1.1",
6161
"fs-extra": "^8.0.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// @ts-ignore
2+
import Helper from "@ember/component/helper";
3+
/// @ts-ignore
4+
import Service from "@ember/service";
5+
6+
/// @ts-ignore
7+
import { data } from "./-css-blocks-data";
8+
9+
// tslint:disable-next-line:no-default-export
10+
export default class CSSBlocksService extends Service {
11+
classNamesFor(_args: Array<string | number | boolean | null>): string {
12+
return data.className;
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"extends": "../../../../tsconfig.json",
3+
"compilerOptions": {
4+
"module": "ESNext",
5+
"composite": true,
6+
"outDir": "../dist/runtime",
7+
"baseUrl": ".",
8+
"strict": true,
9+
"sourceMap": false,
10+
"declarationMap": false,
11+
"tsBuildInfoFile": "../runtime.tsbuildinfo",
12+
"paths": {
13+
"@css-blocks/ember/*": ["addon/*"]
14+
},
15+
"traceResolution": false
16+
},
17+
"include": [
18+
"."
19+
],
20+
"exclude": [
21+
]
22+
}

packages/@css-blocks/ember-app/src/index.ts

+99-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,58 @@
1-
import type { AddonImplementation } from "ember-cli/lib/models/addon";
1+
import funnel = require("broccoli-funnel");
2+
import mergeTrees = require("broccoli-merge-trees");
3+
import type { InputNode } from "broccoli-node-api";
4+
import Filter = require("broccoli-persistent-filter");
5+
import type { PluginOptions } from "broccoli-plugin/dist/interfaces";
6+
import EmberApp from "ember-cli/lib/broccoli/ember-app";
7+
import type Addon from "ember-cli/lib/models/addon";
8+
import type { AddonImplementation, ThisAddon } from "ember-cli/lib/models/addon";
9+
import Project from "ember-cli/lib/models/project";
10+
11+
class CSSBlocksApplicationPlugin extends Filter {
12+
appName: string;
13+
constructor(appName: string, inputNodes: InputNode[], options?: PluginOptions) {
14+
super(mergeTrees(inputNodes), options || {});
15+
this.appName = appName;
16+
}
17+
processString(contents: string, _relativePath: string): string {
18+
return contents;
19+
}
20+
async build() {
21+
await super.build();
22+
// console.log(`XXX ${this.appName}`);
23+
// let entries = this.input.entries(".", {globs: ["**/*"]});
24+
// for (let entry of entries) {
25+
// console.log(entry.relativePath);
26+
// }
27+
this.output.writeFileSync(
28+
`${this.appName}/services/-css-blocks-data.js`,
29+
`// CSS Blocks Generated Data. DO NOT EDIT.
30+
export const data = {className: "it-worked"};
31+
`);
32+
}
33+
}
34+
35+
interface AddonEnvironment {
36+
parent: Addon | EmberApp;
37+
app: EmberApp;
38+
rootDir: string;
39+
isApp: boolean;
40+
modulePrefix: string;
41+
}
42+
43+
interface CSSBlocksApplicationAddon {
44+
_modulePrefix(): string;
45+
env: AddonEnvironment | undefined;
46+
getEnv(parent): AddonEnvironment;
47+
}
248

349
/**
450
* An ember-cli addon for Ember applications using CSS Blocks in its
551
* application code. This addon should be a dependency in Ember applications.
652
*
753
* This addon is responsible for bundling together all CSS Blocks content
854
* from the application, concatenating it into a final artifact, and
9-
* optimizing its content using OptiCSS. Additionaly, this addon generates a
55+
* optimizing its content using OptiCSS. Additionally, this addon generates a
1056
* JSON bundle that contains runtime data that templates need to resolve
1157
* what classes to add to each CSS Blocks-powered component. And, finally,
1258
* this addon provides a runtime helper to actually write out those classes.
@@ -31,12 +77,14 @@ import type { AddonImplementation } from "ember-cli/lib/models/addon";
3177
*
3278
* @todo: Provide a link for Ember build pipeline readme.
3379
*/
34-
const EMBER_ADDON: AddonImplementation = {
80+
const EMBER_ADDON: AddonImplementation<CSSBlocksApplicationAddon> = {
3581
/**
3682
* The name of this addon. Generally matches the package name in package.json.
3783
*/
3884
name: "@css-blocks/ember-app",
3985

86+
env: undefined,
87+
4088
/**
4189
* Initalizes this addon instance for use.
4290
* @param parent - The project or addon that directly depends on this addon.
@@ -47,6 +95,42 @@ const EMBER_ADDON: AddonImplementation = {
4795
// recommend guarding this call, so we're gonna ask TSLint to chill.
4896
// tslint:disable-next-line: no-unused-expression
4997
this._super.init && this._super.init.call(this, parent, project);
98+
this.treePaths.app = "../runtime/app";
99+
this.treePaths.addon = "../runtime/addon";
100+
},
101+
102+
_modulePrefix(): string {
103+
/// @ts-ignore
104+
const parent = this.parent;
105+
const config = typeof parent.config === "function" ? parent.config() || {} : {};
106+
const name = typeof parent.name === "function" ? parent.name() : parent.name;
107+
const moduleName = typeof parent.moduleName === "function" ? parent.moduleName() : parent.moduleName;
108+
return moduleName || parent.modulePrefix || config.modulePrefix || name || "";
109+
},
110+
111+
getEnv(this: ThisAddon<CSSBlocksApplicationAddon>, parent: Addon | EmberApp): AddonEnvironment {
112+
// Fetch a reference to the parent app
113+
let current: Addon | Project = this;
114+
let app: EmberApp | undefined;
115+
do { app = (<Addon>current).app || app; }
116+
while ((<Addon>(<Addon>current).parent).parent && (current = (<Addon>current).parent));
117+
118+
let isApp = parent === app;
119+
120+
// The absolute path to the root of our app (aka: the directory that contains "src").
121+
// Needed because app root !== project root in addons – its located at `tests/dummy`.
122+
// TODO: Is there a better way to get this for Ember?
123+
let rootDir = (<Addon>parent).root || (<EmberApp>parent).project.root;
124+
125+
let modulePrefix = this._modulePrefix();
126+
127+
return {
128+
parent,
129+
app: app!,
130+
rootDir,
131+
isApp,
132+
modulePrefix,
133+
};
50134
},
51135

52136
/**
@@ -57,6 +141,7 @@ const EMBER_ADDON: AddonImplementation = {
57141
included(parent) {
58142
// We must call this._super or weird stuff happens.
59143
this._super.included.apply(this, [parent]);
144+
this.env = this.getEnv(parent);
60145
},
61146

62147
/**
@@ -66,10 +151,17 @@ const EMBER_ADDON: AddonImplementation = {
66151
* @returns - A tree that's ready to process.
67152
*/
68153
preprocessTree(type, tree) {
69-
if (type !== "template") return tree;
70-
71-
// TODO: Do something in the template tree.
72-
return tree;
154+
let env = this.env!;
155+
if (type === "js") {
156+
if (env.isApp) {
157+
let appAndAddonTree = new CSSBlocksApplicationPlugin(env.modulePrefix, [env.app.addonTree(), tree]);
158+
return funnel(appAndAddonTree, {srcDir: env.modulePrefix, destDir: env.modulePrefix});
159+
} else {
160+
return tree;
161+
}
162+
} else {
163+
return tree;
164+
}
73165
},
74166

75167
/**

packages/@css-blocks/ember-app/tsconfig.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
"compilerOptions": {
44
"composite": true,
55
"outDir": "dist",
6-
"baseUrl": "dist",
6+
"baseUrl": ".",
77
"noImplicitAny": false,
88
"paths": {
9+
"ember-cli/*": ["../ember/src/types/ember-cli"],
910
"*": ["types/*"],
10-
}
11+
},
12+
"traceResolution": false
1113
},
1214
"references": [
1315
{"path": "../config"},

packages/@css-blocks/ember/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"scripts": {
1515
"test": "yarn run test:runner",
1616
"test:runner": "mocha --opts test/mocha.opts dist/test",
17-
"compile": "tsc --build",
17+
"compile": "tsc --build && tsc --build runtime",
1818
"pretest": "yarn run compile",
1919
"posttest": "yarn run lint",
2020
"prepublish": "rm -rf dist && yarn run compile && yarn run lintall",
@@ -61,6 +61,7 @@
6161
"broccoli-plugin": "^4.0.0",
6262
"colors": "^1.2.1",
6363
"debug": "^4.1.1",
64+
"ember-cli-babel": "7.11.0",
6465
"ember-cli-htmlbars": "^5.2.0",
6566
"fs-extra": "^8.0.0",
6667
"fs-merger": "^3.0.2",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// @ts-ignore
2+
import Helper from "@ember/component/helper";
3+
/// @ts-ignore
4+
import { inject as service } from "@ember/service";
5+
6+
interface CSSBlocksService {
7+
classNamesFor(args: Array<string | number | boolean | null>): string;
8+
}
9+
10+
// tslint:disable-next-line:no-default-export
11+
export default class CSSBlocksHelper extends Helper {
12+
@service("css-blocks")
13+
cssBlocks!: CSSBlocksService;
14+
15+
compute(...args: Array<string | number | boolean | null>) {
16+
return this.cssBlocks.classNamesFor(args);
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"extends": "../../../../tsconfig.json",
3+
"compilerOptions": {
4+
"module": "ESNext",
5+
"composite": true,
6+
"outDir": "../dist/runtime",
7+
"baseUrl": ".",
8+
"strict": true,
9+
"sourceMap": false,
10+
"declarationMap": false,
11+
"tsBuildInfoFile": "../runtime.tsbuildinfo",
12+
"paths": {
13+
"@css-blocks/ember/*": ["addon/*"]
14+
},
15+
"traceResolution": false
16+
},
17+
"include": [
18+
"."
19+
],
20+
"exclude": [
21+
]
22+
}

packages/@css-blocks/ember/src/TemplateAnalyzingRewriter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ export class TemplateAnalyzingRewriter implements ASTPluginWithDeps {
221221
}
222222

223223
class HelperInvocationGenerator {
224-
static CLASSNAMES_HELPER = "-cssblocks-";
224+
static CLASSNAMES_HELPER = "-css-blocks";
225225
static HELPER_VERSION = 0;
226226

227227
builders: Syntax["builders"];

packages/@css-blocks/ember/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ const EMBER_ADDON: AddonImplementation<CSSBlocksAddon> = {
196196

197197
init(parent, project) {
198198
this._super.init.call(this, parent, project);
199+
this.treePaths.app = "../runtime/app";
200+
this.treePaths.addon = "../runtime/addon";
199201
},
200202

201203
findSiblingAddon(name) {

packages/@css-blocks/ember/src/types/broccoli-persistent-filter/index.d.ts

-7
This file was deleted.

packages/@css-blocks/ember/src/types/ember-cli/index.d.ts

+17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
declare module 'ember-cli/lib/broccoli/ember-app' {
2+
import { Node as BroccoliNode } from 'broccoli-node-api';
23
import CoreObject from 'core-object';
34
import Project from 'ember-cli/lib/models/project';
45

@@ -7,6 +8,7 @@ declare module 'ember-cli/lib/broccoli/ember-app' {
78
name: string;
89
project: Project;
910
isProduction: boolean;
11+
addonTree(): BroccoliNode;
1012
}
1113
}
1214

@@ -340,6 +342,21 @@ declare module 'ember-cli/lib/models/addon' {
340342
* This method is called when the addon is included in a build. You would typically use this hook to perform additional imports.
341343
*/
342344
included(includer: Project | Addon): void;
345+
/**
346+
* This structure represents the paths to use to use when `treeFor(TreeType)` is called, the paths are relative to the addon's own `this.root`.
347+
*/
348+
treePaths: {
349+
app: string;
350+
styles: string;
351+
templates: string;
352+
addon: string;
353+
'addon-styles': string;
354+
'addon-templates': string;
355+
vendor: string;
356+
'test-support': string;
357+
'addon-test-support': string;
358+
public: string;
359+
}
343360
}
344361
}
345362

private-packages/fixtures-ember-v2/ember-app/app/app.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,22 @@ import Resolver from './resolver';
33
import loadInitializers from 'ember-load-initializers';
44
import config from './config/environment';
55

6+
const dependencies = {
7+
services: [
8+
'css-blocks',
9+
]
10+
};
11+
12+
const engines = {
13+
'@cssBlocksFixturesV2/emberEngine': { dependencies },
14+
'@cssBlocksFixturesV2/emberLazyEngine': { dependencies },
15+
}
16+
617
const App = Application.extend({
718
modulePrefix: config.modulePrefix,
819
podModulePrefix: config.podModulePrefix,
9-
Resolver
20+
Resolver,
21+
engines,
1022
});
1123

1224
loadInitializers(App, config.modulePrefix);

private-packages/fixtures-ember-v2/ember-app/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"test": "tests"
1212
},
1313
"scripts": {
14-
"build": "ember build",
15-
"start": "ember serve",
14+
"build": "yarn pretest && ember build",
15+
"start": "yarn pretest && ember serve",
1616
"pretest": "cd ../../../packages/@css-blocks/ember && yarn compile && cd ../ember-app && yarn compile",
1717
"test": "ember test",
1818
"clean:debug": "rm -rf DEBUG"
@@ -31,7 +31,6 @@
3131
"@ember/jquery": "^0.6.0",
3232
"@ember/optional-features": "^0.7.0",
3333
"broccoli-asset-rev": "^3.0.0",
34-
"broccoli-plugin": "^4.0.0",
3534
"ember-ajax": "^5.0.0",
3635
"ember-cli": "~3.17.0",
3736
"ember-cli-app-version": "^3.2.0",

0 commit comments

Comments
 (0)