1 |
|
2 | const loaderDefaults = require('../config').loader;
|
3 | const getAllModules = require('./get-all-modules');
|
4 | const isModuleShouldBeExtracted = require('./is-module-should-be-extracted');
|
5 | const getModuleChunk = require('./get-module-chunk');
|
6 | const interpolate = require('./interpolate');
|
7 | const getMatchedRule = require('./get-matched-rule');
|
8 |
|
9 | class MappedListItem {
|
10 | |
11 |
|
12 |
|
13 |
|
14 |
|
15 | constructor(symbol, module, spriteFilename) {
|
16 | this.symbol = symbol;
|
17 | this.module = module;
|
18 | this.resource = symbol.request.file;
|
19 | this.spriteFilename = spriteFilename;
|
20 | }
|
21 |
|
22 | get url() {
|
23 | return `${this.spriteFilename}#${this.symbol.id}`;
|
24 | }
|
25 |
|
26 | get useUrl() {
|
27 | return `${this.spriteFilename}#${this.symbol.useId}`;
|
28 | }
|
29 | }
|
30 |
|
31 | class MappedList {
|
32 | |
33 |
|
34 |
|
35 |
|
36 | constructor(symbols, compilation, shouldLog = false) {
|
37 | const { compiler } = compilation;
|
38 |
|
39 | this.symbols = symbols;
|
40 | this.rule = getMatchedRule(compiler);
|
41 | this.allModules = getAllModules(compilation);
|
42 | this.spriteModules = this.allModules.filter(isModuleShouldBeExtracted);
|
43 | this.shouldLog = shouldLog;
|
44 | this.items = this.create();
|
45 | }
|
46 |
|
47 | |
48 |
|
49 |
|
50 |
|
51 | static groupItemsBySpriteFilename(data) {
|
52 | return data
|
53 | .map(item => item.spriteFilename)
|
54 | .filter((value, index, self) => self.indexOf(value) === index)
|
55 | .reduce((acc, spriteFilename) => {
|
56 | acc[spriteFilename] = data.filter(item => item.spriteFilename === spriteFilename);
|
57 | return acc;
|
58 | }, {});
|
59 | }
|
60 |
|
61 | |
62 |
|
63 |
|
64 |
|
65 |
|
66 | static groupItemsBySymbolFile(data, mapper) {
|
67 | return data.reduce((acc, item) => {
|
68 | if (mapper) {
|
69 | mapper(acc, item);
|
70 | } else {
|
71 | acc[item.resource] = item;
|
72 | }
|
73 | return acc;
|
74 | }, {});
|
75 | }
|
76 |
|
77 | |
78 |
|
79 |
|
80 | create() {
|
81 | const { symbols, spriteModules, allModules, rule } = this;
|
82 |
|
83 | const data = symbols.reduce((acc, symbol) => {
|
84 | const resource = symbol.request.file;
|
85 | const module = spriteModules.find((m) => {
|
86 | return 'resource' in m ? m.resource.split('?')[0] === resource : false;
|
87 | });
|
88 |
|
89 | let spriteFilename = rule.spriteFilename || loaderDefaults.spriteFilename;
|
90 |
|
91 | const chunk = module ? getModuleChunk(module, allModules) : null;
|
92 |
|
93 | if (typeof spriteFilename !== 'function' && chunk && chunk.name) {
|
94 | spriteFilename = spriteFilename.replace('[chunkname]', chunk.name);
|
95 | } else if (typeof spriteFilename === 'function') {
|
96 | spriteFilename = spriteFilename(resource);
|
97 | }
|
98 |
|
99 | if (rule && module) {
|
100 | acc.push(new MappedListItem(symbol, module, spriteFilename));
|
101 | }
|
102 |
|
103 | return acc;
|
104 | }, []);
|
105 |
|
106 |
|
107 | const itemsBySpriteFilename = MappedList.groupItemsBySpriteFilename(data);
|
108 | const filenames = Object.keys(itemsBySpriteFilename);
|
109 |
|
110 | filenames.forEach((filename) => {
|
111 | if (!filename.includes('hash')) {
|
112 | return;
|
113 | }
|
114 |
|
115 | const items = itemsBySpriteFilename[filename];
|
116 | const spriteSymbols = items.map(item => item.symbol);
|
117 | const content = spriteSymbols.map(s => s.render()).join('');
|
118 | const interpolatedName = interpolate(filename, {
|
119 | resourcePath: filename,
|
120 | content
|
121 | });
|
122 |
|
123 | items
|
124 | .filter(item => item.spriteFilename !== interpolatedName)
|
125 | .forEach(item => item.spriteFilename = interpolatedName);
|
126 | });
|
127 |
|
128 | return data;
|
129 | }
|
130 |
|
131 | |
132 |
|
133 |
|
134 | groupItemsBySpriteFilename() {
|
135 | return MappedList.groupItemsBySpriteFilename(this.items);
|
136 | }
|
137 |
|
138 | |
139 |
|
140 |
|
141 |
|
142 | groupItemsBySymbolFile(mapper) {
|
143 | return MappedList.groupItemsBySymbolFile(this.items, mapper);
|
144 | }
|
145 | }
|
146 |
|
147 | module.exports = MappedList;
|