UNPKG

eyeglass

Version:
97 lines (88 loc) 3.59 kB
import { existsSync } from "fs"; import type { AsyncImporter } from "node-sass"; import EyeglassModule from "../modules/EyeglassModule"; import { URI } from "../util/URI"; import { ImporterFactory } from "./ImporterFactory"; import ImportUtilities from "./ImportUtilities"; import { ROOT_NAME } from "../modules/EyeglassModules"; import { isPresent } from "../util/typescriptUtils"; interface HasAssets { name?: string; assets?: { asAssetImport: (name: string | undefined) => string; cacheKey: (name: string) => string; }; } // import pattern matches `assets` and `foo/assets`, but not `foo/bar/assets` const rAssetsImport = /^(?:([^/]+)\/)?assets$/; const AssetImporter: ImporterFactory = function (eyeglass, sass, options, fallbackImporter?: AsyncImporter | Array<AsyncImporter>): AsyncImporter { return ImportUtilities.createImporter("assets", function(uri, prev, done) { let importUtils = new ImportUtilities(eyeglass, sass, options, fallbackImporter, this); let isRealFile = existsSync(prev); let mod: EyeglassModule | null; function importAssetsFor(mod: HasAssets): void { let file = "autoGenerated:" + URI.join(mod.name || ROOT_NAME, "assets"); let contents: () => string; function getAssetImport(): string { // XXX what is the correct behavior for when mod.name isn't found? return mod.assets ? mod.assets.asAssetImport(mod.name) : ""; } // allow build tools to specify a function to cache the imports if (isPresent(mod.assets) && isPresent(options.assetsCache)) { contents = options.assetsCache.bind(options.assetsCache, mod.assets.cacheKey(mod.name || ROOT_NAME), getAssetImport); } else { contents = getAssetImport; } importUtils.importOnce({file, contents}, done); } let isRelativeImport = URI.isRelative(uri); let assetsImport = !isRelativeImport && rAssetsImport.exec(uri); // the first fragment of the match is the module name let moduleName = assetsImport && assetsImport[1]; // if it's not an assets import, or it's `eyeglass/assets`, // just use the fallback importer if (!assetsImport) { importUtils.fallback(uri, prev, done, function() { done(null); }); } else { // if the module name wasn't specified in the import, // infer it from the origin if (!moduleName && isRealFile) { mod = eyeglass.modules.findByPath(prev); // if it's an eyeglass module... if (mod && mod.isEyeglassModule) { // use the module's name moduleName = mod.name; } } // if we have a module name... if (moduleName) { // try to access the module mod = eyeglass.modules.access(moduleName, isRealFile ? prev : options.eyeglass.root); // if we can access it... if (mod) { /* eslint max-depth:0 */ // if it has assets... if (mod.assets) { // import them importAssetsFor(mod); } else { // otherwise throw an error done(new Error("No assets specified for eyeglass plugin " + mod.name)); } } else { // if we can't find/access it, throw an error done(new Error("No eyeglass plugin named: " + moduleName)); } } else { // otherwise, import the app assets // TODO: Move app assets to the root module and pass the root eyeglass // module here importAssetsFor(eyeglass); } } }); }; export default AssetImporter;