UNPKG

2.87 kBJavaScriptView Raw
1const Promise = require('bluebird');
2const merge = require('merge-options');
3const FileRequest = require('./request');
4const RuleSet = require('./rules');
5const Sprite = require('./sprite');
6const SpriteSymbol = require('./symbol');
7const symbolFactory = require('./symbol-factory');
8const spriteFactory = require('./sprite-factory');
9
10const defaultConfig = {
11 rules: [
12 { test: /\.svg$/, value: 'sprite.svg' }
13 ],
14 symbolFactory,
15 spriteFactory
16};
17
18class Compiler {
19 static sortSymbols(symbols) {
20 symbols.sort((leftSymbol, rightSymbol) => {
21 const leftId = leftSymbol.id;
22 const rightId = rightSymbol.id;
23
24 if (leftId === rightId) {
25 return 0;
26 }
27 return leftId < rightId ? -1 : 1;
28 });
29
30 return symbols;
31 }
32
33 constructor(cfg = {}) {
34 const config = this.config = merge(defaultConfig, cfg);
35 this.rules = new RuleSet(config.rules);
36 this.symbols = [];
37 }
38
39 /**
40 * @param {string} content
41 * @param {string} path
42 * @param {string} [id]
43 * @return {Promise<SpriteSymbol>}
44 */
45 addSymbol({ path, content, id }) {
46 const symbols = this.symbols;
47 const factory = this.config.symbolFactory;
48 const request = new FileRequest(path);
49 const options = { id, request, content, factory };
50
51 return SpriteSymbol.create(options).then((newSymbol) => {
52 const existing = symbols.find(s => s.request.equals(request));
53
54 if (!existing) {
55 symbols.push(newSymbol);
56 Compiler.sortSymbols(symbols);
57 return newSymbol;
58 }
59
60 const existingIndex = existing ? symbols.indexOf(existing) : -1;
61 const allExceptCurrent = symbols
62 .filter(s => s.request.fileEquals(request) && !s.request.queryEquals(request))
63 .map(symbol => ({ symbol, index: symbols.indexOf(symbol) }));
64
65 symbols[existingIndex] = newSymbol;
66 Compiler.sortSymbols(symbols);
67
68 return Promise.map(allExceptCurrent, ({ symbol, index }) => {
69 const opts = { id: symbol.id, request: symbol.request, content, factory };
70 return SpriteSymbol.create(opts).then(created => symbols[index] = created);
71 }).then(() => newSymbol);
72 });
73 }
74
75 /**
76 * @return {Promise<Array<Sprite>>}
77 */
78 compile() {
79 const symbols = this.symbols;
80 const rules = this.rules.rules;
81 const factory = this.config.spriteFactory;
82
83 return Promise.map(rules, (rule) => {
84 const spriteSymbols = [];
85 const filename = rule.uri;
86
87 symbols.forEach((symbol) => {
88 const isMatch = rule.match(symbol.request.file);
89 if (isMatch) {
90 spriteSymbols.push(symbol);
91 }
92 });
93
94 return spriteSymbols.length > 0 ?
95 Sprite.create({ symbols: spriteSymbols, filename, factory }) :
96 null;
97 }).filter(result => result !== null);
98 }
99}
100
101module.exports = Compiler;
102module.exports.defaultConfig = defaultConfig;