UNPKG

4.83 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5'use strict';
6
7const Tapable = require('tapable');
8const ConcatSource = require('webpack-sources').ConcatSource;
9
10const START_LOWERCASE_ALPHABET_CODE = 'a'.charCodeAt(0);
11const START_UPPERCASE_ALPHABET_CODE = 'A'.charCodeAt(0);
12const DELTA_A_TO_Z = 'z'.charCodeAt(0) - START_LOWERCASE_ALPHABET_CODE + 1;
13
14module.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 // map number to a single character a-z, A-Z or <_ + number> if number is too big
35 static numberToIdentifer(n) {
36 // lower case
37 if (n < DELTA_A_TO_Z) return String.fromCharCode(START_LOWERCASE_ALPHABET_CODE + n);
38
39 // upper case
40 n -= DELTA_A_TO_Z;
41 if (n < DELTA_A_TO_Z) return String.fromCharCode(START_UPPERCASE_ALPHABET_CODE + n);
42
43 // fall back to _ + number
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 // add minId x ',' instead of 'Array(minId).concat(...)'
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 // Render a spare array
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 // Render an object
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
164function moduleIdIsNumber(module) {
165 return typeof module.id === 'number';
166}