UNPKG

3.19 kBJavaScriptView Raw
1const path = require('path');
2const fs = require('fs');
3const _ = require('lodash');
4const CachingWriter = require('broccoli-caching-writer');
5const mkdirp = require('mkdirp');
6const validateAssets = require('./validate-assets');
7const svgDataFor = require('./utils/svg-data-for');
8const { filePathsOnlyFor, idGenPathFor } = require('./utils/filepath');
9
10function svgSizeFor(svgAttrs) {
11 let [, , vbWidth, vgHeight] = (svgAttrs.viewBox || '').split(/\s+/);
12
13 return {
14 width: parseFloat(svgAttrs.width || vbWidth) || null,
15 height: parseFloat(svgAttrs.height || vgHeight) || null
16 };
17}
18
19function stringSizeInKb(string) {
20 let bytes = Buffer.byteLength(string, 'utf8');
21 return parseFloat((bytes / 1024).toFixed(2));
22}
23
24function ViewerAssetsBuilder(inputNode, options = {}) {
25 if (!options.outputFile) {
26 throw new Error('the outputFile option is required');
27 }
28
29 CachingWriter.call(this, [inputNode], {
30 name: 'ViewerAssetsBuilder',
31 annotation: options.annotation,
32 });
33
34 this.options = options;
35}
36
37ViewerAssetsBuilder.prototype = Object.create(CachingWriter.prototype);
38ViewerAssetsBuilder.prototype.constructor = ViewerAssetsBuilder;
39
40ViewerAssetsBuilder.prototype.build = function() {
41 let { strategy, ui } = this.options;
42 let inputPath = this.inputPaths[0];
43 let assets = this.getAssets(
44 filePathsOnlyFor(this.listFiles()), inputPath, this.options
45 );
46
47 if (ui) {
48 validateAssets(assets, strategy, ui);
49 }
50
51 let viewerItems = this.viewerItemsFor(assets, inputPath, this.options);
52 let outputFilePath = path.join(this.outputPath, this.options.outputFile);
53 mkdirp.sync(path.dirname(outputFilePath));
54 fs.writeFileSync(outputFilePath, JSON.stringify(viewerItems));
55};
56
57ViewerAssetsBuilder.prototype.viewerItemsFor = function(assets, inputPath, options) {
58 let { strategy, copypastaGen } = options;
59
60 return assets.map((asset) => {
61 let { width, height } = svgSizeFor(asset.svgData.attrs);
62 let originalFilePath = path.join(inputPath, '__original__', asset.relativePath);
63 let originalSvg = fs.readFileSync(originalFilePath, 'UTF-8');
64
65 return {
66 svg: asset.svgData,
67 originalSvg,
68 width,
69 height,
70 fileName: path.basename(asset.relativePath),
71 fileDir: path.dirname(asset.relativePath).replace('.', '/'),
72 fileSize: `${stringSizeInKb(originalSvg)} KB`,
73 optimizedFileSize: `${stringSizeInKb(asset.optimizedSvg)} KB`,
74 baseSize: _.isNull(height) ? 'unknown' : `${height}px`,
75 fullBaseSize: `${width}x${height}px`,
76 copypasta: copypastaGen(asset.id),
77 strategy
78 };
79 });
80};
81
82ViewerAssetsBuilder.prototype.getAssets = function(filePaths, inputPath, options) {
83 let { stripPath, idGen, idGenOpts } = options;
84
85 return _(filePaths)
86 .filter((filePath) => filePath.indexOf('__original__') === -1)
87 .map((filePath) => {
88 let svg = fs.readFileSync(filePath, 'UTF-8');
89
90 return {
91 id: idGen(idGenPathFor(filePath, inputPath, stripPath), idGenOpts),
92 svgData: svgDataFor(svg),
93 optimizedSvg: svg,
94 relativePath: filePath.replace(`${inputPath}${path.sep}`, '')
95 };
96 })
97 .value();
98};
99
100module.exports = ViewerAssetsBuilder;