UNPKG

9.16 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.minifyTemplate = exports.createMinifier = void 0;
4const ts = require("typescript");
5const ts_is_kind_1 = require("./ts-is-kind");
6function isSymbol(ch) {
7 return ch == ';' || ch == ':' || ch == '{' || ch == '}' || ch == ',';
8}
9function isSpace(ch) {
10 return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
11}
12const stateMachine = {
13 ';': {
14 next(ch) {
15 if (ch == '(')
16 return { state: ['(', { count: 1 }] };
17 if (ch == '\'' || ch == '"')
18 return { state: ch };
19 if (isSpace(ch))
20 return { skipEmit: true };
21 if (ch == '/')
22 return { state: ';/', skipEmit: true };
23 if (isSymbol(ch))
24 return;
25 return { state: 'x' };
26 },
27 flush() {
28 return { state: ';$' };
29 }
30 },
31 ';$': {
32 next(ch) {
33 if (ch == '(')
34 return { state: ['(', { count: 1 }] };
35 if (ch == '\'' || ch == '"')
36 return { state: ch };
37 if (isSpace(ch))
38 return { skipEmit: true, state: ' ' }; // we may need a space
39 if (ch == '/')
40 return { state: '/', skipEmit: true };
41 if (isSymbol(ch))
42 return { state: ';' };
43 return { state: 'x' };
44 }
45 },
46 'x': {
47 next(ch) {
48 if (ch == '(')
49 return { state: ['(', { count: 1 }] };
50 if (ch == '\'' || ch == '"')
51 return { state: ch };
52 if (isSpace(ch))
53 return { state: ' ', skipEmit: true };
54 if (ch == '/')
55 return { state: '/', skipEmit: true };
56 if (isSymbol(ch))
57 return { state: ';' };
58 }
59 },
60 ' ': {
61 next(ch) {
62 if (ch == '(')
63 return { state: ['(', { count: 1 }], emit: ' ' + ch };
64 if (ch == '\'' || ch == '"')
65 return { state: ch, emit: ' ' + ch };
66 if (isSpace(ch))
67 return { state: ' ', skipEmit: true };
68 if (ch == '/')
69 return { state: '/', skipEmit: true };
70 if (isSymbol(ch))
71 return { state: ';' };
72 return { state: 'x', emit: ' ' + ch };
73 },
74 flush(last) {
75 if (!last)
76 return { emit: ' ', state: ';$' };
77 }
78 },
79 '\n': {
80 next(ch) {
81 if (ch == '(')
82 return { state: ['(', { count: 1 }], emit: '\n' + ch };
83 if (ch == '\'' || ch == '"')
84 return { state: ch, emit: '\n' + ch };
85 if (isSpace(ch))
86 return { state: '\n', skipEmit: true };
87 if (ch == '/')
88 return { state: '/', emit: '\n' };
89 if (isSymbol(ch))
90 return { state: ';', emit: '\n' + ch };
91 return { state: 'x', emit: '\n' + ch };
92 }
93 },
94 "'": {
95 next(ch) {
96 if (ch == '\'')
97 return { state: ';' };
98 }
99 },
100 '"': {
101 next(ch) {
102 if (ch == '"')
103 return { state: ';' };
104 }
105 },
106 '(': {
107 next(ch, { count }) {
108 if (ch == '(')
109 return { state: ['(', { count: count + 1 }] };
110 if (ch == ')')
111 if (count > 1)
112 return { state: ['(', { count: count - 1 }] };
113 else
114 return { state: ';' }; // maybe return ' '? then it'd always add space after
115 }
116 },
117 '/': {
118 next(ch) {
119 if (ch == '/')
120 return { state: '//', skipEmit: true };
121 if (ch == '*')
122 return { state: '/*', skipEmit: true };
123 return { state: ';', emit: '/' + ch };
124 },
125 flush() {
126 return { state: '/$', emit: '/' };
127 }
128 },
129 '//': {
130 next(ch) {
131 if (ch == '\n')
132 return { state: ' ', skipEmit: true };
133 return { skipEmit: true };
134 },
135 flush(last) {
136 if (last)
137 return { skipEmit: true };
138 return { state: '//$', emit: '//' };
139 }
140 },
141 ';/': {
142 next(ch) {
143 if (ch == '/')
144 return { state: ';//', skipEmit: true };
145 if (ch == '*')
146 return { state: ';/*', skipEmit: true };
147 return { state: ';', emit: '/' + ch };
148 },
149 flush() {
150 return { state: '/$', emit: '/' };
151 }
152 },
153 ';//': {
154 next(ch) {
155 if (ch == '\n')
156 return { state: ';', skipEmit: true };
157 return { skipEmit: true };
158 },
159 flush(last) {
160 if (last)
161 return { skipEmit: true };
162 return { state: '//$', emit: '//' };
163 }
164 },
165 '/$': {},
166 '//$': {
167 next(ch) {
168 if (ch == '\n')
169 return { state: '\n', skipEmit: true };
170 return { skipEmit: true };
171 }
172 },
173 '/*': {
174 next(ch) {
175 if (ch == '*')
176 return { state: '/**', skipEmit: true };
177 return { skipEmit: true };
178 },
179 flush(last) {
180 if (last)
181 return { skipEmit: true };
182 return { state: '/*$', emit: '/*' };
183 }
184 },
185 '/**': {
186 next(ch) {
187 if (ch == '/')
188 return { state: ' ', skipEmit: true };
189 return { state: '/*', skipEmit: true };
190 }
191 },
192 ';/*': {
193 next(ch) {
194 if (ch == '*')
195 return { state: ';/**', skipEmit: true };
196 return { skipEmit: true };
197 },
198 flush(last) {
199 if (last)
200 return { skipEmit: true };
201 return { state: '/*$', emit: '/*' };
202 }
203 },
204 ';/**': {
205 next(ch) {
206 if (ch == '/')
207 return { state: ';', skipEmit: true };
208 return { state: ';/*', skipEmit: true };
209 }
210 },
211 '/*$': {
212 next(ch) {
213 if (ch == '*')
214 return { state: '/*$*', skipEmit: true };
215 return { skipEmit: true };
216 }
217 },
218 '/*$*': {
219 next(ch) {
220 if (ch == '/')
221 return { state: ';', emit: '*/' };
222 return { state: '/*$', skipEmit: true };
223 }
224 }
225};
226function createMinifier() {
227 let state = ';';
228 let stateData = undefined;
229 return (next, last = false) => {
230 let minified = '';
231 function apply(result, ch) {
232 if (!result) {
233 if (ch !== undefined)
234 minified += ch;
235 }
236 else {
237 if (result.state !== undefined) {
238 if (typeof result.state === 'string')
239 state = result.state;
240 else {
241 state = result.state[0];
242 stateData = result.state[1];
243 }
244 }
245 if (result.emit !== undefined)
246 minified += result.emit;
247 else if (result.skipEmit !== true && ch !== undefined)
248 minified += ch;
249 }
250 }
251 let pos = 0;
252 let len = next.length;
253 while (pos < len) {
254 const ch = next[pos++];
255 const reducer = stateMachine[state];
256 const prevState = state;
257 const reducerResult = reducer.next && reducer.next(ch, stateData);
258 apply(reducerResult, ch);
259 // console.log('next(', { ch, state: prevState }, '): ', reducerResult, ' -> ', { state, minified });
260 }
261 const reducer = stateMachine[state];
262 const prevState = state;
263 const reducerResult = reducer.flush && reducer.flush(last);
264 apply(reducerResult);
265 // console.log('flush', { state: prevState }, '): ', reducerResult, ' -> ', { state, minified });
266 return minified;
267 };
268}
269exports.createMinifier = createMinifier;
270function minifyTemplate(templateLiteral, factory) {
271 const minifier = createMinifier();
272 if ((0, ts_is_kind_1.isNoSubstitutionTemplateLiteral)(templateLiteral)) {
273 const node = factory.createNoSubstitutionTemplateLiteral(minifier(templateLiteral.text, true));
274 return node;
275 }
276 else if ((0, ts_is_kind_1.isTemplateExpression)(templateLiteral)) {
277 const head = factory.createTemplateHead(minifier(templateLiteral.head.text));
278 const templateSpans = templateLiteral.templateSpans.map(span => factory.createTemplateSpan(span.expression, span.literal.kind === ts.SyntaxKind.TemplateMiddle
279 ? factory.createTemplateMiddle(minifier(span.literal.text))
280 : factory.createTemplateTail(minifier(span.literal.text, true))));
281 const node = factory.createTemplateExpression(head, templateSpans);
282 return node;
283 }
284 return templateLiteral;
285}
286exports.minifyTemplate = minifyTemplate;