UNPKG

7.65 kBJavaScriptView Raw
1'use strict';
2
3var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
4
5function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
6
7const URL = require('url');
8const path = require('path');
9const fs = require('./utils/fs');
10const objectHash = require('./utils/objectHash');
11const md5 = require('./utils/md5');
12const isURL = require('./utils/is-url');
13const config = require('./utils/config');
14
15let ASSET_ID = 1;
16
17/**
18 * An Asset represents a file in the dependency tree. Assets can have multiple
19 * parents that depend on it, and can be added to multiple output bundles.
20 * The base Asset class doesn't do much by itself, but sets up an interface
21 * for subclasses to implement.
22 */
23class Asset {
24 constructor(name, pkg, options) {
25 this.id = ASSET_ID++;
26 this.name = name;
27 this.basename = path.basename(this.name);
28 this.relativeName = path.relative(options.rootDir, this.name);
29 this.package = pkg || {};
30 this.options = options;
31 this.encoding = 'utf8';
32 this.type = path.extname(this.name).slice(1);
33
34 this.processed = false;
35 this.contents = options.rendition ? options.rendition.value : null;
36 this.ast = null;
37 this.generated = null;
38 this.hash = null;
39 this.parentDeps = new Set();
40 this.dependencies = new Map();
41 this.depAssets = new Map();
42 this.parentBundle = null;
43 this.bundles = new Set();
44 this.cacheData = {};
45 this.buildTime = 0;
46 this.bundledSize = 0;
47 }
48
49 shouldInvalidate() {
50 return false;
51 }
52
53 loadIfNeeded() {
54 var _this = this;
55
56 return _asyncToGenerator(function* () {
57 if (_this.contents == null) {
58 _this.contents = yield _this.load();
59 }
60 })();
61 }
62
63 parseIfNeeded() {
64 var _this2 = this;
65
66 return _asyncToGenerator(function* () {
67 yield _this2.loadIfNeeded();
68 if (!_this2.ast) {
69 _this2.ast = yield _this2.parse(_this2.contents);
70 }
71 })();
72 }
73
74 getDependencies() {
75 var _this3 = this;
76
77 return _asyncToGenerator(function* () {
78 if (_this3.options.rendition && _this3.options.rendition.hasDependencies === false) {
79 return;
80 }
81
82 yield _this3.loadIfNeeded();
83
84 if (_this3.contents && _this3.mightHaveDependencies()) {
85 yield _this3.parseIfNeeded();
86 yield _this3.collectDependencies();
87 }
88 })();
89 }
90
91 addDependency(name, opts) {
92 this.dependencies.set(name, Object.assign({ name }, opts));
93 }
94
95 addURLDependency(url, from = this.name, opts) {
96 if (!url || isURL(url)) {
97 return url;
98 }
99
100 if (typeof from === 'object') {
101 opts = from;
102 from = this.name;
103 }
104
105 const parsed = URL.parse(url);
106 const resolved = path.resolve(path.dirname(from), parsed.pathname);
107 this.addDependency('./' + path.relative(path.dirname(this.name), resolved), Object.assign({ dynamic: true }, opts));
108
109 parsed.pathname = this.options.parser.getAsset(resolved, this.package, this.options).generateBundleName();
110
111 return URL.format(parsed);
112 }
113
114 getConfig(filenames, opts = {}) {
115 var _this4 = this;
116
117 return _asyncToGenerator(function* () {
118 // Resolve the config file
119 let conf = yield config.resolve(opts.path || _this4.name, filenames);
120 if (conf) {
121 // Add as a dependency so it is added to the watcher and invalidates
122 // this asset when the config changes.
123 _this4.addDependency(conf, { includedInParent: true });
124 if (opts.load === false) {
125 return conf;
126 }
127
128 return yield config.load(opts.path || _this4.name, filenames);
129 }
130
131 return null;
132 })();
133 }
134
135 mightHaveDependencies() {
136 return true;
137 }
138
139 load() {
140 var _this5 = this;
141
142 return _asyncToGenerator(function* () {
143 return yield fs.readFile(_this5.name, _this5.encoding);
144 })();
145 }
146
147 parse() {
148 // do nothing by default
149 }
150
151 collectDependencies() {
152 // do nothing by default
153 }
154
155 pretransform() {
156 // do nothing by default
157
158 return _asyncToGenerator(function* () {})();
159 }
160
161 transform() {
162 // do nothing by default
163
164 return _asyncToGenerator(function* () {})();
165 }
166
167 generate() {
168 var _this6 = this;
169
170 return _asyncToGenerator(function* () {
171 return {
172 [_this6.type]: _this6.contents
173 };
174 })();
175 }
176
177 process() {
178 var _this7 = this;
179
180 return _asyncToGenerator(function* () {
181 if (!_this7.generated) {
182 yield _this7.loadIfNeeded();
183 yield _this7.pretransform();
184 yield _this7.getDependencies();
185 yield _this7.transform();
186 _this7.generated = yield _this7.generate();
187 _this7.hash = yield _this7.generateHash();
188 }
189
190 return _this7.generated;
191 })();
192 }
193
194 postProcess(generated) {
195 return _asyncToGenerator(function* () {
196 return generated;
197 })();
198 }
199
200 generateHash() {
201 return objectHash(this.generated);
202 }
203
204 invalidate() {
205 this.processed = false;
206 this.contents = null;
207 this.ast = null;
208 this.generated = null;
209 this.hash = null;
210 this.dependencies.clear();
211 this.depAssets.clear();
212 }
213
214 invalidateBundle() {
215 this.parentBundle = null;
216 this.bundles.clear();
217 this.parentDeps.clear();
218 }
219
220 generateBundleName() {
221 // Generate a unique name. This will be replaced with a nicer
222 // name later as part of content hashing.
223 return md5(this.name) + '.' + this.type;
224 }
225
226 replaceBundleNames(bundleNameMap) {
227 for (let key in this.generated) {
228 let value = this.generated[key];
229 if (typeof value === 'string') {
230 // Replace temporary bundle names in the output with the final content-hashed names.
231 var _iteratorNormalCompletion = true;
232 var _didIteratorError = false;
233 var _iteratorError = undefined;
234
235 try {
236 for (var _iterator = bundleNameMap[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
237 let _ref = _step.value;
238
239 var _ref2 = _slicedToArray(_ref, 2);
240
241 let name = _ref2[0];
242 let map = _ref2[1];
243
244 value = value.split(name).join(map);
245 }
246 } catch (err) {
247 _didIteratorError = true;
248 _iteratorError = err;
249 } finally {
250 try {
251 if (!_iteratorNormalCompletion && _iterator.return) {
252 _iterator.return();
253 }
254 } finally {
255 if (_didIteratorError) {
256 throw _iteratorError;
257 }
258 }
259 }
260
261 this.generated[key] = value;
262 }
263 }
264 }
265
266 generateErrorMessage(err) {
267 return err;
268 }
269}
270
271module.exports = Asset;
\No newline at end of file