/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * * @format */ "use strict"; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } const AssetPaths = require("./lib/AssetPaths"); const MapWithDefaults = require("./lib/MapWithDefaults"); /** * Lazily build an index of assets for the directories in which we're looking * for specific assets. For example if we're looking for `foo.png` in a `bar` * directory, we'll look at all the files there and identify all the assets * related to `foo.png`, for example `foo@2x.png` and `foo.ios.png`. */ class AssetResolutionCache { constructor(options) { _defineProperty(this, "_findAssets", dirPath => { const results = new Map(); const fileNames = this._opts.getDirFiles(dirPath); for (let i = 0; i < fileNames.length; ++i) { const fileName = fileNames[i]; const assetData = AssetPaths.tryParse(fileName, this._opts.platforms); if (assetData == null || !this._isValidAsset(assetData)) { continue; } getWithDefaultArray(results, assetData.assetName).push({ fileName, platform: assetData.platform }); if (assetData.platform) { const assetNameWithPlatform = `${assetData.name}.${ assetData.platform }.${assetData.type}`; getWithDefaultArray(results, assetNameWithPlatform).push({ fileName, platform: null }); } } return results; }); this._assetsByDirPath = new MapWithDefaults(this._findAssets); this._opts = options; } /** * The cache needs to be emptied if any file changes. This could be made more * selective if performance demands it: for example, we could clear * exclusively the directories in which files have changed. But that'd be * more error-prone. */ clear() { this._assetsByDirPath.clear(); } /** * Get the file paths of all the variants (resolutions, platforms, etc.) of a * particular asset name, only looking at a specific directory. If needed this * function could be changed to return pre-parsed information about the assets * such as the resolution. */ resolve(dirPath, assetName, platform) { const results = this._assetsByDirPath.get(dirPath); const assets = results.get(assetName); if (assets == null) { return null; } return assets .filter(asset => asset.platform == null || asset.platform === platform) .map(asset => asset.fileName); } /** * Build an index of assets for a particular directory. Several file can * fulfill a single asset name, for example the different resolutions or * platforms: ex. `foo.png` could contain `foo@2x.png`, `foo.ios.js`, etc. */ _isValidAsset(assetData) { return this._opts.assetExtensions.has(assetData.type); } } /** * Used instead of `MapWithDefaults` so that we don't create empty arrays * anymore once the index is built. */ function getWithDefaultArray(map, key) { let el = map.get(key); if (el != null) { return el; } el = []; map.set(key, el); return el; } module.exports = AssetResolutionCache;