1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | var __importStar = (this && this.__importStar) || function (mod) {
|
6 | if (mod && mod.__esModule) return mod;
|
7 | var result = {};
|
8 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
9 | result["default"] = mod;
|
10 | return result;
|
11 | };
|
12 | const EyeglassCompiler = require("broccoli-eyeglass");
|
13 | const Eyeglass = require("eyeglass");
|
14 | const findHost_1 = __importDefault(require("./findHost"));
|
15 | const MergeTrees = require("broccoli-merge-trees");
|
16 | const path = __importStar(require("path"));
|
17 | const cloneDeep = require("lodash.clonedeep");
|
18 | const defaultsDeep = require("lodash.defaultsdeep");
|
19 | const broccoli_ln_s_1 = require("./broccoli-ln-s");
|
20 | const debugGenerator = require("debug");
|
21 | const url_1 = require("url");
|
22 | const debug = debugGenerator("ember-cli-eyeglass");
|
23 | const debugSetup = debug.extend("setup");
|
24 | const debugBuild = debug.extend("build");
|
25 | const debugCache = debug.extend("cache");
|
26 | const debugAssets = debug.extend("assets");
|
27 | const g = global;
|
28 | if (!g.EYEGLASS) {
|
29 | g.EYEGLASS = {
|
30 | infoPerAddon: new WeakMap(),
|
31 | infoPerApp: new WeakMap(),
|
32 | projectInfo: {
|
33 | apps: []
|
34 | }
|
35 | };
|
36 | }
|
37 | const EYEGLASS_INFO_PER_ADDON = g.EYEGLASS.infoPerAddon;
|
38 | const EYEGLASS_INFO_PER_APP = g.EYEGLASS.infoPerApp;
|
39 | const APPS = g.EYEGLASS.projectInfo.apps;
|
40 |
|
41 | function isLazyEngine(addon) {
|
42 | if (addon.lazyLoading === true) {
|
43 |
|
44 | return true;
|
45 | }
|
46 | if (addon.lazyLoading && addon.lazyLoading.enabled === true) {
|
47 | return true;
|
48 | }
|
49 | return false;
|
50 | }
|
51 |
|
52 | function getDefaultAssetHttpPrefix(parent) {
|
53 |
|
54 |
|
55 |
|
56 | let current = parent;
|
57 | while (current.parent) {
|
58 | if (isLazyEngine(current)) {
|
59 |
|
60 | return `engines-dist/${current.name}/assets`;
|
61 | }
|
62 | current = current.parent;
|
63 | }
|
64 |
|
65 | return 'assets';
|
66 | }
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | function localEyeglassAddons(addon) {
|
78 | let paths = new Array();
|
79 | if (typeof addon.addons !== 'object' ||
|
80 | typeof addon.addonPackages !== 'object') {
|
81 | return paths;
|
82 | }
|
83 | let packages = Object.keys(addon.addonPackages);
|
84 | for (let i = 0; i < packages.length; i++) {
|
85 | let p = addon.addonPackages[packages[i]];
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 | if (p.pkg.keywords.some(kw => kw == 'eyeglass-module')) {
|
92 | paths.push({ path: p.path });
|
93 | }
|
94 | }
|
95 |
|
96 | for (let i = 0; i < addon.addons.length; i++) {
|
97 | paths = paths.concat(localEyeglassAddons(addon.addons[i]));
|
98 | }
|
99 | return paths;
|
100 | }
|
101 | const EMBER_CLI_EYEGLASS = {
|
102 | name: require("../package.json").name,
|
103 | included(parent) {
|
104 | this._super.included.apply(this, arguments);
|
105 | this.initSelf();
|
106 | },
|
107 | initSelf() {
|
108 | if (EYEGLASS_INFO_PER_ADDON.has(this))
|
109 | return;
|
110 | let app = findHost_1.default(this);
|
111 | if (!app)
|
112 | return;
|
113 | let isApp = (this.app === app);
|
114 | let name = app.name;
|
115 | if (!isApp) {
|
116 | let thisName = typeof this.parent.name === "function" ? this.parent.name() : this.parent.name;
|
117 | name = `${name}/${thisName}`;
|
118 | }
|
119 | let parentPath = this.parent.root;
|
120 | debugSetup("Initializing %s with eyeglass support for %s at %s", isApp ? "app" : "addon", name, parentPath);
|
121 | if (isApp) {
|
122 | APPS.push(app);
|
123 |
|
124 |
|
125 |
|
126 |
|
127 | EYEGLASS_INFO_PER_APP.set(app, {
|
128 | sessionCache: new Map(),
|
129 | assets: new broccoli_ln_s_1.BroccoliSymbolicLinker({}, { annotation: app.name, persistentOutput: true })
|
130 | });
|
131 | }
|
132 | let addonInfo = { isApp, name, parentPath, app };
|
133 | EYEGLASS_INFO_PER_ADDON.set(this, addonInfo);
|
134 | },
|
135 | postBuild(_result) {
|
136 | debugBuild("Build Succeeded.");
|
137 | this._resetCaches();
|
138 | },
|
139 | _resetCaches() {
|
140 | debugCache("clearing eyeglass global cache");
|
141 | Eyeglass.resetGlobalCaches();
|
142 | for (let app of APPS) {
|
143 | let appInfo = EYEGLASS_INFO_PER_APP.get(app);
|
144 | appInfo.assets.reset();
|
145 | debugCache("clearing %d cached items from the eyeglass build cache for %s", appInfo.sessionCache.size, app.name);
|
146 | appInfo.sessionCache.clear();
|
147 | }
|
148 | },
|
149 | buildError(_error) {
|
150 | debugBuild("Build Failed.");
|
151 | this._resetCaches();
|
152 | },
|
153 | postprocessTree(type, tree) {
|
154 | let addonInfo = EYEGLASS_INFO_PER_ADDON.get(this);
|
155 | if (type === "all" && addonInfo.isApp) {
|
156 | debugBuild("Merging eyeglass asset tree with the '%s' tree", type);
|
157 | let appInfo = EYEGLASS_INFO_PER_APP.get(addonInfo.app);
|
158 | return new MergeTrees([tree, appInfo.assets], { overwrite: true });
|
159 | }
|
160 | else {
|
161 | return tree;
|
162 | }
|
163 | },
|
164 | setupPreprocessorRegistry(type, registry) {
|
165 | let addon = this;
|
166 | registry.add('css', {
|
167 | name: 'eyeglass',
|
168 | ext: 'scss',
|
169 | toTree: (tree, inputPath, outputPath) => {
|
170 |
|
171 | let cssDir = outputPath.slice(1) || './';
|
172 | let sassDir = inputPath.slice(1) || './';
|
173 | let { app, name } = EYEGLASS_INFO_PER_ADDON.get(this);
|
174 | let extracted = this.extractConfig(app, addon);
|
175 | extracted.cssDir = cssDir;
|
176 | extracted.sassDir = sassDir;
|
177 | const config = this.setupConfig(extracted);
|
178 | debugSetup("Broccoli Configuration for %s: %O", name, config);
|
179 | let httpRoot = config.eyeglass && config.eyeglass.httpRoot || "/";
|
180 | let compiler = new EyeglassCompiler(tree, config);
|
181 | compiler.events.on("cached-asset", (absolutePathToSource, httpPathToOutput) => {
|
182 | debugBuild("will symlink %s to %s", absolutePathToSource, httpPathToOutput);
|
183 | try {
|
184 | this.linkAsset(absolutePathToSource, httpRoot, httpPathToOutput);
|
185 | }
|
186 | catch (e) {
|
187 |
|
188 | }
|
189 | });
|
190 | return compiler;
|
191 | }
|
192 | });
|
193 | },
|
194 | extractConfig(host, addon) {
|
195 | const isNestedAddon = typeof addon.parent.parent === 'object';
|
196 |
|
197 | const hostConfig = cloneDeep(host.options.eyeglass || {});
|
198 | const addonConfig = isNestedAddon ? cloneDeep(addon.parent.options.eyeglass || {}) : {};
|
199 | return defaultsDeep(addonConfig, hostConfig);
|
200 | },
|
201 | linkAsset(srcFile, httpRoot, destUri) {
|
202 | let rootPath = httpRoot.startsWith("/") ? httpRoot.substring(1) : httpRoot;
|
203 | let destPath = destUri.startsWith("/") ? destUri.substring(1) : destUri;
|
204 | if (process.platform === "win32") {
|
205 | destPath = convertURLToPath(destPath);
|
206 | rootPath = convertURLToPath(rootPath);
|
207 | }
|
208 | if (destPath.startsWith(rootPath)) {
|
209 | destPath = path.relative(rootPath, destPath);
|
210 | }
|
211 | let { app } = EYEGLASS_INFO_PER_ADDON.get(this);
|
212 | let { assets } = EYEGLASS_INFO_PER_APP.get(app);
|
213 | debugAssets("Will link asset %s to %s to expose it at %s relative to %s", srcFile, destPath, destUri, httpRoot);
|
214 | return assets.ln_s(srcFile, destPath);
|
215 | },
|
216 | setupConfig(config, options) {
|
217 | let { isApp, app, parentPath } = EYEGLASS_INFO_PER_ADDON.get(this);
|
218 | let { sessionCache } = EYEGLASS_INFO_PER_APP.get(app);
|
219 | config.sessionCache = sessionCache;
|
220 | config.annotation = `EyeglassCompiler(${parentPath})`;
|
221 | if (!config.sourceFiles && !config.discover) {
|
222 | config.sourceFiles = [isApp ? 'app.scss' : 'addon.scss'];
|
223 | }
|
224 | config.assets = ['public', 'app'].concat(config.assets || []);
|
225 | config.eyeglass = config.eyeglass || {};
|
226 |
|
227 |
|
228 | config.eyeglass.httpRoot = config.eyeglass.httpRoot || config["httpRoot"];
|
229 | if (config.persistentCache) {
|
230 | let cacheDir = parentPath.replace(/\//g, "$");
|
231 | config.persistentCache += `/${cacheDir}`;
|
232 | }
|
233 | config.assetsHttpPrefix = config.assetsHttpPrefix || getDefaultAssetHttpPrefix(this.parent);
|
234 | if (config.eyeglass.modules) {
|
235 | config.eyeglass.modules =
|
236 | config.eyeglass.modules.concat(localEyeglassAddons(this.parent));
|
237 | }
|
238 | else {
|
239 | config.eyeglass.modules = localEyeglassAddons(this.parent);
|
240 | }
|
241 | let originalConfigureEyeglass = config.configureEyeglass;
|
242 | config.configureEyeglass = (eyeglass, sass, details) => {
|
243 | eyeglass.assets.installer((file, uri, fallbackInstaller, cb) => {
|
244 | try {
|
245 | cb(null, this.linkAsset(file, eyeglass.options.eyeglass.httpRoot || "/", uri));
|
246 | }
|
247 | catch (e) {
|
248 | cb(e);
|
249 | }
|
250 | });
|
251 | if (originalConfigureEyeglass) {
|
252 | originalConfigureEyeglass(eyeglass, sass, details);
|
253 | }
|
254 | };
|
255 |
|
256 |
|
257 | let originalGenerator = config.optionsGenerator;
|
258 | config.optionsGenerator = (sassFile, cssFile, sassOptions, compilationCallback) => {
|
259 | if (isApp) {
|
260 | cssFile = cssFile.replace(/app\.css$/, `${this.app.name}.css`);
|
261 | }
|
262 | else {
|
263 | cssFile = cssFile.replace(/addon\.css$/, `${this.parent.name}.css`);
|
264 | }
|
265 | if (originalGenerator) {
|
266 | originalGenerator(sassFile, cssFile, sassOptions, compilationCallback);
|
267 | }
|
268 | else {
|
269 | compilationCallback(cssFile, sassOptions);
|
270 | }
|
271 | };
|
272 | return config;
|
273 | }
|
274 | };
|
275 | function convertURLToPath(fragment) {
|
276 | return (new url_1.URL(`file://${fragment}`)).pathname;
|
277 | }
|
278 | module.exports = EMBER_CLI_EYEGLASS;
|
279 |
|
\ | No newline at end of file |