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