UNPKG

6.24 kBJavaScriptView Raw
1'use strict';
2
3var fs = require('fs');
4var path = require('path');
5var _ = require('lodash');
6var Funnel = require('broccoli-funnel');
7var MergeTrees = require('broccoli-merge-trees');
8var SVGOptimizer = require('broccoli-svg-optimizer');
9var Symbolizer = require('broccoli-symbolizer');
10var InlinePacker = require('./inline-packer');
11var ViewerAssetsBuilder = require('./viewer-assets-builder');
12var ViewerBuilder = require('./viewer-builder');
13var validateOptions = require('./validate-options');
14var defaultGenerators = require('./default-generators');
15
16// GLOBAL_OPTIONS can be defined as both a root or strategy specific option.
17var GLOBAL_OPTIONS = ['sourceDirs', 'stripPath', 'optimizer'];
18
19var symbolsLoaderScript = fs.readFileSync(path.join(__dirname, '../symbols-loader.html'), 'utf8');
20
21function mergeTreesIfNeeded(trees, options) {
22 return trees.length === 1 ? trees[0] : new MergeTrees(trees, options);
23}
24
25function memoize(fn) {
26 var cache = {};
27
28 return function () {
29 var cacheKey = JSON.stringify(arguments);
30 cache[cacheKey] = cache[cacheKey] || fn.apply(this, arguments);
31 return cache[cacheKey];
32 };
33}
34
35module.exports = {
36 name: 'ember-svg-jar',
37
38 isDevelopingAddon: function isDevelopingAddon() {
39 return false;
40 },
41 included: function included(app) {
42 this._super.included.apply(this, arguments);
43
44 // see: https://github.com/ember-cli/ember-cli/issues/3718
45 if (typeof app.import !== 'function' && app.app) {
46 // eslint-disable-next-line no-param-reassign
47 app = app.app;
48 }
49
50 this.initializeOptions(app.options.svgJar, app.env);
51 },
52 treeForPublic: function treeForPublic() {
53 var trees = [];
54
55 if (this.options.viewer.enabled) {
56 trees.push(this.getViewerTree());
57
58 if (this.options.viewer.embed) {
59 trees.push(this._super.treeForPublic.apply(this, arguments));
60 }
61 }
62
63 if (this.hasSymbolStrategy()) {
64 trees.push(this.getSymbolStrategyTree());
65 }
66
67 return mergeTreesIfNeeded(trees);
68 },
69 treeForApp: function treeForApp(appTree) {
70 var trees = [appTree];
71
72 if (this.hasInlineStrategy()) {
73 trees.push(this.getInlineStrategyTree());
74 }
75
76 return mergeTreesIfNeeded(trees, { overwrite: true });
77 },
78 contentFor: function contentFor(type) {
79 var includeLoader = this.hasSymbolStrategy() && this.optionFor('symbol', 'includeLoader');
80
81 if (type === 'body' && includeLoader) {
82 return symbolsLoaderScript.replace('{{FILE_PATH}}', this.optionFor('symbol', 'outputFile'));
83 }
84
85 return '';
86 },
87 initializeOptions: function initializeOptions(options, env) {
88 this.options = _.merge({
89 sourceDirs: ['public'],
90 strategy: 'inline',
91 stripPath: true,
92 optimizer: {},
93 persist: true,
94
95 viewer: {
96 enabled: env === 'development',
97 embed: env === 'development'
98 },
99
100 inline: {
101 idGen: defaultGenerators.inlineIdGen,
102 copypastaGen: defaultGenerators.inlineCopypastaGen
103 },
104
105 symbol: {
106 idGen: defaultGenerators.symbolIdGen,
107 copypastaGen: defaultGenerators.symbolCopypastaGen,
108 outputFile: '/assets/symbols.svg',
109 prefix: '',
110 includeLoader: true
111 }
112 }, options || {});
113
114 validateOptions(this.options);
115 this.options.strategy = _.castArray(this.options.strategy);
116 },
117 optionFor: function optionFor(strategy, optionName) {
118 return _.isUndefined(this.options[strategy][optionName]) ? GLOBAL_OPTIONS.indexOf(optionName) !== -1 && this.options[optionName] : this.options[strategy][optionName];
119 },
120 sourceDirsFor: function sourceDirsFor(strategy) {
121 return this.optionFor(strategy, 'sourceDirs').filter(function (sourceDir) {
122 return fs.existsSync(sourceDir);
123 });
124 },
125
126
127 optimizedSvgsFor: memoize(function (strategy) {
128 var sourceDirs = this.sourceDirsFor(strategy);
129 var svgFiles = new Funnel(mergeTreesIfNeeded(sourceDirs), {
130 include: ['**/*.svg']
131 });
132
133 var svgoConfig = this.optionFor(strategy, 'optimizer');
134 if (svgoConfig) {
135 svgFiles = new SVGOptimizer(svgFiles, {
136 svgoConfig: svgoConfig,
137 persist: this.options.persist
138 });
139 }
140
141 return svgFiles;
142 }),
143
144 originalSvgsFor: function originalSvgsFor(strategy) {
145 var sourceDirs = this.sourceDirsFor(strategy);
146
147 return new Funnel(mergeTreesIfNeeded(sourceDirs), {
148 include: ['**/*.svg'],
149 destDir: '__original__'
150 });
151 },
152 getViewerTree: function getViewerTree() {
153 var _this = this;
154
155 var idGenOpts = {
156 symbol: {
157 prefix: this.optionFor('symbol', 'prefix')
158 }
159 };
160
161 var viewerBuilderNodes = this.options.strategy.map(function (strategy) {
162 var inputNode = new MergeTrees([_this.optimizedSvgsFor(strategy), _this.originalSvgsFor(strategy)]);
163
164 return new ViewerAssetsBuilder(inputNode, {
165 strategy: strategy,
166 idGen: _this.optionFor(strategy, 'idGen'),
167 idGenOpts: idGenOpts[strategy],
168 copypastaGen: _this.optionFor(strategy, 'copypastaGen'),
169 stripPath: _this.optionFor(strategy, 'stripPath'),
170 outputFile: strategy + '.json',
171 ui: _this.ui
172 });
173 });
174
175 return new ViewerBuilder(mergeTreesIfNeeded(viewerBuilderNodes), {
176 outputFile: 'svg-jar.json',
177 hasManyStrategies: this.options.strategy.length > 1
178 });
179 },
180 getInlineStrategyTree: function getInlineStrategyTree() {
181 return new InlinePacker(this.optimizedSvgsFor('inline'), {
182 idGen: this.optionFor('inline', 'idGen'),
183 stripPath: this.optionFor('inline', 'stripPath'),
184 outputFile: 'inline-assets.js'
185 });
186 },
187 getSymbolStrategyTree: function getSymbolStrategyTree() {
188 return new Symbolizer(this.optimizedSvgsFor('symbol'), {
189 idGen: this.optionFor('symbol', 'idGen'),
190 stripPath: this.optionFor('symbol', 'stripPath'),
191 outputFile: this.optionFor('symbol', 'outputFile'),
192 prefix: this.optionFor('symbol', 'prefix'),
193 persist: this.options.persist
194 });
195 },
196 hasInlineStrategy: function hasInlineStrategy() {
197 return this.options.strategy.indexOf('inline') !== -1;
198 },
199 hasSymbolStrategy: function hasSymbolStrategy() {
200 return this.options.strategy.indexOf('symbol') !== -1;
201 }
202};
\No newline at end of file