svelte-origin 0.0.0 → 1.0.0-next.15
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.
Potentially problematic release.
This version of svelte-origin might be problematic. Click here for more details.
- package/LLM.md +754 -0
- package/README.md +412 -1
- package/dist/aliases.d.ts +44 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +3440 -0
- package/dist/generate-dts.d.ts +31 -0
- package/dist/globals.d.ts +576 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +6685 -0
- package/dist/plugin.d.ts +143 -0
- package/dist/plugin.js +3467 -0
- package/dist/post-process.d.ts +27 -0
- package/dist/post-process.js +3071 -0
- package/dist/preprocess.d.ts +73 -0
- package/dist/preprocess.js +3360 -0
- package/dist/runtime/attrs.d.ts +52 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +3665 -0
- package/dist/runtime/origin.d.ts +144 -0
- package/dist/runtime/types.d.ts +173 -0
- package/dist/transform/attrs-for-transform.d.ts +24 -0
- package/dist/transform/attrs-origin-transform.d.ts +62 -0
- package/dist/transform/attrs-schema.d.ts +52 -0
- package/dist/transform/codegen.d.ts +15 -0
- package/dist/transform/core.d.ts +62 -0
- package/dist/transform/declaration-parser.d.ts +77 -0
- package/dist/transform/element-types.d.ts +10 -0
- package/dist/transform/origin-transform.d.ts +51 -0
- package/dist/transform/patterns.d.ts +82 -0
- package/dist/transform/schema.d.ts +116 -0
- package/dist/transform/standalone-attrs-transform.d.ts +36 -0
- package/dist/vite-dts.d.ts +17 -0
- package/dist/vite-dts.js +606 -0
- package/package.json +73 -3
|
@@ -0,0 +1,3071 @@
|
|
|
1
|
+
// src/post-process.ts
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
|
|
5
|
+
// ../../node_modules/.bun/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs
|
|
6
|
+
var comma = 44;
|
|
7
|
+
var semicolon = 59;
|
|
8
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
9
|
+
var intToChar = new Uint8Array(64);
|
|
10
|
+
var charToInt = new Uint8Array(128);
|
|
11
|
+
for (let i = 0;i < chars.length; i++) {
|
|
12
|
+
const c = chars.charCodeAt(i);
|
|
13
|
+
intToChar[i] = c;
|
|
14
|
+
charToInt[c] = i;
|
|
15
|
+
}
|
|
16
|
+
function encodeInteger(builder, num, relative) {
|
|
17
|
+
let delta = num - relative;
|
|
18
|
+
delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
|
|
19
|
+
do {
|
|
20
|
+
let clamped = delta & 31;
|
|
21
|
+
delta >>>= 5;
|
|
22
|
+
if (delta > 0)
|
|
23
|
+
clamped |= 32;
|
|
24
|
+
builder.write(intToChar[clamped]);
|
|
25
|
+
} while (delta > 0);
|
|
26
|
+
return num;
|
|
27
|
+
}
|
|
28
|
+
var bufLength = 1024 * 16;
|
|
29
|
+
var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder : typeof Buffer !== "undefined" ? {
|
|
30
|
+
decode(buf) {
|
|
31
|
+
const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
32
|
+
return out.toString();
|
|
33
|
+
}
|
|
34
|
+
} : {
|
|
35
|
+
decode(buf) {
|
|
36
|
+
let out = "";
|
|
37
|
+
for (let i = 0;i < buf.length; i++) {
|
|
38
|
+
out += String.fromCharCode(buf[i]);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var StringWriter = class {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.pos = 0;
|
|
46
|
+
this.out = "";
|
|
47
|
+
this.buffer = new Uint8Array(bufLength);
|
|
48
|
+
}
|
|
49
|
+
write(v) {
|
|
50
|
+
const { buffer } = this;
|
|
51
|
+
buffer[this.pos++] = v;
|
|
52
|
+
if (this.pos === bufLength) {
|
|
53
|
+
this.out += td.decode(buffer);
|
|
54
|
+
this.pos = 0;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
flush() {
|
|
58
|
+
const { buffer, out, pos } = this;
|
|
59
|
+
return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
function encode(decoded) {
|
|
63
|
+
const writer = new StringWriter;
|
|
64
|
+
let sourcesIndex = 0;
|
|
65
|
+
let sourceLine = 0;
|
|
66
|
+
let sourceColumn = 0;
|
|
67
|
+
let namesIndex = 0;
|
|
68
|
+
for (let i = 0;i < decoded.length; i++) {
|
|
69
|
+
const line = decoded[i];
|
|
70
|
+
if (i > 0)
|
|
71
|
+
writer.write(semicolon);
|
|
72
|
+
if (line.length === 0)
|
|
73
|
+
continue;
|
|
74
|
+
let genColumn = 0;
|
|
75
|
+
for (let j = 0;j < line.length; j++) {
|
|
76
|
+
const segment = line[j];
|
|
77
|
+
if (j > 0)
|
|
78
|
+
writer.write(comma);
|
|
79
|
+
genColumn = encodeInteger(writer, segment[0], genColumn);
|
|
80
|
+
if (segment.length === 1)
|
|
81
|
+
continue;
|
|
82
|
+
sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
|
|
83
|
+
sourceLine = encodeInteger(writer, segment[2], sourceLine);
|
|
84
|
+
sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
|
|
85
|
+
if (segment.length === 4)
|
|
86
|
+
continue;
|
|
87
|
+
namesIndex = encodeInteger(writer, segment[4], namesIndex);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return writer.flush();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ../../node_modules/.bun/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.mjs
|
|
94
|
+
class BitSet {
|
|
95
|
+
constructor(arg) {
|
|
96
|
+
this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
|
|
97
|
+
}
|
|
98
|
+
add(n) {
|
|
99
|
+
this.bits[n >> 5] |= 1 << (n & 31);
|
|
100
|
+
}
|
|
101
|
+
has(n) {
|
|
102
|
+
return !!(this.bits[n >> 5] & 1 << (n & 31));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
class Chunk {
|
|
107
|
+
constructor(start, end, content) {
|
|
108
|
+
this.start = start;
|
|
109
|
+
this.end = end;
|
|
110
|
+
this.original = content;
|
|
111
|
+
this.intro = "";
|
|
112
|
+
this.outro = "";
|
|
113
|
+
this.content = content;
|
|
114
|
+
this.storeName = false;
|
|
115
|
+
this.edited = false;
|
|
116
|
+
{
|
|
117
|
+
this.previous = null;
|
|
118
|
+
this.next = null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
appendLeft(content) {
|
|
122
|
+
this.outro += content;
|
|
123
|
+
}
|
|
124
|
+
appendRight(content) {
|
|
125
|
+
this.intro = this.intro + content;
|
|
126
|
+
}
|
|
127
|
+
clone() {
|
|
128
|
+
const chunk = new Chunk(this.start, this.end, this.original);
|
|
129
|
+
chunk.intro = this.intro;
|
|
130
|
+
chunk.outro = this.outro;
|
|
131
|
+
chunk.content = this.content;
|
|
132
|
+
chunk.storeName = this.storeName;
|
|
133
|
+
chunk.edited = this.edited;
|
|
134
|
+
return chunk;
|
|
135
|
+
}
|
|
136
|
+
contains(index) {
|
|
137
|
+
return this.start < index && index < this.end;
|
|
138
|
+
}
|
|
139
|
+
eachNext(fn) {
|
|
140
|
+
let chunk = this;
|
|
141
|
+
while (chunk) {
|
|
142
|
+
fn(chunk);
|
|
143
|
+
chunk = chunk.next;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
eachPrevious(fn) {
|
|
147
|
+
let chunk = this;
|
|
148
|
+
while (chunk) {
|
|
149
|
+
fn(chunk);
|
|
150
|
+
chunk = chunk.previous;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
edit(content, storeName, contentOnly) {
|
|
154
|
+
this.content = content;
|
|
155
|
+
if (!contentOnly) {
|
|
156
|
+
this.intro = "";
|
|
157
|
+
this.outro = "";
|
|
158
|
+
}
|
|
159
|
+
this.storeName = storeName;
|
|
160
|
+
this.edited = true;
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
prependLeft(content) {
|
|
164
|
+
this.outro = content + this.outro;
|
|
165
|
+
}
|
|
166
|
+
prependRight(content) {
|
|
167
|
+
this.intro = content + this.intro;
|
|
168
|
+
}
|
|
169
|
+
reset() {
|
|
170
|
+
this.intro = "";
|
|
171
|
+
this.outro = "";
|
|
172
|
+
if (this.edited) {
|
|
173
|
+
this.content = this.original;
|
|
174
|
+
this.storeName = false;
|
|
175
|
+
this.edited = false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
split(index) {
|
|
179
|
+
const sliceIndex = index - this.start;
|
|
180
|
+
const originalBefore = this.original.slice(0, sliceIndex);
|
|
181
|
+
const originalAfter = this.original.slice(sliceIndex);
|
|
182
|
+
this.original = originalBefore;
|
|
183
|
+
const newChunk = new Chunk(index, this.end, originalAfter);
|
|
184
|
+
newChunk.outro = this.outro;
|
|
185
|
+
this.outro = "";
|
|
186
|
+
this.end = index;
|
|
187
|
+
if (this.edited) {
|
|
188
|
+
newChunk.edit("", false);
|
|
189
|
+
this.content = "";
|
|
190
|
+
} else {
|
|
191
|
+
this.content = originalBefore;
|
|
192
|
+
}
|
|
193
|
+
newChunk.next = this.next;
|
|
194
|
+
if (newChunk.next)
|
|
195
|
+
newChunk.next.previous = newChunk;
|
|
196
|
+
newChunk.previous = this;
|
|
197
|
+
this.next = newChunk;
|
|
198
|
+
return newChunk;
|
|
199
|
+
}
|
|
200
|
+
toString() {
|
|
201
|
+
return this.intro + this.content + this.outro;
|
|
202
|
+
}
|
|
203
|
+
trimEnd(rx) {
|
|
204
|
+
this.outro = this.outro.replace(rx, "");
|
|
205
|
+
if (this.outro.length)
|
|
206
|
+
return true;
|
|
207
|
+
const trimmed = this.content.replace(rx, "");
|
|
208
|
+
if (trimmed.length) {
|
|
209
|
+
if (trimmed !== this.content) {
|
|
210
|
+
this.split(this.start + trimmed.length).edit("", undefined, true);
|
|
211
|
+
if (this.edited) {
|
|
212
|
+
this.edit(trimmed, this.storeName, true);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return true;
|
|
216
|
+
} else {
|
|
217
|
+
this.edit("", undefined, true);
|
|
218
|
+
this.intro = this.intro.replace(rx, "");
|
|
219
|
+
if (this.intro.length)
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
trimStart(rx) {
|
|
224
|
+
this.intro = this.intro.replace(rx, "");
|
|
225
|
+
if (this.intro.length)
|
|
226
|
+
return true;
|
|
227
|
+
const trimmed = this.content.replace(rx, "");
|
|
228
|
+
if (trimmed.length) {
|
|
229
|
+
if (trimmed !== this.content) {
|
|
230
|
+
const newChunk = this.split(this.end - trimmed.length);
|
|
231
|
+
if (this.edited) {
|
|
232
|
+
newChunk.edit(trimmed, this.storeName, true);
|
|
233
|
+
}
|
|
234
|
+
this.edit("", undefined, true);
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
} else {
|
|
238
|
+
this.edit("", undefined, true);
|
|
239
|
+
this.outro = this.outro.replace(rx, "");
|
|
240
|
+
if (this.outro.length)
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function getBtoa() {
|
|
246
|
+
if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") {
|
|
247
|
+
return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
|
|
248
|
+
} else if (typeof Buffer === "function") {
|
|
249
|
+
return (str) => Buffer.from(str, "utf-8").toString("base64");
|
|
250
|
+
} else {
|
|
251
|
+
return () => {
|
|
252
|
+
throw new Error("Unsupported environment: `window.btoa` or `Buffer` should be supported.");
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
var btoa = /* @__PURE__ */ getBtoa();
|
|
257
|
+
|
|
258
|
+
class SourceMap {
|
|
259
|
+
constructor(properties) {
|
|
260
|
+
this.version = 3;
|
|
261
|
+
this.file = properties.file;
|
|
262
|
+
this.sources = properties.sources;
|
|
263
|
+
this.sourcesContent = properties.sourcesContent;
|
|
264
|
+
this.names = properties.names;
|
|
265
|
+
this.mappings = encode(properties.mappings);
|
|
266
|
+
if (typeof properties.x_google_ignoreList !== "undefined") {
|
|
267
|
+
this.x_google_ignoreList = properties.x_google_ignoreList;
|
|
268
|
+
}
|
|
269
|
+
if (typeof properties.debugId !== "undefined") {
|
|
270
|
+
this.debugId = properties.debugId;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
toString() {
|
|
274
|
+
return JSON.stringify(this);
|
|
275
|
+
}
|
|
276
|
+
toUrl() {
|
|
277
|
+
return "data:application/json;charset=utf-8;base64," + btoa(this.toString());
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function guessIndent(code) {
|
|
281
|
+
const lines = code.split(`
|
|
282
|
+
`);
|
|
283
|
+
const tabbed = lines.filter((line) => /^\t+/.test(line));
|
|
284
|
+
const spaced = lines.filter((line) => /^ {2,}/.test(line));
|
|
285
|
+
if (tabbed.length === 0 && spaced.length === 0) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
if (tabbed.length >= spaced.length) {
|
|
289
|
+
return "\t";
|
|
290
|
+
}
|
|
291
|
+
const min = spaced.reduce((previous, current) => {
|
|
292
|
+
const numSpaces = /^ +/.exec(current)[0].length;
|
|
293
|
+
return Math.min(numSpaces, previous);
|
|
294
|
+
}, Infinity);
|
|
295
|
+
return new Array(min + 1).join(" ");
|
|
296
|
+
}
|
|
297
|
+
function getRelativePath(from, to) {
|
|
298
|
+
const fromParts = from.split(/[/\\]/);
|
|
299
|
+
const toParts = to.split(/[/\\]/);
|
|
300
|
+
fromParts.pop();
|
|
301
|
+
while (fromParts[0] === toParts[0]) {
|
|
302
|
+
fromParts.shift();
|
|
303
|
+
toParts.shift();
|
|
304
|
+
}
|
|
305
|
+
if (fromParts.length) {
|
|
306
|
+
let i = fromParts.length;
|
|
307
|
+
while (i--)
|
|
308
|
+
fromParts[i] = "..";
|
|
309
|
+
}
|
|
310
|
+
return fromParts.concat(toParts).join("/");
|
|
311
|
+
}
|
|
312
|
+
var toString = Object.prototype.toString;
|
|
313
|
+
function isObject(thing) {
|
|
314
|
+
return toString.call(thing) === "[object Object]";
|
|
315
|
+
}
|
|
316
|
+
function getLocator(source) {
|
|
317
|
+
const originalLines = source.split(`
|
|
318
|
+
`);
|
|
319
|
+
const lineOffsets = [];
|
|
320
|
+
for (let i = 0, pos = 0;i < originalLines.length; i++) {
|
|
321
|
+
lineOffsets.push(pos);
|
|
322
|
+
pos += originalLines[i].length + 1;
|
|
323
|
+
}
|
|
324
|
+
return function locate(index) {
|
|
325
|
+
let i = 0;
|
|
326
|
+
let j = lineOffsets.length;
|
|
327
|
+
while (i < j) {
|
|
328
|
+
const m = i + j >> 1;
|
|
329
|
+
if (index < lineOffsets[m]) {
|
|
330
|
+
j = m;
|
|
331
|
+
} else {
|
|
332
|
+
i = m + 1;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const line = i - 1;
|
|
336
|
+
const column = index - lineOffsets[line];
|
|
337
|
+
return { line, column };
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
var wordRegex = /\w/;
|
|
341
|
+
|
|
342
|
+
class Mappings {
|
|
343
|
+
constructor(hires) {
|
|
344
|
+
this.hires = hires;
|
|
345
|
+
this.generatedCodeLine = 0;
|
|
346
|
+
this.generatedCodeColumn = 0;
|
|
347
|
+
this.raw = [];
|
|
348
|
+
this.rawSegments = this.raw[this.generatedCodeLine] = [];
|
|
349
|
+
this.pending = null;
|
|
350
|
+
}
|
|
351
|
+
addEdit(sourceIndex, content, loc, nameIndex) {
|
|
352
|
+
if (content.length) {
|
|
353
|
+
const contentLengthMinusOne = content.length - 1;
|
|
354
|
+
let contentLineEnd = content.indexOf(`
|
|
355
|
+
`, 0);
|
|
356
|
+
let previousContentLineEnd = -1;
|
|
357
|
+
while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {
|
|
358
|
+
const segment2 = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
|
|
359
|
+
if (nameIndex >= 0) {
|
|
360
|
+
segment2.push(nameIndex);
|
|
361
|
+
}
|
|
362
|
+
this.rawSegments.push(segment2);
|
|
363
|
+
this.generatedCodeLine += 1;
|
|
364
|
+
this.raw[this.generatedCodeLine] = this.rawSegments = [];
|
|
365
|
+
this.generatedCodeColumn = 0;
|
|
366
|
+
previousContentLineEnd = contentLineEnd;
|
|
367
|
+
contentLineEnd = content.indexOf(`
|
|
368
|
+
`, contentLineEnd + 1);
|
|
369
|
+
}
|
|
370
|
+
const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
|
|
371
|
+
if (nameIndex >= 0) {
|
|
372
|
+
segment.push(nameIndex);
|
|
373
|
+
}
|
|
374
|
+
this.rawSegments.push(segment);
|
|
375
|
+
this.advance(content.slice(previousContentLineEnd + 1));
|
|
376
|
+
} else if (this.pending) {
|
|
377
|
+
this.rawSegments.push(this.pending);
|
|
378
|
+
this.advance(content);
|
|
379
|
+
}
|
|
380
|
+
this.pending = null;
|
|
381
|
+
}
|
|
382
|
+
addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {
|
|
383
|
+
let originalCharIndex = chunk.start;
|
|
384
|
+
let first = true;
|
|
385
|
+
let charInHiresBoundary = false;
|
|
386
|
+
while (originalCharIndex < chunk.end) {
|
|
387
|
+
if (original[originalCharIndex] === `
|
|
388
|
+
`) {
|
|
389
|
+
loc.line += 1;
|
|
390
|
+
loc.column = 0;
|
|
391
|
+
this.generatedCodeLine += 1;
|
|
392
|
+
this.raw[this.generatedCodeLine] = this.rawSegments = [];
|
|
393
|
+
this.generatedCodeColumn = 0;
|
|
394
|
+
first = true;
|
|
395
|
+
charInHiresBoundary = false;
|
|
396
|
+
} else {
|
|
397
|
+
if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {
|
|
398
|
+
const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];
|
|
399
|
+
if (this.hires === "boundary") {
|
|
400
|
+
if (wordRegex.test(original[originalCharIndex])) {
|
|
401
|
+
if (!charInHiresBoundary) {
|
|
402
|
+
this.rawSegments.push(segment);
|
|
403
|
+
charInHiresBoundary = true;
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
this.rawSegments.push(segment);
|
|
407
|
+
charInHiresBoundary = false;
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
this.rawSegments.push(segment);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
loc.column += 1;
|
|
414
|
+
this.generatedCodeColumn += 1;
|
|
415
|
+
first = false;
|
|
416
|
+
}
|
|
417
|
+
originalCharIndex += 1;
|
|
418
|
+
}
|
|
419
|
+
this.pending = null;
|
|
420
|
+
}
|
|
421
|
+
advance(str) {
|
|
422
|
+
if (!str)
|
|
423
|
+
return;
|
|
424
|
+
const lines = str.split(`
|
|
425
|
+
`);
|
|
426
|
+
if (lines.length > 1) {
|
|
427
|
+
for (let i = 0;i < lines.length - 1; i++) {
|
|
428
|
+
this.generatedCodeLine++;
|
|
429
|
+
this.raw[this.generatedCodeLine] = this.rawSegments = [];
|
|
430
|
+
}
|
|
431
|
+
this.generatedCodeColumn = 0;
|
|
432
|
+
}
|
|
433
|
+
this.generatedCodeColumn += lines[lines.length - 1].length;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
var n = `
|
|
437
|
+
`;
|
|
438
|
+
var warned = {
|
|
439
|
+
insertLeft: false,
|
|
440
|
+
insertRight: false,
|
|
441
|
+
storeName: false
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
class MagicString {
|
|
445
|
+
constructor(string, options = {}) {
|
|
446
|
+
const chunk = new Chunk(0, string.length, string);
|
|
447
|
+
Object.defineProperties(this, {
|
|
448
|
+
original: { writable: true, value: string },
|
|
449
|
+
outro: { writable: true, value: "" },
|
|
450
|
+
intro: { writable: true, value: "" },
|
|
451
|
+
firstChunk: { writable: true, value: chunk },
|
|
452
|
+
lastChunk: { writable: true, value: chunk },
|
|
453
|
+
lastSearchedChunk: { writable: true, value: chunk },
|
|
454
|
+
byStart: { writable: true, value: {} },
|
|
455
|
+
byEnd: { writable: true, value: {} },
|
|
456
|
+
filename: { writable: true, value: options.filename },
|
|
457
|
+
indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
|
|
458
|
+
sourcemapLocations: { writable: true, value: new BitSet },
|
|
459
|
+
storedNames: { writable: true, value: {} },
|
|
460
|
+
indentStr: { writable: true, value: undefined },
|
|
461
|
+
ignoreList: { writable: true, value: options.ignoreList },
|
|
462
|
+
offset: { writable: true, value: options.offset || 0 }
|
|
463
|
+
});
|
|
464
|
+
this.byStart[0] = chunk;
|
|
465
|
+
this.byEnd[string.length] = chunk;
|
|
466
|
+
}
|
|
467
|
+
addSourcemapLocation(char) {
|
|
468
|
+
this.sourcemapLocations.add(char);
|
|
469
|
+
}
|
|
470
|
+
append(content) {
|
|
471
|
+
if (typeof content !== "string")
|
|
472
|
+
throw new TypeError("outro content must be a string");
|
|
473
|
+
this.outro += content;
|
|
474
|
+
return this;
|
|
475
|
+
}
|
|
476
|
+
appendLeft(index, content) {
|
|
477
|
+
index = index + this.offset;
|
|
478
|
+
if (typeof content !== "string")
|
|
479
|
+
throw new TypeError("inserted content must be a string");
|
|
480
|
+
this._split(index);
|
|
481
|
+
const chunk = this.byEnd[index];
|
|
482
|
+
if (chunk) {
|
|
483
|
+
chunk.appendLeft(content);
|
|
484
|
+
} else {
|
|
485
|
+
this.intro += content;
|
|
486
|
+
}
|
|
487
|
+
return this;
|
|
488
|
+
}
|
|
489
|
+
appendRight(index, content) {
|
|
490
|
+
index = index + this.offset;
|
|
491
|
+
if (typeof content !== "string")
|
|
492
|
+
throw new TypeError("inserted content must be a string");
|
|
493
|
+
this._split(index);
|
|
494
|
+
const chunk = this.byStart[index];
|
|
495
|
+
if (chunk) {
|
|
496
|
+
chunk.appendRight(content);
|
|
497
|
+
} else {
|
|
498
|
+
this.outro += content;
|
|
499
|
+
}
|
|
500
|
+
return this;
|
|
501
|
+
}
|
|
502
|
+
clone() {
|
|
503
|
+
const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });
|
|
504
|
+
let originalChunk = this.firstChunk;
|
|
505
|
+
let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
|
|
506
|
+
while (originalChunk) {
|
|
507
|
+
cloned.byStart[clonedChunk.start] = clonedChunk;
|
|
508
|
+
cloned.byEnd[clonedChunk.end] = clonedChunk;
|
|
509
|
+
const nextOriginalChunk = originalChunk.next;
|
|
510
|
+
const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
|
|
511
|
+
if (nextClonedChunk) {
|
|
512
|
+
clonedChunk.next = nextClonedChunk;
|
|
513
|
+
nextClonedChunk.previous = clonedChunk;
|
|
514
|
+
clonedChunk = nextClonedChunk;
|
|
515
|
+
}
|
|
516
|
+
originalChunk = nextOriginalChunk;
|
|
517
|
+
}
|
|
518
|
+
cloned.lastChunk = clonedChunk;
|
|
519
|
+
if (this.indentExclusionRanges) {
|
|
520
|
+
cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
|
|
521
|
+
}
|
|
522
|
+
cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);
|
|
523
|
+
cloned.intro = this.intro;
|
|
524
|
+
cloned.outro = this.outro;
|
|
525
|
+
return cloned;
|
|
526
|
+
}
|
|
527
|
+
generateDecodedMap(options) {
|
|
528
|
+
options = options || {};
|
|
529
|
+
const sourceIndex = 0;
|
|
530
|
+
const names = Object.keys(this.storedNames);
|
|
531
|
+
const mappings = new Mappings(options.hires);
|
|
532
|
+
const locate = getLocator(this.original);
|
|
533
|
+
if (this.intro) {
|
|
534
|
+
mappings.advance(this.intro);
|
|
535
|
+
}
|
|
536
|
+
this.firstChunk.eachNext((chunk) => {
|
|
537
|
+
const loc = locate(chunk.start);
|
|
538
|
+
if (chunk.intro.length)
|
|
539
|
+
mappings.advance(chunk.intro);
|
|
540
|
+
if (chunk.edited) {
|
|
541
|
+
mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);
|
|
542
|
+
} else {
|
|
543
|
+
mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);
|
|
544
|
+
}
|
|
545
|
+
if (chunk.outro.length)
|
|
546
|
+
mappings.advance(chunk.outro);
|
|
547
|
+
});
|
|
548
|
+
if (this.outro) {
|
|
549
|
+
mappings.advance(this.outro);
|
|
550
|
+
}
|
|
551
|
+
return {
|
|
552
|
+
file: options.file ? options.file.split(/[/\\]/).pop() : undefined,
|
|
553
|
+
sources: [
|
|
554
|
+
options.source ? getRelativePath(options.file || "", options.source) : options.file || ""
|
|
555
|
+
],
|
|
556
|
+
sourcesContent: options.includeContent ? [this.original] : undefined,
|
|
557
|
+
names,
|
|
558
|
+
mappings: mappings.raw,
|
|
559
|
+
x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
generateMap(options) {
|
|
563
|
+
return new SourceMap(this.generateDecodedMap(options));
|
|
564
|
+
}
|
|
565
|
+
_ensureindentStr() {
|
|
566
|
+
if (this.indentStr === undefined) {
|
|
567
|
+
this.indentStr = guessIndent(this.original);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
_getRawIndentString() {
|
|
571
|
+
this._ensureindentStr();
|
|
572
|
+
return this.indentStr;
|
|
573
|
+
}
|
|
574
|
+
getIndentString() {
|
|
575
|
+
this._ensureindentStr();
|
|
576
|
+
return this.indentStr === null ? "\t" : this.indentStr;
|
|
577
|
+
}
|
|
578
|
+
indent(indentStr, options) {
|
|
579
|
+
const pattern = /^[^\r\n]/gm;
|
|
580
|
+
if (isObject(indentStr)) {
|
|
581
|
+
options = indentStr;
|
|
582
|
+
indentStr = undefined;
|
|
583
|
+
}
|
|
584
|
+
if (indentStr === undefined) {
|
|
585
|
+
this._ensureindentStr();
|
|
586
|
+
indentStr = this.indentStr || "\t";
|
|
587
|
+
}
|
|
588
|
+
if (indentStr === "")
|
|
589
|
+
return this;
|
|
590
|
+
options = options || {};
|
|
591
|
+
const isExcluded = {};
|
|
592
|
+
if (options.exclude) {
|
|
593
|
+
const exclusions = typeof options.exclude[0] === "number" ? [options.exclude] : options.exclude;
|
|
594
|
+
exclusions.forEach((exclusion) => {
|
|
595
|
+
for (let i = exclusion[0];i < exclusion[1]; i += 1) {
|
|
596
|
+
isExcluded[i] = true;
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
let shouldIndentNextCharacter = options.indentStart !== false;
|
|
601
|
+
const replacer = (match) => {
|
|
602
|
+
if (shouldIndentNextCharacter)
|
|
603
|
+
return `${indentStr}${match}`;
|
|
604
|
+
shouldIndentNextCharacter = true;
|
|
605
|
+
return match;
|
|
606
|
+
};
|
|
607
|
+
this.intro = this.intro.replace(pattern, replacer);
|
|
608
|
+
let charIndex = 0;
|
|
609
|
+
let chunk = this.firstChunk;
|
|
610
|
+
while (chunk) {
|
|
611
|
+
const end = chunk.end;
|
|
612
|
+
if (chunk.edited) {
|
|
613
|
+
if (!isExcluded[charIndex]) {
|
|
614
|
+
chunk.content = chunk.content.replace(pattern, replacer);
|
|
615
|
+
if (chunk.content.length) {
|
|
616
|
+
shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === `
|
|
617
|
+
`;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
} else {
|
|
621
|
+
charIndex = chunk.start;
|
|
622
|
+
while (charIndex < end) {
|
|
623
|
+
if (!isExcluded[charIndex]) {
|
|
624
|
+
const char = this.original[charIndex];
|
|
625
|
+
if (char === `
|
|
626
|
+
`) {
|
|
627
|
+
shouldIndentNextCharacter = true;
|
|
628
|
+
} else if (char !== "\r" && shouldIndentNextCharacter) {
|
|
629
|
+
shouldIndentNextCharacter = false;
|
|
630
|
+
if (charIndex === chunk.start) {
|
|
631
|
+
chunk.prependRight(indentStr);
|
|
632
|
+
} else {
|
|
633
|
+
this._splitChunk(chunk, charIndex);
|
|
634
|
+
chunk = chunk.next;
|
|
635
|
+
chunk.prependRight(indentStr);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
charIndex += 1;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
charIndex = chunk.end;
|
|
643
|
+
chunk = chunk.next;
|
|
644
|
+
}
|
|
645
|
+
this.outro = this.outro.replace(pattern, replacer);
|
|
646
|
+
return this;
|
|
647
|
+
}
|
|
648
|
+
insert() {
|
|
649
|
+
throw new Error("magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)");
|
|
650
|
+
}
|
|
651
|
+
insertLeft(index, content) {
|
|
652
|
+
if (!warned.insertLeft) {
|
|
653
|
+
console.warn("magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead");
|
|
654
|
+
warned.insertLeft = true;
|
|
655
|
+
}
|
|
656
|
+
return this.appendLeft(index, content);
|
|
657
|
+
}
|
|
658
|
+
insertRight(index, content) {
|
|
659
|
+
if (!warned.insertRight) {
|
|
660
|
+
console.warn("magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead");
|
|
661
|
+
warned.insertRight = true;
|
|
662
|
+
}
|
|
663
|
+
return this.prependRight(index, content);
|
|
664
|
+
}
|
|
665
|
+
move(start, end, index) {
|
|
666
|
+
start = start + this.offset;
|
|
667
|
+
end = end + this.offset;
|
|
668
|
+
index = index + this.offset;
|
|
669
|
+
if (index >= start && index <= end)
|
|
670
|
+
throw new Error("Cannot move a selection inside itself");
|
|
671
|
+
this._split(start);
|
|
672
|
+
this._split(end);
|
|
673
|
+
this._split(index);
|
|
674
|
+
const first = this.byStart[start];
|
|
675
|
+
const last = this.byEnd[end];
|
|
676
|
+
const oldLeft = first.previous;
|
|
677
|
+
const oldRight = last.next;
|
|
678
|
+
const newRight = this.byStart[index];
|
|
679
|
+
if (!newRight && last === this.lastChunk)
|
|
680
|
+
return this;
|
|
681
|
+
const newLeft = newRight ? newRight.previous : this.lastChunk;
|
|
682
|
+
if (oldLeft)
|
|
683
|
+
oldLeft.next = oldRight;
|
|
684
|
+
if (oldRight)
|
|
685
|
+
oldRight.previous = oldLeft;
|
|
686
|
+
if (newLeft)
|
|
687
|
+
newLeft.next = first;
|
|
688
|
+
if (newRight)
|
|
689
|
+
newRight.previous = last;
|
|
690
|
+
if (!first.previous)
|
|
691
|
+
this.firstChunk = last.next;
|
|
692
|
+
if (!last.next) {
|
|
693
|
+
this.lastChunk = first.previous;
|
|
694
|
+
this.lastChunk.next = null;
|
|
695
|
+
}
|
|
696
|
+
first.previous = newLeft;
|
|
697
|
+
last.next = newRight || null;
|
|
698
|
+
if (!newLeft)
|
|
699
|
+
this.firstChunk = first;
|
|
700
|
+
if (!newRight)
|
|
701
|
+
this.lastChunk = last;
|
|
702
|
+
return this;
|
|
703
|
+
}
|
|
704
|
+
overwrite(start, end, content, options) {
|
|
705
|
+
options = options || {};
|
|
706
|
+
return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });
|
|
707
|
+
}
|
|
708
|
+
update(start, end, content, options) {
|
|
709
|
+
start = start + this.offset;
|
|
710
|
+
end = end + this.offset;
|
|
711
|
+
if (typeof content !== "string")
|
|
712
|
+
throw new TypeError("replacement content must be a string");
|
|
713
|
+
if (this.original.length !== 0) {
|
|
714
|
+
while (start < 0)
|
|
715
|
+
start += this.original.length;
|
|
716
|
+
while (end < 0)
|
|
717
|
+
end += this.original.length;
|
|
718
|
+
}
|
|
719
|
+
if (end > this.original.length)
|
|
720
|
+
throw new Error("end is out of bounds");
|
|
721
|
+
if (start === end)
|
|
722
|
+
throw new Error("Cannot overwrite a zero-length range – use appendLeft or prependRight instead");
|
|
723
|
+
this._split(start);
|
|
724
|
+
this._split(end);
|
|
725
|
+
if (options === true) {
|
|
726
|
+
if (!warned.storeName) {
|
|
727
|
+
console.warn("The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string");
|
|
728
|
+
warned.storeName = true;
|
|
729
|
+
}
|
|
730
|
+
options = { storeName: true };
|
|
731
|
+
}
|
|
732
|
+
const storeName = options !== undefined ? options.storeName : false;
|
|
733
|
+
const overwrite = options !== undefined ? options.overwrite : false;
|
|
734
|
+
if (storeName) {
|
|
735
|
+
const original = this.original.slice(start, end);
|
|
736
|
+
Object.defineProperty(this.storedNames, original, {
|
|
737
|
+
writable: true,
|
|
738
|
+
value: true,
|
|
739
|
+
enumerable: true
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
const first = this.byStart[start];
|
|
743
|
+
const last = this.byEnd[end];
|
|
744
|
+
if (first) {
|
|
745
|
+
let chunk = first;
|
|
746
|
+
while (chunk !== last) {
|
|
747
|
+
if (chunk.next !== this.byStart[chunk.end]) {
|
|
748
|
+
throw new Error("Cannot overwrite across a split point");
|
|
749
|
+
}
|
|
750
|
+
chunk = chunk.next;
|
|
751
|
+
chunk.edit("", false);
|
|
752
|
+
}
|
|
753
|
+
first.edit(content, storeName, !overwrite);
|
|
754
|
+
} else {
|
|
755
|
+
const newChunk = new Chunk(start, end, "").edit(content, storeName);
|
|
756
|
+
last.next = newChunk;
|
|
757
|
+
newChunk.previous = last;
|
|
758
|
+
}
|
|
759
|
+
return this;
|
|
760
|
+
}
|
|
761
|
+
prepend(content) {
|
|
762
|
+
if (typeof content !== "string")
|
|
763
|
+
throw new TypeError("outro content must be a string");
|
|
764
|
+
this.intro = content + this.intro;
|
|
765
|
+
return this;
|
|
766
|
+
}
|
|
767
|
+
prependLeft(index, content) {
|
|
768
|
+
index = index + this.offset;
|
|
769
|
+
if (typeof content !== "string")
|
|
770
|
+
throw new TypeError("inserted content must be a string");
|
|
771
|
+
this._split(index);
|
|
772
|
+
const chunk = this.byEnd[index];
|
|
773
|
+
if (chunk) {
|
|
774
|
+
chunk.prependLeft(content);
|
|
775
|
+
} else {
|
|
776
|
+
this.intro = content + this.intro;
|
|
777
|
+
}
|
|
778
|
+
return this;
|
|
779
|
+
}
|
|
780
|
+
prependRight(index, content) {
|
|
781
|
+
index = index + this.offset;
|
|
782
|
+
if (typeof content !== "string")
|
|
783
|
+
throw new TypeError("inserted content must be a string");
|
|
784
|
+
this._split(index);
|
|
785
|
+
const chunk = this.byStart[index];
|
|
786
|
+
if (chunk) {
|
|
787
|
+
chunk.prependRight(content);
|
|
788
|
+
} else {
|
|
789
|
+
this.outro = content + this.outro;
|
|
790
|
+
}
|
|
791
|
+
return this;
|
|
792
|
+
}
|
|
793
|
+
remove(start, end) {
|
|
794
|
+
start = start + this.offset;
|
|
795
|
+
end = end + this.offset;
|
|
796
|
+
if (this.original.length !== 0) {
|
|
797
|
+
while (start < 0)
|
|
798
|
+
start += this.original.length;
|
|
799
|
+
while (end < 0)
|
|
800
|
+
end += this.original.length;
|
|
801
|
+
}
|
|
802
|
+
if (start === end)
|
|
803
|
+
return this;
|
|
804
|
+
if (start < 0 || end > this.original.length)
|
|
805
|
+
throw new Error("Character is out of bounds");
|
|
806
|
+
if (start > end)
|
|
807
|
+
throw new Error("end must be greater than start");
|
|
808
|
+
this._split(start);
|
|
809
|
+
this._split(end);
|
|
810
|
+
let chunk = this.byStart[start];
|
|
811
|
+
while (chunk) {
|
|
812
|
+
chunk.intro = "";
|
|
813
|
+
chunk.outro = "";
|
|
814
|
+
chunk.edit("");
|
|
815
|
+
chunk = end > chunk.end ? this.byStart[chunk.end] : null;
|
|
816
|
+
}
|
|
817
|
+
return this;
|
|
818
|
+
}
|
|
819
|
+
reset(start, end) {
|
|
820
|
+
start = start + this.offset;
|
|
821
|
+
end = end + this.offset;
|
|
822
|
+
if (this.original.length !== 0) {
|
|
823
|
+
while (start < 0)
|
|
824
|
+
start += this.original.length;
|
|
825
|
+
while (end < 0)
|
|
826
|
+
end += this.original.length;
|
|
827
|
+
}
|
|
828
|
+
if (start === end)
|
|
829
|
+
return this;
|
|
830
|
+
if (start < 0 || end > this.original.length)
|
|
831
|
+
throw new Error("Character is out of bounds");
|
|
832
|
+
if (start > end)
|
|
833
|
+
throw new Error("end must be greater than start");
|
|
834
|
+
this._split(start);
|
|
835
|
+
this._split(end);
|
|
836
|
+
let chunk = this.byStart[start];
|
|
837
|
+
while (chunk) {
|
|
838
|
+
chunk.reset();
|
|
839
|
+
chunk = end > chunk.end ? this.byStart[chunk.end] : null;
|
|
840
|
+
}
|
|
841
|
+
return this;
|
|
842
|
+
}
|
|
843
|
+
lastChar() {
|
|
844
|
+
if (this.outro.length)
|
|
845
|
+
return this.outro[this.outro.length - 1];
|
|
846
|
+
let chunk = this.lastChunk;
|
|
847
|
+
do {
|
|
848
|
+
if (chunk.outro.length)
|
|
849
|
+
return chunk.outro[chunk.outro.length - 1];
|
|
850
|
+
if (chunk.content.length)
|
|
851
|
+
return chunk.content[chunk.content.length - 1];
|
|
852
|
+
if (chunk.intro.length)
|
|
853
|
+
return chunk.intro[chunk.intro.length - 1];
|
|
854
|
+
} while (chunk = chunk.previous);
|
|
855
|
+
if (this.intro.length)
|
|
856
|
+
return this.intro[this.intro.length - 1];
|
|
857
|
+
return "";
|
|
858
|
+
}
|
|
859
|
+
lastLine() {
|
|
860
|
+
let lineIndex = this.outro.lastIndexOf(n);
|
|
861
|
+
if (lineIndex !== -1)
|
|
862
|
+
return this.outro.substr(lineIndex + 1);
|
|
863
|
+
let lineStr = this.outro;
|
|
864
|
+
let chunk = this.lastChunk;
|
|
865
|
+
do {
|
|
866
|
+
if (chunk.outro.length > 0) {
|
|
867
|
+
lineIndex = chunk.outro.lastIndexOf(n);
|
|
868
|
+
if (lineIndex !== -1)
|
|
869
|
+
return chunk.outro.substr(lineIndex + 1) + lineStr;
|
|
870
|
+
lineStr = chunk.outro + lineStr;
|
|
871
|
+
}
|
|
872
|
+
if (chunk.content.length > 0) {
|
|
873
|
+
lineIndex = chunk.content.lastIndexOf(n);
|
|
874
|
+
if (lineIndex !== -1)
|
|
875
|
+
return chunk.content.substr(lineIndex + 1) + lineStr;
|
|
876
|
+
lineStr = chunk.content + lineStr;
|
|
877
|
+
}
|
|
878
|
+
if (chunk.intro.length > 0) {
|
|
879
|
+
lineIndex = chunk.intro.lastIndexOf(n);
|
|
880
|
+
if (lineIndex !== -1)
|
|
881
|
+
return chunk.intro.substr(lineIndex + 1) + lineStr;
|
|
882
|
+
lineStr = chunk.intro + lineStr;
|
|
883
|
+
}
|
|
884
|
+
} while (chunk = chunk.previous);
|
|
885
|
+
lineIndex = this.intro.lastIndexOf(n);
|
|
886
|
+
if (lineIndex !== -1)
|
|
887
|
+
return this.intro.substr(lineIndex + 1) + lineStr;
|
|
888
|
+
return this.intro + lineStr;
|
|
889
|
+
}
|
|
890
|
+
slice(start = 0, end = this.original.length - this.offset) {
|
|
891
|
+
start = start + this.offset;
|
|
892
|
+
end = end + this.offset;
|
|
893
|
+
if (this.original.length !== 0) {
|
|
894
|
+
while (start < 0)
|
|
895
|
+
start += this.original.length;
|
|
896
|
+
while (end < 0)
|
|
897
|
+
end += this.original.length;
|
|
898
|
+
}
|
|
899
|
+
let result = "";
|
|
900
|
+
let chunk = this.firstChunk;
|
|
901
|
+
while (chunk && (chunk.start > start || chunk.end <= start)) {
|
|
902
|
+
if (chunk.start < end && chunk.end >= end) {
|
|
903
|
+
return result;
|
|
904
|
+
}
|
|
905
|
+
chunk = chunk.next;
|
|
906
|
+
}
|
|
907
|
+
if (chunk && chunk.edited && chunk.start !== start)
|
|
908
|
+
throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);
|
|
909
|
+
const startChunk = chunk;
|
|
910
|
+
while (chunk) {
|
|
911
|
+
if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {
|
|
912
|
+
result += chunk.intro;
|
|
913
|
+
}
|
|
914
|
+
const containsEnd = chunk.start < end && chunk.end >= end;
|
|
915
|
+
if (containsEnd && chunk.edited && chunk.end !== end)
|
|
916
|
+
throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);
|
|
917
|
+
const sliceStart = startChunk === chunk ? start - chunk.start : 0;
|
|
918
|
+
const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
|
|
919
|
+
result += chunk.content.slice(sliceStart, sliceEnd);
|
|
920
|
+
if (chunk.outro && (!containsEnd || chunk.end === end)) {
|
|
921
|
+
result += chunk.outro;
|
|
922
|
+
}
|
|
923
|
+
if (containsEnd) {
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
chunk = chunk.next;
|
|
927
|
+
}
|
|
928
|
+
return result;
|
|
929
|
+
}
|
|
930
|
+
snip(start, end) {
|
|
931
|
+
const clone = this.clone();
|
|
932
|
+
clone.remove(0, start);
|
|
933
|
+
clone.remove(end, clone.original.length);
|
|
934
|
+
return clone;
|
|
935
|
+
}
|
|
936
|
+
_split(index) {
|
|
937
|
+
if (this.byStart[index] || this.byEnd[index])
|
|
938
|
+
return;
|
|
939
|
+
let chunk = this.lastSearchedChunk;
|
|
940
|
+
let previousChunk = chunk;
|
|
941
|
+
const searchForward = index > chunk.end;
|
|
942
|
+
while (chunk) {
|
|
943
|
+
if (chunk.contains(index))
|
|
944
|
+
return this._splitChunk(chunk, index);
|
|
945
|
+
chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
|
|
946
|
+
if (chunk === previousChunk)
|
|
947
|
+
return;
|
|
948
|
+
previousChunk = chunk;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
_splitChunk(chunk, index) {
|
|
952
|
+
if (chunk.edited && chunk.content.length) {
|
|
953
|
+
const loc = getLocator(this.original)(index);
|
|
954
|
+
throw new Error(`Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`);
|
|
955
|
+
}
|
|
956
|
+
const newChunk = chunk.split(index);
|
|
957
|
+
this.byEnd[index] = chunk;
|
|
958
|
+
this.byStart[index] = newChunk;
|
|
959
|
+
this.byEnd[newChunk.end] = newChunk;
|
|
960
|
+
if (chunk === this.lastChunk)
|
|
961
|
+
this.lastChunk = newChunk;
|
|
962
|
+
this.lastSearchedChunk = chunk;
|
|
963
|
+
return true;
|
|
964
|
+
}
|
|
965
|
+
toString() {
|
|
966
|
+
let str = this.intro;
|
|
967
|
+
let chunk = this.firstChunk;
|
|
968
|
+
while (chunk) {
|
|
969
|
+
str += chunk.toString();
|
|
970
|
+
chunk = chunk.next;
|
|
971
|
+
}
|
|
972
|
+
return str + this.outro;
|
|
973
|
+
}
|
|
974
|
+
isEmpty() {
|
|
975
|
+
let chunk = this.firstChunk;
|
|
976
|
+
do {
|
|
977
|
+
if (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim())
|
|
978
|
+
return false;
|
|
979
|
+
} while (chunk = chunk.next);
|
|
980
|
+
return true;
|
|
981
|
+
}
|
|
982
|
+
length() {
|
|
983
|
+
let chunk = this.firstChunk;
|
|
984
|
+
let length = 0;
|
|
985
|
+
do {
|
|
986
|
+
length += chunk.intro.length + chunk.content.length + chunk.outro.length;
|
|
987
|
+
} while (chunk = chunk.next);
|
|
988
|
+
return length;
|
|
989
|
+
}
|
|
990
|
+
trimLines() {
|
|
991
|
+
return this.trim("[\\r\\n]");
|
|
992
|
+
}
|
|
993
|
+
trim(charType) {
|
|
994
|
+
return this.trimStart(charType).trimEnd(charType);
|
|
995
|
+
}
|
|
996
|
+
trimEndAborted(charType) {
|
|
997
|
+
const rx = new RegExp((charType || "\\s") + "+$");
|
|
998
|
+
this.outro = this.outro.replace(rx, "");
|
|
999
|
+
if (this.outro.length)
|
|
1000
|
+
return true;
|
|
1001
|
+
let chunk = this.lastChunk;
|
|
1002
|
+
do {
|
|
1003
|
+
const end = chunk.end;
|
|
1004
|
+
const aborted = chunk.trimEnd(rx);
|
|
1005
|
+
if (chunk.end !== end) {
|
|
1006
|
+
if (this.lastChunk === chunk) {
|
|
1007
|
+
this.lastChunk = chunk.next;
|
|
1008
|
+
}
|
|
1009
|
+
this.byEnd[chunk.end] = chunk;
|
|
1010
|
+
this.byStart[chunk.next.start] = chunk.next;
|
|
1011
|
+
this.byEnd[chunk.next.end] = chunk.next;
|
|
1012
|
+
}
|
|
1013
|
+
if (aborted)
|
|
1014
|
+
return true;
|
|
1015
|
+
chunk = chunk.previous;
|
|
1016
|
+
} while (chunk);
|
|
1017
|
+
return false;
|
|
1018
|
+
}
|
|
1019
|
+
trimEnd(charType) {
|
|
1020
|
+
this.trimEndAborted(charType);
|
|
1021
|
+
return this;
|
|
1022
|
+
}
|
|
1023
|
+
trimStartAborted(charType) {
|
|
1024
|
+
const rx = new RegExp("^" + (charType || "\\s") + "+");
|
|
1025
|
+
this.intro = this.intro.replace(rx, "");
|
|
1026
|
+
if (this.intro.length)
|
|
1027
|
+
return true;
|
|
1028
|
+
let chunk = this.firstChunk;
|
|
1029
|
+
do {
|
|
1030
|
+
const end = chunk.end;
|
|
1031
|
+
const aborted = chunk.trimStart(rx);
|
|
1032
|
+
if (chunk.end !== end) {
|
|
1033
|
+
if (chunk === this.lastChunk)
|
|
1034
|
+
this.lastChunk = chunk.next;
|
|
1035
|
+
this.byEnd[chunk.end] = chunk;
|
|
1036
|
+
this.byStart[chunk.next.start] = chunk.next;
|
|
1037
|
+
this.byEnd[chunk.next.end] = chunk.next;
|
|
1038
|
+
}
|
|
1039
|
+
if (aborted)
|
|
1040
|
+
return true;
|
|
1041
|
+
chunk = chunk.next;
|
|
1042
|
+
} while (chunk);
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
trimStart(charType) {
|
|
1046
|
+
this.trimStartAborted(charType);
|
|
1047
|
+
return this;
|
|
1048
|
+
}
|
|
1049
|
+
hasChanged() {
|
|
1050
|
+
return this.original !== this.toString();
|
|
1051
|
+
}
|
|
1052
|
+
_replaceRegexp(searchValue, replacement) {
|
|
1053
|
+
function getReplacement(match, str) {
|
|
1054
|
+
if (typeof replacement === "string") {
|
|
1055
|
+
return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {
|
|
1056
|
+
if (i === "$")
|
|
1057
|
+
return "$";
|
|
1058
|
+
if (i === "&")
|
|
1059
|
+
return match[0];
|
|
1060
|
+
const num = +i;
|
|
1061
|
+
if (num < match.length)
|
|
1062
|
+
return match[+i];
|
|
1063
|
+
return `$${i}`;
|
|
1064
|
+
});
|
|
1065
|
+
} else {
|
|
1066
|
+
return replacement(...match, match.index, str, match.groups);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
function matchAll(re, str) {
|
|
1070
|
+
let match;
|
|
1071
|
+
const matches = [];
|
|
1072
|
+
while (match = re.exec(str)) {
|
|
1073
|
+
matches.push(match);
|
|
1074
|
+
}
|
|
1075
|
+
return matches;
|
|
1076
|
+
}
|
|
1077
|
+
if (searchValue.global) {
|
|
1078
|
+
const matches = matchAll(searchValue, this.original);
|
|
1079
|
+
matches.forEach((match) => {
|
|
1080
|
+
if (match.index != null) {
|
|
1081
|
+
const replacement2 = getReplacement(match, this.original);
|
|
1082
|
+
if (replacement2 !== match[0]) {
|
|
1083
|
+
this.overwrite(match.index, match.index + match[0].length, replacement2);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
} else {
|
|
1088
|
+
const match = this.original.match(searchValue);
|
|
1089
|
+
if (match && match.index != null) {
|
|
1090
|
+
const replacement2 = getReplacement(match, this.original);
|
|
1091
|
+
if (replacement2 !== match[0]) {
|
|
1092
|
+
this.overwrite(match.index, match.index + match[0].length, replacement2);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
return this;
|
|
1097
|
+
}
|
|
1098
|
+
_replaceString(string, replacement) {
|
|
1099
|
+
const { original } = this;
|
|
1100
|
+
const index = original.indexOf(string);
|
|
1101
|
+
if (index !== -1) {
|
|
1102
|
+
if (typeof replacement === "function") {
|
|
1103
|
+
replacement = replacement(string, index, original);
|
|
1104
|
+
}
|
|
1105
|
+
if (string !== replacement) {
|
|
1106
|
+
this.overwrite(index, index + string.length, replacement);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
return this;
|
|
1110
|
+
}
|
|
1111
|
+
replace(searchValue, replacement) {
|
|
1112
|
+
if (typeof searchValue === "string") {
|
|
1113
|
+
return this._replaceString(searchValue, replacement);
|
|
1114
|
+
}
|
|
1115
|
+
return this._replaceRegexp(searchValue, replacement);
|
|
1116
|
+
}
|
|
1117
|
+
_replaceAllString(string, replacement) {
|
|
1118
|
+
const { original } = this;
|
|
1119
|
+
const stringLength = string.length;
|
|
1120
|
+
for (let index = original.indexOf(string);index !== -1; index = original.indexOf(string, index + stringLength)) {
|
|
1121
|
+
const previous = original.slice(index, index + stringLength);
|
|
1122
|
+
let _replacement = replacement;
|
|
1123
|
+
if (typeof replacement === "function") {
|
|
1124
|
+
_replacement = replacement(previous, index, original);
|
|
1125
|
+
}
|
|
1126
|
+
if (previous !== _replacement)
|
|
1127
|
+
this.overwrite(index, index + stringLength, _replacement);
|
|
1128
|
+
}
|
|
1129
|
+
return this;
|
|
1130
|
+
}
|
|
1131
|
+
replaceAll(searchValue, replacement) {
|
|
1132
|
+
if (typeof searchValue === "string") {
|
|
1133
|
+
return this._replaceAllString(searchValue, replacement);
|
|
1134
|
+
}
|
|
1135
|
+
if (!searchValue.global) {
|
|
1136
|
+
throw new TypeError("MagicString.prototype.replaceAll called with a non-global RegExp argument");
|
|
1137
|
+
}
|
|
1138
|
+
return this._replaceRegexp(searchValue, replacement);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// src/transform/patterns.ts
|
|
1143
|
+
var patterns = {
|
|
1144
|
+
hasMacros: /\$origin|\$attrs\.(origin|for)|\$attrs\s*\(/,
|
|
1145
|
+
origin: /\$origin\s*\(/g,
|
|
1146
|
+
originWithParents: /\$origin\s*\(\s*\[/,
|
|
1147
|
+
attrsInOrigin: /\$attrs\s*\(\s*\{/g,
|
|
1148
|
+
standaloneAttrs: /(?:let|const|export\s+const|export\s+let)\s+\w+\s*=\s*\$attrs\s*\(/g,
|
|
1149
|
+
bindableInAttrs: /\$bindable\s*\(/g,
|
|
1150
|
+
attrsOrigin: /\$attrs\s*\.\s*origin\s*\(\s*(\w+)\s*\)/g,
|
|
1151
|
+
attrsForOrigin: /\$attrs\s*\.\s*for\s*\(\s*(\w+)\s*\)/g,
|
|
1152
|
+
attrsForElement: /\$attrs\s*\.\s*for\s*\(\s*['"]([\w-]+)['"]\s*\)/g
|
|
1153
|
+
};
|
|
1154
|
+
function containsMacros(source) {
|
|
1155
|
+
return patterns.hasMacros.test(source);
|
|
1156
|
+
}
|
|
1157
|
+
function isInsideStringOrComment(source, position) {
|
|
1158
|
+
let i = 0;
|
|
1159
|
+
while (i < position) {
|
|
1160
|
+
const char = source[i];
|
|
1161
|
+
if (char === "/" && source[i + 1] === "/") {
|
|
1162
|
+
const endLine = source.indexOf(`
|
|
1163
|
+
`, i + 2);
|
|
1164
|
+
if (endLine === -1) {
|
|
1165
|
+
return position > i;
|
|
1166
|
+
}
|
|
1167
|
+
if (position > i && position <= endLine) {
|
|
1168
|
+
return true;
|
|
1169
|
+
}
|
|
1170
|
+
i = endLine + 1;
|
|
1171
|
+
continue;
|
|
1172
|
+
}
|
|
1173
|
+
if (char === "/" && source[i + 1] === "*") {
|
|
1174
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
1175
|
+
if (endComment === -1) {
|
|
1176
|
+
return position > i;
|
|
1177
|
+
}
|
|
1178
|
+
if (position > i && position < endComment + 2) {
|
|
1179
|
+
return true;
|
|
1180
|
+
}
|
|
1181
|
+
i = endComment + 2;
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1185
|
+
const quote = char;
|
|
1186
|
+
const stringStart = i;
|
|
1187
|
+
i++;
|
|
1188
|
+
while (i < source.length) {
|
|
1189
|
+
if (source[i] === "\\") {
|
|
1190
|
+
i += 2;
|
|
1191
|
+
continue;
|
|
1192
|
+
}
|
|
1193
|
+
if (source[i] === quote) {
|
|
1194
|
+
if (position > stringStart && position <= i) {
|
|
1195
|
+
return true;
|
|
1196
|
+
}
|
|
1197
|
+
i++;
|
|
1198
|
+
break;
|
|
1199
|
+
}
|
|
1200
|
+
if (quote === "`" && source[i] === "$" && source[i + 1] === "{") {
|
|
1201
|
+
const exprStart = i;
|
|
1202
|
+
i += 2;
|
|
1203
|
+
let depth = 1;
|
|
1204
|
+
while (i < source.length && depth > 0) {
|
|
1205
|
+
if (source[i] === "{")
|
|
1206
|
+
depth++;
|
|
1207
|
+
else if (source[i] === "}")
|
|
1208
|
+
depth--;
|
|
1209
|
+
else if (source[i] === "\\")
|
|
1210
|
+
i++;
|
|
1211
|
+
i++;
|
|
1212
|
+
}
|
|
1213
|
+
if (position > stringStart && position < exprStart) {
|
|
1214
|
+
return true;
|
|
1215
|
+
}
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
i++;
|
|
1219
|
+
}
|
|
1220
|
+
continue;
|
|
1221
|
+
}
|
|
1222
|
+
i++;
|
|
1223
|
+
}
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
function extractBindable(value) {
|
|
1227
|
+
if (!value.startsWith("$bindable"))
|
|
1228
|
+
return { isBindable: false };
|
|
1229
|
+
let i = 9;
|
|
1230
|
+
if (value[i] === "<") {
|
|
1231
|
+
let depth = 1;
|
|
1232
|
+
i++;
|
|
1233
|
+
while (i < value.length && depth > 0) {
|
|
1234
|
+
const char = value[i];
|
|
1235
|
+
if (char === "=" && value[i + 1] === ">") {
|
|
1236
|
+
i += 2;
|
|
1237
|
+
continue;
|
|
1238
|
+
}
|
|
1239
|
+
if (char === "<")
|
|
1240
|
+
depth++;
|
|
1241
|
+
else if (char === ">")
|
|
1242
|
+
depth--;
|
|
1243
|
+
i++;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
while (i < value.length && /\s/.test(value[i]))
|
|
1247
|
+
i++;
|
|
1248
|
+
if (value[i] !== "(")
|
|
1249
|
+
return { isBindable: false };
|
|
1250
|
+
const openParen = i;
|
|
1251
|
+
const closeParen = findMatchingBracket(value, openParen);
|
|
1252
|
+
if (closeParen === -1)
|
|
1253
|
+
return { isBindable: false };
|
|
1254
|
+
const innerValue = value.slice(openParen + 1, closeParen).trim() || "undefined";
|
|
1255
|
+
return { isBindable: true, innerValue };
|
|
1256
|
+
}
|
|
1257
|
+
function findTopLevelAs(value) {
|
|
1258
|
+
let depth = 0;
|
|
1259
|
+
let angleDepth = 0;
|
|
1260
|
+
for (let i = 0;i < value.length - 4; i++) {
|
|
1261
|
+
const char = value[i];
|
|
1262
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1263
|
+
const quote = char;
|
|
1264
|
+
i++;
|
|
1265
|
+
while (i < value.length && value[i] !== quote) {
|
|
1266
|
+
if (value[i] === "\\")
|
|
1267
|
+
i++;
|
|
1268
|
+
i++;
|
|
1269
|
+
}
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1272
|
+
if (char === "{" || char === "(" || char === "[") {
|
|
1273
|
+
depth++;
|
|
1274
|
+
} else if (char === "}" || char === ")" || char === "]") {
|
|
1275
|
+
depth--;
|
|
1276
|
+
} else if (char === "<") {
|
|
1277
|
+
const prevChar = i > 0 ? value[i - 1] : "";
|
|
1278
|
+
if (/[\w$)]/.test(prevChar)) {
|
|
1279
|
+
angleDepth++;
|
|
1280
|
+
}
|
|
1281
|
+
} else if (char === ">") {
|
|
1282
|
+
if (i > 0 && value[i - 1] === "=") {
|
|
1283
|
+
continue;
|
|
1284
|
+
}
|
|
1285
|
+
if (angleDepth > 0) {
|
|
1286
|
+
angleDepth--;
|
|
1287
|
+
}
|
|
1288
|
+
} else if (depth === 0 && angleDepth === 0 && value.slice(i, i + 4) === " as ") {
|
|
1289
|
+
return i;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return -1;
|
|
1293
|
+
}
|
|
1294
|
+
function findMatchingBracket(source, openIndex, openChar = "(", closeChar = ")") {
|
|
1295
|
+
let depth = 0;
|
|
1296
|
+
for (let i = openIndex;i < source.length; i++) {
|
|
1297
|
+
const char = source[i];
|
|
1298
|
+
if (char === "/" && source[i + 1] === "/") {
|
|
1299
|
+
const endLine = source.indexOf(`
|
|
1300
|
+
`, i + 2);
|
|
1301
|
+
if (endLine !== -1) {
|
|
1302
|
+
i = endLine;
|
|
1303
|
+
} else {
|
|
1304
|
+
i = source.length;
|
|
1305
|
+
}
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
if (char === "/" && source[i + 1] === "*") {
|
|
1309
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
1310
|
+
if (endComment !== -1) {
|
|
1311
|
+
i = endComment + 1;
|
|
1312
|
+
} else {
|
|
1313
|
+
i = source.length;
|
|
1314
|
+
}
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1318
|
+
const quote = char;
|
|
1319
|
+
i++;
|
|
1320
|
+
while (i < source.length && source[i] !== quote) {
|
|
1321
|
+
if (source[i] === "\\")
|
|
1322
|
+
i++;
|
|
1323
|
+
i++;
|
|
1324
|
+
}
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1327
|
+
if (char === openChar) {
|
|
1328
|
+
depth++;
|
|
1329
|
+
} else if (char === closeChar) {
|
|
1330
|
+
depth--;
|
|
1331
|
+
if (depth === 0) {
|
|
1332
|
+
return i;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
return -1;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
// src/transform/codegen.ts
|
|
1340
|
+
function generateRuntimeImport(functions) {
|
|
1341
|
+
return `import { ${functions.join(", ")} } from 'svelte-origin/runtime'`;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// src/transform/declaration-parser.ts
|
|
1345
|
+
function findVariableDeclarationsWithMacro(source, macroPattern) {
|
|
1346
|
+
const results = [];
|
|
1347
|
+
const parts = macroPattern.split(".");
|
|
1348
|
+
const escapedParts = parts.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
1349
|
+
const patternWithSpaces = escapedParts.join("\\s*\\.\\s*");
|
|
1350
|
+
const macroRegex = new RegExp(patternWithSpaces + "\\s*\\(", "g");
|
|
1351
|
+
let match;
|
|
1352
|
+
while ((match = macroRegex.exec(source)) !== null) {
|
|
1353
|
+
const macroStart = match.index;
|
|
1354
|
+
const macroOpenParen = macroStart + match[0].length - 1;
|
|
1355
|
+
if (isInsideStringOrComment(source, macroStart)) {
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
const declaration = findDeclarationBefore(source, macroStart);
|
|
1359
|
+
if (declaration) {
|
|
1360
|
+
results.push({
|
|
1361
|
+
...declaration,
|
|
1362
|
+
macroOpenParen
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
return results;
|
|
1367
|
+
}
|
|
1368
|
+
function findDeclarationBefore(source, beforeIndex) {
|
|
1369
|
+
let i = beforeIndex - 1;
|
|
1370
|
+
while (i >= 0 && /\s/.test(source[i]))
|
|
1371
|
+
i--;
|
|
1372
|
+
if (source[i] !== "=")
|
|
1373
|
+
return null;
|
|
1374
|
+
const equalsIndex = i;
|
|
1375
|
+
i--;
|
|
1376
|
+
while (i >= 0 && /\s/.test(source[i]))
|
|
1377
|
+
i--;
|
|
1378
|
+
let typeAnnotation = null;
|
|
1379
|
+
let typeEnd = -1;
|
|
1380
|
+
const posAfterTypeOrName = i + 1;
|
|
1381
|
+
let depth = 0;
|
|
1382
|
+
let colonIndex = -1;
|
|
1383
|
+
let tempI = i;
|
|
1384
|
+
while (tempI >= 0) {
|
|
1385
|
+
const char = source[tempI];
|
|
1386
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1387
|
+
tempI--;
|
|
1388
|
+
while (tempI >= 0 && source[tempI] !== char) {
|
|
1389
|
+
if (source[tempI - 1] === "\\")
|
|
1390
|
+
tempI--;
|
|
1391
|
+
tempI--;
|
|
1392
|
+
}
|
|
1393
|
+
tempI--;
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
if (char === ">" || char === ")" || char === "]" || char === "}") {
|
|
1397
|
+
depth++;
|
|
1398
|
+
} else if (char === "<" || char === "(" || char === "[" || char === "{") {
|
|
1399
|
+
depth--;
|
|
1400
|
+
} else if (char === ":" && depth === 0) {
|
|
1401
|
+
colonIndex = tempI;
|
|
1402
|
+
break;
|
|
1403
|
+
} else if (depth === 0 && /[;\n{]/.test(char)) {
|
|
1404
|
+
break;
|
|
1405
|
+
}
|
|
1406
|
+
tempI--;
|
|
1407
|
+
}
|
|
1408
|
+
if (colonIndex !== -1) {
|
|
1409
|
+
typeEnd = posAfterTypeOrName;
|
|
1410
|
+
typeAnnotation = source.slice(colonIndex + 1, typeEnd).trim();
|
|
1411
|
+
i = colonIndex - 1;
|
|
1412
|
+
while (i >= 0 && /\s/.test(source[i]))
|
|
1413
|
+
i--;
|
|
1414
|
+
}
|
|
1415
|
+
if (!/[\w$]/.test(source[i]))
|
|
1416
|
+
return null;
|
|
1417
|
+
const nameEnd = i + 1;
|
|
1418
|
+
while (i >= 0 && /[\w$]/.test(source[i]))
|
|
1419
|
+
i--;
|
|
1420
|
+
const nameStart = i + 1;
|
|
1421
|
+
const varName = source.slice(nameStart, nameEnd);
|
|
1422
|
+
if (!varName)
|
|
1423
|
+
return null;
|
|
1424
|
+
while (i >= 0 && /\s/.test(source[i]))
|
|
1425
|
+
i--;
|
|
1426
|
+
let keywordStart = -1;
|
|
1427
|
+
if (source.slice(i - 4, i + 1) === "const") {
|
|
1428
|
+
keywordStart = i - 4;
|
|
1429
|
+
i -= 5;
|
|
1430
|
+
} else if (source.slice(i - 2, i + 1) === "let") {
|
|
1431
|
+
keywordStart = i - 2;
|
|
1432
|
+
i -= 3;
|
|
1433
|
+
} else if (source.slice(i - 2, i + 1) === "var") {
|
|
1434
|
+
keywordStart = i - 2;
|
|
1435
|
+
i -= 3;
|
|
1436
|
+
} else {
|
|
1437
|
+
return null;
|
|
1438
|
+
}
|
|
1439
|
+
let startIndex = keywordStart;
|
|
1440
|
+
while (i >= 0 && /\s/.test(source[i]))
|
|
1441
|
+
i--;
|
|
1442
|
+
let hasExport = false;
|
|
1443
|
+
if (source.slice(i - 5, i + 1) === "export") {
|
|
1444
|
+
hasExport = true;
|
|
1445
|
+
startIndex = i - 5;
|
|
1446
|
+
i -= 6;
|
|
1447
|
+
while (i >= 0 && /\s/.test(source[i]))
|
|
1448
|
+
i--;
|
|
1449
|
+
}
|
|
1450
|
+
const valueStartIndex = equalsIndex + 1;
|
|
1451
|
+
return {
|
|
1452
|
+
varName,
|
|
1453
|
+
startIndex,
|
|
1454
|
+
valueStartIndex,
|
|
1455
|
+
hasExport,
|
|
1456
|
+
typeAnnotation
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
function hasExistingPropsDeclaration(source) {
|
|
1460
|
+
return /\b(type|interface)\s+\$\$Props\b/.test(source);
|
|
1461
|
+
}
|
|
1462
|
+
function findPropsInjectionPosition(source) {
|
|
1463
|
+
let lastImportEnd = 0;
|
|
1464
|
+
let i = 0;
|
|
1465
|
+
const scriptTagMatch = source.match(/^<script[^>]*>/);
|
|
1466
|
+
if (scriptTagMatch) {
|
|
1467
|
+
i = scriptTagMatch[0].length;
|
|
1468
|
+
lastImportEnd = i;
|
|
1469
|
+
}
|
|
1470
|
+
while (i < source.length) {
|
|
1471
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1472
|
+
i++;
|
|
1473
|
+
if (source.slice(i, i + 6) === "import") {
|
|
1474
|
+
i += 6;
|
|
1475
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1476
|
+
i++;
|
|
1477
|
+
if (source.slice(i, i + 4) === "type" && /\s/.test(source[i + 4])) {
|
|
1478
|
+
i += 4;
|
|
1479
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1480
|
+
i++;
|
|
1481
|
+
}
|
|
1482
|
+
let foundFrom = false;
|
|
1483
|
+
while (i < source.length) {
|
|
1484
|
+
const char = source[i];
|
|
1485
|
+
if (char === "{") {
|
|
1486
|
+
const closeIndex = findMatchingBracket(source, i, "{", "}");
|
|
1487
|
+
if (closeIndex !== -1) {
|
|
1488
|
+
i = closeIndex + 1;
|
|
1489
|
+
continue;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1493
|
+
const quote = char;
|
|
1494
|
+
i++;
|
|
1495
|
+
while (i < source.length && source[i] !== quote) {
|
|
1496
|
+
if (source[i] === "\\")
|
|
1497
|
+
i++;
|
|
1498
|
+
i++;
|
|
1499
|
+
}
|
|
1500
|
+
i++;
|
|
1501
|
+
while (i < source.length && source[i] !== `
|
|
1502
|
+
` && source[i] !== ";") {
|
|
1503
|
+
i++;
|
|
1504
|
+
}
|
|
1505
|
+
if (source[i] === ";")
|
|
1506
|
+
i++;
|
|
1507
|
+
if (source[i] === `
|
|
1508
|
+
`)
|
|
1509
|
+
i++;
|
|
1510
|
+
lastImportEnd = i;
|
|
1511
|
+
foundFrom = true;
|
|
1512
|
+
break;
|
|
1513
|
+
}
|
|
1514
|
+
if (source.slice(i, i + 4) === "from" && /\s/.test(source[i + 4])) {
|
|
1515
|
+
i += 4;
|
|
1516
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1517
|
+
i++;
|
|
1518
|
+
continue;
|
|
1519
|
+
}
|
|
1520
|
+
i++;
|
|
1521
|
+
}
|
|
1522
|
+
if (!foundFrom) {
|
|
1523
|
+
break;
|
|
1524
|
+
}
|
|
1525
|
+
continue;
|
|
1526
|
+
}
|
|
1527
|
+
if (source[i] === "<") {
|
|
1528
|
+
break;
|
|
1529
|
+
}
|
|
1530
|
+
if (/[a-zA-Z_$]/.test(source[i])) {
|
|
1531
|
+
if (source.slice(i, i + 6) === "export") {
|
|
1532
|
+
const afterExport = source.slice(i + 6, i + 20);
|
|
1533
|
+
if (!/\s*(const|let|var|function|class|default|type|interface|\{)/.test(afterExport)) {
|
|
1534
|
+
break;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
break;
|
|
1538
|
+
}
|
|
1539
|
+
i++;
|
|
1540
|
+
}
|
|
1541
|
+
if (lastImportEnd > 0) {
|
|
1542
|
+
return lastImportEnd;
|
|
1543
|
+
}
|
|
1544
|
+
const scriptMatch = source.match(/<script[^>]*>/);
|
|
1545
|
+
if (scriptMatch) {
|
|
1546
|
+
return scriptMatch.index + scriptMatch[0].length;
|
|
1547
|
+
}
|
|
1548
|
+
return 0;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
// src/transform/attrs-schema.ts
|
|
1552
|
+
function generateAttrSchemaFromSource(attrsSource) {
|
|
1553
|
+
const entries = [];
|
|
1554
|
+
const attrs = splitAttrsSource(attrsSource);
|
|
1555
|
+
for (const attr of attrs) {
|
|
1556
|
+
const trimmed = attr.trim();
|
|
1557
|
+
if (!trimmed)
|
|
1558
|
+
continue;
|
|
1559
|
+
const colonIndex = trimmed.indexOf(":");
|
|
1560
|
+
if (colonIndex === -1)
|
|
1561
|
+
continue;
|
|
1562
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
1563
|
+
let value = trimmed.slice(colonIndex + 1).trim();
|
|
1564
|
+
const asIndex = findTopLevelAs(value);
|
|
1565
|
+
if (asIndex !== -1) {
|
|
1566
|
+
value = value.slice(0, asIndex).trim();
|
|
1567
|
+
}
|
|
1568
|
+
const bindableResult = extractBindable(value);
|
|
1569
|
+
if (bindableResult.isBindable) {
|
|
1570
|
+
const defaultVal = bindableResult.innerValue;
|
|
1571
|
+
const hasDefault = defaultVal !== "" && defaultVal !== "undefined";
|
|
1572
|
+
entries.push(`${key}: { default: ${defaultVal}, bindable: true, hasDefault: ${hasDefault} }`);
|
|
1573
|
+
} else {
|
|
1574
|
+
const hasDefault = value !== "undefined";
|
|
1575
|
+
entries.push(`${key}: { default: ${value}, bindable: false, hasDefault: ${hasDefault} }`);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
return `{ ${entries.join(", ")} }`;
|
|
1579
|
+
}
|
|
1580
|
+
function parseAttrsSource(attrsSource) {
|
|
1581
|
+
const result = [];
|
|
1582
|
+
const attrs = splitAttrsSource(attrsSource);
|
|
1583
|
+
for (const attr of attrs) {
|
|
1584
|
+
let trimmed = attr.trim();
|
|
1585
|
+
if (!trimmed)
|
|
1586
|
+
continue;
|
|
1587
|
+
while (trimmed.startsWith("/*")) {
|
|
1588
|
+
const endComment = trimmed.indexOf("*/");
|
|
1589
|
+
if (endComment !== -1) {
|
|
1590
|
+
trimmed = trimmed.slice(endComment + 2).trim();
|
|
1591
|
+
} else {
|
|
1592
|
+
break;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
while (trimmed.startsWith("//")) {
|
|
1596
|
+
const endLine = trimmed.indexOf(`
|
|
1597
|
+
`);
|
|
1598
|
+
if (endLine !== -1) {
|
|
1599
|
+
trimmed = trimmed.slice(endLine + 1).trim();
|
|
1600
|
+
} else {
|
|
1601
|
+
trimmed = "";
|
|
1602
|
+
break;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
if (!trimmed)
|
|
1606
|
+
continue;
|
|
1607
|
+
const colonIndex = trimmed.indexOf(":");
|
|
1608
|
+
if (colonIndex === -1)
|
|
1609
|
+
continue;
|
|
1610
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
1611
|
+
let value = trimmed.slice(colonIndex + 1).trim();
|
|
1612
|
+
const asIndex = findTopLevelAs(value);
|
|
1613
|
+
if (asIndex !== -1) {
|
|
1614
|
+
value = value.slice(0, asIndex).trim();
|
|
1615
|
+
}
|
|
1616
|
+
const bindableResult = extractBindable(value);
|
|
1617
|
+
if (bindableResult.isBindable) {
|
|
1618
|
+
const defaultVal = bindableResult.innerValue;
|
|
1619
|
+
const hasDefault = defaultVal !== "" && defaultVal !== "undefined";
|
|
1620
|
+
result.push({ key, defaultValue: defaultVal, bindable: true, hasDefault });
|
|
1621
|
+
} else {
|
|
1622
|
+
const hasDefault = value !== "undefined";
|
|
1623
|
+
result.push({ key, defaultValue: value, bindable: false, hasDefault });
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
return result;
|
|
1627
|
+
}
|
|
1628
|
+
function splitAttrsSource(source) {
|
|
1629
|
+
const parts = [];
|
|
1630
|
+
let current = "";
|
|
1631
|
+
let depth = 0;
|
|
1632
|
+
let angleDepth = 0;
|
|
1633
|
+
let i = 0;
|
|
1634
|
+
while (i < source.length) {
|
|
1635
|
+
const char = source[i];
|
|
1636
|
+
if (char === "/" && source[i + 1] === "/") {
|
|
1637
|
+
const endLine = source.indexOf(`
|
|
1638
|
+
`, i + 2);
|
|
1639
|
+
if (endLine !== -1) {
|
|
1640
|
+
current += source.slice(i, endLine + 1);
|
|
1641
|
+
i = endLine + 1;
|
|
1642
|
+
} else {
|
|
1643
|
+
current += source.slice(i);
|
|
1644
|
+
i = source.length;
|
|
1645
|
+
}
|
|
1646
|
+
continue;
|
|
1647
|
+
}
|
|
1648
|
+
if (char === "/" && source[i + 1] === "*") {
|
|
1649
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
1650
|
+
if (endComment !== -1) {
|
|
1651
|
+
current += source.slice(i, endComment + 2);
|
|
1652
|
+
i = endComment + 2;
|
|
1653
|
+
} else {
|
|
1654
|
+
current += source.slice(i);
|
|
1655
|
+
i = source.length;
|
|
1656
|
+
}
|
|
1657
|
+
continue;
|
|
1658
|
+
}
|
|
1659
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1660
|
+
const quote = char;
|
|
1661
|
+
current += char;
|
|
1662
|
+
i++;
|
|
1663
|
+
while (i < source.length && source[i] !== quote) {
|
|
1664
|
+
if (source[i] === "\\") {
|
|
1665
|
+
current += source[i];
|
|
1666
|
+
i++;
|
|
1667
|
+
}
|
|
1668
|
+
if (i < source.length) {
|
|
1669
|
+
current += source[i];
|
|
1670
|
+
i++;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
if (i < source.length) {
|
|
1674
|
+
current += source[i];
|
|
1675
|
+
i++;
|
|
1676
|
+
}
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
if (char === "<") {
|
|
1680
|
+
const prevChar = current.length > 0 ? current[current.length - 1] : "";
|
|
1681
|
+
const isGeneric = /[\w$)]/.test(prevChar);
|
|
1682
|
+
if (isGeneric) {
|
|
1683
|
+
angleDepth++;
|
|
1684
|
+
}
|
|
1685
|
+
current += char;
|
|
1686
|
+
i++;
|
|
1687
|
+
continue;
|
|
1688
|
+
}
|
|
1689
|
+
if (char === ">") {
|
|
1690
|
+
if (i > 0 && source[i - 1] === "=") {
|
|
1691
|
+
current += char;
|
|
1692
|
+
i++;
|
|
1693
|
+
continue;
|
|
1694
|
+
}
|
|
1695
|
+
if (angleDepth > 0) {
|
|
1696
|
+
angleDepth--;
|
|
1697
|
+
}
|
|
1698
|
+
current += char;
|
|
1699
|
+
i++;
|
|
1700
|
+
continue;
|
|
1701
|
+
}
|
|
1702
|
+
if (char === "{" || char === "(" || char === "[") {
|
|
1703
|
+
depth++;
|
|
1704
|
+
current += char;
|
|
1705
|
+
} else if (char === "}" || char === ")" || char === "]") {
|
|
1706
|
+
depth--;
|
|
1707
|
+
current += char;
|
|
1708
|
+
} else if (char === "," && depth === 0 && angleDepth === 0) {
|
|
1709
|
+
parts.push(current);
|
|
1710
|
+
current = "";
|
|
1711
|
+
} else {
|
|
1712
|
+
current += char;
|
|
1713
|
+
}
|
|
1714
|
+
i++;
|
|
1715
|
+
}
|
|
1716
|
+
if (current.trim()) {
|
|
1717
|
+
parts.push(current);
|
|
1718
|
+
}
|
|
1719
|
+
return parts;
|
|
1720
|
+
}
|
|
1721
|
+
function parseObjectMembers(source) {
|
|
1722
|
+
const members = [];
|
|
1723
|
+
let i = 0;
|
|
1724
|
+
while (i < source.length) {
|
|
1725
|
+
while (i < source.length && /[\s,]/.test(source[i]))
|
|
1726
|
+
i++;
|
|
1727
|
+
if (i >= source.length)
|
|
1728
|
+
break;
|
|
1729
|
+
if (source.slice(i, i + 2) === "/*") {
|
|
1730
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
1731
|
+
if (endComment !== -1) {
|
|
1732
|
+
i = endComment + 2;
|
|
1733
|
+
continue;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
if (source.slice(i, i + 2) === "//") {
|
|
1737
|
+
const endLine = source.indexOf(`
|
|
1738
|
+
`, i + 2);
|
|
1739
|
+
if (endLine !== -1) {
|
|
1740
|
+
i = endLine + 1;
|
|
1741
|
+
continue;
|
|
1742
|
+
} else {
|
|
1743
|
+
break;
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
let isGetter = false;
|
|
1747
|
+
let isSetter = false;
|
|
1748
|
+
let isAsync = false;
|
|
1749
|
+
let isGenerator = false;
|
|
1750
|
+
if (source.slice(i).match(/^get\s+/)) {
|
|
1751
|
+
isGetter = true;
|
|
1752
|
+
i += source.slice(i).match(/^get\s+/)[0].length;
|
|
1753
|
+
} else if (source.slice(i).match(/^set\s+/)) {
|
|
1754
|
+
isSetter = true;
|
|
1755
|
+
i += source.slice(i).match(/^set\s+/)[0].length;
|
|
1756
|
+
} else if (source.slice(i).match(/^async\s+\*/)) {
|
|
1757
|
+
isAsync = true;
|
|
1758
|
+
isGenerator = true;
|
|
1759
|
+
i += source.slice(i).match(/^async\s+\*/)[0].length;
|
|
1760
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1761
|
+
i++;
|
|
1762
|
+
} else if (source.slice(i).match(/^async\s+/)) {
|
|
1763
|
+
isAsync = true;
|
|
1764
|
+
i += source.slice(i).match(/^async\s+/)[0].length;
|
|
1765
|
+
} else if (source[i] === "*") {
|
|
1766
|
+
isGenerator = true;
|
|
1767
|
+
i++;
|
|
1768
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1769
|
+
i++;
|
|
1770
|
+
}
|
|
1771
|
+
let isComputed = false;
|
|
1772
|
+
let key = "";
|
|
1773
|
+
if (source[i] === "[") {
|
|
1774
|
+
isComputed = true;
|
|
1775
|
+
const bracketStart = i;
|
|
1776
|
+
let depth = 1;
|
|
1777
|
+
i++;
|
|
1778
|
+
while (i < source.length && depth > 0) {
|
|
1779
|
+
if (source[i] === "[")
|
|
1780
|
+
depth++;
|
|
1781
|
+
else if (source[i] === "]")
|
|
1782
|
+
depth--;
|
|
1783
|
+
i++;
|
|
1784
|
+
}
|
|
1785
|
+
key = source.slice(bracketStart, i);
|
|
1786
|
+
} else {
|
|
1787
|
+
const keyMatch = source.slice(i).match(/^(\$?\w+)/);
|
|
1788
|
+
if (!keyMatch)
|
|
1789
|
+
break;
|
|
1790
|
+
key = keyMatch[1];
|
|
1791
|
+
i += key.length;
|
|
1792
|
+
}
|
|
1793
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1794
|
+
i++;
|
|
1795
|
+
if (source[i] === ":") {
|
|
1796
|
+
i++;
|
|
1797
|
+
const valueStart = i;
|
|
1798
|
+
let depth = 0;
|
|
1799
|
+
let angleDepth = 0;
|
|
1800
|
+
while (i < source.length) {
|
|
1801
|
+
const char = source[i];
|
|
1802
|
+
if (char === "/" && source[i + 1] === "/") {
|
|
1803
|
+
const endLine = source.indexOf(`
|
|
1804
|
+
`, i + 2);
|
|
1805
|
+
if (endLine !== -1) {
|
|
1806
|
+
i = endLine + 1;
|
|
1807
|
+
continue;
|
|
1808
|
+
} else {
|
|
1809
|
+
break;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
if (char === "/" && source[i + 1] === "*") {
|
|
1813
|
+
const endComment = source.indexOf("*/", i + 2);
|
|
1814
|
+
if (endComment !== -1) {
|
|
1815
|
+
i = endComment + 2;
|
|
1816
|
+
continue;
|
|
1817
|
+
} else {
|
|
1818
|
+
break;
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
1822
|
+
const quote = char;
|
|
1823
|
+
i++;
|
|
1824
|
+
while (i < source.length && source[i] !== quote) {
|
|
1825
|
+
if (source[i] === "\\")
|
|
1826
|
+
i++;
|
|
1827
|
+
i++;
|
|
1828
|
+
}
|
|
1829
|
+
i++;
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
if ((char === "," || char === "}") && depth === 0 && angleDepth === 0)
|
|
1833
|
+
break;
|
|
1834
|
+
if (char === "{" || char === "(" || char === "[")
|
|
1835
|
+
depth++;
|
|
1836
|
+
if (char === "}" || char === ")" || char === "]")
|
|
1837
|
+
depth--;
|
|
1838
|
+
if (char === "<" && i > 0 && /\w/.test(source[i - 1]))
|
|
1839
|
+
angleDepth++;
|
|
1840
|
+
if (char === ">" && angleDepth > 0)
|
|
1841
|
+
angleDepth--;
|
|
1842
|
+
i++;
|
|
1843
|
+
}
|
|
1844
|
+
const value = source.slice(valueStart, i).trim();
|
|
1845
|
+
members.push({ key, value, isGetter, isSetter, isMethod: false, isAsync, isGenerator, isComputed });
|
|
1846
|
+
} else if (source[i] === "(") {
|
|
1847
|
+
const bodyStart = i;
|
|
1848
|
+
let depth = 1;
|
|
1849
|
+
i++;
|
|
1850
|
+
while (i < source.length && depth > 0) {
|
|
1851
|
+
if (source[i] === "(")
|
|
1852
|
+
depth++;
|
|
1853
|
+
if (source[i] === ")")
|
|
1854
|
+
depth--;
|
|
1855
|
+
i++;
|
|
1856
|
+
}
|
|
1857
|
+
while (i < source.length && /\s/.test(source[i]))
|
|
1858
|
+
i++;
|
|
1859
|
+
if (source[i] === ":") {
|
|
1860
|
+
i++;
|
|
1861
|
+
let typeDepth = 0;
|
|
1862
|
+
while (i < source.length) {
|
|
1863
|
+
const char = source[i];
|
|
1864
|
+
if (char === "<" || char === "(" || char === "[")
|
|
1865
|
+
typeDepth++;
|
|
1866
|
+
if (char === ">" || char === ")" || char === "]")
|
|
1867
|
+
typeDepth--;
|
|
1868
|
+
if (char === "{" && typeDepth === 0)
|
|
1869
|
+
break;
|
|
1870
|
+
i++;
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
if (source[i] === "{") {
|
|
1874
|
+
const braceStart = i;
|
|
1875
|
+
depth = 1;
|
|
1876
|
+
i++;
|
|
1877
|
+
while (i < source.length && depth > 0) {
|
|
1878
|
+
if (source[i] === "{")
|
|
1879
|
+
depth++;
|
|
1880
|
+
if (source[i] === "}")
|
|
1881
|
+
depth--;
|
|
1882
|
+
i++;
|
|
1883
|
+
}
|
|
1884
|
+
const bodyEnd = i;
|
|
1885
|
+
if (isGetter) {
|
|
1886
|
+
const value = source.slice(braceStart, bodyEnd);
|
|
1887
|
+
members.push({ key, value, isGetter, isSetter, isMethod: false, isAsync, isGenerator, isComputed });
|
|
1888
|
+
} else if (isSetter) {
|
|
1889
|
+
const value = source.slice(bodyStart, bodyEnd);
|
|
1890
|
+
members.push({ key, value, isGetter, isSetter, isMethod: false, isAsync, isGenerator, isComputed });
|
|
1891
|
+
} else {
|
|
1892
|
+
const value = source.slice(bodyStart, bodyEnd);
|
|
1893
|
+
members.push({ key, value, isGetter: false, isSetter: false, isMethod: true, isAsync, isGenerator, isComputed });
|
|
1894
|
+
}
|
|
1895
|
+
} else {
|
|
1896
|
+
const value = source.slice(bodyStart, i);
|
|
1897
|
+
members.push({ key, value, isGetter, isSetter, isMethod: !isGetter && !isSetter, isAsync, isGenerator, isComputed });
|
|
1898
|
+
}
|
|
1899
|
+
} else if (source[i] === "{") {
|
|
1900
|
+
const bodyStart = i;
|
|
1901
|
+
let depth = 1;
|
|
1902
|
+
i++;
|
|
1903
|
+
while (i < source.length && depth > 0) {
|
|
1904
|
+
if (source[i] === "{")
|
|
1905
|
+
depth++;
|
|
1906
|
+
if (source[i] === "}")
|
|
1907
|
+
depth--;
|
|
1908
|
+
i++;
|
|
1909
|
+
}
|
|
1910
|
+
const value = source.slice(bodyStart, i);
|
|
1911
|
+
members.push({ key, value, isGetter, isSetter, isMethod: false, isAsync, isGenerator, isComputed });
|
|
1912
|
+
} else {
|
|
1913
|
+
break;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
return members;
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
// src/transform/origin-transform.ts
|
|
1920
|
+
function transformOriginCalls(s, source, neededImports) {
|
|
1921
|
+
const regex = /\$origin\s*\(/g;
|
|
1922
|
+
let match;
|
|
1923
|
+
let changed = false;
|
|
1924
|
+
while ((match = regex.exec(source)) !== null) {
|
|
1925
|
+
const startIndex = match.index;
|
|
1926
|
+
if (isInsideStringOrComment(source, startIndex)) {
|
|
1927
|
+
continue;
|
|
1928
|
+
}
|
|
1929
|
+
const openParenIndex = startIndex + match[0].length - 1;
|
|
1930
|
+
const closeParenIndex = findMatchingBracket(source, openParenIndex);
|
|
1931
|
+
if (closeParenIndex === -1) {
|
|
1932
|
+
console.warn(`[svelte-origin] Could not find matching ) for $origin( at index ${startIndex}`);
|
|
1933
|
+
continue;
|
|
1934
|
+
}
|
|
1935
|
+
const definitionContent = source.slice(openParenIndex + 1, closeParenIndex);
|
|
1936
|
+
const transformed = transformOriginDefinition(definitionContent);
|
|
1937
|
+
s.overwrite(startIndex, closeParenIndex + 1, `__createOrigin(${transformed})`);
|
|
1938
|
+
neededImports.add("__createOrigin");
|
|
1939
|
+
changed = true;
|
|
1940
|
+
}
|
|
1941
|
+
return changed;
|
|
1942
|
+
}
|
|
1943
|
+
function transformOriginDefinition(content) {
|
|
1944
|
+
let parents = [];
|
|
1945
|
+
let bodyContent = content.trim();
|
|
1946
|
+
let initCallback = null;
|
|
1947
|
+
if (bodyContent.startsWith("[")) {
|
|
1948
|
+
const closeBracket = findMatchingBracket(bodyContent, 0, "[", "]");
|
|
1949
|
+
if (closeBracket !== -1) {
|
|
1950
|
+
const parentsContent = bodyContent.slice(1, closeBracket);
|
|
1951
|
+
parents = parentsContent.split(",").map((p) => p.trim()).filter((p) => p);
|
|
1952
|
+
let i = closeBracket + 1;
|
|
1953
|
+
while (i < bodyContent.length && /[\s,]/.test(bodyContent[i]))
|
|
1954
|
+
i++;
|
|
1955
|
+
bodyContent = bodyContent.slice(i);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
if (bodyContent.startsWith("{")) {
|
|
1959
|
+
const closeIndex = findMatchingBracket(bodyContent, 0, "{", "}");
|
|
1960
|
+
if (closeIndex !== -1) {
|
|
1961
|
+
let remaining = bodyContent.slice(closeIndex + 1).trim();
|
|
1962
|
+
if (remaining.startsWith(",")) {
|
|
1963
|
+
remaining = remaining.slice(1).trim();
|
|
1964
|
+
if (remaining) {
|
|
1965
|
+
initCallback = remaining;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
bodyContent = bodyContent.slice(1, closeIndex);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
const attrsMatch = bodyContent.match(/(\w+)\s*:\s*\$attrs\s*\(/);
|
|
1972
|
+
let attrSchemaCode = "{}";
|
|
1973
|
+
let attrsContent = "";
|
|
1974
|
+
let contentWithoutAttrs = bodyContent;
|
|
1975
|
+
let attrPropertyName = "props";
|
|
1976
|
+
if (attrsMatch) {
|
|
1977
|
+
attrPropertyName = attrsMatch[1];
|
|
1978
|
+
const attrsStart = attrsMatch.index;
|
|
1979
|
+
const attrsCallOpenParen = attrsStart + attrsMatch[0].length - 1;
|
|
1980
|
+
const attrsCallCloseParen = findMatchingBracket(bodyContent, attrsCallOpenParen);
|
|
1981
|
+
if (attrsCallCloseParen !== -1) {
|
|
1982
|
+
let attrsCallContent = bodyContent.slice(attrsCallOpenParen + 1, attrsCallCloseParen).trim();
|
|
1983
|
+
if (attrsCallContent.startsWith("[")) {
|
|
1984
|
+
const closeBracket = findMatchingBracket(attrsCallContent, 0, "[", "]");
|
|
1985
|
+
if (closeBracket !== -1) {
|
|
1986
|
+
let i = closeBracket + 1;
|
|
1987
|
+
while (i < attrsCallContent.length && /[\s,]/.test(attrsCallContent[i]))
|
|
1988
|
+
i++;
|
|
1989
|
+
attrsCallContent = attrsCallContent.slice(i);
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
if (attrsCallContent.startsWith("{")) {
|
|
1993
|
+
const objCloseIndex = findMatchingBracket(attrsCallContent, 0, "{", "}");
|
|
1994
|
+
if (objCloseIndex !== -1) {
|
|
1995
|
+
attrsContent = attrsCallContent.slice(1, objCloseIndex);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
attrSchemaCode = generateAttrSchemaFromSource(attrsContent);
|
|
1999
|
+
let cutEnd = attrsCallCloseParen + 1;
|
|
2000
|
+
while (cutEnd < bodyContent.length && (bodyContent[cutEnd] === "," || bodyContent[cutEnd] === " " || bodyContent[cutEnd] === `
|
|
2001
|
+
` || bodyContent[cutEnd] === "\t")) {
|
|
2002
|
+
cutEnd++;
|
|
2003
|
+
}
|
|
2004
|
+
contentWithoutAttrs = bodyContent.slice(0, attrsStart) + bodyContent.slice(cutEnd);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
const attrDetails = parseAttrsSource(attrsContent);
|
|
2008
|
+
const { body: createFnBody, attachments } = transformOriginBody(contentWithoutAttrs.trim(), parents, attrDetails, attrPropertyName);
|
|
2009
|
+
const parentsCode = parents.length > 0 ? `[${parents.join(", ")}]` : "undefined";
|
|
2010
|
+
let configCode = `{
|
|
2011
|
+
__attrSchema: ${attrSchemaCode},
|
|
2012
|
+
__parents: ${parentsCode},
|
|
2013
|
+
__create: (__inputAttrs${parents.length > 0 ? ", __super" : ""}) => {
|
|
2014
|
+
${createFnBody}
|
|
2015
|
+
}`;
|
|
2016
|
+
if (attachments.length > 0) {
|
|
2017
|
+
configCode += `,
|
|
2018
|
+
__attachments: { ${attachments.join(", ")} }`;
|
|
2019
|
+
}
|
|
2020
|
+
if (initCallback) {
|
|
2021
|
+
configCode += `,
|
|
2022
|
+
__onInit: ${initCallback}`;
|
|
2023
|
+
}
|
|
2024
|
+
configCode += `
|
|
2025
|
+
}`;
|
|
2026
|
+
return configCode;
|
|
2027
|
+
}
|
|
2028
|
+
function transformOriginBody(content, parents = [], attrDetails = [], propName = "props") {
|
|
2029
|
+
let body = content.trim();
|
|
2030
|
+
const hasParents = parents.length > 0;
|
|
2031
|
+
const attrGettersSetters = [];
|
|
2032
|
+
for (const attr of attrDetails) {
|
|
2033
|
+
if (attr.hasDefault) {
|
|
2034
|
+
attrGettersSetters.push(`get ${attr.key}() { return __inputAttrs.${attr.key} ?? ${attr.defaultValue} }`);
|
|
2035
|
+
} else {
|
|
2036
|
+
attrGettersSetters.push(`get ${attr.key}() { return __inputAttrs.${attr.key} }`);
|
|
2037
|
+
}
|
|
2038
|
+
attrGettersSetters.push(`set ${attr.key}(v) { __inputAttrs.${attr.key} = v }`);
|
|
2039
|
+
}
|
|
2040
|
+
const propsObjectCode = attrGettersSetters.length > 0 ? ` const __props = {
|
|
2041
|
+
${attrGettersSetters.join(`,
|
|
2042
|
+
`)}
|
|
2043
|
+
}` : ` const __props = __inputAttrs`;
|
|
2044
|
+
if (!body) {
|
|
2045
|
+
const baseMembers = [`get ${propName}() { return __props }`];
|
|
2046
|
+
if (hasParents)
|
|
2047
|
+
baseMembers.push("get super() { return __super }");
|
|
2048
|
+
return {
|
|
2049
|
+
body: `${propsObjectCode}
|
|
2050
|
+
return { ${baseMembers.join(", ")} }`,
|
|
2051
|
+
attachments: []
|
|
2052
|
+
};
|
|
2053
|
+
}
|
|
2054
|
+
const members = parseObjectMembers(body);
|
|
2055
|
+
const derivedNames = new Set;
|
|
2056
|
+
const stateNames = new Set;
|
|
2057
|
+
const valueNames = new Set;
|
|
2058
|
+
const methodNames = new Set;
|
|
2059
|
+
for (const member of members) {
|
|
2060
|
+
const { key, value, isGetter, isMethod, isSetter } = member;
|
|
2061
|
+
if (!isGetter && !isMethod && !isSetter && value.startsWith("$state")) {
|
|
2062
|
+
stateNames.add(key);
|
|
2063
|
+
} else if (!isGetter && !isMethod && !isSetter) {
|
|
2064
|
+
valueNames.add(key);
|
|
2065
|
+
}
|
|
2066
|
+
if (isMethod) {
|
|
2067
|
+
methodNames.add(key);
|
|
2068
|
+
}
|
|
2069
|
+
if (isGetter && /return\s+\$derived(\.by)?\s*\(/.test(value)) {
|
|
2070
|
+
derivedNames.add(key);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
const stateDeclarations = [];
|
|
2074
|
+
const returnMembers = [`get ${propName}() { return __props }`];
|
|
2075
|
+
const attachmentMethods = [];
|
|
2076
|
+
if (hasParents) {
|
|
2077
|
+
returnMembers.push("get super() { return __super }");
|
|
2078
|
+
}
|
|
2079
|
+
for (const member of members) {
|
|
2080
|
+
const { key, value, isGetter, isMethod, isSetter, isAsync, isGenerator, isComputed } = member;
|
|
2081
|
+
if (key === propName)
|
|
2082
|
+
continue;
|
|
2083
|
+
if (isMethod && key.startsWith("$")) {
|
|
2084
|
+
const attachmentName = key.slice(1);
|
|
2085
|
+
const asyncPrefix2 = isAsync ? "async " : "";
|
|
2086
|
+
attachmentMethods.push(`${attachmentName}: ${asyncPrefix2}function${value}`);
|
|
2087
|
+
continue;
|
|
2088
|
+
}
|
|
2089
|
+
if (!isGetter && !isMethod && !isSetter && value.startsWith("$state")) {
|
|
2090
|
+
let stateVariant = "$state";
|
|
2091
|
+
let genericType = "";
|
|
2092
|
+
let parenStart = 6;
|
|
2093
|
+
if (value[parenStart] === ".") {
|
|
2094
|
+
const methodMatch = value.slice(parenStart).match(/^\.([a-zA-Z_][a-zA-Z0-9_]*)/);
|
|
2095
|
+
if (methodMatch) {
|
|
2096
|
+
stateVariant = `$state.${methodMatch[1]}`;
|
|
2097
|
+
parenStart += methodMatch[0].length;
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
if (value[parenStart] === "<") {
|
|
2101
|
+
const closeAngle = findMatchingBracket(value, parenStart, "<", ">");
|
|
2102
|
+
if (closeAngle !== -1) {
|
|
2103
|
+
genericType = value.slice(parenStart, closeAngle + 1);
|
|
2104
|
+
parenStart = closeAngle + 1;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
while (parenStart < value.length && /\s/.test(value[parenStart])) {
|
|
2108
|
+
parenStart++;
|
|
2109
|
+
}
|
|
2110
|
+
if (value[parenStart] === "(") {
|
|
2111
|
+
const closeParen = findMatchingBracket(value, parenStart);
|
|
2112
|
+
if (closeParen !== -1) {
|
|
2113
|
+
const initialValue = value.slice(parenStart + 1, closeParen).trim() || "undefined";
|
|
2114
|
+
stateDeclarations.push(` let ${key} = ${stateVariant}${genericType}(${initialValue})`);
|
|
2115
|
+
returnMembers.push(`get ${key}() { return ${key} }`);
|
|
2116
|
+
returnMembers.push(`set ${key}(v) { ${key} = v }`);
|
|
2117
|
+
continue;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
const propAccessPattern = new RegExp(`\\bthis\\.${propName}\\.`, "g");
|
|
2122
|
+
let transformedValue = value.replace(propAccessPattern, "__props.").replace(/\bthis\.super\./g, "__super.").replace(/\bthis\.super\b/g, "__super").replace(/\bthis\.(\w+)/g, (_, name) => {
|
|
2123
|
+
if (derivedNames.has(name)) {
|
|
2124
|
+
return `__${name}`;
|
|
2125
|
+
}
|
|
2126
|
+
if (stateNames.has(name)) {
|
|
2127
|
+
return name;
|
|
2128
|
+
}
|
|
2129
|
+
if (valueNames.has(name)) {
|
|
2130
|
+
return name;
|
|
2131
|
+
}
|
|
2132
|
+
return `this.${name}`;
|
|
2133
|
+
});
|
|
2134
|
+
const asyncPrefix = isAsync ? "async " : "";
|
|
2135
|
+
const generatorPrefix = isGenerator ? "*" : "";
|
|
2136
|
+
const outputKey = isComputed ? key : key;
|
|
2137
|
+
if (isGetter) {
|
|
2138
|
+
const derivedMatch = transformedValue.match(/return\s+\$derived(\.by)?\s*\(/);
|
|
2139
|
+
if (derivedMatch) {
|
|
2140
|
+
const derivedPrefix = derivedMatch[1] ? "$derived.by" : "$derived";
|
|
2141
|
+
const derivedStart = transformedValue.indexOf(derivedPrefix + "(");
|
|
2142
|
+
const openParen = derivedStart + derivedPrefix.length;
|
|
2143
|
+
const closeParen = findMatchingBracket(transformedValue, openParen);
|
|
2144
|
+
if (closeParen !== -1) {
|
|
2145
|
+
const derivedArg = transformedValue.slice(openParen + 1, closeParen).trim();
|
|
2146
|
+
stateDeclarations.push(` let __${key} = ${derivedPrefix}(${derivedArg})`);
|
|
2147
|
+
returnMembers.push(`get ${key}() { return __${key} }`);
|
|
2148
|
+
continue;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
returnMembers.push(`get ${key}() ${transformedValue}`);
|
|
2152
|
+
} else if (isSetter) {
|
|
2153
|
+
returnMembers.push(`set ${key}${transformedValue}`);
|
|
2154
|
+
} else if (isMethod) {
|
|
2155
|
+
returnMembers.push(`${asyncPrefix}${generatorPrefix}${outputKey}${transformedValue}`);
|
|
2156
|
+
} else {
|
|
2157
|
+
stateDeclarations.push(` let ${key} = ${transformedValue}`);
|
|
2158
|
+
returnMembers.push(`get ${key}() { return ${key} }`);
|
|
2159
|
+
returnMembers.push(`set ${key}(v) { ${key} = v }`);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
const stateSection = stateDeclarations.length > 0 ? stateDeclarations.join(`
|
|
2163
|
+
`) + `
|
|
2164
|
+
` : "";
|
|
2165
|
+
return {
|
|
2166
|
+
body: `${propsObjectCode}
|
|
2167
|
+
${stateSection} return {
|
|
2168
|
+
${returnMembers.join(`,
|
|
2169
|
+
`)}
|
|
2170
|
+
}`,
|
|
2171
|
+
attachments: attachmentMethods
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
// src/transform/standalone-attrs-transform.ts
|
|
2176
|
+
function transformStandaloneAttrsCalls(s, source, neededImports) {
|
|
2177
|
+
const regex = /\$attrs\s*\(/g;
|
|
2178
|
+
let match;
|
|
2179
|
+
let changed = false;
|
|
2180
|
+
while ((match = regex.exec(source)) !== null) {
|
|
2181
|
+
const startIndex = match.index;
|
|
2182
|
+
if (isInsideStringOrComment(source, startIndex)) {
|
|
2183
|
+
continue;
|
|
2184
|
+
}
|
|
2185
|
+
const beforeContent = source.slice(Math.max(0, startIndex - 20), startIndex);
|
|
2186
|
+
if (/:\s*$/.test(beforeContent)) {
|
|
2187
|
+
continue;
|
|
2188
|
+
}
|
|
2189
|
+
const afterDollarAttrs = source.slice(startIndex + 6, startIndex + 20);
|
|
2190
|
+
if (/^\s*\.\s*(origin|for)\s*\(/.test(afterDollarAttrs)) {
|
|
2191
|
+
continue;
|
|
2192
|
+
}
|
|
2193
|
+
const openParenIndex = startIndex + match[0].length - 1;
|
|
2194
|
+
const closeParenIndex = findMatchingBracket(source, openParenIndex);
|
|
2195
|
+
if (closeParenIndex === -1) {
|
|
2196
|
+
console.warn(`[svelte-origin] Could not find matching ) for $attrs( at index ${startIndex}`);
|
|
2197
|
+
continue;
|
|
2198
|
+
}
|
|
2199
|
+
const attrsContent = source.slice(openParenIndex + 1, closeParenIndex).trim();
|
|
2200
|
+
const transformed = transformStandaloneAttrsDefinition(attrsContent);
|
|
2201
|
+
s.overwrite(startIndex, closeParenIndex + 1, `__createAttrs(${transformed})`);
|
|
2202
|
+
neededImports.add("__createAttrs");
|
|
2203
|
+
changed = true;
|
|
2204
|
+
}
|
|
2205
|
+
return changed;
|
|
2206
|
+
}
|
|
2207
|
+
function transformStandaloneAttrsDefinition(content) {
|
|
2208
|
+
let parents = [];
|
|
2209
|
+
let bodyContent = content.trim();
|
|
2210
|
+
if (bodyContent.startsWith("[")) {
|
|
2211
|
+
const closeBracket = findMatchingBracket(bodyContent, 0, "[", "]");
|
|
2212
|
+
if (closeBracket !== -1) {
|
|
2213
|
+
const parentsContent = bodyContent.slice(1, closeBracket);
|
|
2214
|
+
parents = parentsContent.split(",").map((p) => p.trim()).filter((p) => p);
|
|
2215
|
+
let i = closeBracket + 1;
|
|
2216
|
+
while (i < bodyContent.length && /[\s,]/.test(bodyContent[i]))
|
|
2217
|
+
i++;
|
|
2218
|
+
bodyContent = bodyContent.slice(i);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
let attrsContent = "";
|
|
2222
|
+
if (bodyContent.startsWith("{")) {
|
|
2223
|
+
const closeIndex = findMatchingBracket(bodyContent, 0, "{", "}");
|
|
2224
|
+
if (closeIndex !== -1) {
|
|
2225
|
+
attrsContent = bodyContent.slice(1, closeIndex);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
const attrSchemaCode = generateAttrSchemaFromSource(attrsContent);
|
|
2229
|
+
const parentsCode = parents.length > 0 ? `[${parents.join(", ")}]` : "undefined";
|
|
2230
|
+
return `{
|
|
2231
|
+
__attrSchema: ${attrSchemaCode},
|
|
2232
|
+
__parents: ${parentsCode}
|
|
2233
|
+
}`;
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
// src/transform/schema.ts
|
|
2237
|
+
function parseOriginSchemaFromSource(source, exportName) {
|
|
2238
|
+
const exportPattern = new RegExp(`export\\s+const\\s+${exportName}\\s*=\\s*\\$origin\\s*\\(`, "s");
|
|
2239
|
+
const match = exportPattern.exec(source);
|
|
2240
|
+
if (!match)
|
|
2241
|
+
return null;
|
|
2242
|
+
const originStart = match.index + match[0].length - 1;
|
|
2243
|
+
const originEnd = findMatchingBracket(source, originStart);
|
|
2244
|
+
if (originEnd === -1)
|
|
2245
|
+
return null;
|
|
2246
|
+
const originContent = source.slice(originStart + 1, originEnd);
|
|
2247
|
+
let parentNames = [];
|
|
2248
|
+
let bodyContent = originContent.trim();
|
|
2249
|
+
if (bodyContent.startsWith("[")) {
|
|
2250
|
+
const closeBracket = findMatchingBracket(bodyContent, 0, "[", "]");
|
|
2251
|
+
if (closeBracket !== -1) {
|
|
2252
|
+
const parentsContent = bodyContent.slice(1, closeBracket);
|
|
2253
|
+
parentNames = parentsContent.split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
|
|
2254
|
+
let i = closeBracket + 1;
|
|
2255
|
+
while (i < bodyContent.length && /[\s,]/.test(bodyContent[i]))
|
|
2256
|
+
i++;
|
|
2257
|
+
bodyContent = bodyContent.slice(i);
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
const attrsMatch = bodyContent.match(/(\w+)\s*:\s*\$attrs\s*\(\s*\{/);
|
|
2261
|
+
if (!attrsMatch) {
|
|
2262
|
+
return { attrs: [], parentNames };
|
|
2263
|
+
}
|
|
2264
|
+
const attrsStart = attrsMatch.index;
|
|
2265
|
+
const attrsObjStart = bodyContent.indexOf("{", attrsStart + attrsMatch[0].length - 1);
|
|
2266
|
+
const attrsObjEnd = findMatchingBracket(bodyContent, attrsObjStart, "{", "}");
|
|
2267
|
+
if (attrsObjEnd === -1) {
|
|
2268
|
+
return { attrs: [], parentNames };
|
|
2269
|
+
}
|
|
2270
|
+
const attrsContent = bodyContent.slice(attrsObjStart + 1, attrsObjEnd);
|
|
2271
|
+
const attrs = parseAttrsContent(attrsContent);
|
|
2272
|
+
return { attrs, parentNames };
|
|
2273
|
+
}
|
|
2274
|
+
function parseAttrsContent(content) {
|
|
2275
|
+
const result = [];
|
|
2276
|
+
const parts = splitByTopLevelCommas(content);
|
|
2277
|
+
for (const part of parts) {
|
|
2278
|
+
let trimmed = part.trim();
|
|
2279
|
+
if (!trimmed)
|
|
2280
|
+
continue;
|
|
2281
|
+
trimmed = stripComments(trimmed);
|
|
2282
|
+
if (!trimmed)
|
|
2283
|
+
continue;
|
|
2284
|
+
const colonIndex = trimmed.indexOf(":");
|
|
2285
|
+
if (colonIndex === -1)
|
|
2286
|
+
continue;
|
|
2287
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
2288
|
+
let value = trimmed.slice(colonIndex + 1).trim();
|
|
2289
|
+
const asIndex = findTopLevelAs(value);
|
|
2290
|
+
if (asIndex !== -1) {
|
|
2291
|
+
value = value.slice(0, asIndex).trim();
|
|
2292
|
+
}
|
|
2293
|
+
const bindableResult = extractBindable(value);
|
|
2294
|
+
if (bindableResult.isBindable) {
|
|
2295
|
+
const defaultVal = bindableResult.innerValue;
|
|
2296
|
+
const hasDefault = defaultVal !== "" && defaultVal !== "undefined";
|
|
2297
|
+
result.push({
|
|
2298
|
+
key,
|
|
2299
|
+
defaultValue: defaultVal,
|
|
2300
|
+
bindable: true,
|
|
2301
|
+
hasDefault
|
|
2302
|
+
});
|
|
2303
|
+
} else {
|
|
2304
|
+
const hasDefault = value !== "undefined";
|
|
2305
|
+
result.push({
|
|
2306
|
+
key,
|
|
2307
|
+
defaultValue: value,
|
|
2308
|
+
bindable: false,
|
|
2309
|
+
hasDefault
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
return result;
|
|
2314
|
+
}
|
|
2315
|
+
function splitByTopLevelCommas(source) {
|
|
2316
|
+
const parts = [];
|
|
2317
|
+
let current = "";
|
|
2318
|
+
let depth = 0;
|
|
2319
|
+
let angleDepth = 0;
|
|
2320
|
+
for (let i = 0;i < source.length; i++) {
|
|
2321
|
+
const char = source[i];
|
|
2322
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
2323
|
+
const quote = char;
|
|
2324
|
+
current += char;
|
|
2325
|
+
i++;
|
|
2326
|
+
while (i < source.length && source[i] !== quote) {
|
|
2327
|
+
if (source[i] === "\\") {
|
|
2328
|
+
current += source[i];
|
|
2329
|
+
i++;
|
|
2330
|
+
}
|
|
2331
|
+
if (i < source.length) {
|
|
2332
|
+
current += source[i];
|
|
2333
|
+
i++;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
if (i < source.length) {
|
|
2337
|
+
current += source[i];
|
|
2338
|
+
}
|
|
2339
|
+
continue;
|
|
2340
|
+
}
|
|
2341
|
+
if (char === "<") {
|
|
2342
|
+
const prevChar = current.length > 0 ? current[current.length - 1] : "";
|
|
2343
|
+
if (/[\w$)]/.test(prevChar)) {
|
|
2344
|
+
angleDepth++;
|
|
2345
|
+
}
|
|
2346
|
+
current += char;
|
|
2347
|
+
} else if (char === ">") {
|
|
2348
|
+
if (current.length > 0 && current[current.length - 1] === "=") {
|
|
2349
|
+
current += char;
|
|
2350
|
+
continue;
|
|
2351
|
+
}
|
|
2352
|
+
if (angleDepth > 0) {
|
|
2353
|
+
angleDepth--;
|
|
2354
|
+
}
|
|
2355
|
+
current += char;
|
|
2356
|
+
} else if (char === "{" || char === "(" || char === "[") {
|
|
2357
|
+
depth++;
|
|
2358
|
+
current += char;
|
|
2359
|
+
} else if (char === "}" || char === ")" || char === "]") {
|
|
2360
|
+
depth--;
|
|
2361
|
+
current += char;
|
|
2362
|
+
} else if (char === "," && depth === 0 && angleDepth === 0) {
|
|
2363
|
+
parts.push(current);
|
|
2364
|
+
current = "";
|
|
2365
|
+
} else {
|
|
2366
|
+
current += char;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
if (current.trim()) {
|
|
2370
|
+
parts.push(current);
|
|
2371
|
+
}
|
|
2372
|
+
return parts;
|
|
2373
|
+
}
|
|
2374
|
+
function stripComments(str) {
|
|
2375
|
+
let result = str.trim();
|
|
2376
|
+
while (result.startsWith("/*")) {
|
|
2377
|
+
const endComment = result.indexOf("*/");
|
|
2378
|
+
if (endComment !== -1) {
|
|
2379
|
+
result = result.slice(endComment + 2).trim();
|
|
2380
|
+
} else {
|
|
2381
|
+
break;
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
while (result.startsWith("//")) {
|
|
2385
|
+
const endLine = result.indexOf(`
|
|
2386
|
+
`);
|
|
2387
|
+
if (endLine !== -1) {
|
|
2388
|
+
result = result.slice(endLine + 1).trim();
|
|
2389
|
+
} else {
|
|
2390
|
+
result = "";
|
|
2391
|
+
break;
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
return result;
|
|
2395
|
+
}
|
|
2396
|
+
function generatePropsDestructuring(attrs, factoryName) {
|
|
2397
|
+
const parts = [];
|
|
2398
|
+
for (const attr of attrs) {
|
|
2399
|
+
if (attr.bindable) {
|
|
2400
|
+
if (attr.hasDefault) {
|
|
2401
|
+
parts.push(`${attr.key} = $bindable(${attr.defaultValue})`);
|
|
2402
|
+
} else {
|
|
2403
|
+
parts.push(`${attr.key} = $bindable()`);
|
|
2404
|
+
}
|
|
2405
|
+
} else if (attr.hasDefault) {
|
|
2406
|
+
parts.push(`${attr.key} = ${attr.defaultValue}`);
|
|
2407
|
+
} else {
|
|
2408
|
+
parts.push(attr.key);
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
return `let { ${parts.join(", ")} }: $attrs.Of<typeof ${factoryName}> = $props()`;
|
|
2412
|
+
}
|
|
2413
|
+
function generateFactoryCallFromAttrs(factoryName, attrs) {
|
|
2414
|
+
const parts = [];
|
|
2415
|
+
for (const attr of attrs) {
|
|
2416
|
+
parts.push(`get ${attr.key}() { return ${attr.key} }`);
|
|
2417
|
+
if (attr.bindable) {
|
|
2418
|
+
parts.push(`set ${attr.key}(v) { ${attr.key} = v }`);
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
return `${factoryName}({ ${parts.join(", ")} })`;
|
|
2422
|
+
}
|
|
2423
|
+
function findImportPath(source, identifier) {
|
|
2424
|
+
const patterns2 = [
|
|
2425
|
+
new RegExp(`import\\s*\\{[^}]*\\b${identifier}\\b[^}]*\\}\\s*from\\s*['"]([^'"]+)['"]`),
|
|
2426
|
+
new RegExp(`import\\s*\\{[^}]*\\bas\\s+${identifier}\\b[^}]*\\}\\s*from\\s*['"]([^'"]+)['"]`),
|
|
2427
|
+
new RegExp(`import\\s+${identifier}\\s+from\\s*['"]([^'"]+)['"]`),
|
|
2428
|
+
new RegExp(`import\\s*\\*\\s*as\\s+${identifier}\\s+from\\s*['"]([^'"]+)['"]`)
|
|
2429
|
+
];
|
|
2430
|
+
for (const pattern of patterns2) {
|
|
2431
|
+
const match = pattern.exec(source);
|
|
2432
|
+
if (match) {
|
|
2433
|
+
return match[1];
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
return null;
|
|
2437
|
+
}
|
|
2438
|
+
function generatePropsInterface(schema) {
|
|
2439
|
+
const lines = [];
|
|
2440
|
+
const bindings = [];
|
|
2441
|
+
for (const attr of schema.attrs) {
|
|
2442
|
+
const type = inferTypeFromDefault(attr.defaultValue);
|
|
2443
|
+
const optional = attr.hasDefault ? "?" : "";
|
|
2444
|
+
lines.push(`${attr.key}${optional}: ${type}`);
|
|
2445
|
+
if (attr.bindable) {
|
|
2446
|
+
bindings.push(attr.key);
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
const interfaceContent = lines.length > 0 ? `{ ${lines.join("; ")} }` : "{}";
|
|
2450
|
+
return { interfaceContent, bindings };
|
|
2451
|
+
}
|
|
2452
|
+
function inferTypeFromDefault(defaultValue) {
|
|
2453
|
+
if (defaultValue === "undefined")
|
|
2454
|
+
return "unknown";
|
|
2455
|
+
if (defaultValue === "true" || defaultValue === "false")
|
|
2456
|
+
return "boolean";
|
|
2457
|
+
if (/^-?\d+$/.test(defaultValue))
|
|
2458
|
+
return "number";
|
|
2459
|
+
if (/^-?\d+\.\d+$/.test(defaultValue))
|
|
2460
|
+
return "number";
|
|
2461
|
+
if (/^['"]/.test(defaultValue))
|
|
2462
|
+
return "string";
|
|
2463
|
+
if (defaultValue.startsWith("["))
|
|
2464
|
+
return "unknown[]";
|
|
2465
|
+
if (defaultValue.startsWith("{"))
|
|
2466
|
+
return "Record<string, unknown>";
|
|
2467
|
+
if (defaultValue === "null")
|
|
2468
|
+
return "null";
|
|
2469
|
+
return "unknown";
|
|
2470
|
+
}
|
|
2471
|
+
function generateDtsContent(factoryName, importPath, schema, comment = "regenerated on save") {
|
|
2472
|
+
const propsLines = [];
|
|
2473
|
+
const bindableProps = [];
|
|
2474
|
+
for (const attr of schema.attrs) {
|
|
2475
|
+
const type = inferTypeFromDefault(attr.defaultValue);
|
|
2476
|
+
const optional = attr.hasDefault ? "?" : "";
|
|
2477
|
+
propsLines.push(` ${attr.key}${optional}: ${type};`);
|
|
2478
|
+
if (attr.bindable) {
|
|
2479
|
+
bindableProps.push(`"${attr.key}"`);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
const propsType = propsLines.length > 0 ? `{
|
|
2483
|
+
${propsLines.join(`
|
|
2484
|
+
`)}
|
|
2485
|
+
}` : "{}";
|
|
2486
|
+
const bindingsType = bindableProps.length > 0 ? bindableProps.join(" | ") : "never";
|
|
2487
|
+
return `// Auto-generated by svelte-origin
|
|
2488
|
+
// Do not edit manually - ${comment}
|
|
2489
|
+
|
|
2490
|
+
import type { Component } from 'svelte';
|
|
2491
|
+
import type { ${factoryName} } from '${importPath}';
|
|
2492
|
+
|
|
2493
|
+
/**
|
|
2494
|
+
* Props derived from ${factoryName} origin factory.
|
|
2495
|
+
*
|
|
2496
|
+
* Bindable props: ${bindableProps.length > 0 ? bindableProps.join(", ") : "none"}
|
|
2497
|
+
*/
|
|
2498
|
+
type Props = ${propsType};
|
|
2499
|
+
|
|
2500
|
+
declare const __component: Component<Props, {}, ${bindingsType}>;
|
|
2501
|
+
export default __component;
|
|
2502
|
+
`;
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
// src/transform/attrs-origin-transform.ts
|
|
2506
|
+
function isCallExpression(expr) {
|
|
2507
|
+
const trimmed = expr.trim();
|
|
2508
|
+
return trimmed.endsWith(")");
|
|
2509
|
+
}
|
|
2510
|
+
function hasGenericTypeParams(expr) {
|
|
2511
|
+
const trimmed = expr.trim();
|
|
2512
|
+
let depth = 0;
|
|
2513
|
+
for (let i = 0;i < trimmed.length; i++) {
|
|
2514
|
+
const char = trimmed[i];
|
|
2515
|
+
if (char === "(")
|
|
2516
|
+
depth++;
|
|
2517
|
+
else if (char === ")")
|
|
2518
|
+
depth--;
|
|
2519
|
+
else if (char === "<" && depth === 0)
|
|
2520
|
+
return true;
|
|
2521
|
+
}
|
|
2522
|
+
return false;
|
|
2523
|
+
}
|
|
2524
|
+
function normalizeFactoryCall(expr) {
|
|
2525
|
+
const trimmed = expr.trim();
|
|
2526
|
+
if (hasGenericTypeParams(trimmed) && !isCallExpression(trimmed)) {
|
|
2527
|
+
return `${trimmed}()`;
|
|
2528
|
+
}
|
|
2529
|
+
return trimmed;
|
|
2530
|
+
}
|
|
2531
|
+
function extractFactoryFromCall(expr) {
|
|
2532
|
+
const trimmed = expr.trim();
|
|
2533
|
+
let depth = 0;
|
|
2534
|
+
for (let i = trimmed.length - 1;i >= 0; i--) {
|
|
2535
|
+
if (trimmed[i] === ")")
|
|
2536
|
+
depth++;
|
|
2537
|
+
else if (trimmed[i] === "(") {
|
|
2538
|
+
depth--;
|
|
2539
|
+
if (depth === 0) {
|
|
2540
|
+
return trimmed.slice(0, i);
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
return trimmed;
|
|
2545
|
+
}
|
|
2546
|
+
function transformAttrsOriginCallsSync(s, source, neededImports) {
|
|
2547
|
+
const declarations = findVariableDeclarationsWithMacro(source, "$attrs.origin");
|
|
2548
|
+
let changed = false;
|
|
2549
|
+
let firstFactoryExpr = null;
|
|
2550
|
+
let propsTypeDeclaration = null;
|
|
2551
|
+
let isFirstDeclaration = true;
|
|
2552
|
+
const needsPropsInjection = declarations.length > 0 && !hasExistingPropsDeclaration(source);
|
|
2553
|
+
for (const decl of declarations) {
|
|
2554
|
+
const { varName, startIndex, macroOpenParen } = decl;
|
|
2555
|
+
const closeParenIndex = findMatchingBracket(source, macroOpenParen);
|
|
2556
|
+
if (closeParenIndex === -1) {
|
|
2557
|
+
console.warn(`[svelte-origin] Could not find matching ) for $attrs.origin( at index ${macroOpenParen}`);
|
|
2558
|
+
continue;
|
|
2559
|
+
}
|
|
2560
|
+
const factoryExpr = source.slice(macroOpenParen + 1, closeParenIndex).trim();
|
|
2561
|
+
const endIndex = closeParenIndex + 1;
|
|
2562
|
+
if (!firstFactoryExpr) {
|
|
2563
|
+
firstFactoryExpr = factoryExpr;
|
|
2564
|
+
}
|
|
2565
|
+
const normalizedFactoryCall = normalizeFactoryCall(factoryExpr);
|
|
2566
|
+
const expansionLines = [];
|
|
2567
|
+
if (isFirstDeclaration && needsPropsInjection) {
|
|
2568
|
+
const isGeneric = hasGenericTypeParams(factoryExpr);
|
|
2569
|
+
const typeExpr = isGeneric ? `ReturnType<typeof ${extractFactoryFromCall(normalizedFactoryCall)}>` : `typeof ${factoryExpr}`;
|
|
2570
|
+
expansionLines.push(`type $$Props = $attrs.Of<${typeExpr}>`);
|
|
2571
|
+
propsTypeDeclaration = "";
|
|
2572
|
+
}
|
|
2573
|
+
expansionLines.push(`let ___attrs: $$Props = $props()`, `let ${varName} = ${normalizedFactoryCall}(__attrsFor(${normalizedFactoryCall}, ___attrs))`);
|
|
2574
|
+
s.overwrite(startIndex, endIndex, expansionLines.join(`
|
|
2575
|
+
`));
|
|
2576
|
+
neededImports.add("__attrsFor");
|
|
2577
|
+
changed = true;
|
|
2578
|
+
isFirstDeclaration = false;
|
|
2579
|
+
}
|
|
2580
|
+
return { changed, propsTypeDeclaration };
|
|
2581
|
+
}
|
|
2582
|
+
async function transformAttrsOriginCalls(s, source, neededImports, schemaResolver) {
|
|
2583
|
+
const declarations = findVariableDeclarationsWithMacro(source, "$attrs.origin");
|
|
2584
|
+
let changed = false;
|
|
2585
|
+
let propsTypeDeclaration = null;
|
|
2586
|
+
const needsPropsInjection = declarations.length > 0 && !hasExistingPropsDeclaration(source);
|
|
2587
|
+
const matches = [];
|
|
2588
|
+
for (const decl of declarations) {
|
|
2589
|
+
const { varName, startIndex, macroOpenParen } = decl;
|
|
2590
|
+
const closeParenIndex = findMatchingBracket(source, macroOpenParen);
|
|
2591
|
+
if (closeParenIndex === -1) {
|
|
2592
|
+
console.warn(`[svelte-origin] Could not find matching ) for $attrs.origin( at index ${macroOpenParen}`);
|
|
2593
|
+
continue;
|
|
2594
|
+
}
|
|
2595
|
+
const factoryExpr = source.slice(macroOpenParen + 1, closeParenIndex).trim();
|
|
2596
|
+
matches.push({
|
|
2597
|
+
varName,
|
|
2598
|
+
factoryExpr,
|
|
2599
|
+
startIndex,
|
|
2600
|
+
endIndex: closeParenIndex + 1,
|
|
2601
|
+
isGeneric: hasGenericTypeParams(factoryExpr)
|
|
2602
|
+
});
|
|
2603
|
+
}
|
|
2604
|
+
let firstFactoryExpr = null;
|
|
2605
|
+
let isFirstDeclaration = true;
|
|
2606
|
+
for (const { varName, factoryExpr, startIndex, endIndex, isGeneric } of matches) {
|
|
2607
|
+
const expansionLines = [];
|
|
2608
|
+
let usesFallback = true;
|
|
2609
|
+
if (!firstFactoryExpr) {
|
|
2610
|
+
firstFactoryExpr = factoryExpr;
|
|
2611
|
+
}
|
|
2612
|
+
if (isFirstDeclaration && needsPropsInjection) {
|
|
2613
|
+
const isGenericFirst = hasGenericTypeParams(factoryExpr);
|
|
2614
|
+
const normalizedFactoryCallFirst = normalizeFactoryCall(factoryExpr);
|
|
2615
|
+
const typeExpr = isGenericFirst ? `ReturnType<typeof ${extractFactoryFromCall(normalizedFactoryCallFirst)}>` : `typeof ${factoryExpr}`;
|
|
2616
|
+
expansionLines.push(`type $$Props = $attrs.Of<${typeExpr}>`);
|
|
2617
|
+
propsTypeDeclaration = "";
|
|
2618
|
+
}
|
|
2619
|
+
if (schemaResolver && !isGeneric) {
|
|
2620
|
+
const importPath = findImportPath(source, factoryExpr);
|
|
2621
|
+
if (importPath) {
|
|
2622
|
+
const schema = await schemaResolver.resolve(importPath, factoryExpr);
|
|
2623
|
+
if (schema && schema.attrs.length > 0) {
|
|
2624
|
+
const propsDestructure = generatePropsDestructuring(schema.attrs, factoryExpr);
|
|
2625
|
+
const factoryCall = generateFactoryCallFromAttrs(factoryExpr, schema.attrs);
|
|
2626
|
+
expansionLines.push(propsDestructure, `let ${varName} = ${factoryCall}`);
|
|
2627
|
+
usesFallback = false;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
if (usesFallback) {
|
|
2632
|
+
const normalizedFactoryCall = normalizeFactoryCall(factoryExpr);
|
|
2633
|
+
expansionLines.push(`let ___attrs: $$Props = $props()`, `let ${varName} = ${normalizedFactoryCall}(__attrsFor(${normalizedFactoryCall}, ___attrs))`);
|
|
2634
|
+
neededImports.add("__attrsFor");
|
|
2635
|
+
}
|
|
2636
|
+
s.overwrite(startIndex, endIndex, expansionLines.join(`
|
|
2637
|
+
`));
|
|
2638
|
+
changed = true;
|
|
2639
|
+
isFirstDeclaration = false;
|
|
2640
|
+
}
|
|
2641
|
+
return { changed, propsTypeDeclaration };
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
// src/transform/element-types.ts
|
|
2645
|
+
function getElementTypeImport(element) {
|
|
2646
|
+
return `svelteHTML.IntrinsicElements['${element}']`;
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
// src/transform/attrs-for-transform.ts
|
|
2650
|
+
function transformAttrsForCalls(s, source, neededImports) {
|
|
2651
|
+
let changed = false;
|
|
2652
|
+
const existingPropsMatch = source.match(/let\s*\{([^}]*)\}\s*(?::\s*[^=]+)?\s*=\s*\$props\s*\(\s*\)/);
|
|
2653
|
+
let restVarName = null;
|
|
2654
|
+
let existingPropsStart = -1;
|
|
2655
|
+
let existingDestructureContent = "";
|
|
2656
|
+
if (existingPropsMatch) {
|
|
2657
|
+
existingPropsStart = existingPropsMatch.index;
|
|
2658
|
+
existingDestructureContent = existingPropsMatch[1];
|
|
2659
|
+
const restMatch = existingDestructureContent.match(/\.\.\.\s*(\w+)\s*$/);
|
|
2660
|
+
if (restMatch) {
|
|
2661
|
+
restVarName = restMatch[1];
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
const originDeclarations = findVariableDeclarationsWithMacro(source, "$attrs.for");
|
|
2665
|
+
for (const decl of originDeclarations) {
|
|
2666
|
+
const { varName, startIndex, macroOpenParen } = decl;
|
|
2667
|
+
const closeParenIndex = findMatchingBracket(source, macroOpenParen);
|
|
2668
|
+
if (closeParenIndex === -1)
|
|
2669
|
+
continue;
|
|
2670
|
+
const arg = source.slice(macroOpenParen + 1, closeParenIndex).trim();
|
|
2671
|
+
const endIndex = closeParenIndex + 1;
|
|
2672
|
+
const stringMatch = arg.match(/^['"](\w+)['"]$/);
|
|
2673
|
+
if (stringMatch) {
|
|
2674
|
+
const element = stringMatch[1];
|
|
2675
|
+
const typeImport = getElementTypeImport(element);
|
|
2676
|
+
if (existingPropsMatch && existingPropsStart !== -1) {
|
|
2677
|
+
if (!restVarName) {
|
|
2678
|
+
restVarName = "___restAttrs";
|
|
2679
|
+
const newDestructure = existingDestructureContent.trimEnd() ? `${existingDestructureContent.trimEnd()}, ...${restVarName}` : `...${restVarName}`;
|
|
2680
|
+
const braceEnd = source.indexOf("}", existingPropsStart + 5);
|
|
2681
|
+
if (braceEnd !== -1) {
|
|
2682
|
+
s.overwrite(existingPropsStart + 5, braceEnd, ` ${newDestructure} `);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
s.overwrite(startIndex, endIndex, `let ${varName} = ${restVarName} as ${typeImport}`);
|
|
2686
|
+
} else {
|
|
2687
|
+
const expansion = `let { ...${varName} } = $props<${typeImport}>()`;
|
|
2688
|
+
s.overwrite(startIndex, endIndex, expansion);
|
|
2689
|
+
}
|
|
2690
|
+
} else {
|
|
2691
|
+
const factoryName = arg;
|
|
2692
|
+
if (existingPropsMatch && existingPropsStart !== -1) {
|
|
2693
|
+
if (!restVarName) {
|
|
2694
|
+
restVarName = "___restAttrs";
|
|
2695
|
+
const newDestructure = existingDestructureContent.trimEnd() ? `${existingDestructureContent.trimEnd()}, ...${restVarName}` : `...${restVarName}`;
|
|
2696
|
+
const braceEnd = source.indexOf("}", existingPropsStart + 5);
|
|
2697
|
+
if (braceEnd !== -1) {
|
|
2698
|
+
s.overwrite(existingPropsStart + 5, braceEnd, ` ${newDestructure} `);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
s.overwrite(startIndex, endIndex, `let ${varName} = __attrsFor(${factoryName}, ${restVarName})`);
|
|
2702
|
+
} else {
|
|
2703
|
+
const expansion = [
|
|
2704
|
+
`let ___attrs: $attrs.Of<typeof ${factoryName}> = $props()`,
|
|
2705
|
+
`let ${varName} = __attrsFor(${factoryName}, ___attrs)`
|
|
2706
|
+
].join(`
|
|
2707
|
+
`);
|
|
2708
|
+
s.overwrite(startIndex, endIndex, expansion);
|
|
2709
|
+
}
|
|
2710
|
+
neededImports.add("__attrsFor");
|
|
2711
|
+
}
|
|
2712
|
+
changed = true;
|
|
2713
|
+
}
|
|
2714
|
+
return changed;
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
// src/transform/core.ts
|
|
2718
|
+
function transformScript(source, options = {}) {
|
|
2719
|
+
if (options.schemaResolver) {
|
|
2720
|
+
return transformScriptAsync(source, options);
|
|
2721
|
+
}
|
|
2722
|
+
if (!containsMacros(source)) {
|
|
2723
|
+
return { code: source, changed: false };
|
|
2724
|
+
}
|
|
2725
|
+
const s = new MagicString(source);
|
|
2726
|
+
const { isComponent = false } = options;
|
|
2727
|
+
let changed = false;
|
|
2728
|
+
const neededImports = new Set;
|
|
2729
|
+
let propsTypeDeclaration = null;
|
|
2730
|
+
if (!isComponent) {
|
|
2731
|
+
changed = transformOriginCalls(s, source, neededImports) || changed;
|
|
2732
|
+
changed = transformStandaloneAttrsCalls(s, source, neededImports) || changed;
|
|
2733
|
+
}
|
|
2734
|
+
if (isComponent) {
|
|
2735
|
+
const result = transformAttrsOriginCallsSync(s, source, neededImports);
|
|
2736
|
+
changed = result.changed || changed;
|
|
2737
|
+
propsTypeDeclaration = result.propsTypeDeclaration;
|
|
2738
|
+
}
|
|
2739
|
+
if (isComponent) {
|
|
2740
|
+
changed = transformAttrsForCalls(s, source, neededImports) || changed;
|
|
2741
|
+
}
|
|
2742
|
+
const needsPropsInjection = propsTypeDeclaration && propsTypeDeclaration.length > 0;
|
|
2743
|
+
if (isComponent && (neededImports.size > 0 || needsPropsInjection)) {
|
|
2744
|
+
const scriptMatch = source.match(/<script[^>]*>/);
|
|
2745
|
+
if (scriptMatch) {
|
|
2746
|
+
const scriptEnd = scriptMatch.index + scriptMatch[0].length;
|
|
2747
|
+
const afterImports = findPropsInjectionPosition(source);
|
|
2748
|
+
if (neededImports.size > 0) {
|
|
2749
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2750
|
+
s.appendLeft(scriptEnd, `
|
|
2751
|
+
` + importStatement);
|
|
2752
|
+
}
|
|
2753
|
+
if (needsPropsInjection) {
|
|
2754
|
+
const propsPos = afterImports > scriptEnd ? afterImports : scriptEnd;
|
|
2755
|
+
s.appendLeft(propsPos, `
|
|
2756
|
+
` + propsTypeDeclaration);
|
|
2757
|
+
}
|
|
2758
|
+
} else {
|
|
2759
|
+
const afterImports = findPropsInjectionPosition(source);
|
|
2760
|
+
if (neededImports.size > 0) {
|
|
2761
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2762
|
+
s.prepend(importStatement + `
|
|
2763
|
+
`);
|
|
2764
|
+
}
|
|
2765
|
+
if (needsPropsInjection) {
|
|
2766
|
+
s.appendLeft(afterImports, propsTypeDeclaration + `
|
|
2767
|
+
`);
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
} else if (neededImports.size > 0) {
|
|
2771
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2772
|
+
s.prepend(importStatement + `
|
|
2773
|
+
`);
|
|
2774
|
+
}
|
|
2775
|
+
if (!changed) {
|
|
2776
|
+
return { code: source, changed: false };
|
|
2777
|
+
}
|
|
2778
|
+
return {
|
|
2779
|
+
code: s.toString(),
|
|
2780
|
+
changed: true,
|
|
2781
|
+
map: s.generateMap({ hires: true })
|
|
2782
|
+
};
|
|
2783
|
+
}
|
|
2784
|
+
async function transformScriptAsync(source, options) {
|
|
2785
|
+
if (!containsMacros(source)) {
|
|
2786
|
+
return { code: source, changed: false };
|
|
2787
|
+
}
|
|
2788
|
+
const s = new MagicString(source);
|
|
2789
|
+
const { isComponent = false, schemaResolver } = options;
|
|
2790
|
+
let changed = false;
|
|
2791
|
+
const neededImports = new Set;
|
|
2792
|
+
let propsTypeDeclaration = null;
|
|
2793
|
+
if (!isComponent) {
|
|
2794
|
+
changed = transformOriginCalls(s, source, neededImports) || changed;
|
|
2795
|
+
changed = transformStandaloneAttrsCalls(s, source, neededImports) || changed;
|
|
2796
|
+
}
|
|
2797
|
+
if (isComponent) {
|
|
2798
|
+
const result = await transformAttrsOriginCalls(s, source, neededImports, schemaResolver);
|
|
2799
|
+
changed = result.changed || changed;
|
|
2800
|
+
propsTypeDeclaration = result.propsTypeDeclaration;
|
|
2801
|
+
}
|
|
2802
|
+
if (isComponent) {
|
|
2803
|
+
changed = transformAttrsForCalls(s, source, neededImports) || changed;
|
|
2804
|
+
}
|
|
2805
|
+
const needsPropsInjectionAsync = propsTypeDeclaration && propsTypeDeclaration.length > 0;
|
|
2806
|
+
if (isComponent && (neededImports.size > 0 || needsPropsInjectionAsync)) {
|
|
2807
|
+
const scriptMatch = source.match(/<script[^>]*>/);
|
|
2808
|
+
if (scriptMatch) {
|
|
2809
|
+
const scriptEnd = scriptMatch.index + scriptMatch[0].length;
|
|
2810
|
+
const afterImports = findPropsInjectionPosition(source);
|
|
2811
|
+
if (neededImports.size > 0) {
|
|
2812
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2813
|
+
s.appendLeft(scriptEnd, `
|
|
2814
|
+
` + importStatement);
|
|
2815
|
+
}
|
|
2816
|
+
if (needsPropsInjectionAsync) {
|
|
2817
|
+
const propsPos = afterImports > scriptEnd ? afterImports : scriptEnd;
|
|
2818
|
+
s.appendLeft(propsPos, `
|
|
2819
|
+
` + propsTypeDeclaration);
|
|
2820
|
+
}
|
|
2821
|
+
} else {
|
|
2822
|
+
const afterImports = findPropsInjectionPosition(source);
|
|
2823
|
+
if (neededImports.size > 0) {
|
|
2824
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2825
|
+
s.prepend(importStatement + `
|
|
2826
|
+
`);
|
|
2827
|
+
}
|
|
2828
|
+
if (needsPropsInjectionAsync) {
|
|
2829
|
+
s.appendLeft(afterImports, propsTypeDeclaration + `
|
|
2830
|
+
`);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
} else if (neededImports.size > 0) {
|
|
2834
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2835
|
+
s.prepend(importStatement + `
|
|
2836
|
+
`);
|
|
2837
|
+
}
|
|
2838
|
+
if (!changed) {
|
|
2839
|
+
return { code: source, changed: false };
|
|
2840
|
+
}
|
|
2841
|
+
return {
|
|
2842
|
+
code: s.toString(),
|
|
2843
|
+
changed: true,
|
|
2844
|
+
map: s.generateMap({ hires: true })
|
|
2845
|
+
};
|
|
2846
|
+
}
|
|
2847
|
+
async function transformScriptContent(source, options) {
|
|
2848
|
+
if (!containsMacros(source)) {
|
|
2849
|
+
return { code: source, changed: false };
|
|
2850
|
+
}
|
|
2851
|
+
const s = new MagicString(source);
|
|
2852
|
+
const { isComponent = false, schemaResolver } = options;
|
|
2853
|
+
let changed = false;
|
|
2854
|
+
const neededImports = new Set;
|
|
2855
|
+
let propsTypeDeclaration = null;
|
|
2856
|
+
if (!isComponent) {
|
|
2857
|
+
changed = transformOriginCalls(s, source, neededImports) || changed;
|
|
2858
|
+
}
|
|
2859
|
+
if (isComponent) {
|
|
2860
|
+
const result = await transformAttrsOriginCalls(s, source, neededImports, schemaResolver);
|
|
2861
|
+
changed = result.changed || changed;
|
|
2862
|
+
propsTypeDeclaration = result.propsTypeDeclaration;
|
|
2863
|
+
}
|
|
2864
|
+
if (isComponent) {
|
|
2865
|
+
changed = transformAttrsForCalls(s, source, neededImports) || changed;
|
|
2866
|
+
}
|
|
2867
|
+
if (neededImports.size > 0) {
|
|
2868
|
+
const importStatement = generateRuntimeImport([...neededImports]);
|
|
2869
|
+
s.prepend(importStatement + `
|
|
2870
|
+
`);
|
|
2871
|
+
}
|
|
2872
|
+
if (propsTypeDeclaration) {
|
|
2873
|
+
const afterImports = findPropsInjectionPosition(source);
|
|
2874
|
+
const offset = neededImports.size > 0 ? generateRuntimeImport([...neededImports]).length + 1 : 0;
|
|
2875
|
+
s.appendLeft(afterImports + offset, propsTypeDeclaration + `
|
|
2876
|
+
`);
|
|
2877
|
+
}
|
|
2878
|
+
if (!changed) {
|
|
2879
|
+
return { code: source, changed: false };
|
|
2880
|
+
}
|
|
2881
|
+
return {
|
|
2882
|
+
code: s.toString(),
|
|
2883
|
+
changed: true,
|
|
2884
|
+
map: s.generateMap({ hires: true })
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
// src/post-process.ts
|
|
2889
|
+
var EXTENSIONS = [".svelte", ".svelte.ts", ".svelte.js", ".js", ".ts"];
|
|
2890
|
+
function cleanupForLibrary(code, schemaCache) {
|
|
2891
|
+
let result = code;
|
|
2892
|
+
result = result.replace(/\ntype \$\$Props = \$attrs\.Of<[^>]+>\n/g, `
|
|
2893
|
+
`);
|
|
2894
|
+
const attrsOfPattern = /(\}\s*:\s*)\$attrs\.Of<typeof (\w+)>(\s*=\s*\$props\(\))/g;
|
|
2895
|
+
result = result.replace(attrsOfPattern, (_match, prefix, factoryName, suffix) => {
|
|
2896
|
+
for (const [key, schema] of schemaCache.entries()) {
|
|
2897
|
+
if (schema && key.endsWith(`::${factoryName}`)) {
|
|
2898
|
+
const { interfaceContent } = generatePropsInterface(schema);
|
|
2899
|
+
return `${prefix}${interfaceContent}${suffix}`;
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
return `${prefix}Record<string, unknown>${suffix}`;
|
|
2903
|
+
});
|
|
2904
|
+
return result;
|
|
2905
|
+
}
|
|
2906
|
+
function generateCleanDts(componentName, schema) {
|
|
2907
|
+
if (!schema || schema.attrs.length === 0) {
|
|
2908
|
+
return `import type { Component } from 'svelte'
|
|
2909
|
+
|
|
2910
|
+
declare const ${componentName}: Component<{}, {}, ''>
|
|
2911
|
+
type ${componentName} = typeof ${componentName}
|
|
2912
|
+
|
|
2913
|
+
export { ${componentName} as default }
|
|
2914
|
+
`;
|
|
2915
|
+
}
|
|
2916
|
+
const { interfaceContent, bindings } = generatePropsInterface(schema);
|
|
2917
|
+
const bindingsStr = bindings.length > 0 ? `'${bindings.join("' | '")}'` : "''";
|
|
2918
|
+
return `import type { Component } from 'svelte'
|
|
2919
|
+
|
|
2920
|
+
export interface Props ${interfaceContent}
|
|
2921
|
+
|
|
2922
|
+
declare const ${componentName}: Component<Props, {}, ${bindingsStr}>
|
|
2923
|
+
type ${componentName} = typeof ${componentName}
|
|
2924
|
+
|
|
2925
|
+
export { ${componentName} as default }
|
|
2926
|
+
`;
|
|
2927
|
+
}
|
|
2928
|
+
function findOriginFactoryName(source) {
|
|
2929
|
+
const match = source.match(/\$attrs\.origin\s*\(\s*(\w+)\s*\)/);
|
|
2930
|
+
return match ? match[1] : null;
|
|
2931
|
+
}
|
|
2932
|
+
function findFiles(dir, extensions) {
|
|
2933
|
+
const files = [];
|
|
2934
|
+
function walk(currentDir) {
|
|
2935
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
2936
|
+
for (const entry of entries) {
|
|
2937
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
2938
|
+
if (entry.isDirectory()) {
|
|
2939
|
+
walk(fullPath);
|
|
2940
|
+
} else if (entry.isFile()) {
|
|
2941
|
+
const matchesExt = extensions.some((ext) => entry.name.endsWith(ext));
|
|
2942
|
+
if (matchesExt) {
|
|
2943
|
+
files.push(fullPath);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
walk(dir);
|
|
2949
|
+
return files;
|
|
2950
|
+
}
|
|
2951
|
+
function createDistSchemaResolver(distDir, schemaCache, verbose) {
|
|
2952
|
+
return {
|
|
2953
|
+
resolve: async (importPath, exportName) => {
|
|
2954
|
+
const cacheKey = `${importPath}::${exportName}`;
|
|
2955
|
+
if (schemaCache.has(cacheKey)) {
|
|
2956
|
+
return schemaCache.get(cacheKey) || null;
|
|
2957
|
+
}
|
|
2958
|
+
try {
|
|
2959
|
+
let resolvedPath;
|
|
2960
|
+
if (importPath.startsWith(".")) {
|
|
2961
|
+
resolvedPath = path.resolve(distDir, importPath);
|
|
2962
|
+
} else {
|
|
2963
|
+
schemaCache.set(cacheKey, null);
|
|
2964
|
+
return null;
|
|
2965
|
+
}
|
|
2966
|
+
const extensions = [".svelte.ts", ".svelte.js", ".ts", ".js"];
|
|
2967
|
+
let filePath = resolvedPath;
|
|
2968
|
+
if (!fs.existsSync(filePath)) {
|
|
2969
|
+
for (const ext of extensions) {
|
|
2970
|
+
if (fs.existsSync(resolvedPath + ext)) {
|
|
2971
|
+
filePath = resolvedPath + ext;
|
|
2972
|
+
break;
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
if (!fs.existsSync(filePath)) {
|
|
2977
|
+
schemaCache.set(cacheKey, null);
|
|
2978
|
+
return null;
|
|
2979
|
+
}
|
|
2980
|
+
const source = fs.readFileSync(filePath, "utf-8");
|
|
2981
|
+
const schema = parseOriginSchemaFromSource(source, exportName);
|
|
2982
|
+
if (verbose && schema) {
|
|
2983
|
+
console.log(` Resolved schema for ${exportName}: ${schema.attrs.map((a) => a.key).join(", ")}`);
|
|
2984
|
+
}
|
|
2985
|
+
schemaCache.set(cacheKey, schema);
|
|
2986
|
+
return schema;
|
|
2987
|
+
} catch {
|
|
2988
|
+
schemaCache.set(cacheKey, null);
|
|
2989
|
+
return null;
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
async function postProcess(options) {
|
|
2995
|
+
const { dir, dryRun = false, verbose = false } = options;
|
|
2996
|
+
const result = {
|
|
2997
|
+
filesProcessed: 0,
|
|
2998
|
+
files: [],
|
|
2999
|
+
errors: []
|
|
3000
|
+
};
|
|
3001
|
+
const files = findFiles(dir, EXTENSIONS);
|
|
3002
|
+
if (verbose) {
|
|
3003
|
+
console.log(` Found ${files.length} files to check`);
|
|
3004
|
+
}
|
|
3005
|
+
const schemaCache = new Map;
|
|
3006
|
+
const schemaResolver = createDistSchemaResolver(dir, schemaCache, verbose);
|
|
3007
|
+
for (const filePath of files) {
|
|
3008
|
+
try {
|
|
3009
|
+
const source = fs.readFileSync(filePath, "utf-8");
|
|
3010
|
+
if (!containsMacros(source)) {
|
|
3011
|
+
continue;
|
|
3012
|
+
}
|
|
3013
|
+
if (verbose) {
|
|
3014
|
+
console.log(` Processing: ${path.relative(dir, filePath)}`);
|
|
3015
|
+
}
|
|
3016
|
+
const isComponent = filePath.endsWith(".svelte");
|
|
3017
|
+
const transformed = await transformScript(source, {
|
|
3018
|
+
filename: filePath,
|
|
3019
|
+
isComponent,
|
|
3020
|
+
schemaResolver
|
|
3021
|
+
});
|
|
3022
|
+
if (transformed.changed) {
|
|
3023
|
+
result.filesProcessed++;
|
|
3024
|
+
result.files.push(filePath);
|
|
3025
|
+
let finalCode = cleanupForLibrary(transformed.code, schemaCache);
|
|
3026
|
+
if (!dryRun) {
|
|
3027
|
+
fs.writeFileSync(filePath, finalCode, "utf-8");
|
|
3028
|
+
}
|
|
3029
|
+
if (verbose) {
|
|
3030
|
+
console.log(` ${dryRun ? "Would transform" : "Transformed"}: ${path.relative(dir, filePath)}`);
|
|
3031
|
+
}
|
|
3032
|
+
if (isComponent) {
|
|
3033
|
+
const dtsPath = filePath + ".d.ts";
|
|
3034
|
+
if (fs.existsSync(dtsPath)) {
|
|
3035
|
+
const factoryName = findOriginFactoryName(source);
|
|
3036
|
+
let schema = null;
|
|
3037
|
+
if (factoryName) {
|
|
3038
|
+
for (const [key, cachedSchema] of schemaCache.entries()) {
|
|
3039
|
+
if (cachedSchema && key.endsWith(`::${factoryName}`)) {
|
|
3040
|
+
schema = cachedSchema;
|
|
3041
|
+
break;
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
const componentName = path.basename(filePath, ".svelte");
|
|
3046
|
+
const cleanDts = generateCleanDts(componentName, schema);
|
|
3047
|
+
if (!dryRun) {
|
|
3048
|
+
fs.writeFileSync(dtsPath, cleanDts, "utf-8");
|
|
3049
|
+
}
|
|
3050
|
+
if (verbose) {
|
|
3051
|
+
console.log(` ${dryRun ? "Would regenerate" : "Regenerated"} .d.ts: ${path.basename(dtsPath)}`);
|
|
3052
|
+
}
|
|
3053
|
+
result.files.push(dtsPath);
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
} catch (error) {
|
|
3058
|
+
const errorMsg = `Error processing ${path.relative(dir, filePath)}: ${error}`;
|
|
3059
|
+
result.errors.push(errorMsg);
|
|
3060
|
+
if (verbose) {
|
|
3061
|
+
console.error(` ${errorMsg}`);
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
return result;
|
|
3066
|
+
}
|
|
3067
|
+
var post_process_default = postProcess;
|
|
3068
|
+
export {
|
|
3069
|
+
postProcess,
|
|
3070
|
+
post_process_default as default
|
|
3071
|
+
};
|