1 | const Promise = require('bluebird');
|
2 | const merge = require('merge-options');
|
3 | const FileRequest = require('./request');
|
4 | const RuleSet = require('./rules');
|
5 | const Sprite = require('./sprite');
|
6 | const SpriteSymbol = require('./symbol');
|
7 | const symbolFactory = require('./symbol-factory');
|
8 | const spriteFactory = require('./sprite-factory');
|
9 |
|
10 | const defaultConfig = {
|
11 | rules: [
|
12 | { test: /\.svg$/, value: 'sprite.svg' }
|
13 | ],
|
14 | symbolFactory,
|
15 | spriteFactory
|
16 | };
|
17 |
|
18 | class 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 |
|
41 |
|
42 |
|
43 |
|
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 |
|
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 |
|
101 | module.exports = Compiler;
|
102 | module.exports.defaultConfig = defaultConfig;
|