svelte-origin 1.0.0-next.24 → 1.0.0-next.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LLM.md CHANGED
@@ -102,8 +102,7 @@ function $origin<Parents extends OriginFactory[], T>(parents: Parents, definitio
102
102
 
103
103
  | Property | Description |
104
104
  |----------|-------------|
105
- | `props: $attrs({...})` | Props schema (becomes component props) |
106
- | `attrs: $attrs({...})` | Alternative name for props schema |
105
+ | `props: $attrs({...})` | Props schema (recommended name) |
107
106
  | `_privateField` | Private state/method (not exposed on instance) |
108
107
  | `get propertyName()` | Derived value (use `$derived` inside) |
109
108
  | `methodName()` | Method accessible on the instance |
@@ -313,6 +312,99 @@ export const Timer = $origin({
313
312
  - Can return a cleanup function that runs when the component is destroyed
314
313
  - Useful for side effects, subscriptions, or DOM interactions
315
314
 
315
+ ## Origin Destructuring
316
+
317
+ Destructure methods and props from origin instances with automatic handling.
318
+
319
+ ### Method Destructuring
320
+
321
+ Methods are automatically bound to preserve `this` context:
322
+
323
+ ```svelte
324
+ <script lang="ts">
325
+ import { Counter } from './counter.svelte'
326
+ let counter = $attrs.origin(Counter)
327
+
328
+ // Destructure methods - automatically bound
329
+ let { increment, decrement } = counter
330
+
331
+ // Transforms to:
332
+ // let increment = counter.increment.bind(counter)
333
+ // let decrement = counter.decrement.bind(counter)
334
+ </script>
335
+
336
+ <button onclick={increment}>+</button>
337
+ <button onclick={decrement}>-</button>
338
+ ```
339
+
340
+ ### Props Destructuring
341
+
342
+ Props are automatically wrapped in `$derived` for reactivity:
343
+
344
+ ```svelte
345
+ <script lang="ts">
346
+ import { Counter } from './counter.svelte'
347
+ let counter = $attrs.origin(Counter)
348
+
349
+ // Destructure props - automatically reactive
350
+ let { count, label } = counter.props
351
+
352
+ // Transforms to:
353
+ // let count = $derived(counter.props.count)
354
+ // let label = $derived(counter.props.label)
355
+ </script>
356
+
357
+ <p>{label}: {count}</p>
358
+ ```
359
+
360
+ ### Nested Props Destructuring
361
+
362
+ Combine method and props destructuring in a single pattern:
363
+
364
+ ```svelte
365
+ <script lang="ts">
366
+ let { increment, props: { count, label } } = counter
367
+
368
+ // Transforms to:
369
+ // let increment = counter.increment.bind(counter)
370
+ // let count = $derived(counter.props.count)
371
+ // let label = $derived(counter.props.label)
372
+ </script>
373
+ ```
374
+
375
+ ### Aliases and Defaults
376
+
377
+ ```svelte
378
+ <script lang="ts">
379
+ // Alias methods
380
+ let { increment: inc } = counter
381
+
382
+ // Alias props with defaults
383
+ let { count: counterValue = 0 } = counter.props
384
+
385
+ // Transforms to:
386
+ // let inc = counter.increment.bind(counter)
387
+ // let counterValue = $derived(counter.props.count ?? 0)
388
+ </script>
389
+ ```
390
+
391
+ ### Coexistence with $props()
392
+
393
+ When you have your own `$props()` and also use `$attrs.origin()`:
394
+
395
+ ```svelte
396
+ <script lang="ts">
397
+ import { Counter } from './counter.svelte'
398
+
399
+ let { myOwnProp = 'hello' } = $props()
400
+ let counter = $attrs.origin(Counter)
401
+
402
+ // Transforms to:
403
+ // let { myOwnProp = 'hello', ...___originAttrs } = $props()
404
+ // let counter = Counter(__attrsFor(Counter, ___originAttrs))
405
+ </script>
406
+ ```
407
+
316
408
  ## Attachments
317
409
 
318
410
  Origins can define **attachment methods** that run when an element is attached to the DOM. These are methods prefixed with `$` that receive the element and optionally return a cleanup function.
@@ -507,13 +599,13 @@ interface SvelteOriginFactory<TDef, TAllAttrs> {
507
599
 
508
600
  ```ts
509
601
  type SvelteOriginInstance<T> = {
510
- props: ReactiveAttrs<T['props']> // Or 'attrs' if that's what you named it
602
+ props: ReactiveAttrs<T['props']>
511
603
  super?: ParentInstance
512
604
  $attachments: SvelteOriginAttachments
513
605
  } & PublicMembers<T>
514
606
  ```
515
607
 
516
- **Note:** The `props`/`attrs` property name matches what you use in your origin definition.
608
+ **Note:** The property name `props` is the recommended convention for the props schema.
517
609
 
518
610
  ## Common Patterns
519
611
 
package/README.md CHANGED
@@ -121,8 +121,6 @@ svelteOrigin({
121
121
 
122
122
  Write origins in a file where runes are allowed (e.g. `.svelte.ts`).
123
123
 
124
- This README describes the **macro** style (preferred direction):
125
-
126
124
  ```ts
127
125
  // counter.svelte.ts
128
126
  export const Counter = $origin({
@@ -164,11 +162,11 @@ export const Counter = $origin({
164
162
  Notes:
165
163
 
166
164
  - `$origin(...)` is a **compile-time macro** provided by `svelte-origin` (not a Svelte rune)
167
- - `props: $attrs({...})` is also a macro in origin definitions
168
- - this uses `$attrs` to avoid conflict with Svelte's `$props()` rune
169
- - it compiles into the origin's prop schema and default/bindable handling
170
- - the property name (`props`) is arbitrary—you can name it `attrs`, `options`, or anything else
171
- - `$bindable(...)` inside `props: $attrs({...})` is treated as a marker (macro) and compiles away
165
+ - `props: $attrs({...})` defines the component props schema
166
+ - uses `$attrs` to avoid conflict with Svelte's `$props()` rune
167
+ - compiles into the origin's prop schema with defaults and bindable handling
168
+ - the property name (`props`) is the recommended convention
169
+ - `$bindable(...)` inside `props: $attrs({...})` marks props for two-way binding
172
170
  - `$state`/`$derived` are real Svelte runes
173
171
  - Properties prefixed with `_` (like `_incrementCount`) are private and not exposed on the instance type
174
172
 
@@ -393,6 +391,62 @@ svelte-package && svelte-origin post-process [dist-dir]
393
391
 
394
392
  See `svelte-origin --help` for all options.
395
393
 
394
+ ## Origin Destructuring
395
+
396
+ Destructure methods and props from origin instances with automatic handling:
397
+
398
+ ### Method Destructuring
399
+
400
+ Methods are automatically bound to preserve `this` context:
401
+
402
+ ```svelte
403
+ <script lang="ts">
404
+ import { Counter } from './counter.svelte'
405
+ let counter = $attrs.origin(Counter)
406
+
407
+ // Destructure methods - automatically bound
408
+ let { increment, decrement } = counter
409
+ </script>
410
+
411
+ <button onclick={increment}>+</button>
412
+ <button onclick={decrement}>-</button>
413
+ ```
414
+
415
+ ### Props Destructuring
416
+
417
+ Props are automatically wrapped in `$derived` for reactivity:
418
+
419
+ ```svelte
420
+ <script lang="ts">
421
+ import { Counter } from './counter.svelte'
422
+ let counter = $attrs.origin(Counter)
423
+
424
+ // Destructure props - automatically reactive
425
+ let { count, label } = counter.props
426
+ </script>
427
+
428
+ <p>{label}: {count}</p>
429
+ ```
430
+
431
+ ### Nested Destructuring
432
+
433
+ Combine method and props destructuring:
434
+
435
+ ```svelte
436
+ <script lang="ts">
437
+ let { increment, props: { count, label } } = counter
438
+ </script>
439
+ ```
440
+
441
+ ### Aliases and Defaults
442
+
443
+ ```svelte
444
+ <script lang="ts">
445
+ let { increment: inc } = counter
446
+ let { count: counterValue = 0 } = counter.props
447
+ </script>
448
+ ```
449
+
396
450
  ## Known limitations
397
451
 
398
452
  ### svelte-check type inference
package/dist/cli.js CHANGED
@@ -1551,11 +1551,93 @@ function findPropsInjectionPosition(source) {
1551
1551
  }
1552
1552
 
1553
1553
  // src/transform/attrs-schema.ts
1554
+ function stripLeadingComments(str) {
1555
+ let result = str.trim();
1556
+ while (true) {
1557
+ if (result.startsWith("/*")) {
1558
+ const endComment = result.indexOf("*/");
1559
+ if (endComment !== -1) {
1560
+ result = result.slice(endComment + 2).trim();
1561
+ continue;
1562
+ }
1563
+ break;
1564
+ }
1565
+ if (result.startsWith("//")) {
1566
+ const endLine = result.indexOf(`
1567
+ `);
1568
+ if (endLine !== -1) {
1569
+ result = result.slice(endLine + 1).trim();
1570
+ continue;
1571
+ }
1572
+ result = "";
1573
+ break;
1574
+ }
1575
+ break;
1576
+ }
1577
+ return result;
1578
+ }
1579
+ function stripTrailingComments(str) {
1580
+ let result = str.trim();
1581
+ let i = 0;
1582
+ let lastValidEnd = result.length;
1583
+ while (i < result.length) {
1584
+ const char = result[i];
1585
+ if (char === '"' || char === "'" || char === "`") {
1586
+ const quote = char;
1587
+ i++;
1588
+ while (i < result.length && result[i] !== quote) {
1589
+ if (result[i] === "\\")
1590
+ i++;
1591
+ i++;
1592
+ }
1593
+ i++;
1594
+ lastValidEnd = i;
1595
+ continue;
1596
+ }
1597
+ if (char === "{" || char === "(" || char === "[") {
1598
+ let depth = 1;
1599
+ i++;
1600
+ while (i < result.length && depth > 0) {
1601
+ const c = result[i];
1602
+ if (c === "{" || c === "(" || c === "[")
1603
+ depth++;
1604
+ else if (c === "}" || c === ")" || c === "]")
1605
+ depth--;
1606
+ else if (c === '"' || c === "'" || c === "`") {
1607
+ const quote = c;
1608
+ i++;
1609
+ while (i < result.length && result[i] !== quote) {
1610
+ if (result[i] === "\\")
1611
+ i++;
1612
+ i++;
1613
+ }
1614
+ }
1615
+ i++;
1616
+ }
1617
+ lastValidEnd = i;
1618
+ continue;
1619
+ }
1620
+ if (char === "/" && result[i + 1] === "*") {
1621
+ result = result.slice(0, i).trim();
1622
+ break;
1623
+ }
1624
+ if (char === "/" && result[i + 1] === "/") {
1625
+ result = result.slice(0, i).trim();
1626
+ break;
1627
+ }
1628
+ i++;
1629
+ lastValidEnd = i;
1630
+ }
1631
+ return result;
1632
+ }
1554
1633
  function generateAttrSchemaFromSource(attrsSource) {
1555
1634
  const entries = [];
1556
1635
  const attrs = splitAttrsSource(attrsSource);
1557
1636
  for (const attr of attrs) {
1558
- const trimmed = attr.trim();
1637
+ let trimmed = attr.trim();
1638
+ if (!trimmed)
1639
+ continue;
1640
+ trimmed = stripLeadingComments(trimmed);
1559
1641
  if (!trimmed)
1560
1642
  continue;
1561
1643
  const colonIndex = trimmed.indexOf(":");
@@ -1563,6 +1645,7 @@ function generateAttrSchemaFromSource(attrsSource) {
1563
1645
  continue;
1564
1646
  const key = trimmed.slice(0, colonIndex).trim();
1565
1647
  let value = trimmed.slice(colonIndex + 1).trim();
1648
+ value = stripTrailingComments(value);
1566
1649
  const asIndex = findTopLevelAs(value);
1567
1650
  if (asIndex !== -1) {
1568
1651
  value = value.slice(0, asIndex).trim();
@@ -1586,24 +1669,7 @@ function parseAttrsSource(attrsSource) {
1586
1669
  let trimmed = attr.trim();
1587
1670
  if (!trimmed)
1588
1671
  continue;
1589
- while (trimmed.startsWith("/*")) {
1590
- const endComment = trimmed.indexOf("*/");
1591
- if (endComment !== -1) {
1592
- trimmed = trimmed.slice(endComment + 2).trim();
1593
- } else {
1594
- break;
1595
- }
1596
- }
1597
- while (trimmed.startsWith("//")) {
1598
- const endLine = trimmed.indexOf(`
1599
- `);
1600
- if (endLine !== -1) {
1601
- trimmed = trimmed.slice(endLine + 1).trim();
1602
- } else {
1603
- trimmed = "";
1604
- break;
1605
- }
1606
- }
1672
+ trimmed = stripLeadingComments(trimmed);
1607
1673
  if (!trimmed)
1608
1674
  continue;
1609
1675
  const colonIndex = trimmed.indexOf(":");
@@ -1611,6 +1677,7 @@ function parseAttrsSource(attrsSource) {
1611
1677
  continue;
1612
1678
  const key = trimmed.slice(0, colonIndex).trim();
1613
1679
  let value = trimmed.slice(colonIndex + 1).trim();
1680
+ value = stripTrailingComments(value);
1614
1681
  const asIndex = findTopLevelAs(value);
1615
1682
  if (asIndex !== -1) {
1616
1683
  value = value.slice(0, asIndex).trim();
@@ -2554,6 +2621,7 @@ function parseAttrsContent(content) {
2554
2621
  continue;
2555
2622
  const key = trimmed.slice(0, colonIndex).trim();
2556
2623
  let value = trimmed.slice(colonIndex + 1).trim();
2624
+ value = stripTrailingComments2(value);
2557
2625
  const asIndex = findTopLevelAs(value);
2558
2626
  if (asIndex !== -1) {
2559
2627
  value = value.slice(0, asIndex).trim();
@@ -2661,6 +2729,56 @@ function stripComments(str) {
2661
2729
  }
2662
2730
  return result;
2663
2731
  }
2732
+ function stripTrailingComments2(str) {
2733
+ let result = str.trim();
2734
+ let i = 0;
2735
+ while (i < result.length) {
2736
+ const char = result[i];
2737
+ if (char === '"' || char === "'" || char === "`") {
2738
+ const quote = char;
2739
+ i++;
2740
+ while (i < result.length && result[i] !== quote) {
2741
+ if (result[i] === "\\")
2742
+ i++;
2743
+ i++;
2744
+ }
2745
+ i++;
2746
+ continue;
2747
+ }
2748
+ if (char === "{" || char === "(" || char === "[") {
2749
+ let depth = 1;
2750
+ i++;
2751
+ while (i < result.length && depth > 0) {
2752
+ const c = result[i];
2753
+ if (c === "{" || c === "(" || c === "[")
2754
+ depth++;
2755
+ else if (c === "}" || c === ")" || c === "]")
2756
+ depth--;
2757
+ else if (c === '"' || c === "'" || c === "`") {
2758
+ const quote = c;
2759
+ i++;
2760
+ while (i < result.length && result[i] !== quote) {
2761
+ if (result[i] === "\\")
2762
+ i++;
2763
+ i++;
2764
+ }
2765
+ }
2766
+ i++;
2767
+ }
2768
+ continue;
2769
+ }
2770
+ if (char === "/" && result[i + 1] === "*") {
2771
+ result = result.slice(0, i).trim();
2772
+ break;
2773
+ }
2774
+ if (char === "/" && result[i + 1] === "/") {
2775
+ result = result.slice(0, i).trim();
2776
+ break;
2777
+ }
2778
+ i++;
2779
+ }
2780
+ return result;
2781
+ }
2664
2782
  function generatePropsDestructuring(attrs, factoryName) {
2665
2783
  const parts = [];
2666
2784
  for (const attr of attrs) {
package/dist/index.js CHANGED
@@ -4162,6 +4162,7 @@ function parseAttrsContent(content) {
4162
4162
  continue;
4163
4163
  const key2 = trimmed.slice(0, colonIndex).trim();
4164
4164
  let value = trimmed.slice(colonIndex + 1).trim();
4165
+ value = stripTrailingComments(value);
4165
4166
  const asIndex = findTopLevelAs(value);
4166
4167
  if (asIndex !== -1) {
4167
4168
  value = value.slice(0, asIndex).trim();
@@ -4269,6 +4270,56 @@ function stripComments(str) {
4269
4270
  }
4270
4271
  return result;
4271
4272
  }
4273
+ function stripTrailingComments(str) {
4274
+ let result = str.trim();
4275
+ let i = 0;
4276
+ while (i < result.length) {
4277
+ const char = result[i];
4278
+ if (char === '"' || char === "'" || char === "`") {
4279
+ const quote = char;
4280
+ i++;
4281
+ while (i < result.length && result[i] !== quote) {
4282
+ if (result[i] === "\\")
4283
+ i++;
4284
+ i++;
4285
+ }
4286
+ i++;
4287
+ continue;
4288
+ }
4289
+ if (char === "{" || char === "(" || char === "[") {
4290
+ let depth = 1;
4291
+ i++;
4292
+ while (i < result.length && depth > 0) {
4293
+ const c = result[i];
4294
+ if (c === "{" || c === "(" || c === "[")
4295
+ depth++;
4296
+ else if (c === "}" || c === ")" || c === "]")
4297
+ depth--;
4298
+ else if (c === '"' || c === "'" || c === "`") {
4299
+ const quote = c;
4300
+ i++;
4301
+ while (i < result.length && result[i] !== quote) {
4302
+ if (result[i] === "\\")
4303
+ i++;
4304
+ i++;
4305
+ }
4306
+ }
4307
+ i++;
4308
+ }
4309
+ continue;
4310
+ }
4311
+ if (char === "/" && result[i + 1] === "*") {
4312
+ result = result.slice(0, i).trim();
4313
+ break;
4314
+ }
4315
+ if (char === "/" && result[i + 1] === "/") {
4316
+ result = result.slice(0, i).trim();
4317
+ break;
4318
+ }
4319
+ i++;
4320
+ }
4321
+ return result;
4322
+ }
4272
4323
  function generatePropsDestructuring(attrs, factoryName) {
4273
4324
  const parts = [];
4274
4325
  for (const attr2 of attrs) {
@@ -5859,11 +5910,93 @@ function findPropsInjectionPosition(source2) {
5859
5910
  }
5860
5911
 
5861
5912
  // src/transform/attrs-schema.ts
5913
+ function stripLeadingComments(str) {
5914
+ let result = str.trim();
5915
+ while (true) {
5916
+ if (result.startsWith("/*")) {
5917
+ const endComment = result.indexOf("*/");
5918
+ if (endComment !== -1) {
5919
+ result = result.slice(endComment + 2).trim();
5920
+ continue;
5921
+ }
5922
+ break;
5923
+ }
5924
+ if (result.startsWith("//")) {
5925
+ const endLine = result.indexOf(`
5926
+ `);
5927
+ if (endLine !== -1) {
5928
+ result = result.slice(endLine + 1).trim();
5929
+ continue;
5930
+ }
5931
+ result = "";
5932
+ break;
5933
+ }
5934
+ break;
5935
+ }
5936
+ return result;
5937
+ }
5938
+ function stripTrailingComments2(str) {
5939
+ let result = str.trim();
5940
+ let i = 0;
5941
+ let lastValidEnd = result.length;
5942
+ while (i < result.length) {
5943
+ const char = result[i];
5944
+ if (char === '"' || char === "'" || char === "`") {
5945
+ const quote = char;
5946
+ i++;
5947
+ while (i < result.length && result[i] !== quote) {
5948
+ if (result[i] === "\\")
5949
+ i++;
5950
+ i++;
5951
+ }
5952
+ i++;
5953
+ lastValidEnd = i;
5954
+ continue;
5955
+ }
5956
+ if (char === "{" || char === "(" || char === "[") {
5957
+ let depth = 1;
5958
+ i++;
5959
+ while (i < result.length && depth > 0) {
5960
+ const c = result[i];
5961
+ if (c === "{" || c === "(" || c === "[")
5962
+ depth++;
5963
+ else if (c === "}" || c === ")" || c === "]")
5964
+ depth--;
5965
+ else if (c === '"' || c === "'" || c === "`") {
5966
+ const quote = c;
5967
+ i++;
5968
+ while (i < result.length && result[i] !== quote) {
5969
+ if (result[i] === "\\")
5970
+ i++;
5971
+ i++;
5972
+ }
5973
+ }
5974
+ i++;
5975
+ }
5976
+ lastValidEnd = i;
5977
+ continue;
5978
+ }
5979
+ if (char === "/" && result[i + 1] === "*") {
5980
+ result = result.slice(0, i).trim();
5981
+ break;
5982
+ }
5983
+ if (char === "/" && result[i + 1] === "/") {
5984
+ result = result.slice(0, i).trim();
5985
+ break;
5986
+ }
5987
+ i++;
5988
+ lastValidEnd = i;
5989
+ }
5990
+ return result;
5991
+ }
5862
5992
  function generateAttrSchemaFromSource(attrsSource) {
5863
5993
  const entries = [];
5864
5994
  const attrs = splitAttrsSource(attrsSource);
5865
5995
  for (const attr2 of attrs) {
5866
- const trimmed = attr2.trim();
5996
+ let trimmed = attr2.trim();
5997
+ if (!trimmed)
5998
+ continue;
5999
+ trimmed = stripLeadingComments(trimmed);
5867
6000
  if (!trimmed)
5868
6001
  continue;
5869
6002
  const colonIndex = trimmed.indexOf(":");
@@ -5871,6 +6004,7 @@ function generateAttrSchemaFromSource(attrsSource) {
5871
6004
  continue;
5872
6005
  const key2 = trimmed.slice(0, colonIndex).trim();
5873
6006
  let value = trimmed.slice(colonIndex + 1).trim();
6007
+ value = stripTrailingComments2(value);
5874
6008
  const asIndex = findTopLevelAs(value);
5875
6009
  if (asIndex !== -1) {
5876
6010
  value = value.slice(0, asIndex).trim();
@@ -5894,24 +6028,7 @@ function parseAttrsSource(attrsSource) {
5894
6028
  let trimmed = attr2.trim();
5895
6029
  if (!trimmed)
5896
6030
  continue;
5897
- while (trimmed.startsWith("/*")) {
5898
- const endComment = trimmed.indexOf("*/");
5899
- if (endComment !== -1) {
5900
- trimmed = trimmed.slice(endComment + 2).trim();
5901
- } else {
5902
- break;
5903
- }
5904
- }
5905
- while (trimmed.startsWith("//")) {
5906
- const endLine = trimmed.indexOf(`
5907
- `);
5908
- if (endLine !== -1) {
5909
- trimmed = trimmed.slice(endLine + 1).trim();
5910
- } else {
5911
- trimmed = "";
5912
- break;
5913
- }
5914
- }
6031
+ trimmed = stripLeadingComments(trimmed);
5915
6032
  if (!trimmed)
5916
6033
  continue;
5917
6034
  const colonIndex = trimmed.indexOf(":");
@@ -5919,6 +6036,7 @@ function parseAttrsSource(attrsSource) {
5919
6036
  continue;
5920
6037
  const key2 = trimmed.slice(0, colonIndex).trim();
5921
6038
  let value = trimmed.slice(colonIndex + 1).trim();
6039
+ value = stripTrailingComments2(value);
5922
6040
  const asIndex = findTopLevelAs(value);
5923
6041
  if (asIndex !== -1) {
5924
6042
  value = value.slice(0, asIndex).trim();
package/dist/plugin.js CHANGED
@@ -1545,11 +1545,93 @@ function findPropsInjectionPosition(source) {
1545
1545
  }
1546
1546
 
1547
1547
  // src/transform/attrs-schema.ts
1548
+ function stripLeadingComments(str) {
1549
+ let result = str.trim();
1550
+ while (true) {
1551
+ if (result.startsWith("/*")) {
1552
+ const endComment = result.indexOf("*/");
1553
+ if (endComment !== -1) {
1554
+ result = result.slice(endComment + 2).trim();
1555
+ continue;
1556
+ }
1557
+ break;
1558
+ }
1559
+ if (result.startsWith("//")) {
1560
+ const endLine = result.indexOf(`
1561
+ `);
1562
+ if (endLine !== -1) {
1563
+ result = result.slice(endLine + 1).trim();
1564
+ continue;
1565
+ }
1566
+ result = "";
1567
+ break;
1568
+ }
1569
+ break;
1570
+ }
1571
+ return result;
1572
+ }
1573
+ function stripTrailingComments(str) {
1574
+ let result = str.trim();
1575
+ let i = 0;
1576
+ let lastValidEnd = result.length;
1577
+ while (i < result.length) {
1578
+ const char = result[i];
1579
+ if (char === '"' || char === "'" || char === "`") {
1580
+ const quote = char;
1581
+ i++;
1582
+ while (i < result.length && result[i] !== quote) {
1583
+ if (result[i] === "\\")
1584
+ i++;
1585
+ i++;
1586
+ }
1587
+ i++;
1588
+ lastValidEnd = i;
1589
+ continue;
1590
+ }
1591
+ if (char === "{" || char === "(" || char === "[") {
1592
+ let depth = 1;
1593
+ i++;
1594
+ while (i < result.length && depth > 0) {
1595
+ const c = result[i];
1596
+ if (c === "{" || c === "(" || c === "[")
1597
+ depth++;
1598
+ else if (c === "}" || c === ")" || c === "]")
1599
+ depth--;
1600
+ else if (c === '"' || c === "'" || c === "`") {
1601
+ const quote = c;
1602
+ i++;
1603
+ while (i < result.length && result[i] !== quote) {
1604
+ if (result[i] === "\\")
1605
+ i++;
1606
+ i++;
1607
+ }
1608
+ }
1609
+ i++;
1610
+ }
1611
+ lastValidEnd = i;
1612
+ continue;
1613
+ }
1614
+ if (char === "/" && result[i + 1] === "*") {
1615
+ result = result.slice(0, i).trim();
1616
+ break;
1617
+ }
1618
+ if (char === "/" && result[i + 1] === "/") {
1619
+ result = result.slice(0, i).trim();
1620
+ break;
1621
+ }
1622
+ i++;
1623
+ lastValidEnd = i;
1624
+ }
1625
+ return result;
1626
+ }
1548
1627
  function generateAttrSchemaFromSource(attrsSource) {
1549
1628
  const entries = [];
1550
1629
  const attrs = splitAttrsSource(attrsSource);
1551
1630
  for (const attr of attrs) {
1552
- const trimmed = attr.trim();
1631
+ let trimmed = attr.trim();
1632
+ if (!trimmed)
1633
+ continue;
1634
+ trimmed = stripLeadingComments(trimmed);
1553
1635
  if (!trimmed)
1554
1636
  continue;
1555
1637
  const colonIndex = trimmed.indexOf(":");
@@ -1557,6 +1639,7 @@ function generateAttrSchemaFromSource(attrsSource) {
1557
1639
  continue;
1558
1640
  const key = trimmed.slice(0, colonIndex).trim();
1559
1641
  let value = trimmed.slice(colonIndex + 1).trim();
1642
+ value = stripTrailingComments(value);
1560
1643
  const asIndex = findTopLevelAs(value);
1561
1644
  if (asIndex !== -1) {
1562
1645
  value = value.slice(0, asIndex).trim();
@@ -1580,24 +1663,7 @@ function parseAttrsSource(attrsSource) {
1580
1663
  let trimmed = attr.trim();
1581
1664
  if (!trimmed)
1582
1665
  continue;
1583
- while (trimmed.startsWith("/*")) {
1584
- const endComment = trimmed.indexOf("*/");
1585
- if (endComment !== -1) {
1586
- trimmed = trimmed.slice(endComment + 2).trim();
1587
- } else {
1588
- break;
1589
- }
1590
- }
1591
- while (trimmed.startsWith("//")) {
1592
- const endLine = trimmed.indexOf(`
1593
- `);
1594
- if (endLine !== -1) {
1595
- trimmed = trimmed.slice(endLine + 1).trim();
1596
- } else {
1597
- trimmed = "";
1598
- break;
1599
- }
1600
- }
1666
+ trimmed = stripLeadingComments(trimmed);
1601
1667
  if (!trimmed)
1602
1668
  continue;
1603
1669
  const colonIndex = trimmed.indexOf(":");
@@ -1605,6 +1671,7 @@ function parseAttrsSource(attrsSource) {
1605
1671
  continue;
1606
1672
  const key = trimmed.slice(0, colonIndex).trim();
1607
1673
  let value = trimmed.slice(colonIndex + 1).trim();
1674
+ value = stripTrailingComments(value);
1608
1675
  const asIndex = findTopLevelAs(value);
1609
1676
  if (asIndex !== -1) {
1610
1677
  value = value.slice(0, asIndex).trim();
@@ -2548,6 +2615,7 @@ function parseAttrsContent(content) {
2548
2615
  continue;
2549
2616
  const key = trimmed.slice(0, colonIndex).trim();
2550
2617
  let value = trimmed.slice(colonIndex + 1).trim();
2618
+ value = stripTrailingComments2(value);
2551
2619
  const asIndex = findTopLevelAs(value);
2552
2620
  if (asIndex !== -1) {
2553
2621
  value = value.slice(0, asIndex).trim();
@@ -2655,6 +2723,56 @@ function stripComments(str) {
2655
2723
  }
2656
2724
  return result;
2657
2725
  }
2726
+ function stripTrailingComments2(str) {
2727
+ let result = str.trim();
2728
+ let i = 0;
2729
+ while (i < result.length) {
2730
+ const char = result[i];
2731
+ if (char === '"' || char === "'" || char === "`") {
2732
+ const quote = char;
2733
+ i++;
2734
+ while (i < result.length && result[i] !== quote) {
2735
+ if (result[i] === "\\")
2736
+ i++;
2737
+ i++;
2738
+ }
2739
+ i++;
2740
+ continue;
2741
+ }
2742
+ if (char === "{" || char === "(" || char === "[") {
2743
+ let depth = 1;
2744
+ i++;
2745
+ while (i < result.length && depth > 0) {
2746
+ const c = result[i];
2747
+ if (c === "{" || c === "(" || c === "[")
2748
+ depth++;
2749
+ else if (c === "}" || c === ")" || c === "]")
2750
+ depth--;
2751
+ else if (c === '"' || c === "'" || c === "`") {
2752
+ const quote = c;
2753
+ i++;
2754
+ while (i < result.length && result[i] !== quote) {
2755
+ if (result[i] === "\\")
2756
+ i++;
2757
+ i++;
2758
+ }
2759
+ }
2760
+ i++;
2761
+ }
2762
+ continue;
2763
+ }
2764
+ if (char === "/" && result[i + 1] === "*") {
2765
+ result = result.slice(0, i).trim();
2766
+ break;
2767
+ }
2768
+ if (char === "/" && result[i + 1] === "/") {
2769
+ result = result.slice(0, i).trim();
2770
+ break;
2771
+ }
2772
+ i++;
2773
+ }
2774
+ return result;
2775
+ }
2658
2776
  function generatePropsDestructuring(attrs, factoryName) {
2659
2777
  const parts = [];
2660
2778
  for (const attr of attrs) {
@@ -1549,11 +1549,93 @@ function findPropsInjectionPosition(source) {
1549
1549
  }
1550
1550
 
1551
1551
  // src/transform/attrs-schema.ts
1552
+ function stripLeadingComments(str) {
1553
+ let result = str.trim();
1554
+ while (true) {
1555
+ if (result.startsWith("/*")) {
1556
+ const endComment = result.indexOf("*/");
1557
+ if (endComment !== -1) {
1558
+ result = result.slice(endComment + 2).trim();
1559
+ continue;
1560
+ }
1561
+ break;
1562
+ }
1563
+ if (result.startsWith("//")) {
1564
+ const endLine = result.indexOf(`
1565
+ `);
1566
+ if (endLine !== -1) {
1567
+ result = result.slice(endLine + 1).trim();
1568
+ continue;
1569
+ }
1570
+ result = "";
1571
+ break;
1572
+ }
1573
+ break;
1574
+ }
1575
+ return result;
1576
+ }
1577
+ function stripTrailingComments(str) {
1578
+ let result = str.trim();
1579
+ let i = 0;
1580
+ let lastValidEnd = result.length;
1581
+ while (i < result.length) {
1582
+ const char = result[i];
1583
+ if (char === '"' || char === "'" || char === "`") {
1584
+ const quote = char;
1585
+ i++;
1586
+ while (i < result.length && result[i] !== quote) {
1587
+ if (result[i] === "\\")
1588
+ i++;
1589
+ i++;
1590
+ }
1591
+ i++;
1592
+ lastValidEnd = i;
1593
+ continue;
1594
+ }
1595
+ if (char === "{" || char === "(" || char === "[") {
1596
+ let depth = 1;
1597
+ i++;
1598
+ while (i < result.length && depth > 0) {
1599
+ const c = result[i];
1600
+ if (c === "{" || c === "(" || c === "[")
1601
+ depth++;
1602
+ else if (c === "}" || c === ")" || c === "]")
1603
+ depth--;
1604
+ else if (c === '"' || c === "'" || c === "`") {
1605
+ const quote = c;
1606
+ i++;
1607
+ while (i < result.length && result[i] !== quote) {
1608
+ if (result[i] === "\\")
1609
+ i++;
1610
+ i++;
1611
+ }
1612
+ }
1613
+ i++;
1614
+ }
1615
+ lastValidEnd = i;
1616
+ continue;
1617
+ }
1618
+ if (char === "/" && result[i + 1] === "*") {
1619
+ result = result.slice(0, i).trim();
1620
+ break;
1621
+ }
1622
+ if (char === "/" && result[i + 1] === "/") {
1623
+ result = result.slice(0, i).trim();
1624
+ break;
1625
+ }
1626
+ i++;
1627
+ lastValidEnd = i;
1628
+ }
1629
+ return result;
1630
+ }
1552
1631
  function generateAttrSchemaFromSource(attrsSource) {
1553
1632
  const entries = [];
1554
1633
  const attrs = splitAttrsSource(attrsSource);
1555
1634
  for (const attr of attrs) {
1556
- const trimmed = attr.trim();
1635
+ let trimmed = attr.trim();
1636
+ if (!trimmed)
1637
+ continue;
1638
+ trimmed = stripLeadingComments(trimmed);
1557
1639
  if (!trimmed)
1558
1640
  continue;
1559
1641
  const colonIndex = trimmed.indexOf(":");
@@ -1561,6 +1643,7 @@ function generateAttrSchemaFromSource(attrsSource) {
1561
1643
  continue;
1562
1644
  const key = trimmed.slice(0, colonIndex).trim();
1563
1645
  let value = trimmed.slice(colonIndex + 1).trim();
1646
+ value = stripTrailingComments(value);
1564
1647
  const asIndex = findTopLevelAs(value);
1565
1648
  if (asIndex !== -1) {
1566
1649
  value = value.slice(0, asIndex).trim();
@@ -1584,24 +1667,7 @@ function parseAttrsSource(attrsSource) {
1584
1667
  let trimmed = attr.trim();
1585
1668
  if (!trimmed)
1586
1669
  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
- }
1670
+ trimmed = stripLeadingComments(trimmed);
1605
1671
  if (!trimmed)
1606
1672
  continue;
1607
1673
  const colonIndex = trimmed.indexOf(":");
@@ -1609,6 +1675,7 @@ function parseAttrsSource(attrsSource) {
1609
1675
  continue;
1610
1676
  const key = trimmed.slice(0, colonIndex).trim();
1611
1677
  let value = trimmed.slice(colonIndex + 1).trim();
1678
+ value = stripTrailingComments(value);
1612
1679
  const asIndex = findTopLevelAs(value);
1613
1680
  if (asIndex !== -1) {
1614
1681
  value = value.slice(0, asIndex).trim();
@@ -2552,6 +2619,7 @@ function parseAttrsContent(content) {
2552
2619
  continue;
2553
2620
  const key = trimmed.slice(0, colonIndex).trim();
2554
2621
  let value = trimmed.slice(colonIndex + 1).trim();
2622
+ value = stripTrailingComments2(value);
2555
2623
  const asIndex = findTopLevelAs(value);
2556
2624
  if (asIndex !== -1) {
2557
2625
  value = value.slice(0, asIndex).trim();
@@ -2659,6 +2727,56 @@ function stripComments(str) {
2659
2727
  }
2660
2728
  return result;
2661
2729
  }
2730
+ function stripTrailingComments2(str) {
2731
+ let result = str.trim();
2732
+ let i = 0;
2733
+ while (i < result.length) {
2734
+ const char = result[i];
2735
+ if (char === '"' || char === "'" || char === "`") {
2736
+ const quote = char;
2737
+ i++;
2738
+ while (i < result.length && result[i] !== quote) {
2739
+ if (result[i] === "\\")
2740
+ i++;
2741
+ i++;
2742
+ }
2743
+ i++;
2744
+ continue;
2745
+ }
2746
+ if (char === "{" || char === "(" || char === "[") {
2747
+ let depth = 1;
2748
+ i++;
2749
+ while (i < result.length && depth > 0) {
2750
+ const c = result[i];
2751
+ if (c === "{" || c === "(" || c === "[")
2752
+ depth++;
2753
+ else if (c === "}" || c === ")" || c === "]")
2754
+ depth--;
2755
+ else if (c === '"' || c === "'" || c === "`") {
2756
+ const quote = c;
2757
+ i++;
2758
+ while (i < result.length && result[i] !== quote) {
2759
+ if (result[i] === "\\")
2760
+ i++;
2761
+ i++;
2762
+ }
2763
+ }
2764
+ i++;
2765
+ }
2766
+ continue;
2767
+ }
2768
+ if (char === "/" && result[i + 1] === "*") {
2769
+ result = result.slice(0, i).trim();
2770
+ break;
2771
+ }
2772
+ if (char === "/" && result[i + 1] === "/") {
2773
+ result = result.slice(0, i).trim();
2774
+ break;
2775
+ }
2776
+ i++;
2777
+ }
2778
+ return result;
2779
+ }
2662
2780
  function generatePropsDestructuring(attrs, factoryName) {
2663
2781
  const parts = [];
2664
2782
  for (const attr of attrs) {
@@ -1545,11 +1545,93 @@ function findPropsInjectionPosition(source) {
1545
1545
  }
1546
1546
 
1547
1547
  // src/transform/attrs-schema.ts
1548
+ function stripLeadingComments(str) {
1549
+ let result = str.trim();
1550
+ while (true) {
1551
+ if (result.startsWith("/*")) {
1552
+ const endComment = result.indexOf("*/");
1553
+ if (endComment !== -1) {
1554
+ result = result.slice(endComment + 2).trim();
1555
+ continue;
1556
+ }
1557
+ break;
1558
+ }
1559
+ if (result.startsWith("//")) {
1560
+ const endLine = result.indexOf(`
1561
+ `);
1562
+ if (endLine !== -1) {
1563
+ result = result.slice(endLine + 1).trim();
1564
+ continue;
1565
+ }
1566
+ result = "";
1567
+ break;
1568
+ }
1569
+ break;
1570
+ }
1571
+ return result;
1572
+ }
1573
+ function stripTrailingComments(str) {
1574
+ let result = str.trim();
1575
+ let i = 0;
1576
+ let lastValidEnd = result.length;
1577
+ while (i < result.length) {
1578
+ const char = result[i];
1579
+ if (char === '"' || char === "'" || char === "`") {
1580
+ const quote = char;
1581
+ i++;
1582
+ while (i < result.length && result[i] !== quote) {
1583
+ if (result[i] === "\\")
1584
+ i++;
1585
+ i++;
1586
+ }
1587
+ i++;
1588
+ lastValidEnd = i;
1589
+ continue;
1590
+ }
1591
+ if (char === "{" || char === "(" || char === "[") {
1592
+ let depth = 1;
1593
+ i++;
1594
+ while (i < result.length && depth > 0) {
1595
+ const c = result[i];
1596
+ if (c === "{" || c === "(" || c === "[")
1597
+ depth++;
1598
+ else if (c === "}" || c === ")" || c === "]")
1599
+ depth--;
1600
+ else if (c === '"' || c === "'" || c === "`") {
1601
+ const quote = c;
1602
+ i++;
1603
+ while (i < result.length && result[i] !== quote) {
1604
+ if (result[i] === "\\")
1605
+ i++;
1606
+ i++;
1607
+ }
1608
+ }
1609
+ i++;
1610
+ }
1611
+ lastValidEnd = i;
1612
+ continue;
1613
+ }
1614
+ if (char === "/" && result[i + 1] === "*") {
1615
+ result = result.slice(0, i).trim();
1616
+ break;
1617
+ }
1618
+ if (char === "/" && result[i + 1] === "/") {
1619
+ result = result.slice(0, i).trim();
1620
+ break;
1621
+ }
1622
+ i++;
1623
+ lastValidEnd = i;
1624
+ }
1625
+ return result;
1626
+ }
1548
1627
  function generateAttrSchemaFromSource(attrsSource) {
1549
1628
  const entries = [];
1550
1629
  const attrs = splitAttrsSource(attrsSource);
1551
1630
  for (const attr of attrs) {
1552
- const trimmed = attr.trim();
1631
+ let trimmed = attr.trim();
1632
+ if (!trimmed)
1633
+ continue;
1634
+ trimmed = stripLeadingComments(trimmed);
1553
1635
  if (!trimmed)
1554
1636
  continue;
1555
1637
  const colonIndex = trimmed.indexOf(":");
@@ -1557,6 +1639,7 @@ function generateAttrSchemaFromSource(attrsSource) {
1557
1639
  continue;
1558
1640
  const key = trimmed.slice(0, colonIndex).trim();
1559
1641
  let value = trimmed.slice(colonIndex + 1).trim();
1642
+ value = stripTrailingComments(value);
1560
1643
  const asIndex = findTopLevelAs(value);
1561
1644
  if (asIndex !== -1) {
1562
1645
  value = value.slice(0, asIndex).trim();
@@ -1580,24 +1663,7 @@ function parseAttrsSource(attrsSource) {
1580
1663
  let trimmed = attr.trim();
1581
1664
  if (!trimmed)
1582
1665
  continue;
1583
- while (trimmed.startsWith("/*")) {
1584
- const endComment = trimmed.indexOf("*/");
1585
- if (endComment !== -1) {
1586
- trimmed = trimmed.slice(endComment + 2).trim();
1587
- } else {
1588
- break;
1589
- }
1590
- }
1591
- while (trimmed.startsWith("//")) {
1592
- const endLine = trimmed.indexOf(`
1593
- `);
1594
- if (endLine !== -1) {
1595
- trimmed = trimmed.slice(endLine + 1).trim();
1596
- } else {
1597
- trimmed = "";
1598
- break;
1599
- }
1600
- }
1666
+ trimmed = stripLeadingComments(trimmed);
1601
1667
  if (!trimmed)
1602
1668
  continue;
1603
1669
  const colonIndex = trimmed.indexOf(":");
@@ -1605,6 +1671,7 @@ function parseAttrsSource(attrsSource) {
1605
1671
  continue;
1606
1672
  const key = trimmed.slice(0, colonIndex).trim();
1607
1673
  let value = trimmed.slice(colonIndex + 1).trim();
1674
+ value = stripTrailingComments(value);
1608
1675
  const asIndex = findTopLevelAs(value);
1609
1676
  if (asIndex !== -1) {
1610
1677
  value = value.slice(0, asIndex).trim();
@@ -2548,6 +2615,7 @@ function parseAttrsContent(content) {
2548
2615
  continue;
2549
2616
  const key = trimmed.slice(0, colonIndex).trim();
2550
2617
  let value = trimmed.slice(colonIndex + 1).trim();
2618
+ value = stripTrailingComments2(value);
2551
2619
  const asIndex = findTopLevelAs(value);
2552
2620
  if (asIndex !== -1) {
2553
2621
  value = value.slice(0, asIndex).trim();
@@ -2655,6 +2723,56 @@ function stripComments(str) {
2655
2723
  }
2656
2724
  return result;
2657
2725
  }
2726
+ function stripTrailingComments2(str) {
2727
+ let result = str.trim();
2728
+ let i = 0;
2729
+ while (i < result.length) {
2730
+ const char = result[i];
2731
+ if (char === '"' || char === "'" || char === "`") {
2732
+ const quote = char;
2733
+ i++;
2734
+ while (i < result.length && result[i] !== quote) {
2735
+ if (result[i] === "\\")
2736
+ i++;
2737
+ i++;
2738
+ }
2739
+ i++;
2740
+ continue;
2741
+ }
2742
+ if (char === "{" || char === "(" || char === "[") {
2743
+ let depth = 1;
2744
+ i++;
2745
+ while (i < result.length && depth > 0) {
2746
+ const c = result[i];
2747
+ if (c === "{" || c === "(" || c === "[")
2748
+ depth++;
2749
+ else if (c === "}" || c === ")" || c === "]")
2750
+ depth--;
2751
+ else if (c === '"' || c === "'" || c === "`") {
2752
+ const quote = c;
2753
+ i++;
2754
+ while (i < result.length && result[i] !== quote) {
2755
+ if (result[i] === "\\")
2756
+ i++;
2757
+ i++;
2758
+ }
2759
+ }
2760
+ i++;
2761
+ }
2762
+ continue;
2763
+ }
2764
+ if (char === "/" && result[i + 1] === "*") {
2765
+ result = result.slice(0, i).trim();
2766
+ break;
2767
+ }
2768
+ if (char === "/" && result[i + 1] === "/") {
2769
+ result = result.slice(0, i).trim();
2770
+ break;
2771
+ }
2772
+ i++;
2773
+ }
2774
+ return result;
2775
+ }
2658
2776
  function generatePropsDestructuring(attrs, factoryName) {
2659
2777
  const parts = [];
2660
2778
  for (const attr of attrs) {
package/dist/vite-dts.js CHANGED
@@ -499,6 +499,7 @@ function parseAttrsContent(content) {
499
499
  continue;
500
500
  const key = trimmed.slice(0, colonIndex).trim();
501
501
  let value = trimmed.slice(colonIndex + 1).trim();
502
+ value = stripTrailingComments(value);
502
503
  const asIndex = findTopLevelAs(value);
503
504
  if (asIndex !== -1) {
504
505
  value = value.slice(0, asIndex).trim();
@@ -606,6 +607,56 @@ function stripComments(str) {
606
607
  }
607
608
  return result;
608
609
  }
610
+ function stripTrailingComments(str) {
611
+ let result = str.trim();
612
+ let i = 0;
613
+ while (i < result.length) {
614
+ const char = result[i];
615
+ if (char === '"' || char === "'" || char === "`") {
616
+ const quote = char;
617
+ i++;
618
+ while (i < result.length && result[i] !== quote) {
619
+ if (result[i] === "\\")
620
+ i++;
621
+ i++;
622
+ }
623
+ i++;
624
+ continue;
625
+ }
626
+ if (char === "{" || char === "(" || char === "[") {
627
+ let depth = 1;
628
+ i++;
629
+ while (i < result.length && depth > 0) {
630
+ const c = result[i];
631
+ if (c === "{" || c === "(" || c === "[")
632
+ depth++;
633
+ else if (c === "}" || c === ")" || c === "]")
634
+ depth--;
635
+ else if (c === '"' || c === "'" || c === "`") {
636
+ const quote = c;
637
+ i++;
638
+ while (i < result.length && result[i] !== quote) {
639
+ if (result[i] === "\\")
640
+ i++;
641
+ i++;
642
+ }
643
+ }
644
+ i++;
645
+ }
646
+ continue;
647
+ }
648
+ if (char === "/" && result[i + 1] === "*") {
649
+ result = result.slice(0, i).trim();
650
+ break;
651
+ }
652
+ if (char === "/" && result[i + 1] === "/") {
653
+ result = result.slice(0, i).trim();
654
+ break;
655
+ }
656
+ i++;
657
+ }
658
+ return result;
659
+ }
609
660
  function generatePropsDestructuring(attrs, factoryName) {
610
661
  const parts = [];
611
662
  for (const attr of attrs) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-origin",
3
- "version": "1.0.0-next.24",
3
+ "version": "1.0.0-next.25",
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",