UNPKG

eyeglass

Version:
256 lines 10.5 kB
"use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const debug = __importStar(require("../util/debug")); const SassImplementation_1 = require("../util/SassImplementation"); const URI_1 = require("../util/URI"); const AssetsCollection_1 = __importDefault(require("./AssetsCollection")); const typescriptUtils_1 = require("../util/typescriptUtils"); const errorFor_1 = __importDefault(require("../util/errorFor")); /* eslint-disable-next-line @typescript-eslint/no-var-requires */ const ensureSymlink = require("ensure-symlink"); class Assets { constructor(eyeglass, sassImpl) { this.sassImpl = sassImpl; this.eyeglass = eyeglass; // create a master collection this.collection = new AssetsCollection_1.default(eyeglass.options); // and keep a list of module collections this.moduleCollections = []; } /** * @see AssetsCollection#asAssetImport */ asAssetImport(name) { return this.collection.asAssetImport(name); } /** * @see AssetsCollection#addSource */ addSource(src, opts) { return this.collection.addSource(src, opts); } /** * @see AssetsCollection#cacheKey */ cacheKey(name) { return this.collection.cacheKey(name); } /** * creates a new AssetsCollection and adds the given source * @see #addSource * @param {String} src - the source directory * @param {Object} opts - the options * @returns {AssetsCollection} the instance of the AssetsCollection */ export(src, opts) { let assets = new AssetsCollection_1.default(this.eyeglass.options); this.moduleCollections.push(assets); return assets.addSource(src, opts); } /** * resolves an asset given a uri * @param {SassMap} $assetsMap - the map of registered Sass assets * @param {SassString} $uri - the uri of the asset * @param {Function} cb - the callback that is invoked when the asset resolves */ resolveAsset($assetsMap, $uri, cb) { let sass = this.eyeglass.options.eyeglass.engines.sass; let options = this.eyeglass.options.eyeglass; let assets = this.eyeglass.assets; if (!SassImplementation_1.isType(sass, $uri, "string")) { cb(new SassImplementation_1.SassTypeError(sass, "string", $uri)); return; } // get a URI instance let originalUri = $uri.getValue(); let uri = new URI_1.URI(originalUri); // normalize the uri and resolve it let $data = this.resolveAssetDefaults($assetsMap, uri.getPath()); if ($data) { let filepath; let assetUri; for (let i = 0; i < $data.getLength(); i++) { let k = $data.getKey(i).getValue(); let v = $data.getValue(i).getValue(); if (k === "filepath") { filepath = v; } else if (k === "uri") { assetUri = v; } } // create the URI let fullUri = URI_1.URI.join(options.httpRoot, options.assets.httpPrefix, assetUri); assets.resolve(filepath, fullUri, function (error, assetInfo) { if (error || !typescriptUtils_1.isPresent(assetInfo)) { cb(errorFor_1.default(error, "Unable to resolve asset")); } else { // if relativeTo is set if (options.assets.relativeTo) { // make the URI relative to the httpRoot + relativeTo path uri.setPath(path.relative(URI_1.URI.join(options.httpRoot, options.assets.relativeTo), assetInfo.path)); } else { // otherwise, just update it to the path as is uri.setPath(assetInfo.path); } // if a query param was specified, append it to the uri query if (assetInfo.query) { uri.addQuery(assetInfo.query); } assets.install(filepath, assetInfo.path, function (error, file) { if (error) { cb(errorFor_1.default(error, "Unable to install asset")); } else { if (file) { /* istanbul ignore next - don't test debug */ debug.assets && debug.assets("%s resolved to %s with URI %s", originalUri, path.relative(options.root, file), uri.toString()); } cb(null, uri.toString(), file); } }); } }); } else { cb(new Error("Asset not found: " + uri.getPath())); } } /** * resolves the asset uri * @param {String} assetFile - the source file path * @param {String} assetUri - the resolved uri path * @param {Function} cb - the callback to pass the resolved uri to */ resolve(_assetFile, assetUri, cb) { cb(null, { path: assetUri }); } /** * wraps the current resolver with a custom resolver * @param {Function} resolver - the new resolver function */ resolver(resolver) { let oldResolver = this.resolve.bind(this); this.resolve = function (assetFile, assetUri, cb) { resolver(assetFile, assetUri, oldResolver, cb); }; } /** * installs the given asset * @param {String} file - the source file path to install from * @param {String} uri - the resolved uri path * @param {Function} cb - the callback invoked after the installation is successful */ install(file, uri, cb) { let options = this.eyeglass.options.eyeglass; let httpRoot = options.httpRoot; if (options.buildDir) { // normalize the uri using the system OS path separator // and make it relative to the httpRoot uri = (new URI_1.URI(uri)).getPath(path.sep, httpRoot); let dest = path.join(options.buildDir, uri); this.eyeglass.once(`install:${dest}`, () => { try { if (options.installWithSymlinks) { fs.mkdirpSync(path.dirname(dest)); ensureSymlink(file, dest); debug.assets && debug.assets("symlinked %s to %s", file, dest); } else { // we explicitly use copySync rather than copy to avoid starving system resources fs.copySync(file, dest); debug.assets && debug.assets("copied %s to %s", file, dest); } cb(null, dest); } catch (error) { cb(errorFor_1.default(error, `Failed to install asset from ${file}:\n`)); } }, () => { cb(null, dest); }); } else { cb(null, file); } } /** * wraps the current installer with a custom installer * @param {Function} installer - the new installer function */ installer(installer) { let oldInstaller = this.install.bind(this); this.install = function (assetFile, assetUri, cb) { installer(assetFile, assetUri, oldInstaller, cb); }; } // need types for sass utils // eslint-disable-next-line @typescript-eslint/no-explicit-any resolveAssetDefaults($registeredAssetsMap, relativePath) { let appAssets; let moduleAssets; let moduleName, moduleRelativePath; let slashAt = relativePath.indexOf("/"); if (slashAt > 0) { moduleName = relativePath.substring(0, slashAt); moduleRelativePath = relativePath.substring(slashAt + 1); } let size = $registeredAssetsMap.getLength(); for (let i = 0; i < size; i++) { let k = $registeredAssetsMap.getKey(i); if (k === this.sassImpl.types.Null.NULL) { let v = $registeredAssetsMap.getValue(i); if (SassImplementation_1.isSassMap(this.sassImpl, v)) { appAssets = v; } } else if (SassImplementation_1.isSassString(this.sassImpl, k) && k.getValue() === moduleName) { let v = $registeredAssetsMap.getValue(i); if (SassImplementation_1.isSassMap(this.sassImpl, v)) { moduleAssets = v; } } } if (appAssets) { let size = appAssets.getLength(); for (let i = 0; i < size; i++) { let k = appAssets.getKey(i); if (SassImplementation_1.isSassString(this.sassImpl, k) && k.getValue() === relativePath) { let v = appAssets.getValue(i); if (SassImplementation_1.isSassMap(this.sassImpl, v)) { return v; } } } } if (moduleAssets) { let size = moduleAssets.getLength(); for (let i = 0; i < size; i++) { let k = moduleAssets.getKey(i); if (SassImplementation_1.isSassString(this.sassImpl, k) && k.getValue() === moduleRelativePath) { let v = moduleAssets.getValue(i); if (SassImplementation_1.isSassMap(this.sassImpl, v)) { return v; } } } } return; } } exports.default = Assets; //# sourceMappingURL=Assets.js.map