svelte-origin 1.0.0-next.20 → 1.0.0-next.22

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.

@@ -1969,6 +1969,7 @@ function transformOriginDefinition(content, svelteImports) {
1969
1969
  let attrsContent = "";
1970
1970
  let contentWithoutAttrs = bodyContent;
1971
1971
  let attrPropertyName = "props";
1972
+ let propsRef = null;
1972
1973
  if (attrsMatch) {
1973
1974
  attrPropertyName = attrsMatch[1];
1974
1975
  const attrsStart = attrsMatch.index;
@@ -1999,13 +2000,31 @@ function transformOriginDefinition(content, svelteImports) {
1999
2000
  }
2000
2001
  contentWithoutAttrs = bodyContent.slice(0, attrsStart) + bodyContent.slice(cutEnd);
2001
2002
  }
2003
+ } else {
2004
+ const externalRefMatch = bodyContent.match(/(\w+)\s*:\s*(\w+)\s*,/);
2005
+ if (externalRefMatch) {
2006
+ const propName = externalRefMatch[1];
2007
+ const refName = externalRefMatch[2];
2008
+ if ((propName === "props" || propName === "attrs") && /^[A-Z]/.test(refName) && !["$state", "$derived", "$effect", "$bindable"].includes(refName)) {
2009
+ attrPropertyName = propName;
2010
+ propsRef = refName;
2011
+ const refStart = externalRefMatch.index;
2012
+ const refEnd = refStart + externalRefMatch[0].length;
2013
+ contentWithoutAttrs = bodyContent.slice(0, refStart) + bodyContent.slice(refEnd);
2014
+ }
2015
+ }
2002
2016
  }
2003
2017
  const attrDetails = parseAttrsSource(attrsContent);
2004
2018
  const { body: createFnBody, attachments } = transformOriginBody(contentWithoutAttrs.trim(), parents, attrDetails, attrPropertyName, svelteImports);
2005
2019
  const parentsCode = parents.length > 0 ? `[${parents.join(", ")}]` : "undefined";
2006
2020
  let configCode = `{
2007
2021
  __attrSchema: ${attrSchemaCode},
2008
- __parents: ${parentsCode},
2022
+ __parents: ${parentsCode},`;
2023
+ if (propsRef) {
2024
+ configCode += `
2025
+ __propsRef: ${propsRef},`;
2026
+ }
2027
+ configCode += `
2009
2028
  __create: (__inputAttrs${parents.length > 0 ? ", __super" : ""}) => {
2010
2029
  ${createFnBody}
2011
2030
  }`;
