1 |
|
2 |
|
3 |
|
4 |
|
5 | 'use strict';
|
6 |
|
7 | const Tapable = require('tapable');
|
8 | const ConcatSource = require('webpack-sources').ConcatSource;
|
9 |
|
10 | const START_LOWERCASE_ALPHABET_CODE = 'a'.charCodeAt(0);
|
11 | const START_UPPERCASE_ALPHABET_CODE = 'A'.charCodeAt(0);
|
12 | const DELTA_A_TO_Z = 'z'.charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1;
|
13 |
|
14 | module.exports = class Template extends Tapable {
|
15 | constructor(outputOptions) {
|
16 | super();
|
17 | this.outputOptions = outputOptions || {};
|
18 | }
|
19 |
|
20 | static getFunctionContent(fn) {
|
21 | return fn.toString().replace(/^function\s?\(\)\s?\{\n?|\n?\}$/g, '').replace(/^\t/mg, '');
|
22 | }
|
23 |
|
24 | static toIdentifier(str) {
|
25 | if (typeof str !== 'string') return '';
|
26 | return str.replace(/^[^a-zA-Z$_]/, '_').replace(/[^a-zA-Z0-9$_]/g, '_');
|
27 | }
|
28 |
|
29 | static toPath(str) {
|
30 | if (typeof str !== 'string') return '';
|
31 | return str.replace(/[^a-zA-Z0-9_!§$()=\-\^°]+/g, '-').replace(/^-|-$/, '');
|
32 | }
|
33 |
|
34 |
|
35 | static numberToIdentifer(n) {
|
36 |
|
37 | if (n < DELTA_A_TO_Z) return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
|
38 |
|
39 |
|
40 | n -= DELTA_A_TO_Z;
|
41 | if (n < DELTA_A_TO_Z) return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n);
|
42 |
|
43 |
|
44 | n -= DELTA_A_TO_Z;
|
45 | return '_' + n;
|
46 | }
|
47 |
|
48 | indent(str) {
|
49 | if (Array.isArray(str)) {
|
50 | return str.map(this.indent.bind(this)).join('\n');
|
51 | } else {
|
52 | str = str.trimRight();
|
53 | if (!str) return '';
|
54 | var ind = str[0] === '\n' ? '' : '\t';
|
55 | return ind + str.replace(/\n([^\n])/g, '\n\t$1');
|
56 | }
|
57 | }
|
58 |
|
59 | prefix(str, prefix) {
|
60 | if (Array.isArray(str)) {
|
61 | str = str.join('\n');
|
62 | }
|
63 | str = str.trim();
|
64 | if (!str) return '';
|
65 | const ind = str[0] === '\n' ? '' : prefix;
|
66 | return ind + str.replace(/\n([^\n])/g, '\n' + prefix + '$1');
|
67 | }
|
68 |
|
69 | asString(str) {
|
70 | if (Array.isArray(str)) {
|
71 | return str.join('\n');
|
72 | }
|
73 | return str;
|
74 | }
|
75 |
|
76 | getModulesArrayBounds(modules) {
|
77 | if (!modules.every(moduleIdIsNumber))
|
78 | return false;
|
79 | var maxId = -Infinity;
|
80 | var minId = Infinity;
|
81 | modules.forEach(function(module) {
|
82 | if (maxId < module.id) maxId = module.id;
|
83 | if (minId > module.id) minId = module.id;
|
84 | });
|
85 | if (minId < 16 + ('' + minId).length) {
|
86 |
|
87 | minId = 0;
|
88 | }
|
89 | var objectOverhead = modules.map(function(module) {
|
90 | var idLength = (module.id + '').length;
|
91 | return idLength + 2;
|
92 | }).reduce(function(a, b) {
|
93 | return a + b;
|
94 | }, -1);
|
95 | var arrayOverhead = minId === 0 ? maxId : 16 + ('' + minId).length + maxId;
|
96 | return arrayOverhead < objectOverhead ? [minId, maxId] : false;
|
97 | }
|
98 |
|
99 | renderChunkModules(chunk, moduleTemplate, dependencyTemplates, prefix) {
|
100 | if (!prefix) prefix = '';
|
101 | var source = new ConcatSource();
|
102 | if (chunk.modules.length === 0) {
|
103 | source.add('[]');
|
104 | return source;
|
105 | }
|
106 | var removedModules = chunk.removedModules;
|
107 | var allModules = chunk.modules.map(function(module) {
|
108 | return {
|
109 | id: module.id,
|
110 | source: moduleTemplate.render(module, dependencyTemplates, chunk)
|
111 | };
|
112 | });
|
113 | if (removedModules && removedModules.length > 0) {
|
114 | removedModules.forEach(function(id) {
|
115 | allModules.push({
|
116 | id: id,
|
117 | source: 'false'
|
118 | });
|
119 | });
|
120 | }
|
121 | var bounds = this.getModulesArrayBounds(chunk.modules);
|
122 |
|
123 | if (bounds) {
|
124 |
|
125 | var minId = bounds[0];
|
126 | var maxId = bounds[1];
|
127 | if (minId !== 0) source.add('Array(' + minId + ').concat(');
|
128 | source.add('[\n');
|
129 | var modules = {};
|
130 | allModules.forEach(function(module) {
|
131 | modules[module.id] = module;
|
132 | });
|
133 | for (var idx = minId; idx <= maxId; idx++) {
|
134 | var module = modules[idx];
|
135 | if (idx !== minId) source.add(',\n');
|
136 | source.add('/* ' + idx + ' */');
|
137 | if (module) {
|
138 | source.add('\n');
|
139 | source.add(module.source);
|
140 | }
|
141 | }
|
142 | source.add('\n' + prefix + ']');
|
143 | if (minId !== 0) source.add(')');
|
144 | } else {
|
145 |
|
146 | source.add('{\n');
|
147 | allModules.sort(function(a, b) {
|
148 | var aId = a.id + '';
|
149 | var bId = b.id + '';
|
150 | if (aId < bId) return -1;
|
151 | if (aId > bId) return 1;
|
152 | return 0;
|
153 | }).forEach(function(module, idx) {
|
154 | if (idx !== 0) source.add(',\n');
|
155 | source.add('\n/***/ ' + JSON.stringify(module.id) + ':\n');
|
156 | source.add(module.source);
|
157 | });
|
158 | source.add('\n\n' + prefix + '}');
|
159 | }
|
160 | return source;
|
161 | }
|
162 | };
|
163 |
|
164 | function moduleIdIsNumber(module) {
|
165 | return typeof module.id === 'number';
|
166 | }
|