@qt-test/apex-dsl-compiler 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -0
- package/bin/apexc.js +308 -0
- package/dist/acss/index.d.mts +67 -0
- package/dist/acss/index.d.ts +67 -0
- package/dist/acss/index.js +632 -0
- package/dist/acss/index.mjs +8 -0
- package/dist/ast-DEVgojMx.d.mts +135 -0
- package/dist/ast-DEVgojMx.d.ts +135 -0
- package/dist/axml/index.d.mts +59 -0
- package/dist/axml/index.d.ts +59 -0
- package/dist/axml/index.js +863 -0
- package/dist/axml/index.mjs +8 -0
- package/dist/chunk-7LDI6MFY.mjs +605 -0
- package/dist/chunk-B7VE6TVQ.mjs +605 -0
- package/dist/chunk-GQ3PJZ2P.mjs +836 -0
- package/dist/chunk-IRS3J3N7.mjs +836 -0
- package/dist/index.d.mts +237 -0
- package/dist/index.d.ts +237 -0
- package/dist/index.js +2050 -0
- package/dist/index.mjs +587 -0
- package/package.json +71 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2050 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SourceMapBuilder: () => SourceMapBuilder,
|
|
24
|
+
VERSION: () => VERSION,
|
|
25
|
+
applySourceMap: () => applySourceMap,
|
|
26
|
+
compile: () => compile,
|
|
27
|
+
compileACSS: () => compileACSS,
|
|
28
|
+
compileAXML: () => compileAXML,
|
|
29
|
+
createSourceMap: () => createSourceMap,
|
|
30
|
+
formatErrors: () => formatErrors,
|
|
31
|
+
generateCode: () => generateCode,
|
|
32
|
+
mergeSourceMaps: () => mergeSourceMaps,
|
|
33
|
+
parseACSS: () => parseACSS,
|
|
34
|
+
parseAXML: () => parseAXML,
|
|
35
|
+
validate: () => validate
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/axml/parser.ts
|
|
40
|
+
function createPosition(state) {
|
|
41
|
+
return {
|
|
42
|
+
line: state.line,
|
|
43
|
+
column: state.column,
|
|
44
|
+
offset: state.pos
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function createLoc(start, end, source) {
|
|
48
|
+
return { start, end, source };
|
|
49
|
+
}
|
|
50
|
+
function parseAXML(source) {
|
|
51
|
+
const state = {
|
|
52
|
+
source,
|
|
53
|
+
pos: 0,
|
|
54
|
+
line: 1,
|
|
55
|
+
column: 0,
|
|
56
|
+
errors: []
|
|
57
|
+
};
|
|
58
|
+
const children = parseChildren(state);
|
|
59
|
+
let ast;
|
|
60
|
+
if (children.length === 0) {
|
|
61
|
+
ast = null;
|
|
62
|
+
} else if (children.length === 1 && children[0].type === "Element") {
|
|
63
|
+
ast = children[0];
|
|
64
|
+
} else {
|
|
65
|
+
ast = {
|
|
66
|
+
type: "Element",
|
|
67
|
+
tag: "block",
|
|
68
|
+
attributes: [],
|
|
69
|
+
directives: [],
|
|
70
|
+
children,
|
|
71
|
+
selfClosing: false,
|
|
72
|
+
isComponent: false,
|
|
73
|
+
start: 0,
|
|
74
|
+
end: source.length,
|
|
75
|
+
loc: createLoc(
|
|
76
|
+
{ line: 1, column: 0, offset: 0 },
|
|
77
|
+
{ line: state.line, column: state.column, offset: state.pos }
|
|
78
|
+
)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return { ast, errors: state.errors };
|
|
82
|
+
}
|
|
83
|
+
function parseChildren(state, endTag) {
|
|
84
|
+
const children = [];
|
|
85
|
+
while (state.pos < state.source.length) {
|
|
86
|
+
if (endTag && lookAhead(state, `</${endTag}`)) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const node = parseNode(state);
|
|
90
|
+
if (node) {
|
|
91
|
+
if (node.type === "Text" && children.length > 0 && children[children.length - 1].type === "Text") {
|
|
92
|
+
const prev = children[children.length - 1];
|
|
93
|
+
prev.content += node.content;
|
|
94
|
+
prev.raw += node.raw;
|
|
95
|
+
prev.end = node.end;
|
|
96
|
+
prev.loc.end = node.loc.end;
|
|
97
|
+
} else {
|
|
98
|
+
children.push(node);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return children;
|
|
103
|
+
}
|
|
104
|
+
function parseNode(state) {
|
|
105
|
+
skipWhitespace(state);
|
|
106
|
+
if (state.pos >= state.source.length) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
if (lookAhead(state, "<!--")) {
|
|
110
|
+
return parseComment(state);
|
|
111
|
+
}
|
|
112
|
+
if (lookAhead(state, "<") && !lookAhead(state, "</")) {
|
|
113
|
+
return parseElement(state);
|
|
114
|
+
}
|
|
115
|
+
return parseText(state);
|
|
116
|
+
}
|
|
117
|
+
function parseElement(state) {
|
|
118
|
+
const start = createPosition(state);
|
|
119
|
+
advance(state);
|
|
120
|
+
const tag = parseTagName(state);
|
|
121
|
+
if (!tag) {
|
|
122
|
+
state.errors.push(`Expected tag name at line ${state.line}`);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const { attributes, directives } = parseAttributes(state);
|
|
126
|
+
skipWhitespace(state);
|
|
127
|
+
const selfClosing = lookAhead(state, "/>");
|
|
128
|
+
if (selfClosing) {
|
|
129
|
+
advance(state, 2);
|
|
130
|
+
} else {
|
|
131
|
+
if (!consume(state, ">")) {
|
|
132
|
+
state.errors.push(`Expected '>' at line ${state.line}`);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const children = parseChildren(state, tag);
|
|
136
|
+
if (!consume(state, `</${tag}`)) {
|
|
137
|
+
state.errors.push(`Expected closing tag </${tag}> at line ${state.line}`);
|
|
138
|
+
}
|
|
139
|
+
skipWhitespace(state);
|
|
140
|
+
consume(state, ">");
|
|
141
|
+
const end2 = createPosition(state);
|
|
142
|
+
return {
|
|
143
|
+
type: "Element",
|
|
144
|
+
tag,
|
|
145
|
+
attributes,
|
|
146
|
+
directives,
|
|
147
|
+
children,
|
|
148
|
+
selfClosing: false,
|
|
149
|
+
isComponent: isCustomComponent(tag),
|
|
150
|
+
start: start.offset,
|
|
151
|
+
end: end2.offset,
|
|
152
|
+
loc: createLoc(start, end2)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const end = createPosition(state);
|
|
156
|
+
return {
|
|
157
|
+
type: "Element",
|
|
158
|
+
tag,
|
|
159
|
+
attributes,
|
|
160
|
+
directives,
|
|
161
|
+
children: [],
|
|
162
|
+
selfClosing: true,
|
|
163
|
+
isComponent: isCustomComponent(tag),
|
|
164
|
+
start: start.offset,
|
|
165
|
+
end: end.offset,
|
|
166
|
+
loc: createLoc(start, end)
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function parseTagName(state) {
|
|
170
|
+
let name = "";
|
|
171
|
+
while (state.pos < state.source.length) {
|
|
172
|
+
const char = state.source[state.pos];
|
|
173
|
+
if (/[a-zA-Z0-9_-]/.test(char)) {
|
|
174
|
+
name += char;
|
|
175
|
+
advance(state);
|
|
176
|
+
} else {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return name;
|
|
181
|
+
}
|
|
182
|
+
function parseAttributes(state) {
|
|
183
|
+
const attributes = [];
|
|
184
|
+
const directives = [];
|
|
185
|
+
while (state.pos < state.source.length) {
|
|
186
|
+
skipWhitespace(state);
|
|
187
|
+
if (lookAhead(state, ">") || lookAhead(state, "/>")) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
const start = createPosition(state);
|
|
191
|
+
const name = parseAttributeName(state);
|
|
192
|
+
if (!name) break;
|
|
193
|
+
if (name.startsWith("a:")) {
|
|
194
|
+
const directive = parseDirective(state, name, start);
|
|
195
|
+
if (directive) {
|
|
196
|
+
directives.push(directive);
|
|
197
|
+
}
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
let value = null;
|
|
201
|
+
let isDynamic = false;
|
|
202
|
+
skipWhitespace(state);
|
|
203
|
+
if (consume(state, "=")) {
|
|
204
|
+
skipWhitespace(state);
|
|
205
|
+
const result = parseAttributeValue(state);
|
|
206
|
+
value = result.value;
|
|
207
|
+
isDynamic = result.isDynamic;
|
|
208
|
+
}
|
|
209
|
+
const end = createPosition(state);
|
|
210
|
+
attributes.push({
|
|
211
|
+
type: "Attribute",
|
|
212
|
+
name,
|
|
213
|
+
value,
|
|
214
|
+
isDynamic,
|
|
215
|
+
start: start.offset,
|
|
216
|
+
end: end.offset,
|
|
217
|
+
loc: createLoc(start, end)
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return { attributes, directives };
|
|
221
|
+
}
|
|
222
|
+
function parseAttributeName(state) {
|
|
223
|
+
let name = "";
|
|
224
|
+
while (state.pos < state.source.length) {
|
|
225
|
+
const char = state.source[state.pos];
|
|
226
|
+
if (/[a-zA-Z0-9_\-:]/.test(char)) {
|
|
227
|
+
name += char;
|
|
228
|
+
advance(state);
|
|
229
|
+
} else {
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return name;
|
|
234
|
+
}
|
|
235
|
+
function parseAttributeValue(state) {
|
|
236
|
+
const quote = state.source[state.pos];
|
|
237
|
+
if (quote !== '"' && quote !== "'") {
|
|
238
|
+
const start2 = createPosition(state);
|
|
239
|
+
let raw2 = "";
|
|
240
|
+
while (state.pos < state.source.length && !/[\s>]/.test(state.source[state.pos])) {
|
|
241
|
+
raw2 += state.source[state.pos];
|
|
242
|
+
advance(state);
|
|
243
|
+
}
|
|
244
|
+
const end2 = createPosition(state);
|
|
245
|
+
const isDynamic2 = raw2.includes("{{");
|
|
246
|
+
if (isDynamic2) {
|
|
247
|
+
return {
|
|
248
|
+
value: {
|
|
249
|
+
type: "Expression",
|
|
250
|
+
expression: extractExpression(raw2),
|
|
251
|
+
raw: raw2,
|
|
252
|
+
start: start2.offset,
|
|
253
|
+
end: end2.offset,
|
|
254
|
+
loc: createLoc(start2, end2)
|
|
255
|
+
},
|
|
256
|
+
isDynamic: true
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
value: {
|
|
261
|
+
type: "Literal",
|
|
262
|
+
value: raw2,
|
|
263
|
+
raw: raw2,
|
|
264
|
+
start: start2.offset,
|
|
265
|
+
end: end2.offset,
|
|
266
|
+
loc: createLoc(start2, end2)
|
|
267
|
+
},
|
|
268
|
+
isDynamic: false
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
advance(state);
|
|
272
|
+
const start = createPosition(state);
|
|
273
|
+
let raw = "";
|
|
274
|
+
while (state.pos < state.source.length && state.source[state.pos] !== quote) {
|
|
275
|
+
raw += state.source[state.pos];
|
|
276
|
+
advance(state);
|
|
277
|
+
}
|
|
278
|
+
const end = createPosition(state);
|
|
279
|
+
advance(state);
|
|
280
|
+
const isDynamic = raw.includes("{{");
|
|
281
|
+
if (isDynamic) {
|
|
282
|
+
return {
|
|
283
|
+
value: {
|
|
284
|
+
type: "Expression",
|
|
285
|
+
expression: extractExpression(raw),
|
|
286
|
+
raw,
|
|
287
|
+
start: start.offset,
|
|
288
|
+
end: end.offset,
|
|
289
|
+
loc: createLoc(start, end)
|
|
290
|
+
},
|
|
291
|
+
isDynamic: true
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
value: {
|
|
296
|
+
type: "Literal",
|
|
297
|
+
value: raw,
|
|
298
|
+
raw,
|
|
299
|
+
start: start.offset,
|
|
300
|
+
end: end.offset,
|
|
301
|
+
loc: createLoc(start, end)
|
|
302
|
+
},
|
|
303
|
+
isDynamic: false
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function parseDirective(state, name, start) {
|
|
307
|
+
const directiveName = name.slice(2);
|
|
308
|
+
let value = null;
|
|
309
|
+
skipWhitespace(state);
|
|
310
|
+
if (consume(state, "=")) {
|
|
311
|
+
skipWhitespace(state);
|
|
312
|
+
const result = parseAttributeValue(state);
|
|
313
|
+
if (result.value?.type === "Expression") {
|
|
314
|
+
value = result.value;
|
|
315
|
+
} else if (result.value?.type === "Literal") {
|
|
316
|
+
value = {
|
|
317
|
+
type: "Expression",
|
|
318
|
+
expression: result.value.value,
|
|
319
|
+
raw: result.value.raw,
|
|
320
|
+
start: result.value.start,
|
|
321
|
+
end: result.value.end,
|
|
322
|
+
loc: result.value.loc
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const end = createPosition(state);
|
|
327
|
+
return {
|
|
328
|
+
type: "Directive",
|
|
329
|
+
name: directiveName,
|
|
330
|
+
value,
|
|
331
|
+
modifiers: [],
|
|
332
|
+
start: start.offset,
|
|
333
|
+
end: end.offset,
|
|
334
|
+
loc: createLoc(start, end)
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function parseText(state) {
|
|
338
|
+
const start = createPosition(state);
|
|
339
|
+
let raw = "";
|
|
340
|
+
while (state.pos < state.source.length) {
|
|
341
|
+
if (lookAhead(state, "<")) {
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
raw += state.source[state.pos];
|
|
345
|
+
advance(state);
|
|
346
|
+
}
|
|
347
|
+
if (!raw) return null;
|
|
348
|
+
const end = createPosition(state);
|
|
349
|
+
const trimmed = raw.trim();
|
|
350
|
+
if (trimmed.startsWith("{{") && trimmed.endsWith("}}") && !trimmed.slice(2, -2).includes("{{")) {
|
|
351
|
+
return {
|
|
352
|
+
type: "Expression",
|
|
353
|
+
expression: trimmed.slice(2, -2).trim(),
|
|
354
|
+
raw,
|
|
355
|
+
start: start.offset,
|
|
356
|
+
end: end.offset,
|
|
357
|
+
loc: createLoc(start, end)
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
return {
|
|
361
|
+
type: "Text",
|
|
362
|
+
content: raw,
|
|
363
|
+
raw,
|
|
364
|
+
start: start.offset,
|
|
365
|
+
end: end.offset,
|
|
366
|
+
loc: createLoc(start, end)
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function parseComment(state) {
|
|
370
|
+
const start = createPosition(state);
|
|
371
|
+
advance(state, 4);
|
|
372
|
+
let content = "";
|
|
373
|
+
while (state.pos < state.source.length && !lookAhead(state, "-->")) {
|
|
374
|
+
content += state.source[state.pos];
|
|
375
|
+
advance(state);
|
|
376
|
+
}
|
|
377
|
+
advance(state, 3);
|
|
378
|
+
const end = createPosition(state);
|
|
379
|
+
return {
|
|
380
|
+
type: "Comment",
|
|
381
|
+
content,
|
|
382
|
+
start: start.offset,
|
|
383
|
+
end: end.offset,
|
|
384
|
+
loc: createLoc(start, end)
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function extractExpression(raw) {
|
|
388
|
+
const parts = [];
|
|
389
|
+
let lastIndex = 0;
|
|
390
|
+
const regex = /\{\{(.+?)\}\}/g;
|
|
391
|
+
let match;
|
|
392
|
+
while ((match = regex.exec(raw)) !== null) {
|
|
393
|
+
if (match.index > lastIndex) {
|
|
394
|
+
parts.push(`'${raw.slice(lastIndex, match.index)}'`);
|
|
395
|
+
}
|
|
396
|
+
parts.push(match[1].trim());
|
|
397
|
+
lastIndex = regex.lastIndex;
|
|
398
|
+
}
|
|
399
|
+
if (lastIndex < raw.length) {
|
|
400
|
+
parts.push(`'${raw.slice(lastIndex)}'`);
|
|
401
|
+
}
|
|
402
|
+
return parts.length === 1 ? parts[0] : parts.join(" + ");
|
|
403
|
+
}
|
|
404
|
+
function isCustomComponent(tag) {
|
|
405
|
+
const builtIn = [
|
|
406
|
+
"view",
|
|
407
|
+
"text",
|
|
408
|
+
"image",
|
|
409
|
+
"button",
|
|
410
|
+
"input",
|
|
411
|
+
"textarea",
|
|
412
|
+
"scroll-view",
|
|
413
|
+
"swiper",
|
|
414
|
+
"swiper-item",
|
|
415
|
+
"navigator",
|
|
416
|
+
"block",
|
|
417
|
+
"template",
|
|
418
|
+
"slot",
|
|
419
|
+
"icon",
|
|
420
|
+
"progress",
|
|
421
|
+
"checkbox",
|
|
422
|
+
"checkbox-group",
|
|
423
|
+
"radio",
|
|
424
|
+
"radio-group",
|
|
425
|
+
"switch",
|
|
426
|
+
"slider",
|
|
427
|
+
"picker",
|
|
428
|
+
"picker-view",
|
|
429
|
+
"picker-view-column",
|
|
430
|
+
"form",
|
|
431
|
+
"label",
|
|
432
|
+
"rich-text",
|
|
433
|
+
"web-view",
|
|
434
|
+
"map",
|
|
435
|
+
"canvas",
|
|
436
|
+
"video",
|
|
437
|
+
"audio",
|
|
438
|
+
"camera",
|
|
439
|
+
"live-player",
|
|
440
|
+
"live-pusher"
|
|
441
|
+
];
|
|
442
|
+
return !builtIn.includes(tag);
|
|
443
|
+
}
|
|
444
|
+
function advance(state, count = 1) {
|
|
445
|
+
for (let i = 0; i < count && state.pos < state.source.length; i++) {
|
|
446
|
+
if (state.source[state.pos] === "\n") {
|
|
447
|
+
state.line++;
|
|
448
|
+
state.column = 0;
|
|
449
|
+
} else {
|
|
450
|
+
state.column++;
|
|
451
|
+
}
|
|
452
|
+
state.pos++;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
function lookAhead(state, str) {
|
|
456
|
+
return state.source.slice(state.pos, state.pos + str.length) === str;
|
|
457
|
+
}
|
|
458
|
+
function consume(state, str) {
|
|
459
|
+
if (lookAhead(state, str)) {
|
|
460
|
+
advance(state, str.length);
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
function skipWhitespace(state) {
|
|
466
|
+
while (state.pos < state.source.length && /\s/.test(state.source[state.pos])) {
|
|
467
|
+
advance(state);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// src/axml/compiler.ts
|
|
472
|
+
function compileAXML(source, options = {}) {
|
|
473
|
+
const { ast, errors: parseErrors } = parseAXML(source);
|
|
474
|
+
const ctx = {
|
|
475
|
+
code: "",
|
|
476
|
+
indent: 0,
|
|
477
|
+
components: options.components ?? {},
|
|
478
|
+
usedComponents: /* @__PURE__ */ new Set(),
|
|
479
|
+
usedExpressions: /* @__PURE__ */ new Set(),
|
|
480
|
+
warnings: [],
|
|
481
|
+
errors: [...parseErrors],
|
|
482
|
+
scopeStack: []
|
|
483
|
+
};
|
|
484
|
+
if (!ast) {
|
|
485
|
+
return {
|
|
486
|
+
code: "function render() { return null; }",
|
|
487
|
+
ast: null,
|
|
488
|
+
warnings: ctx.warnings,
|
|
489
|
+
errors: ctx.errors,
|
|
490
|
+
usedComponents: ctx.usedComponents,
|
|
491
|
+
usedExpressions: ctx.usedExpressions
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
const renderCode = generateRenderFunction(ast, ctx);
|
|
495
|
+
return {
|
|
496
|
+
code: renderCode,
|
|
497
|
+
ast,
|
|
498
|
+
warnings: ctx.warnings,
|
|
499
|
+
errors: ctx.errors,
|
|
500
|
+
usedComponents: ctx.usedComponents,
|
|
501
|
+
usedExpressions: ctx.usedExpressions
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
function generateRenderFunction(ast, ctx) {
|
|
505
|
+
const bodyCode = generateElement(ast, ctx);
|
|
506
|
+
return `function render(_ctx, _cache) {
|
|
507
|
+
const { h, Fragment, renderList, renderSlot, withDirectives, resolveComponent } = _ctx._runtime;
|
|
508
|
+
return ${bodyCode};
|
|
509
|
+
}`;
|
|
510
|
+
}
|
|
511
|
+
function generateElement(node, ctx) {
|
|
512
|
+
const { tag, attributes, directives, children, isComponent } = node;
|
|
513
|
+
const forDirective = directives.find((d) => d.name === "for");
|
|
514
|
+
const ifDirective = directives.find((d) => d.name === "if");
|
|
515
|
+
const elifDirective = directives.find((d) => d.name === "elif");
|
|
516
|
+
const elseDirective = directives.find((d) => d.name === "else");
|
|
517
|
+
if (forDirective) {
|
|
518
|
+
return generateForLoop(node, forDirective, ctx);
|
|
519
|
+
}
|
|
520
|
+
if (ifDirective) {
|
|
521
|
+
return generateConditional(node, ifDirective, "if", ctx);
|
|
522
|
+
}
|
|
523
|
+
if (elifDirective) {
|
|
524
|
+
ctx.warnings.push(`a:elif without preceding a:if at line ${node.loc.start.line}`);
|
|
525
|
+
return generateConditional(node, elifDirective, "elif", ctx);
|
|
526
|
+
}
|
|
527
|
+
if (elseDirective) {
|
|
528
|
+
ctx.warnings.push(`a:else without preceding a:if at line ${node.loc.start.line}`);
|
|
529
|
+
return "null";
|
|
530
|
+
}
|
|
531
|
+
if (tag === "block" || tag === "template") {
|
|
532
|
+
return generateFragment(children, ctx);
|
|
533
|
+
}
|
|
534
|
+
if (tag === "slot") {
|
|
535
|
+
return generateSlot(node, ctx);
|
|
536
|
+
}
|
|
537
|
+
let tagCode;
|
|
538
|
+
if (isComponent) {
|
|
539
|
+
ctx.usedComponents.add(tag);
|
|
540
|
+
const componentPath = ctx.components[tag];
|
|
541
|
+
if (componentPath) {
|
|
542
|
+
tagCode = `resolveComponent("${tag}")`;
|
|
543
|
+
} else {
|
|
544
|
+
tagCode = `resolveComponent("${tag}")`;
|
|
545
|
+
ctx.warnings.push(`Unknown component "${tag}" at line ${node.loc.start.line}`);
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
548
|
+
tagCode = `"${tag}"`;
|
|
549
|
+
}
|
|
550
|
+
const propsCode = generateProps(attributes, directives, ctx);
|
|
551
|
+
const childrenCode = generateChildren(children, ctx);
|
|
552
|
+
if (childrenCode === "null") {
|
|
553
|
+
if (propsCode === "null") {
|
|
554
|
+
return `h(${tagCode})`;
|
|
555
|
+
}
|
|
556
|
+
return `h(${tagCode}, ${propsCode})`;
|
|
557
|
+
}
|
|
558
|
+
return `h(${tagCode}, ${propsCode}, ${childrenCode})`;
|
|
559
|
+
}
|
|
560
|
+
function generateForLoop(node, directive, ctx) {
|
|
561
|
+
const expression = directive.value?.expression ?? "";
|
|
562
|
+
const forMatch = expression.match(/^\s*(?:\(([^,]+),\s*([^)]+)\)|([^\s]+))\s+in\s+(.+)$/);
|
|
563
|
+
if (!forMatch) {
|
|
564
|
+
ctx.errors.push(`Invalid a:for expression: ${expression}`);
|
|
565
|
+
return "null";
|
|
566
|
+
}
|
|
567
|
+
const itemVar = forMatch[1] || forMatch[3] || "item";
|
|
568
|
+
const indexVar = forMatch[2] || "index";
|
|
569
|
+
const listExpr = forMatch[4];
|
|
570
|
+
const forItemDir = node.directives.find((d) => d.name === "for-item");
|
|
571
|
+
const forIndexDir = node.directives.find((d) => d.name === "for-index");
|
|
572
|
+
const keyDir = node.directives.find((d) => d.name === "key");
|
|
573
|
+
const finalItemVar = forItemDir?.value?.expression ?? itemVar;
|
|
574
|
+
const finalIndexVar = forIndexDir?.value?.expression ?? indexVar;
|
|
575
|
+
const keyExpr = keyDir?.value?.expression ?? finalIndexVar;
|
|
576
|
+
ctx.usedExpressions.add(listExpr);
|
|
577
|
+
ctx.scopeStack.push(finalItemVar, finalIndexVar);
|
|
578
|
+
const filteredDirectives = node.directives.filter(
|
|
579
|
+
(d) => !["for", "for-item", "for-index", "key"].includes(d.name)
|
|
580
|
+
);
|
|
581
|
+
const elementWithoutFor = { ...node, directives: filteredDirectives };
|
|
582
|
+
const elementCode = generateElement(elementWithoutFor, ctx);
|
|
583
|
+
ctx.scopeStack.pop();
|
|
584
|
+
ctx.scopeStack.pop();
|
|
585
|
+
return `renderList(_ctx.${listExpr}, (${finalItemVar}, ${finalIndexVar}) => {
|
|
586
|
+
return ${elementCode};
|
|
587
|
+
}, "${keyExpr}")`;
|
|
588
|
+
}
|
|
589
|
+
function generateConditional(node, directive, type, ctx) {
|
|
590
|
+
const expression = directive.value?.expression ?? "true";
|
|
591
|
+
ctx.usedExpressions.add(expression);
|
|
592
|
+
const filteredDirectives = node.directives.filter((d) => d.name !== type);
|
|
593
|
+
const elementWithoutCondition = { ...node, directives: filteredDirectives };
|
|
594
|
+
const elementCode = generateElement(elementWithoutCondition, ctx);
|
|
595
|
+
return `(${transformExpression(expression, ctx)}) ? ${elementCode} : null`;
|
|
596
|
+
}
|
|
597
|
+
function generateFragment(children, ctx) {
|
|
598
|
+
if (children.length === 0) {
|
|
599
|
+
return "null";
|
|
600
|
+
}
|
|
601
|
+
if (children.length === 1) {
|
|
602
|
+
return generateNode(children[0], ctx);
|
|
603
|
+
}
|
|
604
|
+
const childrenCode = children.map((child) => generateNode(child, ctx)).filter((code) => code !== "null").join(",\n ");
|
|
605
|
+
return `h(Fragment, null, [
|
|
606
|
+
${childrenCode}
|
|
607
|
+
])`;
|
|
608
|
+
}
|
|
609
|
+
function generateSlot(node, ctx) {
|
|
610
|
+
const nameAttr = node.attributes.find((a) => a.name === "name");
|
|
611
|
+
const slotName = nameAttr?.value?.type === "Literal" ? nameAttr.value.value : "default";
|
|
612
|
+
const fallback = node.children.length > 0 ? generateChildren(node.children, ctx) : "null";
|
|
613
|
+
const slotProps = node.attributes.filter((a) => a.name !== "name").map((a) => {
|
|
614
|
+
const key = a.name;
|
|
615
|
+
const value = a.value ? a.isDynamic ? transformExpression(a.value.type === "Expression" ? a.value.expression : a.value.value, ctx) : `"${a.value.type === "Literal" ? a.value.value : ""}"` : "true";
|
|
616
|
+
return `${key}: ${value}`;
|
|
617
|
+
}).join(", ");
|
|
618
|
+
const propsCode = slotProps ? `{ ${slotProps} }` : "null";
|
|
619
|
+
return `renderSlot(_ctx.$slots, "${slotName}", ${propsCode}, () => ${fallback})`;
|
|
620
|
+
}
|
|
621
|
+
function generateProps(attributes, directives, ctx) {
|
|
622
|
+
const props = [];
|
|
623
|
+
const events = [];
|
|
624
|
+
for (const attr of attributes) {
|
|
625
|
+
const { name, value, isDynamic } = attr;
|
|
626
|
+
if (name.startsWith("on") || name.startsWith("catch")) {
|
|
627
|
+
const isCatch = name.startsWith("catch");
|
|
628
|
+
const eventName = isCatch ? name.slice(5) : name.slice(2);
|
|
629
|
+
const handler = value?.type === "Expression" ? value.expression : value?.type === "Literal" ? value.value : "";
|
|
630
|
+
if (handler) {
|
|
631
|
+
ctx.usedExpressions.add(handler);
|
|
632
|
+
const eventKey = eventName.toLowerCase();
|
|
633
|
+
events.push(`${eventKey}: { handler: _ctx.${handler}, catch: ${isCatch} }`);
|
|
634
|
+
}
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
637
|
+
if (name === "class") {
|
|
638
|
+
if (isDynamic && value?.type === "Expression") {
|
|
639
|
+
ctx.usedExpressions.add(value.expression);
|
|
640
|
+
props.push(`class: ${transformExpression(value.expression, ctx)}`);
|
|
641
|
+
} else if (value?.type === "Literal") {
|
|
642
|
+
props.push(`class: "${value.value}"`);
|
|
643
|
+
}
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
if (name === "style") {
|
|
647
|
+
if (isDynamic && value?.type === "Expression") {
|
|
648
|
+
ctx.usedExpressions.add(value.expression);
|
|
649
|
+
props.push(`style: ${transformExpression(value.expression, ctx)}`);
|
|
650
|
+
} else if (value?.type === "Literal") {
|
|
651
|
+
props.push(`style: "${value.value}"`);
|
|
652
|
+
}
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
655
|
+
if (name.startsWith("data-")) {
|
|
656
|
+
const dataKey = name.slice(5);
|
|
657
|
+
if (isDynamic && value?.type === "Expression") {
|
|
658
|
+
ctx.usedExpressions.add(value.expression);
|
|
659
|
+
props.push(`"data-${dataKey}": ${transformExpression(value.expression, ctx)}`);
|
|
660
|
+
} else if (value?.type === "Literal") {
|
|
661
|
+
props.push(`"data-${dataKey}": "${value.value}"`);
|
|
662
|
+
} else {
|
|
663
|
+
props.push(`"data-${dataKey}": true`);
|
|
664
|
+
}
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
if (isDynamic && value?.type === "Expression") {
|
|
668
|
+
ctx.usedExpressions.add(value.expression);
|
|
669
|
+
props.push(`${name}: ${transformExpression(value.expression, ctx)}`);
|
|
670
|
+
} else if (value?.type === "Literal") {
|
|
671
|
+
props.push(`${name}: "${value.value}"`);
|
|
672
|
+
} else if (value === null) {
|
|
673
|
+
props.push(`${name}: true`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
const refDirective = directives.find((d) => d.name === "ref");
|
|
677
|
+
if (refDirective?.value) {
|
|
678
|
+
props.push(`ref: "${refDirective.value.expression}"`);
|
|
679
|
+
}
|
|
680
|
+
if (events.length > 0) {
|
|
681
|
+
props.push(`_events: { ${events.join(", ")} }`);
|
|
682
|
+
}
|
|
683
|
+
if (props.length === 0) {
|
|
684
|
+
return "null";
|
|
685
|
+
}
|
|
686
|
+
return `{ ${props.join(", ")} }`;
|
|
687
|
+
}
|
|
688
|
+
function generateChildren(children, ctx) {
|
|
689
|
+
const filteredChildren = children.filter((child) => {
|
|
690
|
+
if (child.type === "Comment") return false;
|
|
691
|
+
if (child.type === "Text" && !child.content.trim()) return false;
|
|
692
|
+
return true;
|
|
693
|
+
});
|
|
694
|
+
if (filteredChildren.length === 0) {
|
|
695
|
+
return "null";
|
|
696
|
+
}
|
|
697
|
+
const processedChildren = processConditionalChains(filteredChildren, ctx);
|
|
698
|
+
if (processedChildren.length === 1) {
|
|
699
|
+
return generateNode(processedChildren[0].node, ctx, processedChildren[0].chain);
|
|
700
|
+
}
|
|
701
|
+
const childrenCode = processedChildren.map(({ node, chain }) => generateNode(node, ctx, chain)).join(",\n ");
|
|
702
|
+
return `[
|
|
703
|
+
${childrenCode}
|
|
704
|
+
]`;
|
|
705
|
+
}
|
|
706
|
+
function processConditionalChains(children, _ctx) {
|
|
707
|
+
const result = [];
|
|
708
|
+
let currentChain = [];
|
|
709
|
+
for (let i = 0; i < children.length; i++) {
|
|
710
|
+
const child = children[i];
|
|
711
|
+
if (child.type !== "Element") {
|
|
712
|
+
if (currentChain.length > 0) {
|
|
713
|
+
result.push({ node: currentChain[0], chain: currentChain.slice(1) });
|
|
714
|
+
currentChain = [];
|
|
715
|
+
}
|
|
716
|
+
result.push({ node: child });
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
const hasIf = child.directives.some((d) => d.name === "if");
|
|
720
|
+
const hasElif = child.directives.some((d) => d.name === "elif");
|
|
721
|
+
const hasElse = child.directives.some((d) => d.name === "else");
|
|
722
|
+
if (hasIf) {
|
|
723
|
+
if (currentChain.length > 0) {
|
|
724
|
+
result.push({ node: currentChain[0], chain: currentChain.slice(1) });
|
|
725
|
+
}
|
|
726
|
+
currentChain = [child];
|
|
727
|
+
} else if ((hasElif || hasElse) && currentChain.length > 0) {
|
|
728
|
+
currentChain.push(child);
|
|
729
|
+
if (hasElse) {
|
|
730
|
+
result.push({ node: currentChain[0], chain: currentChain.slice(1) });
|
|
731
|
+
currentChain = [];
|
|
732
|
+
}
|
|
733
|
+
} else {
|
|
734
|
+
if (currentChain.length > 0) {
|
|
735
|
+
result.push({ node: currentChain[0], chain: currentChain.slice(1) });
|
|
736
|
+
currentChain = [];
|
|
737
|
+
}
|
|
738
|
+
result.push({ node: child });
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (currentChain.length > 0) {
|
|
742
|
+
result.push({ node: currentChain[0], chain: currentChain.slice(1) });
|
|
743
|
+
}
|
|
744
|
+
return result;
|
|
745
|
+
}
|
|
746
|
+
function generateNode(node, ctx, conditionalChain) {
|
|
747
|
+
switch (node.type) {
|
|
748
|
+
case "Element":
|
|
749
|
+
if (conditionalChain && conditionalChain.length > 0) {
|
|
750
|
+
return generateConditionalChain(node, conditionalChain, ctx);
|
|
751
|
+
}
|
|
752
|
+
return generateElement(node, ctx);
|
|
753
|
+
case "Text":
|
|
754
|
+
return generateText(node, ctx);
|
|
755
|
+
case "Expression":
|
|
756
|
+
return generateExpression(node, ctx);
|
|
757
|
+
case "Comment":
|
|
758
|
+
return "null";
|
|
759
|
+
default:
|
|
760
|
+
return "null";
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
function generateConditionalChain(ifNode, chain, ctx) {
|
|
764
|
+
const ifDirective = ifNode.directives.find((d) => d.name === "if");
|
|
765
|
+
if (!ifDirective?.value) {
|
|
766
|
+
ctx.errors.push(`Missing condition in a:if at line ${ifNode.loc.start.line}`);
|
|
767
|
+
return "null";
|
|
768
|
+
}
|
|
769
|
+
const ifCondition = transformExpression(ifDirective.value.expression, ctx);
|
|
770
|
+
ctx.usedExpressions.add(ifDirective.value.expression);
|
|
771
|
+
const ifBranchNode = {
|
|
772
|
+
...ifNode,
|
|
773
|
+
directives: ifNode.directives.filter((d) => d.name !== "if")
|
|
774
|
+
};
|
|
775
|
+
const ifBranch = generateElement(ifBranchNode, ctx);
|
|
776
|
+
let code = `(${ifCondition}) ? ${ifBranch}`;
|
|
777
|
+
for (const chainNode of chain) {
|
|
778
|
+
const elifDirective = chainNode.directives.find((d) => d.name === "elif");
|
|
779
|
+
const elseDirective = chainNode.directives.find((d) => d.name === "else");
|
|
780
|
+
const branchNode = {
|
|
781
|
+
...chainNode,
|
|
782
|
+
directives: chainNode.directives.filter((d) => !["elif", "else"].includes(d.name))
|
|
783
|
+
};
|
|
784
|
+
const branchCode = generateElement(branchNode, ctx);
|
|
785
|
+
if (elifDirective?.value) {
|
|
786
|
+
const elifCondition = transformExpression(elifDirective.value.expression, ctx);
|
|
787
|
+
ctx.usedExpressions.add(elifDirective.value.expression);
|
|
788
|
+
code += ` : (${elifCondition}) ? ${branchCode}`;
|
|
789
|
+
} else if (elseDirective) {
|
|
790
|
+
code += ` : ${branchCode}`;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
const hasElse = chain.some((n) => n.directives.some((d) => d.name === "else"));
|
|
794
|
+
if (!hasElse) {
|
|
795
|
+
code += " : null";
|
|
796
|
+
}
|
|
797
|
+
return code;
|
|
798
|
+
}
|
|
799
|
+
function generateText(node, ctx) {
|
|
800
|
+
const content = node.content.trim();
|
|
801
|
+
if (!content) return "null";
|
|
802
|
+
if (content.includes("{{")) {
|
|
803
|
+
return generateInterpolatedText(content, ctx);
|
|
804
|
+
}
|
|
805
|
+
return `"${escapeString(content)}"`;
|
|
806
|
+
}
|
|
807
|
+
function generateInterpolatedText(content, ctx) {
|
|
808
|
+
const parts = [];
|
|
809
|
+
let lastIndex = 0;
|
|
810
|
+
const regex = /\{\{(.+?)\}\}/g;
|
|
811
|
+
let match;
|
|
812
|
+
while ((match = regex.exec(content)) !== null) {
|
|
813
|
+
if (match.index > lastIndex) {
|
|
814
|
+
const text = content.slice(lastIndex, match.index);
|
|
815
|
+
if (text) {
|
|
816
|
+
parts.push(`"${escapeString(text)}"`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
const expr = match[1].trim();
|
|
820
|
+
ctx.usedExpressions.add(expr);
|
|
821
|
+
parts.push(transformExpression(expr, ctx));
|
|
822
|
+
lastIndex = regex.lastIndex;
|
|
823
|
+
}
|
|
824
|
+
if (lastIndex < content.length) {
|
|
825
|
+
const text = content.slice(lastIndex);
|
|
826
|
+
if (text) {
|
|
827
|
+
parts.push(`"${escapeString(text)}"`);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
if (parts.length === 1) {
|
|
831
|
+
return parts[0];
|
|
832
|
+
}
|
|
833
|
+
return parts.join(" + ");
|
|
834
|
+
}
|
|
835
|
+
function generateExpression(node, ctx) {
|
|
836
|
+
ctx.usedExpressions.add(node.expression);
|
|
837
|
+
return transformExpression(node.expression, ctx);
|
|
838
|
+
}
|
|
839
|
+
function transformExpression(expr, ctx) {
|
|
840
|
+
if (/^['"`].*['"`]$/.test(expr)) return expr;
|
|
841
|
+
if (/^\d+(\.\d+)?$/.test(expr)) return expr;
|
|
842
|
+
if (expr === "true" || expr === "false" || expr === "null" || expr === "undefined") {
|
|
843
|
+
return expr;
|
|
844
|
+
}
|
|
845
|
+
const scopeVars = ctx.scopeStack;
|
|
846
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(expr)) {
|
|
847
|
+
if (scopeVars.includes(expr)) {
|
|
848
|
+
return expr;
|
|
849
|
+
}
|
|
850
|
+
return `_ctx.${expr}`;
|
|
851
|
+
}
|
|
852
|
+
const rootMatch = expr.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)/);
|
|
853
|
+
if (rootMatch) {
|
|
854
|
+
const root = rootMatch[1];
|
|
855
|
+
if (scopeVars.includes(root)) {
|
|
856
|
+
return expr;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return expr.replace(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b(?!\s*:)/g, (match, id) => {
|
|
860
|
+
const keywords = ["true", "false", "null", "undefined", "this", "typeof", "instanceof", "new", "void", "delete"];
|
|
861
|
+
if (keywords.includes(id) || scopeVars.includes(id)) {
|
|
862
|
+
return match;
|
|
863
|
+
}
|
|
864
|
+
return `_ctx.${id}`;
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
function escapeString(str) {
|
|
868
|
+
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// src/acss/parser.ts
|
|
872
|
+
function createPosition2(state) {
|
|
873
|
+
return {
|
|
874
|
+
line: state.line,
|
|
875
|
+
column: state.column,
|
|
876
|
+
offset: state.pos
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function createLoc2(start, end, source) {
|
|
880
|
+
return { start, end, source };
|
|
881
|
+
}
|
|
882
|
+
function parseACSS(source) {
|
|
883
|
+
const state = {
|
|
884
|
+
source,
|
|
885
|
+
pos: 0,
|
|
886
|
+
line: 1,
|
|
887
|
+
column: 0,
|
|
888
|
+
errors: []
|
|
889
|
+
};
|
|
890
|
+
const start = createPosition2(state);
|
|
891
|
+
const rules = [];
|
|
892
|
+
const imports = [];
|
|
893
|
+
while (state.pos < state.source.length) {
|
|
894
|
+
skipWhitespaceAndComments(state);
|
|
895
|
+
if (state.pos >= state.source.length) break;
|
|
896
|
+
if (lookAhead2(state, "@import")) {
|
|
897
|
+
const importRule = parseImport(state);
|
|
898
|
+
if (importRule) {
|
|
899
|
+
imports.push(importRule);
|
|
900
|
+
}
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
903
|
+
if (lookAhead2(state, "@media")) {
|
|
904
|
+
const mediaRule = parseMediaRule(state);
|
|
905
|
+
if (mediaRule) {
|
|
906
|
+
rules.push(mediaRule);
|
|
907
|
+
}
|
|
908
|
+
continue;
|
|
909
|
+
}
|
|
910
|
+
if (lookAhead2(state, "@keyframes") || lookAhead2(state, "@-webkit-keyframes")) {
|
|
911
|
+
const keyframesRule = parseKeyframesRule(state);
|
|
912
|
+
if (keyframesRule) {
|
|
913
|
+
rules.push(keyframesRule);
|
|
914
|
+
}
|
|
915
|
+
continue;
|
|
916
|
+
}
|
|
917
|
+
const rule = parseStyleRule(state);
|
|
918
|
+
if (rule) {
|
|
919
|
+
rules.push(rule);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
const end = createPosition2(state);
|
|
923
|
+
return {
|
|
924
|
+
ast: {
|
|
925
|
+
type: "Stylesheet",
|
|
926
|
+
rules,
|
|
927
|
+
imports,
|
|
928
|
+
start: start.offset,
|
|
929
|
+
end: end.offset,
|
|
930
|
+
loc: createLoc2(start, end)
|
|
931
|
+
},
|
|
932
|
+
errors: state.errors
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
function parseImport(state) {
|
|
936
|
+
const start = createPosition2(state);
|
|
937
|
+
advance2(state, 7);
|
|
938
|
+
skipWhitespace2(state);
|
|
939
|
+
let path = "";
|
|
940
|
+
const quote = state.source[state.pos];
|
|
941
|
+
if (quote === '"' || quote === "'") {
|
|
942
|
+
advance2(state);
|
|
943
|
+
while (state.pos < state.source.length && state.source[state.pos] !== quote) {
|
|
944
|
+
path += state.source[state.pos];
|
|
945
|
+
advance2(state);
|
|
946
|
+
}
|
|
947
|
+
advance2(state);
|
|
948
|
+
} else {
|
|
949
|
+
state.errors.push(`Expected quoted string at line ${state.line}`);
|
|
950
|
+
skipToSemicolon(state);
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
skipWhitespace2(state);
|
|
954
|
+
consume2(state, ";");
|
|
955
|
+
const end = createPosition2(state);
|
|
956
|
+
return {
|
|
957
|
+
type: "Import",
|
|
958
|
+
path,
|
|
959
|
+
start: start.offset,
|
|
960
|
+
end: end.offset,
|
|
961
|
+
loc: createLoc2(start, end)
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
function parseMediaRule(state) {
|
|
965
|
+
const start = createPosition2(state);
|
|
966
|
+
advance2(state, 6);
|
|
967
|
+
skipWhitespace2(state);
|
|
968
|
+
let query = "";
|
|
969
|
+
while (state.pos < state.source.length && state.source[state.pos] !== "{") {
|
|
970
|
+
query += state.source[state.pos];
|
|
971
|
+
advance2(state);
|
|
972
|
+
}
|
|
973
|
+
query = query.trim();
|
|
974
|
+
if (!consume2(state, "{")) {
|
|
975
|
+
state.errors.push(`Expected '{' at line ${state.line}`);
|
|
976
|
+
return null;
|
|
977
|
+
}
|
|
978
|
+
const rules = [];
|
|
979
|
+
while (state.pos < state.source.length && state.source[state.pos] !== "}") {
|
|
980
|
+
skipWhitespaceAndComments(state);
|
|
981
|
+
if (state.source[state.pos] === "}") break;
|
|
982
|
+
const rule = parseStyleRule(state);
|
|
983
|
+
if (rule) {
|
|
984
|
+
rules.push(rule);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
consume2(state, "}");
|
|
988
|
+
const end = createPosition2(state);
|
|
989
|
+
return {
|
|
990
|
+
type: "MediaRule",
|
|
991
|
+
query,
|
|
992
|
+
rules,
|
|
993
|
+
start: start.offset,
|
|
994
|
+
end: end.offset,
|
|
995
|
+
loc: createLoc2(start, end)
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
function parseKeyframesRule(state) {
|
|
999
|
+
const start = createPosition2(state);
|
|
1000
|
+
if (lookAhead2(state, "@-webkit-keyframes")) {
|
|
1001
|
+
advance2(state, 18);
|
|
1002
|
+
} else {
|
|
1003
|
+
advance2(state, 10);
|
|
1004
|
+
}
|
|
1005
|
+
skipWhitespace2(state);
|
|
1006
|
+
let name = "";
|
|
1007
|
+
while (state.pos < state.source.length && !/[\s{]/.test(state.source[state.pos])) {
|
|
1008
|
+
name += state.source[state.pos];
|
|
1009
|
+
advance2(state);
|
|
1010
|
+
}
|
|
1011
|
+
skipWhitespace2(state);
|
|
1012
|
+
if (!consume2(state, "{")) {
|
|
1013
|
+
state.errors.push(`Expected '{' at line ${state.line}`);
|
|
1014
|
+
return null;
|
|
1015
|
+
}
|
|
1016
|
+
const keyframes = [];
|
|
1017
|
+
while (state.pos < state.source.length && state.source[state.pos] !== "}") {
|
|
1018
|
+
skipWhitespaceAndComments(state);
|
|
1019
|
+
if (state.source[state.pos] === "}") break;
|
|
1020
|
+
const keyframe = parseKeyframe(state);
|
|
1021
|
+
if (keyframe) {
|
|
1022
|
+
keyframes.push(keyframe);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
consume2(state, "}");
|
|
1026
|
+
const end = createPosition2(state);
|
|
1027
|
+
return {
|
|
1028
|
+
type: "KeyframesRule",
|
|
1029
|
+
name,
|
|
1030
|
+
keyframes,
|
|
1031
|
+
start: start.offset,
|
|
1032
|
+
end: end.offset,
|
|
1033
|
+
loc: createLoc2(start, end)
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
function parseKeyframe(state) {
|
|
1037
|
+
const start = createPosition2(state);
|
|
1038
|
+
let selector = "";
|
|
1039
|
+
while (state.pos < state.source.length && state.source[state.pos] !== "{") {
|
|
1040
|
+
selector += state.source[state.pos];
|
|
1041
|
+
advance2(state);
|
|
1042
|
+
}
|
|
1043
|
+
selector = selector.trim();
|
|
1044
|
+
if (!consume2(state, "{")) {
|
|
1045
|
+
state.errors.push(`Expected '{' at line ${state.line}`);
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
const declarations = parseDeclarations(state);
|
|
1049
|
+
consume2(state, "}");
|
|
1050
|
+
const end = createPosition2(state);
|
|
1051
|
+
return {
|
|
1052
|
+
type: "Keyframe",
|
|
1053
|
+
selector,
|
|
1054
|
+
declarations,
|
|
1055
|
+
start: start.offset,
|
|
1056
|
+
end: end.offset,
|
|
1057
|
+
loc: createLoc2(start, end)
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
function parseStyleRule(state) {
|
|
1061
|
+
const start = createPosition2(state);
|
|
1062
|
+
const selectors = parseSelectors(state);
|
|
1063
|
+
if (selectors.length === 0) {
|
|
1064
|
+
skipToCloseBrace(state);
|
|
1065
|
+
return null;
|
|
1066
|
+
}
|
|
1067
|
+
skipWhitespace2(state);
|
|
1068
|
+
if (!consume2(state, "{")) {
|
|
1069
|
+
state.errors.push(`Expected '{' at line ${state.line}`);
|
|
1070
|
+
skipToCloseBrace(state);
|
|
1071
|
+
return null;
|
|
1072
|
+
}
|
|
1073
|
+
const declarations = parseDeclarations(state);
|
|
1074
|
+
consume2(state, "}");
|
|
1075
|
+
const end = createPosition2(state);
|
|
1076
|
+
return {
|
|
1077
|
+
type: "StyleRule",
|
|
1078
|
+
selectors,
|
|
1079
|
+
declarations,
|
|
1080
|
+
start: start.offset,
|
|
1081
|
+
end: end.offset,
|
|
1082
|
+
loc: createLoc2(start, end)
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
function parseSelectors(state) {
|
|
1086
|
+
const selectors = [];
|
|
1087
|
+
let current = "";
|
|
1088
|
+
const start = createPosition2(state);
|
|
1089
|
+
while (state.pos < state.source.length) {
|
|
1090
|
+
const char = state.source[state.pos];
|
|
1091
|
+
if (char === "{") break;
|
|
1092
|
+
if (char === ",") {
|
|
1093
|
+
const trimmed2 = current.trim();
|
|
1094
|
+
if (trimmed2) {
|
|
1095
|
+
const end = createPosition2(state);
|
|
1096
|
+
selectors.push({
|
|
1097
|
+
type: "Selector",
|
|
1098
|
+
value: trimmed2,
|
|
1099
|
+
specificity: calculateSpecificity(trimmed2),
|
|
1100
|
+
start: start.offset,
|
|
1101
|
+
end: end.offset,
|
|
1102
|
+
loc: createLoc2(start, end)
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
advance2(state);
|
|
1106
|
+
current = "";
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
current += char;
|
|
1110
|
+
advance2(state);
|
|
1111
|
+
}
|
|
1112
|
+
const trimmed = current.trim();
|
|
1113
|
+
if (trimmed) {
|
|
1114
|
+
const end = createPosition2(state);
|
|
1115
|
+
selectors.push({
|
|
1116
|
+
type: "Selector",
|
|
1117
|
+
value: trimmed,
|
|
1118
|
+
specificity: calculateSpecificity(trimmed),
|
|
1119
|
+
start: start.offset,
|
|
1120
|
+
end: end.offset,
|
|
1121
|
+
loc: createLoc2(start, end)
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
return selectors;
|
|
1125
|
+
}
|
|
1126
|
+
function calculateSpecificity(selector) {
|
|
1127
|
+
let ids = 0;
|
|
1128
|
+
let classes = 0;
|
|
1129
|
+
let elements = 0;
|
|
1130
|
+
ids = (selector.match(/#[a-zA-Z_-][a-zA-Z0-9_-]*/g) || []).length;
|
|
1131
|
+
classes = (selector.match(/\.[a-zA-Z_-][a-zA-Z0-9_-]*/g) || []).length;
|
|
1132
|
+
classes += (selector.match(/\[[^\]]+\]/g) || []).length;
|
|
1133
|
+
classes += (selector.match(/:[a-zA-Z-]+(?:\([^)]*\))?/g) || []).filter(
|
|
1134
|
+
(p) => !p.startsWith("::")
|
|
1135
|
+
).length;
|
|
1136
|
+
const withoutIds = selector.replace(/#[a-zA-Z_-][a-zA-Z0-9_-]*/g, "");
|
|
1137
|
+
const withoutClasses = withoutIds.replace(/\.[a-zA-Z_-][a-zA-Z0-9_-]*/g, "");
|
|
1138
|
+
const withoutAttrs = withoutClasses.replace(/\[[^\]]+\]/g, "");
|
|
1139
|
+
const withoutPseudo = withoutAttrs.replace(/:[a-zA-Z-]+(?:\([^)]*\))?/g, "");
|
|
1140
|
+
const tagMatches = withoutPseudo.match(/[a-zA-Z][a-zA-Z0-9-]*/g) || [];
|
|
1141
|
+
elements = tagMatches.filter((t) => !["not", "is", "where", "has"].includes(t)).length;
|
|
1142
|
+
elements += (selector.match(/::[a-zA-Z-]+/g) || []).length;
|
|
1143
|
+
return [ids, classes, elements];
|
|
1144
|
+
}
|
|
1145
|
+
function parseDeclarations(state) {
|
|
1146
|
+
const declarations = [];
|
|
1147
|
+
while (state.pos < state.source.length && state.source[state.pos] !== "}") {
|
|
1148
|
+
skipWhitespaceAndComments(state);
|
|
1149
|
+
if (state.source[state.pos] === "}") break;
|
|
1150
|
+
const declaration = parseDeclaration(state);
|
|
1151
|
+
if (declaration) {
|
|
1152
|
+
declarations.push(declaration);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return declarations;
|
|
1156
|
+
}
|
|
1157
|
+
function parseDeclaration(state) {
|
|
1158
|
+
const start = createPosition2(state);
|
|
1159
|
+
let property = "";
|
|
1160
|
+
while (state.pos < state.source.length && state.source[state.pos] !== ":" && state.source[state.pos] !== "}") {
|
|
1161
|
+
property += state.source[state.pos];
|
|
1162
|
+
advance2(state);
|
|
1163
|
+
}
|
|
1164
|
+
property = property.trim();
|
|
1165
|
+
if (!property || !consume2(state, ":")) {
|
|
1166
|
+
skipToSemicolon(state);
|
|
1167
|
+
return null;
|
|
1168
|
+
}
|
|
1169
|
+
skipWhitespace2(state);
|
|
1170
|
+
let value = "";
|
|
1171
|
+
let important = false;
|
|
1172
|
+
let parenDepth = 0;
|
|
1173
|
+
while (state.pos < state.source.length) {
|
|
1174
|
+
const char = state.source[state.pos];
|
|
1175
|
+
if (char === "(") parenDepth++;
|
|
1176
|
+
if (char === ")") parenDepth--;
|
|
1177
|
+
if (parenDepth === 0 && (char === ";" || char === "}")) {
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
1180
|
+
value += char;
|
|
1181
|
+
advance2(state);
|
|
1182
|
+
}
|
|
1183
|
+
value = value.trim();
|
|
1184
|
+
if (value.endsWith("!important")) {
|
|
1185
|
+
important = true;
|
|
1186
|
+
value = value.slice(0, -10).trim();
|
|
1187
|
+
}
|
|
1188
|
+
consume2(state, ";");
|
|
1189
|
+
const end = createPosition2(state);
|
|
1190
|
+
if (!/^[a-zA-Z-]+$/.test(property)) {
|
|
1191
|
+
state.errors.push(`Invalid property name "${property}" at line ${start.line}`);
|
|
1192
|
+
return null;
|
|
1193
|
+
}
|
|
1194
|
+
return {
|
|
1195
|
+
type: "Declaration",
|
|
1196
|
+
property,
|
|
1197
|
+
value,
|
|
1198
|
+
important,
|
|
1199
|
+
start: start.offset,
|
|
1200
|
+
end: end.offset,
|
|
1201
|
+
loc: createLoc2(start, end)
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function advance2(state, count = 1) {
|
|
1205
|
+
for (let i = 0; i < count && state.pos < state.source.length; i++) {
|
|
1206
|
+
if (state.source[state.pos] === "\n") {
|
|
1207
|
+
state.line++;
|
|
1208
|
+
state.column = 0;
|
|
1209
|
+
} else {
|
|
1210
|
+
state.column++;
|
|
1211
|
+
}
|
|
1212
|
+
state.pos++;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
function lookAhead2(state, str) {
|
|
1216
|
+
return state.source.slice(state.pos, state.pos + str.length) === str;
|
|
1217
|
+
}
|
|
1218
|
+
function consume2(state, str) {
|
|
1219
|
+
if (lookAhead2(state, str)) {
|
|
1220
|
+
advance2(state, str.length);
|
|
1221
|
+
return true;
|
|
1222
|
+
}
|
|
1223
|
+
return false;
|
|
1224
|
+
}
|
|
1225
|
+
function skipWhitespace2(state) {
|
|
1226
|
+
while (state.pos < state.source.length && /\s/.test(state.source[state.pos])) {
|
|
1227
|
+
advance2(state);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
function skipWhitespaceAndComments(state) {
|
|
1231
|
+
while (state.pos < state.source.length) {
|
|
1232
|
+
skipWhitespace2(state);
|
|
1233
|
+
if (lookAhead2(state, "/*")) {
|
|
1234
|
+
advance2(state, 2);
|
|
1235
|
+
while (state.pos < state.source.length && !lookAhead2(state, "*/")) {
|
|
1236
|
+
advance2(state);
|
|
1237
|
+
}
|
|
1238
|
+
advance2(state, 2);
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
if (lookAhead2(state, "//")) {
|
|
1242
|
+
while (state.pos < state.source.length && state.source[state.pos] !== "\n") {
|
|
1243
|
+
advance2(state);
|
|
1244
|
+
}
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
break;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
function skipToSemicolon(state) {
|
|
1251
|
+
while (state.pos < state.source.length && state.source[state.pos] !== ";" && state.source[state.pos] !== "}") {
|
|
1252
|
+
advance2(state);
|
|
1253
|
+
}
|
|
1254
|
+
consume2(state, ";");
|
|
1255
|
+
}
|
|
1256
|
+
function skipToCloseBrace(state) {
|
|
1257
|
+
let depth = 0;
|
|
1258
|
+
while (state.pos < state.source.length) {
|
|
1259
|
+
if (state.source[state.pos] === "{") depth++;
|
|
1260
|
+
if (state.source[state.pos] === "}") {
|
|
1261
|
+
if (depth === 0) {
|
|
1262
|
+
advance2(state);
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
depth--;
|
|
1266
|
+
}
|
|
1267
|
+
advance2(state);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// src/acss/compiler.ts
|
|
1272
|
+
var PREFIXED_PROPERTIES = {
|
|
1273
|
+
"transform": ["-webkit-transform"],
|
|
1274
|
+
"transform-origin": ["-webkit-transform-origin"],
|
|
1275
|
+
"transition": ["-webkit-transition"],
|
|
1276
|
+
"animation": ["-webkit-animation"],
|
|
1277
|
+
"animation-name": ["-webkit-animation-name"],
|
|
1278
|
+
"animation-duration": ["-webkit-animation-duration"],
|
|
1279
|
+
"animation-timing-function": ["-webkit-animation-timing-function"],
|
|
1280
|
+
"animation-delay": ["-webkit-animation-delay"],
|
|
1281
|
+
"animation-iteration-count": ["-webkit-animation-iteration-count"],
|
|
1282
|
+
"animation-direction": ["-webkit-animation-direction"],
|
|
1283
|
+
"animation-fill-mode": ["-webkit-animation-fill-mode"],
|
|
1284
|
+
"animation-play-state": ["-webkit-animation-play-state"],
|
|
1285
|
+
"flex": ["-webkit-flex"],
|
|
1286
|
+
"flex-direction": ["-webkit-flex-direction"],
|
|
1287
|
+
"flex-wrap": ["-webkit-flex-wrap"],
|
|
1288
|
+
"flex-flow": ["-webkit-flex-flow"],
|
|
1289
|
+
"justify-content": ["-webkit-justify-content"],
|
|
1290
|
+
"align-items": ["-webkit-align-items"],
|
|
1291
|
+
"align-content": ["-webkit-align-content"],
|
|
1292
|
+
"align-self": ["-webkit-align-self"],
|
|
1293
|
+
"order": ["-webkit-order"],
|
|
1294
|
+
"flex-grow": ["-webkit-flex-grow"],
|
|
1295
|
+
"flex-shrink": ["-webkit-flex-shrink"],
|
|
1296
|
+
"flex-basis": ["-webkit-flex-basis"],
|
|
1297
|
+
"user-select": ["-webkit-user-select", "-moz-user-select"],
|
|
1298
|
+
"appearance": ["-webkit-appearance", "-moz-appearance"],
|
|
1299
|
+
"backdrop-filter": ["-webkit-backdrop-filter"],
|
|
1300
|
+
"background-clip": ["-webkit-background-clip"]
|
|
1301
|
+
};
|
|
1302
|
+
function compileACSS(source, options = {}) {
|
|
1303
|
+
const { ast, errors: parseErrors } = parseACSS(source);
|
|
1304
|
+
const warnings = [];
|
|
1305
|
+
const errors = [...parseErrors];
|
|
1306
|
+
const animations = /* @__PURE__ */ new Set();
|
|
1307
|
+
const imports = ast.imports.map((i) => i.path);
|
|
1308
|
+
const processedRules = ast.rules.map((rule) => processRule(rule, options, animations, warnings));
|
|
1309
|
+
const css = generateCSS(processedRules, options, warnings);
|
|
1310
|
+
return {
|
|
1311
|
+
css,
|
|
1312
|
+
ast,
|
|
1313
|
+
warnings,
|
|
1314
|
+
errors,
|
|
1315
|
+
imports,
|
|
1316
|
+
animations
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
function processRule(rule, options, animations, warnings) {
|
|
1320
|
+
switch (rule.type) {
|
|
1321
|
+
case "StyleRule":
|
|
1322
|
+
return processStyleRule(rule, options, animations, warnings);
|
|
1323
|
+
case "MediaRule":
|
|
1324
|
+
return {
|
|
1325
|
+
...rule,
|
|
1326
|
+
rules: rule.rules.map((r) => processStyleRule(r, options, animations, warnings))
|
|
1327
|
+
};
|
|
1328
|
+
case "KeyframesRule":
|
|
1329
|
+
animations.add(rule.name);
|
|
1330
|
+
return processKeyframesRule(rule, options, warnings);
|
|
1331
|
+
default:
|
|
1332
|
+
return rule;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
function processStyleRule(rule, options, animations, warnings) {
|
|
1336
|
+
let selectors = rule.selectors;
|
|
1337
|
+
if (options.scoped && options.scopeId) {
|
|
1338
|
+
selectors = selectors.map((s) => ({
|
|
1339
|
+
...s,
|
|
1340
|
+
value: scopeSelector(s.value, options.scopeId)
|
|
1341
|
+
}));
|
|
1342
|
+
}
|
|
1343
|
+
let declarations = rule.declarations.map((d) => processDeclaration(d, options, warnings));
|
|
1344
|
+
if (options.autoprefixer) {
|
|
1345
|
+
declarations = addVendorPrefixes(declarations);
|
|
1346
|
+
}
|
|
1347
|
+
declarations.forEach((d) => {
|
|
1348
|
+
if (d.property === "animation" || d.property === "animation-name") {
|
|
1349
|
+
const animName = d.value.split(/\s+/)[0];
|
|
1350
|
+
if (animName && !animName.startsWith("var(")) {
|
|
1351
|
+
animations.add(animName);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
return {
|
|
1356
|
+
...rule,
|
|
1357
|
+
selectors,
|
|
1358
|
+
declarations
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
function processKeyframesRule(rule, options, warnings) {
|
|
1362
|
+
return {
|
|
1363
|
+
...rule,
|
|
1364
|
+
keyframes: rule.keyframes.map((kf) => ({
|
|
1365
|
+
...kf,
|
|
1366
|
+
declarations: kf.declarations.map((d) => processDeclaration(d, options, warnings))
|
|
1367
|
+
}))
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
function processDeclaration(decl, options, warnings) {
|
|
1371
|
+
let { value } = decl;
|
|
1372
|
+
if (options.rpxToRem) {
|
|
1373
|
+
value = convertRpxToRem(value, options);
|
|
1374
|
+
}
|
|
1375
|
+
if (!value) {
|
|
1376
|
+
warnings.push(`Empty value for property "${decl.property}"`);
|
|
1377
|
+
}
|
|
1378
|
+
return {
|
|
1379
|
+
...decl,
|
|
1380
|
+
value
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
function convertRpxToRem(value, options) {
|
|
1384
|
+
const designWidth = options.designWidth ?? 750;
|
|
1385
|
+
const baseFontSize = options.baseFontSize ?? 16;
|
|
1386
|
+
return value.replace(/(\d+(?:\.\d+)?)\s*rpx/gi, (_, num) => {
|
|
1387
|
+
const px = parseFloat(num) / designWidth * 375;
|
|
1388
|
+
const rem = px / baseFontSize;
|
|
1389
|
+
return `${rem.toFixed(6).replace(/\.?0+$/, "")}rem`;
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
function scopeSelector(selector, scopeId) {
|
|
1393
|
+
const scopeAttr = `[data-v-${scopeId}]`;
|
|
1394
|
+
return selector.split(/\s*([>+~])\s*/).map((part, i) => {
|
|
1395
|
+
if (i % 2 === 1) return part;
|
|
1396
|
+
if (/^(html|body|:root)$/i.test(part)) return part;
|
|
1397
|
+
const pseudoMatch = part.match(/^(.+?)(::[\w-]+)$/);
|
|
1398
|
+
if (pseudoMatch) {
|
|
1399
|
+
return `${pseudoMatch[1]}${scopeAttr}${pseudoMatch[2]}`;
|
|
1400
|
+
}
|
|
1401
|
+
const pseudoClassMatch = part.match(/^(.+?)(:[\w-]+(?:\([^)]*\))?)$/);
|
|
1402
|
+
if (pseudoClassMatch) {
|
|
1403
|
+
return `${pseudoClassMatch[1]}${scopeAttr}${pseudoClassMatch[2]}`;
|
|
1404
|
+
}
|
|
1405
|
+
return `${part}${scopeAttr}`;
|
|
1406
|
+
}).join(" ");
|
|
1407
|
+
}
|
|
1408
|
+
function addVendorPrefixes(declarations) {
|
|
1409
|
+
const result = [];
|
|
1410
|
+
for (const decl of declarations) {
|
|
1411
|
+
const prefixes = PREFIXED_PROPERTIES[decl.property];
|
|
1412
|
+
if (prefixes) {
|
|
1413
|
+
for (const prefix of prefixes) {
|
|
1414
|
+
result.push({
|
|
1415
|
+
...decl,
|
|
1416
|
+
property: prefix
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
result.push(decl);
|
|
1421
|
+
}
|
|
1422
|
+
return result;
|
|
1423
|
+
}
|
|
1424
|
+
function generateCSS(rules, options, _warnings) {
|
|
1425
|
+
const minify = options.minify ?? false;
|
|
1426
|
+
const indent = minify ? "" : " ";
|
|
1427
|
+
const newline = minify ? "" : "\n";
|
|
1428
|
+
const space = minify ? "" : " ";
|
|
1429
|
+
const parts = [];
|
|
1430
|
+
for (const rule of rules) {
|
|
1431
|
+
parts.push(generateRule(rule, indent, newline, space));
|
|
1432
|
+
}
|
|
1433
|
+
return parts.join(minify ? "" : "\n\n");
|
|
1434
|
+
}
|
|
1435
|
+
function generateRule(rule, indent, newline, space) {
|
|
1436
|
+
switch (rule.type) {
|
|
1437
|
+
case "StyleRule":
|
|
1438
|
+
return generateStyleRule(rule, indent, newline, space);
|
|
1439
|
+
case "MediaRule":
|
|
1440
|
+
return generateMediaRule(rule, indent, newline, space);
|
|
1441
|
+
case "KeyframesRule":
|
|
1442
|
+
return generateKeyframesRule(rule, indent, newline, space);
|
|
1443
|
+
default:
|
|
1444
|
+
return "";
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
function generateStyleRule(rule, indent, newline, space, baseIndent = "") {
|
|
1448
|
+
const selectors = rule.selectors.map((s) => s.value).join(`,${space}`);
|
|
1449
|
+
const declarations = rule.declarations.map((d) => {
|
|
1450
|
+
const important = d.important ? `${space}!important` : "";
|
|
1451
|
+
return `${baseIndent}${indent}${d.property}:${space}${d.value}${important};`;
|
|
1452
|
+
}).join(newline);
|
|
1453
|
+
return `${baseIndent}${selectors}${space}{${newline}${declarations}${newline}${baseIndent}}`;
|
|
1454
|
+
}
|
|
1455
|
+
function generateMediaRule(rule, indent, newline, space) {
|
|
1456
|
+
const rules = rule.rules.map((r) => generateStyleRule(r, indent, newline, space, indent)).join(newline + newline);
|
|
1457
|
+
return `@media${space}${rule.query}${space}{${newline}${rules}${newline}}`;
|
|
1458
|
+
}
|
|
1459
|
+
function generateKeyframesRule(rule, indent, newline, space) {
|
|
1460
|
+
const keyframes = rule.keyframes.map((kf) => {
|
|
1461
|
+
const declarations = kf.declarations.map((d) => {
|
|
1462
|
+
const important = d.important ? `${space}!important` : "";
|
|
1463
|
+
return `${indent}${indent}${d.property}:${space}${d.value}${important};`;
|
|
1464
|
+
}).join(newline);
|
|
1465
|
+
return `${indent}${kf.selector}${space}{${newline}${declarations}${newline}${indent}}`;
|
|
1466
|
+
}).join(newline);
|
|
1467
|
+
const standard = `@keyframes${space}${rule.name}${space}{${newline}${keyframes}${newline}}`;
|
|
1468
|
+
const webkit = `@-webkit-keyframes${space}${rule.name}${space}{${newline}${keyframes}${newline}}`;
|
|
1469
|
+
return `${webkit}${newline}${standard}`;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
// src/codegen.ts
|
|
1473
|
+
function generateCode(input, options) {
|
|
1474
|
+
const { template, styles, js } = input;
|
|
1475
|
+
const { isComponent, minify } = options;
|
|
1476
|
+
const parts = [];
|
|
1477
|
+
parts.push(generateImports(input, options));
|
|
1478
|
+
if (js) {
|
|
1479
|
+
parts.push("");
|
|
1480
|
+
parts.push("// User code");
|
|
1481
|
+
parts.push(js);
|
|
1482
|
+
}
|
|
1483
|
+
if (template) {
|
|
1484
|
+
parts.push("");
|
|
1485
|
+
parts.push("// Render function");
|
|
1486
|
+
parts.push(template.code);
|
|
1487
|
+
}
|
|
1488
|
+
if (styles) {
|
|
1489
|
+
parts.push("");
|
|
1490
|
+
parts.push("// Styles");
|
|
1491
|
+
parts.push(generateStylesCode(styles, options));
|
|
1492
|
+
}
|
|
1493
|
+
parts.push("");
|
|
1494
|
+
parts.push(
|
|
1495
|
+
isComponent ? generateComponentDefinition(input, options) : generatePageDefinition(input, options)
|
|
1496
|
+
);
|
|
1497
|
+
parts.push("");
|
|
1498
|
+
parts.push(generateExports(input, options));
|
|
1499
|
+
let code = parts.join("\n");
|
|
1500
|
+
if (minify) {
|
|
1501
|
+
code = minifyCode(code);
|
|
1502
|
+
}
|
|
1503
|
+
return code;
|
|
1504
|
+
}
|
|
1505
|
+
function generateImports(input, _options) {
|
|
1506
|
+
const imports = [];
|
|
1507
|
+
const runtimeImports = ["h", "Fragment"];
|
|
1508
|
+
if (input.template?.usedComponents.size) {
|
|
1509
|
+
runtimeImports.push("resolveComponent");
|
|
1510
|
+
}
|
|
1511
|
+
if (input.template?.code.includes("renderList")) {
|
|
1512
|
+
runtimeImports.push("renderList");
|
|
1513
|
+
}
|
|
1514
|
+
if (input.template?.code.includes("renderSlot")) {
|
|
1515
|
+
runtimeImports.push("renderSlot");
|
|
1516
|
+
}
|
|
1517
|
+
imports.push(`import { ${runtimeImports.join(", ")} } from '@qt-test/apex-runtime';`);
|
|
1518
|
+
const components = input.config.usingComponents ?? {};
|
|
1519
|
+
for (const [name, path] of Object.entries(components)) {
|
|
1520
|
+
imports.push(`import ${toPascalCase(name)} from '${path}';`);
|
|
1521
|
+
}
|
|
1522
|
+
if (input.styles?.imports.length) {
|
|
1523
|
+
for (const importPath of input.styles.imports) {
|
|
1524
|
+
imports.push(`import '${importPath}';`);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return imports.join("\n");
|
|
1528
|
+
}
|
|
1529
|
+
function generateStylesCode(styles, _options) {
|
|
1530
|
+
const css = styles.css.replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
1531
|
+
return `const __styles__ = \`${css}\`;`;
|
|
1532
|
+
}
|
|
1533
|
+
function generateComponentDefinition(input, _options) {
|
|
1534
|
+
const properties = extractComponentProperties(input.js ?? "");
|
|
1535
|
+
const methods = extractComponentMethods(input.js ?? "");
|
|
1536
|
+
const parts = [];
|
|
1537
|
+
parts.push("const __component__ = {");
|
|
1538
|
+
parts.push(' is: "component",');
|
|
1539
|
+
if (properties.length > 0) {
|
|
1540
|
+
parts.push(` properties: {`);
|
|
1541
|
+
for (const prop of properties) {
|
|
1542
|
+
parts.push(` ${prop.name}: { type: ${prop.type}, value: ${prop.default} },`);
|
|
1543
|
+
}
|
|
1544
|
+
parts.push(" },");
|
|
1545
|
+
}
|
|
1546
|
+
parts.push(" data() {");
|
|
1547
|
+
parts.push(" return {};");
|
|
1548
|
+
parts.push(" },");
|
|
1549
|
+
if (methods.length > 0) {
|
|
1550
|
+
parts.push(" methods: {");
|
|
1551
|
+
for (const method of methods) {
|
|
1552
|
+
parts.push(` ${method},`);
|
|
1553
|
+
}
|
|
1554
|
+
parts.push(" },");
|
|
1555
|
+
}
|
|
1556
|
+
if (input.template) {
|
|
1557
|
+
parts.push(" render,");
|
|
1558
|
+
}
|
|
1559
|
+
if (input.styles) {
|
|
1560
|
+
parts.push(" styles: __styles__,");
|
|
1561
|
+
}
|
|
1562
|
+
if (input.config.usingComponents) {
|
|
1563
|
+
const componentEntries = Object.entries(input.config.usingComponents).map(([name]) => ` "${name}": ${toPascalCase(name)}`).join(",\n");
|
|
1564
|
+
parts.push(` components: {
|
|
1565
|
+
${componentEntries}
|
|
1566
|
+
},`);
|
|
1567
|
+
}
|
|
1568
|
+
parts.push("};");
|
|
1569
|
+
return parts.join("\n");
|
|
1570
|
+
}
|
|
1571
|
+
function generatePageDefinition(input, _options) {
|
|
1572
|
+
const parts = [];
|
|
1573
|
+
parts.push("const __page__ = {");
|
|
1574
|
+
parts.push(' is: "page",');
|
|
1575
|
+
if (input.config.navigationBarTitleText) {
|
|
1576
|
+
parts.push(` title: "${input.config.navigationBarTitleText}",`);
|
|
1577
|
+
}
|
|
1578
|
+
if (input.config.enablePullDownRefresh) {
|
|
1579
|
+
parts.push(" enablePullDownRefresh: true,");
|
|
1580
|
+
}
|
|
1581
|
+
parts.push(" data() {");
|
|
1582
|
+
parts.push(" return {};");
|
|
1583
|
+
parts.push(" },");
|
|
1584
|
+
if (input.template) {
|
|
1585
|
+
parts.push(" render,");
|
|
1586
|
+
}
|
|
1587
|
+
if (input.styles) {
|
|
1588
|
+
parts.push(" styles: __styles__,");
|
|
1589
|
+
}
|
|
1590
|
+
if (input.config.usingComponents) {
|
|
1591
|
+
const componentEntries = Object.entries(input.config.usingComponents).map(([name]) => ` "${name}": ${toPascalCase(name)}`).join(",\n");
|
|
1592
|
+
parts.push(` components: {
|
|
1593
|
+
${componentEntries}
|
|
1594
|
+
},`);
|
|
1595
|
+
}
|
|
1596
|
+
parts.push("};");
|
|
1597
|
+
return parts.join("\n");
|
|
1598
|
+
}
|
|
1599
|
+
function generateExports(input, options) {
|
|
1600
|
+
const exports2 = [];
|
|
1601
|
+
if (options.isComponent) {
|
|
1602
|
+
exports2.push("export default __component__;");
|
|
1603
|
+
} else {
|
|
1604
|
+
exports2.push("export default __page__;");
|
|
1605
|
+
}
|
|
1606
|
+
if (input.template) {
|
|
1607
|
+
exports2.push("export { render };");
|
|
1608
|
+
}
|
|
1609
|
+
if (input.styles) {
|
|
1610
|
+
exports2.push("export { __styles__ as styles };");
|
|
1611
|
+
}
|
|
1612
|
+
return exports2.join("\n");
|
|
1613
|
+
}
|
|
1614
|
+
function extractComponentProperties(js) {
|
|
1615
|
+
const properties = [];
|
|
1616
|
+
const propsMatch = js.match(/properties\s*:\s*\{([^}]+)\}/);
|
|
1617
|
+
if (propsMatch) {
|
|
1618
|
+
const propsBlock = propsMatch[1];
|
|
1619
|
+
const propMatches = propsBlock.matchAll(/(\w+)\s*:\s*\{?\s*(?:type\s*:\s*(\w+))?\s*(?:,\s*value\s*:\s*([^,}]+))?\s*\}?/g);
|
|
1620
|
+
for (const match of propMatches) {
|
|
1621
|
+
properties.push({
|
|
1622
|
+
name: match[1],
|
|
1623
|
+
type: match[2] || "String",
|
|
1624
|
+
default: match[3]?.trim() || "null"
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
return properties;
|
|
1629
|
+
}
|
|
1630
|
+
function extractComponentMethods(js) {
|
|
1631
|
+
const methods = [];
|
|
1632
|
+
const methodsMatch = js.match(/methods\s*:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/);
|
|
1633
|
+
if (methodsMatch) {
|
|
1634
|
+
const methodsBlock = methodsMatch[1];
|
|
1635
|
+
const methodMatches = methodsBlock.matchAll(/(\w+)\s*(?:\([^)]*\))?\s*\{/g);
|
|
1636
|
+
for (const match of methodMatches) {
|
|
1637
|
+
methods.push(match[1]);
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
return methods;
|
|
1641
|
+
}
|
|
1642
|
+
function toPascalCase(str) {
|
|
1643
|
+
return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
1644
|
+
}
|
|
1645
|
+
function minifyCode(code) {
|
|
1646
|
+
return code.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").replace(/\s*([{};,:])\s*/g, "$1").replace(/;\s*}/g, "}").trim();
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
// src/sourcemap.ts
|
|
1650
|
+
var SourceMapBuilder = class {
|
|
1651
|
+
constructor(options) {
|
|
1652
|
+
this.sources = [];
|
|
1653
|
+
this.sourcesContent = [];
|
|
1654
|
+
this.names = [];
|
|
1655
|
+
this.mappings = [];
|
|
1656
|
+
this.currentLine = [];
|
|
1657
|
+
if (options) {
|
|
1658
|
+
this.file = options.file;
|
|
1659
|
+
this.sourceRoot = options.sourceRoot;
|
|
1660
|
+
this.sources = [...options.sources];
|
|
1661
|
+
if (options.includeContent && options.sourcesContent) {
|
|
1662
|
+
this.sourcesContent = [...options.sourcesContent];
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Adds a source file
|
|
1668
|
+
*/
|
|
1669
|
+
addSource(source, content) {
|
|
1670
|
+
const index = this.sources.indexOf(source);
|
|
1671
|
+
if (index !== -1) {
|
|
1672
|
+
return index;
|
|
1673
|
+
}
|
|
1674
|
+
this.sources.push(source);
|
|
1675
|
+
this.sourcesContent.push(content ?? null);
|
|
1676
|
+
return this.sources.length - 1;
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Adds a name
|
|
1680
|
+
*/
|
|
1681
|
+
addName(name) {
|
|
1682
|
+
const index = this.names.indexOf(name);
|
|
1683
|
+
if (index !== -1) {
|
|
1684
|
+
return index;
|
|
1685
|
+
}
|
|
1686
|
+
this.names.push(name);
|
|
1687
|
+
return this.names.length - 1;
|
|
1688
|
+
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Adds a mapping
|
|
1691
|
+
*/
|
|
1692
|
+
addMapping(generatedLine, generatedColumn, sourceIndex, sourceLine, sourceColumn, nameIndex) {
|
|
1693
|
+
while (this.mappings.length <= generatedLine) {
|
|
1694
|
+
if (this.currentLine.length > 0) {
|
|
1695
|
+
this.mappings.push(this.currentLine);
|
|
1696
|
+
this.currentLine = [];
|
|
1697
|
+
} else {
|
|
1698
|
+
this.mappings.push([]);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
const segment = { generatedColumn };
|
|
1702
|
+
if (sourceIndex !== void 0) {
|
|
1703
|
+
segment.sourceIndex = sourceIndex;
|
|
1704
|
+
segment.sourceLine = sourceLine;
|
|
1705
|
+
segment.sourceColumn = sourceColumn;
|
|
1706
|
+
if (nameIndex !== void 0) {
|
|
1707
|
+
segment.nameIndex = nameIndex;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
if (this.mappings.length === generatedLine) {
|
|
1711
|
+
this.currentLine.push(segment);
|
|
1712
|
+
} else {
|
|
1713
|
+
this.mappings[generatedLine].push(segment);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Starts a new line
|
|
1718
|
+
*/
|
|
1719
|
+
newLine() {
|
|
1720
|
+
this.mappings.push(this.currentLine);
|
|
1721
|
+
this.currentLine = [];
|
|
1722
|
+
}
|
|
1723
|
+
/**
|
|
1724
|
+
* Generates the source map
|
|
1725
|
+
*/
|
|
1726
|
+
toSourceMap() {
|
|
1727
|
+
if (this.currentLine.length > 0) {
|
|
1728
|
+
this.mappings.push(this.currentLine);
|
|
1729
|
+
this.currentLine = [];
|
|
1730
|
+
}
|
|
1731
|
+
return {
|
|
1732
|
+
version: 3,
|
|
1733
|
+
file: this.file,
|
|
1734
|
+
sourceRoot: this.sourceRoot,
|
|
1735
|
+
sources: this.sources,
|
|
1736
|
+
sourcesContent: this.sourcesContent.length > 0 ? this.sourcesContent : void 0,
|
|
1737
|
+
names: this.names,
|
|
1738
|
+
mappings: this.encodeMappings()
|
|
1739
|
+
};
|
|
1740
|
+
}
|
|
1741
|
+
/**
|
|
1742
|
+
* Encodes mappings to VLQ format
|
|
1743
|
+
*/
|
|
1744
|
+
encodeMappings() {
|
|
1745
|
+
let previousGeneratedColumn = 0;
|
|
1746
|
+
let previousSourceIndex = 0;
|
|
1747
|
+
let previousSourceLine = 0;
|
|
1748
|
+
let previousSourceColumn = 0;
|
|
1749
|
+
let previousNameIndex = 0;
|
|
1750
|
+
const lines = [];
|
|
1751
|
+
for (const line of this.mappings) {
|
|
1752
|
+
previousGeneratedColumn = 0;
|
|
1753
|
+
const segments = [];
|
|
1754
|
+
const sortedSegments = [...line].sort((a, b) => a.generatedColumn - b.generatedColumn);
|
|
1755
|
+
for (const segment of sortedSegments) {
|
|
1756
|
+
const values = [];
|
|
1757
|
+
values.push(segment.generatedColumn - previousGeneratedColumn);
|
|
1758
|
+
previousGeneratedColumn = segment.generatedColumn;
|
|
1759
|
+
if (segment.sourceIndex !== void 0) {
|
|
1760
|
+
values.push(segment.sourceIndex - previousSourceIndex);
|
|
1761
|
+
previousSourceIndex = segment.sourceIndex;
|
|
1762
|
+
values.push((segment.sourceLine ?? 0) - previousSourceLine);
|
|
1763
|
+
previousSourceLine = segment.sourceLine ?? 0;
|
|
1764
|
+
values.push((segment.sourceColumn ?? 0) - previousSourceColumn);
|
|
1765
|
+
previousSourceColumn = segment.sourceColumn ?? 0;
|
|
1766
|
+
if (segment.nameIndex !== void 0) {
|
|
1767
|
+
values.push(segment.nameIndex - previousNameIndex);
|
|
1768
|
+
previousNameIndex = segment.nameIndex;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
segments.push(values.map(encodeVLQ).join(""));
|
|
1772
|
+
}
|
|
1773
|
+
lines.push(segments.join(","));
|
|
1774
|
+
}
|
|
1775
|
+
return lines.join(";");
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Returns JSON string
|
|
1779
|
+
*/
|
|
1780
|
+
toString() {
|
|
1781
|
+
return JSON.stringify(this.toSourceMap());
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Returns data URL
|
|
1785
|
+
*/
|
|
1786
|
+
toDataUrl() {
|
|
1787
|
+
const json = this.toString();
|
|
1788
|
+
const base64 = typeof btoa !== "undefined" ? btoa(json) : Buffer.from(json).toString("base64");
|
|
1789
|
+
return `data:application/json;charset=utf-8;base64,${base64}`;
|
|
1790
|
+
}
|
|
1791
|
+
/**
|
|
1792
|
+
* Returns inline comment
|
|
1793
|
+
*/
|
|
1794
|
+
toComment() {
|
|
1795
|
+
return `//# sourceMappingURL=${this.toDataUrl()}`;
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
var VLQ_BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
1799
|
+
var VLQ_BASE_SHIFT = 5;
|
|
1800
|
+
var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
|
|
1801
|
+
var VLQ_BASE_MASK = VLQ_BASE - 1;
|
|
1802
|
+
var VLQ_CONTINUATION_BIT = VLQ_BASE;
|
|
1803
|
+
function encodeVLQ(value) {
|
|
1804
|
+
let encoded = "";
|
|
1805
|
+
let vlq = value < 0 ? (-value << 1) + 1 : value << 1;
|
|
1806
|
+
do {
|
|
1807
|
+
let digit = vlq & VLQ_BASE_MASK;
|
|
1808
|
+
vlq >>>= VLQ_BASE_SHIFT;
|
|
1809
|
+
if (vlq > 0) {
|
|
1810
|
+
digit |= VLQ_CONTINUATION_BIT;
|
|
1811
|
+
}
|
|
1812
|
+
encoded += VLQ_BASE64[digit];
|
|
1813
|
+
} while (vlq > 0);
|
|
1814
|
+
return encoded;
|
|
1815
|
+
}
|
|
1816
|
+
function decodeVLQ(encoded, start = 0) {
|
|
1817
|
+
let vlq = 0;
|
|
1818
|
+
let shift = 0;
|
|
1819
|
+
let continuation = true;
|
|
1820
|
+
let i = start;
|
|
1821
|
+
while (continuation && i < encoded.length) {
|
|
1822
|
+
const char = encoded[i];
|
|
1823
|
+
const digit = VLQ_BASE64.indexOf(char);
|
|
1824
|
+
if (digit === -1) {
|
|
1825
|
+
throw new Error(`Invalid VLQ character: ${char}`);
|
|
1826
|
+
}
|
|
1827
|
+
continuation = (digit & VLQ_CONTINUATION_BIT) !== 0;
|
|
1828
|
+
vlq += (digit & VLQ_BASE_MASK) << shift;
|
|
1829
|
+
shift += VLQ_BASE_SHIFT;
|
|
1830
|
+
i++;
|
|
1831
|
+
}
|
|
1832
|
+
const value = vlq & 1 ? -(vlq >> 1) : vlq >> 1;
|
|
1833
|
+
return { value, next: i };
|
|
1834
|
+
}
|
|
1835
|
+
function createSourceMap(options) {
|
|
1836
|
+
const builder = new SourceMapBuilder(options);
|
|
1837
|
+
return builder.toSourceMap();
|
|
1838
|
+
}
|
|
1839
|
+
function mergeSourceMaps(maps) {
|
|
1840
|
+
const builder = new SourceMapBuilder();
|
|
1841
|
+
let lineOffset = 0;
|
|
1842
|
+
for (const map of maps) {
|
|
1843
|
+
const sourceIndexMap = /* @__PURE__ */ new Map();
|
|
1844
|
+
for (let i = 0; i < map.sources.length; i++) {
|
|
1845
|
+
const newIndex = builder.addSource(
|
|
1846
|
+
map.sources[i],
|
|
1847
|
+
map.sourcesContent?.[i] ?? void 0
|
|
1848
|
+
);
|
|
1849
|
+
sourceIndexMap.set(i, newIndex);
|
|
1850
|
+
}
|
|
1851
|
+
const nameIndexMap = /* @__PURE__ */ new Map();
|
|
1852
|
+
for (let i = 0; i < map.names.length; i++) {
|
|
1853
|
+
const newIndex = builder.addName(map.names[i]);
|
|
1854
|
+
nameIndexMap.set(i, newIndex);
|
|
1855
|
+
}
|
|
1856
|
+
const decodedMappings = decodeMappings(map.mappings);
|
|
1857
|
+
for (let lineIndex = 0; lineIndex < decodedMappings.length; lineIndex++) {
|
|
1858
|
+
const line = decodedMappings[lineIndex];
|
|
1859
|
+
for (const segment of line) {
|
|
1860
|
+
const sourceIndex = segment.sourceIndex !== void 0 ? sourceIndexMap.get(segment.sourceIndex) : void 0;
|
|
1861
|
+
const nameIndex = segment.nameIndex !== void 0 ? nameIndexMap.get(segment.nameIndex) : void 0;
|
|
1862
|
+
builder.addMapping(
|
|
1863
|
+
lineIndex + lineOffset,
|
|
1864
|
+
segment.generatedColumn,
|
|
1865
|
+
sourceIndex,
|
|
1866
|
+
segment.sourceLine,
|
|
1867
|
+
segment.sourceColumn,
|
|
1868
|
+
nameIndex
|
|
1869
|
+
);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
lineOffset += decodedMappings.length;
|
|
1873
|
+
}
|
|
1874
|
+
return builder.toSourceMap();
|
|
1875
|
+
}
|
|
1876
|
+
function decodeMappings(mappings) {
|
|
1877
|
+
const lines = [];
|
|
1878
|
+
const lineStrings = mappings.split(";");
|
|
1879
|
+
let previousSourceIndex = 0;
|
|
1880
|
+
let previousSourceLine = 0;
|
|
1881
|
+
let previousSourceColumn = 0;
|
|
1882
|
+
let previousNameIndex = 0;
|
|
1883
|
+
for (const lineString of lineStrings) {
|
|
1884
|
+
const line = [];
|
|
1885
|
+
let previousGeneratedColumn = 0;
|
|
1886
|
+
if (lineString) {
|
|
1887
|
+
const segmentStrings = lineString.split(",");
|
|
1888
|
+
for (const segmentString of segmentStrings) {
|
|
1889
|
+
if (!segmentString) continue;
|
|
1890
|
+
const segment = { generatedColumn: 0 };
|
|
1891
|
+
let pos = 0;
|
|
1892
|
+
const col = decodeVLQ(segmentString, pos);
|
|
1893
|
+
segment.generatedColumn = previousGeneratedColumn + col.value;
|
|
1894
|
+
previousGeneratedColumn = segment.generatedColumn;
|
|
1895
|
+
pos = col.next;
|
|
1896
|
+
if (pos < segmentString.length) {
|
|
1897
|
+
const src = decodeVLQ(segmentString, pos);
|
|
1898
|
+
segment.sourceIndex = previousSourceIndex + src.value;
|
|
1899
|
+
previousSourceIndex = segment.sourceIndex;
|
|
1900
|
+
pos = src.next;
|
|
1901
|
+
const srcLine = decodeVLQ(segmentString, pos);
|
|
1902
|
+
segment.sourceLine = previousSourceLine + srcLine.value;
|
|
1903
|
+
previousSourceLine = segment.sourceLine;
|
|
1904
|
+
pos = srcLine.next;
|
|
1905
|
+
const srcCol = decodeVLQ(segmentString, pos);
|
|
1906
|
+
segment.sourceColumn = previousSourceColumn + srcCol.value;
|
|
1907
|
+
previousSourceColumn = segment.sourceColumn;
|
|
1908
|
+
pos = srcCol.next;
|
|
1909
|
+
if (pos < segmentString.length) {
|
|
1910
|
+
const name = decodeVLQ(segmentString, pos);
|
|
1911
|
+
segment.nameIndex = previousNameIndex + name.value;
|
|
1912
|
+
previousNameIndex = segment.nameIndex;
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
line.push(segment);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
lines.push(line);
|
|
1919
|
+
}
|
|
1920
|
+
return lines;
|
|
1921
|
+
}
|
|
1922
|
+
function applySourceMap(map, line, column) {
|
|
1923
|
+
const decodedMappings = decodeMappings(map.mappings);
|
|
1924
|
+
if (line >= decodedMappings.length) {
|
|
1925
|
+
return null;
|
|
1926
|
+
}
|
|
1927
|
+
const lineMappings = decodedMappings[line];
|
|
1928
|
+
let bestSegment = null;
|
|
1929
|
+
for (const segment of lineMappings) {
|
|
1930
|
+
if (segment.generatedColumn <= column) {
|
|
1931
|
+
bestSegment = segment;
|
|
1932
|
+
} else {
|
|
1933
|
+
break;
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
if (!bestSegment || bestSegment.sourceIndex === void 0) {
|
|
1937
|
+
return null;
|
|
1938
|
+
}
|
|
1939
|
+
return {
|
|
1940
|
+
source: map.sources[bestSegment.sourceIndex] ?? null,
|
|
1941
|
+
line: bestSegment.sourceLine ?? 0,
|
|
1942
|
+
column: bestSegment.sourceColumn ?? 0,
|
|
1943
|
+
name: bestSegment.nameIndex !== void 0 ? map.names[bestSegment.nameIndex] ?? null : null
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
// src/compiler.ts
|
|
1948
|
+
function compile(options) {
|
|
1949
|
+
const warnings = [];
|
|
1950
|
+
const errors = [];
|
|
1951
|
+
let config = {};
|
|
1952
|
+
if (options.json) {
|
|
1953
|
+
if (typeof options.json === "string") {
|
|
1954
|
+
try {
|
|
1955
|
+
config = JSON.parse(options.json);
|
|
1956
|
+
} catch (e) {
|
|
1957
|
+
errors.push({
|
|
1958
|
+
code: "INVALID_JSON",
|
|
1959
|
+
message: `Failed to parse JSON config: ${e.message}`
|
|
1960
|
+
});
|
|
1961
|
+
}
|
|
1962
|
+
} else {
|
|
1963
|
+
config = options.json;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
const isComponent = options.isComponent ?? config.component ?? false;
|
|
1967
|
+
let templateResult = null;
|
|
1968
|
+
if (options.axml) {
|
|
1969
|
+
templateResult = compileAXML(options.axml, {
|
|
1970
|
+
filename: options.filename ? `${options.filename}.axml` : void 0,
|
|
1971
|
+
components: { ...config.usingComponents, ...options.components }
|
|
1972
|
+
});
|
|
1973
|
+
warnings.push(...templateResult.warnings.map((w) => ({ message: w })));
|
|
1974
|
+
errors.push(...templateResult.errors.map((e) => ({ code: "AXML_ERROR", message: e })));
|
|
1975
|
+
}
|
|
1976
|
+
let styleResult = null;
|
|
1977
|
+
if (options.acss) {
|
|
1978
|
+
styleResult = compileACSS(options.acss, {
|
|
1979
|
+
filename: options.filename ? `${options.filename}.acss` : void 0
|
|
1980
|
+
});
|
|
1981
|
+
warnings.push(...styleResult.warnings.map((w) => ({ message: w })));
|
|
1982
|
+
errors.push(...styleResult.errors.map((e) => ({ code: "ACSS_ERROR", message: e })));
|
|
1983
|
+
}
|
|
1984
|
+
const generatorOptions = {
|
|
1985
|
+
isComponent,
|
|
1986
|
+
minify: options.minify ?? false,
|
|
1987
|
+
target: options.target ?? "es2020",
|
|
1988
|
+
sourceMap: options.sourceMap ?? false,
|
|
1989
|
+
filename: options.filename
|
|
1990
|
+
};
|
|
1991
|
+
const code = generateCode({
|
|
1992
|
+
template: templateResult,
|
|
1993
|
+
styles: styleResult,
|
|
1994
|
+
config,
|
|
1995
|
+
js: options.js
|
|
1996
|
+
}, generatorOptions);
|
|
1997
|
+
let map;
|
|
1998
|
+
if (options.sourceMap && options.filename) {
|
|
1999
|
+
map = createSourceMap({
|
|
2000
|
+
file: options.filename,
|
|
2001
|
+
sources: [
|
|
2002
|
+
options.axml ? `${options.filename}.axml` : null,
|
|
2003
|
+
options.acss ? `${options.filename}.acss` : null,
|
|
2004
|
+
options.js ? `${options.filename}.js` : null
|
|
2005
|
+
].filter(Boolean)
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
return {
|
|
2009
|
+
code,
|
|
2010
|
+
css: styleResult?.css ?? "",
|
|
2011
|
+
config,
|
|
2012
|
+
map,
|
|
2013
|
+
warnings,
|
|
2014
|
+
errors,
|
|
2015
|
+
templateAst: templateResult?.ast,
|
|
2016
|
+
styleAst: styleResult?.ast
|
|
2017
|
+
};
|
|
2018
|
+
}
|
|
2019
|
+
function validate(result) {
|
|
2020
|
+
return result.errors.length === 0;
|
|
2021
|
+
}
|
|
2022
|
+
function formatErrors(result) {
|
|
2023
|
+
if (result.errors.length === 0) return "";
|
|
2024
|
+
return result.errors.map((error) => {
|
|
2025
|
+
let msg = `[${error.code}] ${error.message}`;
|
|
2026
|
+
if (error.loc) {
|
|
2027
|
+
msg += ` at line ${error.loc.line}, column ${error.loc.column}`;
|
|
2028
|
+
}
|
|
2029
|
+
return msg;
|
|
2030
|
+
}).join("\n");
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
// src/index.ts
|
|
2034
|
+
var VERSION = "0.1.0";
|
|
2035
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2036
|
+
0 && (module.exports = {
|
|
2037
|
+
SourceMapBuilder,
|
|
2038
|
+
VERSION,
|
|
2039
|
+
applySourceMap,
|
|
2040
|
+
compile,
|
|
2041
|
+
compileACSS,
|
|
2042
|
+
compileAXML,
|
|
2043
|
+
createSourceMap,
|
|
2044
|
+
formatErrors,
|
|
2045
|
+
generateCode,
|
|
2046
|
+
mergeSourceMaps,
|
|
2047
|
+
parseACSS,
|
|
2048
|
+
parseAXML,
|
|
2049
|
+
validate
|
|
2050
|
+
});
|