@@ -279,7 +279,7 @@ export function migrate(source, { filename, use_ts } = {}) {
279
279
type = `interface ${ type_name } {${ newline_separator } ${ state . props
280
280
. map ( ( prop ) => {
281
281
const comment = prop . comment ? `${ prop . comment } ${ newline_separator } ` : '' ;
282
- return `${ comment } ${ prop . exported } ${ prop . optional ? '?' : '' } : ${ prop . type } ;` ;
282
+ return `${ comment } ${ prop . exported } ${ prop . optional ? '?' : '' } : ${ prop . type } ;${ prop . trailing_comment ? ' ' + prop . trailing_comment : '' } ` ;
283
283
} )
284
284
. join ( newline_separator ) } `;
285
285
if ( analysis . uses_props || analysis . uses_rest_props ) {
@@ -289,7 +289,7 @@ export function migrate(source, { filename, use_ts } = {}) {
289
289
} else {
290
290
type = `/**\n${ indent } * @typedef {Object} ${ type_name } ${ state . props
291
291
. map ( ( prop ) => {
292
- return `\n${ indent } * @property {${ prop . type } } ${ prop . optional ? `[${ prop . exported } ]` : prop . exported } ${ prop . comment ? ` - ${ prop . comment } ` : '' } ` ;
292
+ return `\n${ indent } * @property {${ prop . type } } ${ prop . optional ? `[${ prop . exported } ]` : prop . exported } ${ prop . comment ? ` - ${ prop . comment } ` : '' } ${ prop . trailing_comment ? ` - ${ prop . trailing_comment . trim ( ) } ` : '' } ` ;
293
293
} )
294
294
. join ( `` ) } \n${ indent } */`;
295
295
}
@@ -414,7 +414,7 @@ export function migrate(source, { filename, use_ts } = {}) {
414
414
* analysis: ComponentAnalysis;
415
415
* filename?: string;
416
416
* indent: string;
417
- * props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string; type_only?: boolean; needs_refine_type?: boolean; }>;
417
+ * props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string; trailing_comment?: string; type_only?: boolean; needs_refine_type?: boolean; }>;
418
418
* props_insertion_point: number;
419
419
* has_props_rune: boolean;
420
420
* has_type_or_fallback: boolean;
@@ -1497,13 +1497,28 @@ function extract_type_and_comment(declarator, state, path) {
1497
1497
str . update ( comment_start , comment_end , '' ) ;
1498
1498
}
1499
1499
1500
+ // Find trailing comments
1501
+ const trailing_comment_node = /** @type {Node } */ ( parent ) ?. trailingComments ?. at ( 0 ) ;
1502
+ const trailing_comment_start = /** @type {any } */ ( trailing_comment_node ) ?. start ;
1503
+ const trailing_comment_end = /** @type {any } */ ( trailing_comment_node ) ?. end ;
1504
+ let trailing_comment =
1505
+ trailing_comment_node && str . original . substring ( trailing_comment_start , trailing_comment_end ) ;
1506
+
1507
+ if ( trailing_comment_node ) {
1508
+ str . update ( trailing_comment_start , trailing_comment_end , '' ) ;
1509
+ }
1510
+
1500
1511
if ( declarator . id . typeAnnotation ) {
1501
1512
state . has_type_or_fallback = true ;
1502
1513
let start = declarator . id . typeAnnotation . start + 1 ; // skip the colon
1503
1514
while ( str . original [ start ] === ' ' ) {
1504
1515
start ++ ;
1505
1516
}
1506
- return { type : str . original . substring ( start , declarator . id . typeAnnotation . end ) , comment } ;
1517
+ return {
1518
+ type : str . original . substring ( start , declarator . id . typeAnnotation . end ) ,
1519
+ comment,
1520
+ trailing_comment
1521
+ } ;
1507
1522
}
1508
1523
1509
1524
let cleaned_comment_arr = comment
@@ -1526,12 +1541,43 @@ function extract_type_and_comment(declarator, state, path) {
1526
1541
?. slice ( 0 , first_at_comment !== - 1 ? first_at_comment : cleaned_comment_arr . length )
1527
1542
. join ( '\n' ) ;
1528
1543
1544
+ let cleaned_comment_arr_trailing = trailing_comment
1545
+ ?. split ( '\n' )
1546
+ . map ( ( line ) =>
1547
+ line
1548
+ . trim ( )
1549
+ // replace `// ` for one liners
1550
+ . replace ( / ^ \/ \/ \s * / g, '' )
1551
+ // replace `\**` for the initial JSDoc
1552
+ . replace ( / ^ \/ \* \* ? \s * / g, '' )
1553
+ // migrate `*/` for the end of JSDoc
1554
+ . replace ( / \s * \* \/ $ / g, '' )
1555
+ // remove any initial `* ` to clean the comment
1556
+ . replace ( / ^ \* \s * / g, '' )
1557
+ )
1558
+ . filter ( Boolean ) ;
1559
+ const first_at_comment_trailing = cleaned_comment_arr_trailing ?. findIndex ( ( line ) =>
1560
+ line . startsWith ( '@' )
1561
+ ) ;
1562
+ let cleaned_comment_trailing = cleaned_comment_arr_trailing
1563
+ ?. slice (
1564
+ 0 ,
1565
+ first_at_comment_trailing !== - 1
1566
+ ? first_at_comment_trailing
1567
+ : cleaned_comment_arr_trailing . length
1568
+ )
1569
+ . join ( '\n' ) ;
1570
+
1529
1571
// try to find a comment with a type annotation, hinting at jsdoc
1530
1572
if ( parent ?. type === 'ExportNamedDeclaration' && comment_node ) {
1531
1573
state . has_type_or_fallback = true ;
1532
1574
const match = / @ t y p e { ( .+ ) } / . exec ( comment_node . value ) ;
1533
1575
if ( match ) {
1534
- return { type : match [ 1 ] , comment : cleaned_comment } ;
1576
+ return {
1577
+ type : match [ 1 ] ,
1578
+ comment : cleaned_comment ,
1579
+ trailing_comment : cleaned_comment_trailing
1580
+ } ;
1535
1581
}
1536
1582
}
1537
1583
@@ -1540,11 +1586,19 @@ function extract_type_and_comment(declarator, state, path) {
1540
1586
state . has_type_or_fallback = true ; // only assume type if it's trivial to infer - else someone would've added a type annotation
1541
1587
const type = typeof declarator . init . value ;
1542
1588
if ( type === 'string' || type === 'number' || type === 'boolean' ) {
1543
- return { type, comment : state . uses_ts ? comment : cleaned_comment } ;
1589
+ return {
1590
+ type,
1591
+ comment : state . uses_ts ? comment : cleaned_comment ,
1592
+ trailing_comment : state . uses_ts ? trailing_comment : cleaned_comment_trailing
1593
+ } ;
1544
1594
}
1545
1595
}
1546
1596
1547
- return { type : 'any' , comment : state . uses_ts ? comment : cleaned_comment } ;
1597
+ return {
1598
+ type : 'any' ,
1599
+ comment : state . uses_ts ? comment : cleaned_comment ,
1600
+ trailing_comment : state . uses_ts ? trailing_comment : cleaned_comment_trailing
1601
+ } ;
1548
1602
}
1549
1603
1550
1604
// Ensure modifiers are applied in the same order as Svelte 4
@@ -1779,10 +1833,13 @@ function handle_identifier(node, state, path) {
1779
1833
comment = state . str . original . substring ( comment_node . start , comment_node . end ) ;
1780
1834
}
1781
1835
1836
+ const trailing_comment = member . trailingComments ?. at ( 0 ) ?. value ;
1837
+
1782
1838
if ( prop ) {
1783
1839
prop . type = type ;
1784
1840
prop . optional = member . optional ;
1785
1841
prop . comment = comment ?? prop . comment ;
1842
+ prop . trailing_comment = trailing_comment ?? prop . trailing_comment ;
1786
1843
} else {
1787
1844
state . props . push ( {
1788
1845
local : member . key . name ,
@@ -1792,6 +1849,7 @@ function handle_identifier(node, state, path) {
1792
1849
optional : member . optional ,
1793
1850
type,
1794
1851
comment,
1852
+ trailing_comment,
1795
1853
type_only : true
1796
1854
} ) ;
1797
1855
}
0 commit comments