@@ -2232,7 +2251,83 @@ function transformStandaloneAttrsDefinition(content) {
2232
2251
 
2233
2252
  // src/transform/schema.ts
2234
2253
  function parseOriginSchemaFromSource(source, exportName) {
2235
- const exportPattern = new RegExp(`export\\s+const\\s+${exportName}\\s*=\\s*\\$origin\\s*\\(`, "s");
2254
+ const sourceResult = parseSourceOrigin(source, exportName);
2255
+ if (sourceResult)
2256
+ return sourceResult;
2257
+ const compiledResult = parseCompiledOrigin(source, exportName);
2258
+ if (compiledResult)
2259
+ return compiledResult;
2260
+ return null;
2261
+ }
2262
+ function parseAttrsSchemaFromSource(source, exportName) {
2263
+ const sourceResult = parseSourceAttrs(source, exportName);
2264
+ if (sourceResult)
2265
+ return sourceResult;
2266
+ const compiledResult = parseCompiledAttrs(source, exportName);
2267
+ if (compiledResult)
2268
+ return compiledResult;
2269
+ return null;
2270
+ }
2271
+ function parseSourceAttrs(source, exportName) {
2272
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*\\$attrs\\s*\\(`, "s");
2273
+ const match = exportPattern.exec(source);
2274
+ if (!match)
2275
+ return null;
2276
+ const attrsStart = match.index + match[0].length - 1;
2277
+ const attrsEnd = findMatchingBracket(source, attrsStart);
2278
+ if (attrsEnd === -1)
2279
+ return null;
2280
+ let attrsContent = source.slice(attrsStart + 1, attrsEnd).trim();
2281
+ let parentNames = [];
2282
+ if (attrsContent.startsWith("[")) {
2283
+ const closeBracket = findMatchingBracket(attrsContent, 0, "[", "]");
2284
+ if (closeBracket !== -1) {
2285
+ const parentsContent = attrsContent.slice(1, closeBracket);
2286
+ parentNames = parentsContent.split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
2287
+ let i = closeBracket + 1;
2288
+ while (i < attrsContent.length && /[\s,]/.test(attrsContent[i]))
2289
+ i++;
2290
+ attrsContent = attrsContent.slice(i);
2291
+ }
2292
+ }
2293
+ if (!attrsContent.startsWith("{")) {
2294
+ return { attrs: [], parentNames };
2295
+ }
2296
+ const objEnd = findMatchingBracket(attrsContent, 0, "{", "}");
2297
+ if (objEnd === -1)
2298
+ return { attrs: [], parentNames };
2299
+ const objContent = attrsContent.slice(1, objEnd);
2300
+ const attrs = parseAttrsContent(objContent);
2301
+ return { attrs, parentNames };
2302
+ }
2303
+ function parseCompiledAttrs(source, exportName) {
2304
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*__createAttrs\\s*\\(\\s*\\{`, "s");
2305
+ const match = exportPattern.exec(source);
2306
+ if (!match)
2307
+ return null;
2308
+ const braceStart = match.index + match[0].length - 1;
2309
+ const braceEnd = findMatchingBracket(source, braceStart, "{", "}");
2310
+ if (braceEnd === -1)
2311
+ return null;
2312
+ const configContent = source.slice(braceStart + 1, braceEnd);
2313
+ const schemaMatch = configContent.match(/__attrSchema\s*:\s*\{/);
2314
+ if (!schemaMatch)
2315
+ return { attrs: [], parentNames: [] };
2316
+ const schemaStart = schemaMatch.index + schemaMatch[0].length - 1;
2317
+ const schemaEnd = findMatchingBracket(configContent, schemaStart, "{", "}");
2318
+ if (schemaEnd === -1)
2319
+ return { attrs: [], parentNames: [] };
2320
+ const schemaContent = configContent.slice(schemaStart + 1, schemaEnd);
2321
+ const attrs = parseCompiledAttrSchema(schemaContent);
2322
+ const parentsMatch = configContent.match(/__parents\s*:\s*\[([^\]]*)\]/);
2323
+ let parentNames = [];
2324
+ if (parentsMatch && parentsMatch[1].trim()) {
2325
+ parentNames = parentsMatch[1].split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
2326
+ }
2327
+ return { attrs, parentNames };
2328
+ }
2329
+ function parseSourceOrigin(source, exportName) {
2330
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*\\$origin\\s*\\(`, "s");
2236
2331
  const match = exportPattern.exec(source);
2237
2332
  if (!match)
2238
2333
  return null;
@@ -2256,6 +2351,13 @@ function parseOriginSchemaFromSource(source, exportName) {
2256
2351
  }
2257
2352
  const attrsMatch = bodyContent.match(/(\w+)\s*:\s*\$attrs\s*\(\s*\{/);
2258
2353
  if (!attrsMatch) {
2354
+ const externalRefMatch = bodyContent.match(/(?:props|attrs)\s*:\s*([A-Z]\w*)\b/);
2355
+ if (externalRefMatch) {
2356
+ const propsRef = externalRefMatch[1];
2357
+ if (!["Object", "Array", "String", "Number", "Boolean"].includes(propsRef)) {
2358
+ return { attrs: [], parentNames, propsRef };
2359
+ }
2360
+ }
2259
2361
  return { attrs: [], parentNames };
2260
2362
  }
2261
2363
  const attrsStart = attrsMatch.index;
@@ -2268,6 +2370,96 @@ function parseOriginSchemaFromSource(source, exportName) {
2268
2370
  const attrs = parseAttrsContent(attrsContent);
2269
2371
  return { attrs, parentNames };
2270
2372
  }
2373
+ function parseCompiledOrigin(source, exportName) {
2374
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*__createOrigin\\s*\\(\\s*\\{`, "s");
2375
+ const match = exportPattern.exec(source);
2376
+ if (!match)
2377
+ return null;
2378
+ const braceStart = match.index + match[0].length - 1;
2379
+ const braceEnd = findMatchingBracket(source, braceStart, "{", "}");
2380
+ if (braceEnd === -1)
2381
+ return null;
2382
+ const configContent = source.slice(braceStart + 1, braceEnd);
2383
+ const schemaMatch = configContent.match(/__attrSchema\s*:\s*\{/);
2384
+ if (!schemaMatch)
2385
+ return { attrs: [], parentNames: [] };
2386
+ const schemaStart = schemaMatch.index + schemaMatch[0].length - 1;
2387
+ const schemaEnd = findMatchingBracket(configContent, schemaStart, "{", "}");
2388
+ if (schemaEnd === -1)
2389
+ return { attrs: [], parentNames: [] };
2390
+ const schemaContent = configContent.slice(schemaStart + 1, schemaEnd);
2391
+ const attrs = parseCompiledAttrSchema(schemaContent);
2392
+ const parentsMatch = configContent.match(/__parents\s*:\s*\[([^\]]*)\]/);
2393
+ let parentNames = [];
2394
+ if (parentsMatch && parentsMatch[1].trim()) {
2395
+ parentNames = parentsMatch[1].split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
2396
+ }
2397
+ const propsRefMatch = configContent.match(/__propsRef\s*:\s*(\w+)/);
2398
+ const propsRef = propsRefMatch ? propsRefMatch[1] : undefined;
2399
+ return { attrs, parentNames, propsRef };
2400
+ }
2401
+ function parseCompiledAttrSchema(content) {
2402
+ const result = [];
2403
+ let pos = 0;
2404
+ while (pos < content.length) {
2405
+ while (pos < content.length && /[\s,]/.test(content[pos]))
2406
+ pos++;
2407
+ if (pos >= content.length)
2408
+ break;
2409
+ if (content.slice(pos, pos + 2) === "/*") {
2410
+ const endComment = content.indexOf("*/", pos + 2);
2411
+ if (endComment !== -1) {
2412
+ pos = endComment + 2;
2413
+ continue;
2414
+ }
2415
+ }
2416
+ const keyMatch = content.slice(pos).match(/^(\w+)\s*:/);
2417
+ if (!keyMatch)
2418
+ break;
2419
+ const key = keyMatch[1];
2420
+ pos += keyMatch[0].length;
2421
+ while (pos < content.length && /\s/.test(content[pos]))
2422
+ pos++;
2423
+ if (content[pos] !== "{")
2424
+ break;
2425
+ const valueStart = pos;
2426
+ const valueEnd = findMatchingBracket(content, valueStart, "{", "}");
2427
+ if (valueEnd === -1)
2428
+ break;
2429
+ const valueContent = content.slice(valueStart + 1, valueEnd);
2430
+ let defaultValue = "undefined";
2431
+ let bindable = false;
2432
+ let hasDefault = false;
2433
+ const defaultMatch = valueContent.match(/\bdefault\s*:\s*/);
2434
+ if (defaultMatch) {
2435
+ const defaultStart = defaultMatch.index + defaultMatch[0].length;
2436
+ let depth = 0;
2437
+ let i = defaultStart;
2438
+ while (i < valueContent.length) {
2439
+ const char = valueContent[i];
2440
+ if (char === "{" || char === "(" || char === "[")
2441
+ depth++;
2442
+ else if (char === "}" || char === ")" || char === "]")
2443
+ depth--;
2444
+ else if (char === "," && depth === 0)
2445
+ break;
2446
+ i++;
2447
+ }
2448
+ defaultValue = valueContent.slice(defaultStart, i).trim();
2449
+ }
2450
+ const bindableMatch = valueContent.match(/\bbindable\s*:\s*(true|false)/);
2451
+ if (bindableMatch) {
2452
+ bindable = bindableMatch[1] === "true";
2453
+ }
2454
+ const hasDefaultMatch = valueContent.match(/\bhasDefault\s*:\s*(true|false)/);
2455
+ if (hasDefaultMatch) {
2456
+ hasDefault = hasDefaultMatch[1] === "true";
2457
+ }
2458
+ result.push({ key, defaultValue, bindable, hasDefault });
2459
+ pos = valueEnd + 1;
2460
+ }
2461
+ return result;
2462
+ }
2271
2463
  function parseAttrsContent(content) {
2272
2464
  const result = [];
2273
2465
  const parts = splitByTopLevelCommas(content);
@@ -3162,6 +3354,108 @@ function resolveImportPath(importPath, aliases, importerDir) {
3162
3354
  return join(aliasPath, remainder);
3163
3355
  }
3164
3356
  }
3357
+ const npmResolved = resolveNpmPackageImport(importPath, importerDir);
3358
+ if (npmResolved) {
3359
+ return npmResolved;
3360
+ }
3361
+ return null;
3362
+ }
3363
+ function resolveNpmPackageImport(importPath, importerDir) {
3364
+ if (importPath.startsWith(".") || importPath.startsWith("/") || /^[a-zA-Z]:/.test(importPath)) {
3365
+ return null;
3366
+ }
3367
+ let packageName;
3368
+ let subpath;
3369
+ if (importPath.startsWith("@")) {
3370
+ const parts = importPath.split("/");
3371
+ if (parts.length < 2)
3372
+ return null;
3373
+ packageName = `${parts[0]}/${parts[1]}`;
3374
+ subpath = parts.slice(2).join("/");
3375
+ } else {
3376
+ const slashIndex = importPath.indexOf("/");
3377
+ if (slashIndex === -1) {
3378
+ packageName = importPath;
3379
+ subpath = "";
3380
+ } else {
3381
+ packageName = importPath.slice(0, slashIndex);
3382
+ subpath = importPath.slice(slashIndex + 1);
3383
+ }
3384
+ }
3385
+ let currentDir = importerDir;
3386
+ const root = isAbsolute(importerDir) ? (importerDir.match(/^[a-zA-Z]:[/\\]/) || ["/"])[0] : "/";
3387
+ while (currentDir !== root && currentDir !== dirname(currentDir)) {
3388
+ const nodeModulesDir = join(currentDir, "node_modules");
3389
+ const packageDir = join(nodeModulesDir, packageName);
3390
+ if (existsSync(packageDir)) {
3391
+ const packageJsonPath = join(packageDir, "package.json");
3392
+ const exportKey = subpath ? `./${subpath}` : ".";
3393
+ if (existsSync(packageJsonPath)) {
3394
+ try {
3395
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
3396
+ if (packageJson.exports) {
3397
+ const resolvedExport = resolvePackageExports(packageJson.exports, exportKey);
3398
+ if (resolvedExport) {
3399
+ return join(packageDir, resolvedExport);
3400
+ }
3401
+ }
3402
+ if (!subpath) {
3403
+ const mainEntry = packageJson.module || packageJson.main || "index.js";
3404
+ return join(packageDir, mainEntry);
3405
+ }
3406
+ } catch {}
3407
+ }
3408
+ if (subpath) {
3409
+ const resolvedSubpath = join(packageDir, subpath);
3410
+ return resolvedSubpath;
3411
+ }
3412
+ return join(packageDir, "index.js");
3413
+ }
3414
+ currentDir = dirname(currentDir);
3415
+ }
3416
+ return null;
3417
+ }
3418
+ function resolvePackageExports(exports, subpath) {
3419
+ if (typeof exports === "string") {
3420
+ return subpath === "." ? exports : null;
3421
+ }
3422
+ if (typeof exports !== "object" || exports === null) {
3423
+ return null;
3424
+ }
3425
+ const exportEntry = exports[subpath];
3426
+ if (exportEntry) {
3427
+ return resolveExportCondition(exportEntry);
3428
+ }
3429
+ if (subpath === "." && exports["."]) {
3430
+ return resolveExportCondition(exports["."]);
3431
+ }
3432
+ if (subpath === ".") {
3433
+ const resolved = resolveExportCondition(exports);
3434
+ if (resolved)
3435
+ return resolved;
3436
+ }
3437
+ return null;
3438
+ }
3439
+ function resolveExportCondition(condition) {
3440
+ if (typeof condition === "string") {
3441
+ return condition;
3442
+ }
3443
+ if (typeof condition !== "object" || condition === null) {
3444
+ return null;
3445
+ }
3446
+ const condObj = condition;
3447
+ const preferredConditions = ["svelte", "import", "module", "default", "require"];
3448
+ for (const cond of preferredConditions) {
3449
+ if (cond in condObj) {
3450
+ const value = condObj[cond];
3451
+ if (typeof value === "string") {
3452
+ return value;
3453
+ }
3454
+ const resolved = resolveExportCondition(value);
3455
+ if (resolved)
3456
+ return resolved;
3457
+ }
3458
+ }
3165
3459
  return null;
3166
3460
  }
