@@ -4,6 +4,7 @@ import fs from 'node:fs';
44import * as acorn from 'acorn' ;
55import { walk } from 'zimmerframe' ;
66import * as esrap from 'esrap' ;
7+ import ts from 'esrap/languages/ts' ;
78
89const DIR = '../../documentation/docs/98-reference/.generated' ;
910
@@ -98,55 +99,18 @@ function run() {
9899 . replace ( / \r \n / g, '\n' ) ;
99100
100101 /**
101- * @type {Array<{
102- * type: string;
103- * value: string;
104- * start: number;
105- * end: number
106- * }>}
102+ * @type {any[] }
107103 */
108104 const comments = [ ] ;
109105
110106 let ast = acorn . parse ( source , {
111107 ecmaVersion : 'latest' ,
112108 sourceType : 'module' ,
113- onComment : ( block , value , start , end ) => {
114- if ( block && / \n / . test ( value ) ) {
115- let a = start ;
116- while ( a > 0 && source [ a - 1 ] !== '\n' ) a -= 1 ;
117-
118- let b = a ;
119- while ( / [ \t ] / . test ( source [ b ] ) ) b += 1 ;
120-
121- const indentation = source . slice ( a , b ) ;
122- value = value . replace ( new RegExp ( `^${ indentation } ` , 'gm' ) , '' ) ;
123- }
124-
125- comments . push ( { type : block ? 'Block' : 'Line' , value, start, end } ) ;
126- }
109+ locations : true ,
110+ onComment : comments
127111 } ) ;
128112
129113 ast = walk ( ast , null , {
130- _ ( node , { next } ) {
131- let comment ;
132-
133- while ( comments [ 0 ] && comments [ 0 ] . start < node . start ) {
134- comment = comments . shift ( ) ;
135- // @ts -expect-error
136- ( node . leadingComments ||= [ ] ) . push ( comment ) ;
137- }
138-
139- next ( ) ;
140-
141- if ( comments [ 0 ] ) {
142- const slice = source . slice ( node . end , comments [ 0 ] . start ) ;
143-
144- if ( / ^ [ , ) \t ] * $ / . test ( slice ) ) {
145- // @ts -expect-error
146- node . trailingComments = [ comments . shift ( ) ] ;
147- }
148- }
149- } ,
150114 // @ts -expect-error
151115 Identifier ( node , context ) {
152116 if ( node . name === 'CODES' ) {
@@ -161,11 +125,6 @@ function run() {
161125 }
162126 } ) ;
163127
164- if ( comments . length > 0 ) {
165- // @ts -expect-error
166- ( ast . trailingComments ||= [ ] ) . push ( ...comments ) ;
167- }
168-
169128 const category = messages [ name ] ;
170129
171130 // find the `export function CODE` node
@@ -184,6 +143,16 @@ function run() {
184143 const template_node = ast . body [ index ] ;
185144 ast . body . splice ( index , 1 ) ;
186145
146+ const jsdoc = comments . findLast ( ( comment ) => comment . start < template_node . start ) ;
147+
148+ const printed = esrap . print (
149+ ast ,
150+ // @ts -expect-error
151+ ts ( {
152+ comments : comments . filter ( ( comment ) => comment !== jsdoc )
153+ } )
154+ ) ;
155+
187156 for ( const code in category ) {
188157 const { messages } = category [ code ] ;
189158 /** @type {string[] } */
@@ -273,41 +242,6 @@ function run() {
273242 }
274243
275244 const clone = walk ( /** @type {import('estree').Node } */ ( template_node ) , null , {
276- // @ts -expect-error Block is a block comment, which is not recognised
277- Block ( node , context ) {
278- if ( ! node . value . includes ( 'PARAMETER' ) ) return ;
279-
280- const value = /** @type {string } */ ( node . value )
281- . split ( '\n' )
282- . map ( ( line ) => {
283- if ( line === ' * MESSAGE' ) {
284- return messages [ messages . length - 1 ]
285- . split ( '\n' )
286- . map ( ( line ) => ` * ${ line } ` )
287- . join ( '\n' ) ;
288- }
289-
290- if ( line . includes ( 'PARAMETER' ) ) {
291- return vars
292- . map ( ( name , i ) => {
293- const optional = i >= group [ 0 ] . vars . length ;
294-
295- return optional
296- ? ` * @param {string | undefined | null} [${ name } ]`
297- : ` * @param {string} ${ name } ` ;
298- } )
299- . join ( '\n' ) ;
300- }
301-
302- return line ;
303- } )
304- . filter ( ( x ) => x !== '' )
305- . join ( '\n' ) ;
306-
307- if ( value !== node . value ) {
308- return { ...node , value } ;
309- }
310- } ,
311245 FunctionDeclaration ( node , context ) {
312246 if ( node . id . name !== 'CODE' ) return ;
313247
@@ -394,16 +328,49 @@ function run() {
394328 }
395329 } ) ;
396330
331+ const jsdoc_clone = {
332+ ...jsdoc ,
333+ value : /** @type {string } */ ( jsdoc . value )
334+ . split ( '\n' )
335+ . map ( ( line ) => {
336+ if ( line === ' * MESSAGE' ) {
337+ return messages [ messages . length - 1 ]
338+ . split ( '\n' )
339+ . map ( ( line ) => ` * ${ line } ` )
340+ . join ( '\n' ) ;
341+ }
342+
343+ if ( line . includes ( 'PARAMETER' ) ) {
344+ return vars
345+ . map ( ( name , i ) => {
346+ const optional = i >= group [ 0 ] . vars . length ;
347+
348+ return optional
349+ ? ` * @param {string | undefined | null} [${ name } ]`
350+ : ` * @param {string} ${ name } ` ;
351+ } )
352+ . join ( '\n' ) ;
353+ }
354+
355+ return line ;
356+ } )
357+ . filter ( ( x ) => x !== '' )
358+ . join ( '\n' )
359+ } ;
360+
361+ // @ts -expect-error
362+ const block = esrap . print ( { ...ast , body : [ clone ] } , ts ( { comments : [ jsdoc_clone ] } ) ) . code ;
363+
364+ printed . code += `\n\n${ block } ` ;
365+
397366 // @ts -expect-error
398367 ast . body . push ( clone ) ;
399368 }
400369
401- const module = esrap . print ( ast ) ;
402-
403370 fs . writeFileSync (
404371 dest ,
405372 `/* This file is generated by scripts/process-messages/index.js. Do not edit! */\n\n` +
406- module . code ,
373+ printed . code ,
407374 'utf-8'
408375 ) ;
409376 }
0 commit comments