UNPKG

2.82 kBJavaScriptView Raw
1const Parser = require('./Parser');
2const path = require('path');
3const md5 = require('./utils/md5');
4
5/**
6 * A Pipeline composes multiple Asset types together.
7 */
8class Pipeline {
9 constructor(options) {
10 this.options = options;
11 this.parser = new Parser(options);
12 }
13
14 async process(path, pkg, options) {
15 let asset = this.parser.getAsset(path, pkg, options);
16 let generated = await this.processAsset(asset);
17 let generatedMap = {};
18 for (let rendition of generated) {
19 generatedMap[rendition.type] = rendition.value;
20 }
21
22 return {
23 dependencies: Array.from(asset.dependencies.values()),
24 generated: generatedMap,
25 hash: asset.hash,
26 cacheData: asset.cacheData
27 };
28 }
29
30 async processAsset(asset) {
31 try {
32 await asset.process();
33 } catch (err) {
34 throw asset.generateErrorMessage(err);
35 }
36
37 let inputType = path.extname(asset.name).slice(1);
38 let generated = [];
39
40 for (let rendition of this.iterateRenditions(asset)) {
41 let {type, value} = rendition;
42 if (typeof value !== 'string' || rendition.final) {
43 generated.push(rendition);
44 continue;
45 }
46
47 // Find an asset type for the rendition type.
48 // If the asset is not already an instance of this asset type, process it.
49 let AssetType = this.parser.findParser(
50 asset.name.slice(0, -inputType.length) + type
51 );
52 if (!(asset instanceof AssetType)) {
53 let opts = Object.assign({rendition}, asset.options);
54 let subAsset = new AssetType(asset.name, asset.package, opts);
55 subAsset.contents = value;
56 subAsset.dependencies = asset.dependencies;
57
58 let processed = await this.processAsset(subAsset);
59 generated = generated.concat(processed);
60 Object.assign(asset.cacheData, subAsset.cacheData);
61 asset.hash = md5(asset.hash + subAsset.hash);
62 } else {
63 generated.push(rendition);
64 }
65 }
66
67 // Post process. This allows assets a chance to modify the output produced by sub-asset types.
68 asset.generated = generated;
69 try {
70 generated = await asset.postProcess(generated);
71 } catch (err) {
72 throw asset.generateErrorMessage(err);
73 }
74
75 return generated;
76 }
77
78 *iterateRenditions(asset) {
79 if (Array.isArray(asset.generated)) {
80 return yield* asset.generated;
81 }
82
83 if (typeof asset.generated === 'string') {
84 return yield {
85 type: asset.type,
86 value: asset.generated
87 };
88 }
89
90 // Backward compatibility support for the old API.
91 // Assume all renditions are final - don't compose asset types together.
92 for (let type in asset.generated) {
93 yield {
94 type,
95 value: asset.generated[type],
96 final: true
97 };
98 }
99 }
100}
101
102module.exports = Pipeline;