UNPKG

broccoli-eyeglass

Version:
200 lines 8.05 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const broccoli_sass_compiler_1 = __importDefault(require("./broccoli_sass_compiler")); const crypto = require("crypto"); const merge = require("lodash.merge"); const path = require("path"); const sortby = require("lodash.sortby"); const stringify = require("json-stable-stringify"); const debugGenerator = require("debug"); const Eyeglass = require("eyeglass"); const dependencyTree = require("dependency-tree"); const assetImportCacheDebug = debugGenerator("broccoli-eyeglass:asset-import-cache"); const dependencyDebug = debugGenerator("broccoli-eyeglass:file-dependencies"); const CURRENT_VERSION = require(path.join(__dirname, "..", "package.json")).version; function httpJoin(...args) { let joined = []; for (let i = 0; i < args.length; i++) { if (args[i]) { let segment = args[i]; if (path.sep !== "/") { segment = segment.replace(path.sep, "/"); } joined.push(segment); } } let result = joined.join("/"); result = result.replace("///", "/"); result = result.replace("//", "/"); return result; } class EyeglassCompiler extends broccoli_sass_compiler_1.default { constructor(inputTrees, options) { options = merge({}, options); if (!Array.isArray(inputTrees)) { inputTrees = [inputTrees]; } let configureEyeglass, assetDirectories, assetsHttpPrefix; if (options.configureEyeglass) { configureEyeglass = options.configureEyeglass; delete options.configureEyeglass; } let relativeAssets = options.relativeAssets; delete options.relativeAssets; if (options.assets) { assetDirectories = options.assets; if (typeof assetDirectories === "string") { assetDirectories = [assetDirectories]; } delete options.assets; } if (options.assetsHttpPrefix) { assetsHttpPrefix = options.assetsHttpPrefix; delete options.assetsHttpPrefix; } super(inputTrees, options); this.configureEyeglass = configureEyeglass; this.relativeAssets = relativeAssets; this.assetDirectories = assetDirectories; this.assetsHttpPrefix = assetsHttpPrefix; this.events.on("compiling", this.handleNewFile.bind(this)); this._assetImportCacheStats = { hits: 0, misses: 0, }; } handleNewFile(details) { let options = details.options; if (!options.eyeglass) { options.eyeglass = {}; } if ((this.assetsHttpPrefix || this.relativeAssets) && !options.eyeglass.assets) { options.eyeglass.assets = {}; } if (this.assetsHttpPrefix) { options.eyeglass.assets.httpPrefix = this.assetsHttpPrefix; } if (this.relativeAssets) { options.eyeglass.assets.relativeTo = httpJoin(options.eyeglass.httpRoot || "/", path.dirname(details.cssFilename)); } options.assetsCache = this.cacheAssetImports.bind(this); options.eyeglass.buildDir = details.destDir; options.eyeglass.engines = options.eyeglass.engines || {}; options.eyeglass.engines.sass = this.sass; options.eyeglass.installWithSymlinks = true; options.eyeglass.buildCache = this.buildCache; let eyeglass = new Eyeglass(options); if (this.assetDirectories) { for (var i = 0; i < this.assetDirectories.length; i++) { eyeglass.assets.addSource(path.resolve(eyeglass.options.eyeglass.root, this.assetDirectories[i]), { globOpts: { ignore: ["**/*.js", "**/*.s[ac]ss"], }, }); } } if (this.configureEyeglass) { this.configureEyeglass(eyeglass, this.sass, details); } // set up asset dependency tracking eyeglass.assets.resolver((filepath, fullUri, realResolve, cb) => { this.events.emit("dependency", filepath).then(() => { realResolve(filepath, fullUri, cb); }, cb); }); eyeglass.assets.installer((file, uri, realInstall, cb) => { realInstall(file, uri, (error, destFile) => { if (error) { cb(error, file); } else { this.events.emit("additional-output", destFile, uri, file).then(() => { cb(null, file); }, cb); } }); }); details.options = eyeglass.options; details.options.eyeglass.engines.eyeglass = eyeglass; } cachableOptions(rawOptions) { rawOptions = merge({}, rawOptions); delete rawOptions.file; if (rawOptions.eyeglass) { delete rawOptions.eyeglass.engines; delete rawOptions.eyeglass.modules; } return rawOptions; } static currentVersion() { return CURRENT_VERSION; } dependenciesHash(_srcDir, _relativeFilename, options) { if (!this._dependenciesHash) { let eyeglass = new Eyeglass(options); let hash = crypto.createHash("sha1"); hash.update("broccoli-eyeglass@" + EyeglassCompiler.currentVersion()); let egModules = sortby(eyeglass.modules.list, m => m.name); egModules.forEach(mod => { let name = mod.name; if (mod.inDevelopment || mod.eyeglass.inDevelopment) { let depHash = this.hashForJs(mod); hash.update(name + "@" + depHash); } else { let version = mod.version || "<unversioned>"; hash.update(name + "@" + version); } }); this._dependenciesHash = hash.digest("hex"); } return this._dependenciesHash; } keyForSourceFile(srcDir, relativeFilename, options) { let key = super.keyForSourceFile(srcDir, relativeFilename, options); let optsString = stringify(this.cachableOptions(options)); let dependencies = this.dependenciesHash(srcDir, relativeFilename, options); return key + "+" + optsString + "+" + dependencies; } // Cache the asset import code that is generated in eyeglass cacheAssetImports(key, getValue) { // if this has already been generated, return it from cache let assetImportKey = `assetImport(${key})`; let assetImport = this.buildCache.get(assetImportKey); if (assetImport !== undefined) { assetImportCacheDebug("cache hit for key '%s'", key); this._assetImportCacheStats.hits += 1; return assetImport; } assetImportCacheDebug("cache miss for key '%s'", key); this._assetImportCacheStats.misses += 1; assetImport = getValue(); this.buildCache.set(assetImportKey, assetImport); return assetImport; } hashForJs(mod) { let jsPath = mod.mainPath; if (!jsPath) { return ""; } let cacheKey = `hashForJs(${jsPath})`; let cachedHash = this.buildCache.get(cacheKey); if (cachedHash) { return cachedHash; } let files = dependencyTree.toList({ filename: jsPath, directory: path.dirname(jsPath) }); dependencyDebug(`${jsPath} => \n\t${files.join("\n\t")}`); let hash = crypto.createHash("sha1"); for (let file of files) { hash.update(file); hash.update(this.fileKey(file)); } let result = hash.digest("base64"); this.buildCache.set(cacheKey, result); return result; } } module.exports = EyeglassCompiler; //# sourceMappingURL=index.js.map