3167
3461
  function resolveFilePath(basePath) {
@@ -3269,6 +3563,25 @@ async function resolveSchema(importPath, exportName, importerId, cache, debug, a
3269
3563
  }
3270
3564
  }
3271
3565
  }
3566
+ if (schema.propsRef) {
3567
+ const propsRefImportPath = findImportPath(source, schema.propsRef);
3568
+ if (propsRefImportPath) {
3569
+ if (debug) {
3570
+ console.log(`[svelte-origin-preprocess] Resolving propsRef: ${schema.propsRef} from ${propsRefImportPath}`);
3571
+ }
3572
+ const propsRefSchema = await resolveAttrsSchema(propsRefImportPath, schema.propsRef, filePath, cache, debug, aliases);
3573
+ if (propsRefSchema) {
3574
+ for (const attr of propsRefSchema.attrs) {
3575
+ const existingIndex = mergedAttrs.findIndex((a) => a.key === attr.key);
3576
+ if (existingIndex === -1) {
3577
+ mergedAttrs.push(attr);
3578
+ } else {
3579
+ mergedAttrs[existingIndex] = attr;
3580
+ }
3581
+ }
3582
+ }
3583
+ }
3584
+ }
3272
3585
  for (const attr of schema.attrs) {
3273
3586
  const existingIndex = mergedAttrs.findIndex((a) => a.key === attr.key);
3274
3587
  if (existingIndex !== -1) {
@@ -3294,6 +3607,75 @@ async function resolveSchema(importPath, exportName, importerId, cache, debug, a
3294
3607
  return null;
3295
3608
  }
3296
3609
  }
3610
+ async function resolveAttrsSchema(importPath, exportName, importerId, cache, debug, aliases) {
3611
+ const cacheKey = `attrs::${importPath}::${exportName}`;
3612
+ if (cache.has(cacheKey)) {
3613
+ if (debug) {
3614
+ console.log(`[svelte-origin-preprocess] Cache hit for ${cacheKey}`);
3615
+ }
3616
+ return cache.get(cacheKey) || null;
3617
+ }
3618
+ try {
3619
+ const importerDir = dirname2(importerId);
3620
+ if (debug) {
3621
+ console.log(`[svelte-origin-preprocess] Resolving attrs: ${exportName} from ${importPath}`);
3622
+ }
3623
+ const resolvedPath = resolveImportPath(importPath, aliases, importerDir);
3624
+ if (!resolvedPath) {
3625
+ cache.set(cacheKey, null);
3626
+ return null;
3627
+ }
3628
+ const filePath = resolveFilePath(resolvedPath);
3629
+ if (!filePath) {
3630
+ cache.set(cacheKey, null);
3631
+ return null;
3632
+ }
3633
+ const source = readFileSync2(filePath, "utf-8");
3634
+ const schema = parseAttrsSchemaFromSource(source, exportName);
3635
+ if (!schema) {
3636
+ cache.set(cacheKey, null);
3637
+ return null;
3638
+ }
3639
+ const mergedAttrs = [];
3640
+ for (const parentName of schema.parentNames) {
3641
+ const parentImportPath = findImportPath(source, parentName);
3642
+ if (parentImportPath) {
3643
+ const parentSchema = await resolveAttrsSchema(parentImportPath, parentName, filePath, cache, debug, aliases);
3644
+ if (parentSchema) {
3645
+ for (const attr of parentSchema.attrs) {
3646
+ const existingIndex = mergedAttrs.findIndex((a) => a.key === attr.key);
3647
+ if (existingIndex === -1) {
3648
+ mergedAttrs.push(attr);
3649
+ }
3650
+ }
3651
+ }
3652
+ }
3653
+ }
3654
+ for (const attr of schema.attrs) {
3655
+ const existingIndex = mergedAttrs.findIndex((a) => a.key === attr.key);
3656
+ if (existingIndex !== -1) {
3657
+ mergedAttrs[existingIndex] = attr;
3658
+ } else {
3659
+ mergedAttrs.push(attr);
3660
+ }
3661
+ }
3662
+ const mergedSchema = {
3663
+ attrs: mergedAttrs,
3664
+ parentNames: schema.parentNames
3665
+ };
3666
+ if (debug) {
3667
+ console.log(`[svelte-origin-preprocess] Resolved attrs schema for ${exportName}:`, mergedSchema.attrs.map((a) => a.key));
3668
+ }
3669
+ cache.set(cacheKey, mergedSchema);
3670
+ return mergedSchema;
3671
+ } catch (error) {
3672
+ if (debug) {
3673
+ console.error(`[svelte-origin-preprocess] Error resolving attrs schema for ${importPath}:`, error);
3674
+ }
3675
+ cache.set(cacheKey, null);
3676
+ return null;
3677
+ }
3678
+ }
3297
3679
  function svelteOriginPreprocess(options = {}) {
3298
3680
  const {
3299
3681
  debug = false,
@@ -19,6 +19,8 @@ export interface ParsedAttrInfo {
19
19
  export interface ParsedOriginSchema {
20
20
  attrs: ParsedAttrInfo[];
21
21
  parentNames: string[];
22
+ /** Reference to external $attrs factory (e.g., 'TextAttrs' when props: TextAttrs is used) */
23
+ propsRef?: string;
22
24
  }
23
25
  /**
24
26
  * Parse an origin's schema from its source code.
@@ -40,6 +42,21 @@ export interface ParsedOriginSchema {
40
42
  * @returns Parsed schema or null if not found
41
43
  */
42
44
  export declare function parseOriginSchemaFromSource(source: string, exportName: string): ParsedOriginSchema | null;
45
+ /**
46
+ * Parse an $attrs factory's schema from its source code.
47
+ *
48
+ * Looks for patterns like:
49
+ * ```ts
50
+ * export const TextAttrs = $attrs({ ... })
51
+ * export const TextAttrs = $attrs([BaseAttrs], { ... })
52
+ * ```
53
+ *
54
+ * Or compiled:
55
+ * ```js
56
+ * export var TextAttrs = __createAttrs({ __attrSchema: {...}, __parents: [...] })
57
+ * ```
58
+ */
59
+ export declare function parseAttrsSchemaFromSource(source: string, exportName: string): ParsedOriginSchema | null;
43
60
  /**
44
61
  * Generate $props() destructuring code from parsed attrs
45
62
  *
package/dist/vite-dts.js CHANGED
@@ -202,7 +202,83 @@ function findMatchingBracket(source, openIndex, openChar = "(", closeChar = ")")
202
202
 
203
203
  // src/transform/schema.ts
204
204
  function parseOriginSchemaFromSource(source, exportName) {
205
- const exportPattern = new RegExp(`export\\s+const\\s+${exportName}\\s*=\\s*\\$origin\\s*\\(`, "s");
205
+ const sourceResult = parseSourceOrigin(source, exportName);
206
+ if (sourceResult)
207
+ return sourceResult;
208
+ const compiledResult = parseCompiledOrigin(source, exportName);
209
+ if (compiledResult)
210
+ return compiledResult;
211
+ return null;
212
+ }
213
+ function parseAttrsSchemaFromSource(source, exportName) {
214
+ const sourceResult = parseSourceAttrs(source, exportName);
215
+ if (sourceResult)
216
+ return sourceResult;
217
+ const compiledResult = parseCompiledAttrs(source, exportName);
218
+ if (compiledResult)
219
+ return compiledResult;
220
+ return null;
221
+ }
222
+ function parseSourceAttrs(source, exportName) {
223
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*\\$attrs\\s*\\(`, "s");
224
+ const match = exportPattern.exec(source);
225
+ if (!match)
226
+ return null;
227
+ const attrsStart = match.index + match[0].length - 1;
228
+ const attrsEnd = findMatchingBracket(source, attrsStart);
229
+ if (attrsEnd === -1)
230
+ return null;
231
+ let attrsContent = source.slice(attrsStart + 1, attrsEnd).trim();
232
+ let parentNames = [];
233
+ if (attrsContent.startsWith("[")) {
234
+ const closeBracket = findMatchingBracket(attrsContent, 0, "[", "]");
235
+ if (closeBracket !== -1) {
236
+ const parentsContent = attrsContent.slice(1, closeBracket);
237
+ parentNames = parentsContent.split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
238
+ let i = closeBracket + 1;
239
+ while (i < attrsContent.length && /[\s,]/.test(attrsContent[i]))
240
+ i++;
241
+ attrsContent = attrsContent.slice(i);
242
+ }
243
+ }
244
+ if (!attrsContent.startsWith("{")) {
245
+ return { attrs: [], parentNames };
246
+ }
247
+ const objEnd = findMatchingBracket(attrsContent, 0, "{", "}");
248
+ if (objEnd === -1)
249
+ return { attrs: [], parentNames };
250
+ const objContent = attrsContent.slice(1, objEnd);
251
+ const attrs = parseAttrsContent(objContent);
252
+ return { attrs, parentNames };
253
+ }
254
+ function parseCompiledAttrs(source, exportName) {
255
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*__createAttrs\\s*\\(\\s*\\{`, "s");
256
+ const match = exportPattern.exec(source);
257
+ if (!match)
258
+ return null;
259
+ const braceStart = match.index + match[0].length - 1;
260
+ const braceEnd = findMatchingBracket(source, braceStart, "{", "}");
261
+ if (braceEnd === -1)
262
+ return null;
263
+ const configContent = source.slice(braceStart + 1, braceEnd);
264
+ const schemaMatch = configContent.match(/__attrSchema\s*:\s*\{/);
265
+ if (!schemaMatch)
266
+ return { attrs: [], parentNames: [] };
267
+ const schemaStart = schemaMatch.index + schemaMatch[0].length - 1;
268
+ const schemaEnd = findMatchingBracket(configContent, schemaStart, "{", "}");
269
+ if (schemaEnd === -1)
270
+ return { attrs: [], parentNames: [] };
271
+ const schemaContent = configContent.slice(schemaStart + 1, schemaEnd);
272
+ const attrs = parseCompiledAttrSchema(schemaContent);
273
+ const parentsMatch = configContent.match(/__parents\s*:\s*\[([^\]]*)\]/);
274
+ let parentNames = [];
275
+ if (parentsMatch && parentsMatch[1].trim()) {
276
+ parentNames = parentsMatch[1].split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
277
+ }
278
+ return { attrs, parentNames };
279
+ }
280
+ function parseSourceOrigin(source, exportName) {
281
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*\\$origin\\s*\\(`, "s");
206
282
  const match = exportPattern.exec(source);
207
283
  if (!match)
208
284
  return null;
@@ -226,6 +302,13 @@ function parseOriginSchemaFromSource(source, exportName) {
226
302
  }
227
303
  const attrsMatch = bodyContent.match(/(\w+)\s*:\s*\$attrs\s*\(\s*\{/);
228
304
  if (!attrsMatch) {
305
+ const externalRefMatch = bodyContent.match(/(?:props|attrs)\s*:\s*([A-Z]\w*)\b/);
306
+ if (externalRefMatch) {
307
+ const propsRef = externalRefMatch[1];
308
+ if (!["Object", "Array", "String", "Number", "Boolean"].includes(propsRef)) {
309
+ return { attrs: [], parentNames, propsRef };
310
+ }
311
+ }
229
312
  return { attrs: [], parentNames };
230
313
  }
231
314
  const attrsStart = attrsMatch.index;
@@ -238,6 +321,96 @@ function parseOriginSchemaFromSource(source, exportName) {
238
321
  const attrs = parseAttrsContent(attrsContent);
239
322
  return { attrs, parentNames };
240
323
  }
324
+ function parseCompiledOrigin(source, exportName) {
325
+ const exportPattern = new RegExp(`export\\s+(?:const|var|let)\\s+${exportName}\\s*=\\s*__createOrigin\\s*\\(\\s*\\{`, "s");
326
+ const match = exportPattern.exec(source);
327
+ if (!match)
328
+ return null;
329
+ const braceStart = match.index + match[0].length - 1;
330
+ const braceEnd = findMatchingBracket(source, braceStart, "{", "}");
331
+ if (braceEnd === -1)
332
+ return null;
333
+ const configContent = source.slice(braceStart + 1, braceEnd);
334
+ const schemaMatch = configContent.match(/__attrSchema\s*:\s*\{/);
335
+ if (!schemaMatch)
336
+ return { attrs: [], parentNames: [] };
337
+ const schemaStart = schemaMatch.index + schemaMatch[0].length - 1;
338
+ const schemaEnd = findMatchingBracket(configContent, schemaStart, "{", "}");
339
+ if (schemaEnd === -1)
340
+ return { attrs: [], parentNames: [] };
341
+ const schemaContent = configContent.slice(schemaStart + 1, schemaEnd);
342
+ const attrs = parseCompiledAttrSchema(schemaContent);
343
+ const parentsMatch = configContent.match(/__parents\s*:\s*\[([^\]]*)\]/);
344
+ let parentNames = [];
345
+ if (parentsMatch && parentsMatch[1].trim()) {
346
+ parentNames = parentsMatch[1].split(",").map((p) => p.trim()).filter((p) => p && /^\w+$/.test(p));
347
+ }
348
+ const propsRefMatch = configContent.match(/__propsRef\s*:\s*(\w+)/);
349
+ const propsRef = propsRefMatch ? propsRefMatch[1] : undefined;
350
+ return { attrs, parentNames, propsRef };
351
+ }
352
+ function parseCompiledAttrSchema(content) {
353
+ const result = [];
354
+ let pos = 0;
355
+ while (pos < content.length) {
356
+ while (pos < content.length && /[\s,]/.test(content[pos]))
357
+ pos++;
358
+ if (pos >= content.length)
359
+ break;
360
+ if (content.slice(pos, pos + 2) === "/*") {
361
+ const endComment = content.indexOf("*/", pos + 2);
362
+ if (endComment !== -1) {
363
+ pos = endComment + 2;
364
+ continue;
365
+ }
366
+ }
367
+ const keyMatch = content.slice(pos).match(/^(\w+)\s*:/);
368
+ if (!keyMatch)
369
+ break;
370
+ const key = keyMatch[1];
371
+ pos += keyMatch[0].length;
372
+ while (pos < content.length && /\s/.test(content[pos]))
373
+ pos++;
374
+ if (content[pos] !== "{")
375
+ break;
376
+ const valueStart = pos;
377
+ const valueEnd = findMatchingBracket(content, valueStart, "{", "}");
378
+ if (valueEnd === -1)
379
+ break;
380
+ const valueContent = content.slice(valueStart + 1, valueEnd);
381
+ let defaultValue = "undefined";
382
+ let bindable = false;
383
+ let hasDefault = false;
384
+ const defaultMatch = valueContent.match(/\bdefault\s*:\s*/);
385
+ if (defaultMatch) {
386
+ const defaultStart = defaultMatch.index + defaultMatch[0].length;
387
+ let depth = 0;
388
+ let i = defaultStart;
389
+ while (i < valueContent.length) {
390
+ const char = valueContent[i];
391
+ if (char === "{" || char === "(" || char === "[")
392
+ depth++;
393
+ else if (char === "}" || char === ")" || char === "]")
394
+ depth--;
395
+ else if (char === "," && depth === 0)
396
+ break;
397
+ i++;
398
+ }
399
+ defaultValue = valueContent.slice(defaultStart, i).trim();
400
+ }
401
+ const bindableMatch = valueContent.match(/\bbindable\s*:\s*(true|false)/);
402
+ if (bindableMatch) {
403
+ bindable = bindableMatch[1] === "true";
404
+ }
405
+ const hasDefaultMatch = valueContent.match(/\bhasDefault\s*:\s*(true|false)/);
406
+ if (hasDefaultMatch) {
407
+ hasDefault = hasDefaultMatch[1] === "true";
408
+ }
409
+ result.push({ key, defaultValue, bindable, hasDefault });
410
+ pos = valueEnd + 1;
411
+ }
412
+ return result;
413
+ }
241
414
  function parseAttrsContent(content) {
242
415
  const result = [];
243
416
  const parts = splitByTopLevelCommas(content);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-origin",
3
- "version": "1.0.0-next.20",
3
+ "version": "1.0.0-next.22",
4
4
  "description": "Compiler-assisted state and prop ergonomics for Svelte 5",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",