@@ -12,7 +12,6 @@ const organized = {
12
12
consts : { }
13
13
} ;
14
14
15
- // Add this helper function at the top with other helpers
16
15
function normalizeClassName ( className ) {
17
16
if ( ! className || className === 'p5' ) return 'p5' ;
18
17
return className . startsWith ( 'p5.' ) ? className : `p5.${ className } ` ;
@@ -25,136 +24,86 @@ function organizeData(data) {
25
24
26
25
// Process modules first
27
26
allData . forEach ( entry => {
28
- if ( entry . tags ?. some ( tag => tag . title === 'module' ) ) {
29
- const { module, submodule } = getModuleInfo ( entry ) ;
30
- organized . modules [ module ] = organized . modules [ module ] || {
31
- name : module ,
32
- submodules : { } ,
33
- classes : { }
34
- } ;
35
- if ( submodule ) {
36
- organized . modules [ module ] . submodules [ submodule ] = true ;
37
- }
38
- }
39
- } ) ;
40
-
41
- // Process classes
42
- allData . forEach ( entry => {
43
- if ( entry . kind === 'class' ) {
44
- const { module, submodule } = getModuleInfo ( entry ) ;
45
- const className = entry . name ;
46
- const extendsTag = entry . tags ?. find ( tag => tag . title === 'extends' ) ;
47
-
48
- organized . classes [ className ] = {
49
- name : className ,
50
- description : extractDescription ( entry . description ) ,
51
- params : ( entry . params || [ ] ) . map ( param => ( {
52
- name : param . name ,
53
- type : generateTypeFromTag ( param ) ,
54
- optional : param . type ?. type === 'OptionalType'
55
- } ) ) ,
56
- module,
57
- submodule,
58
- extends : extendsTag ?. name || null
59
- } ;
60
- }
61
- } ) ;
62
-
63
- // Process class methods and properties
64
- allData . forEach ( entry => {
65
- if ( entry . kind === 'function' || entry . kind === 'property' ) {
66
- const { module, submodule, forEntry } = getModuleInfo ( entry ) ;
67
-
68
- // Normalize memberof and forEntry
69
- let memberof = entry . memberof ;
70
- if ( memberof && memberof !== 'p5' && ! memberof . startsWith ( 'p5.' ) ) {
71
- memberof = 'p5.' + memberof ;
72
- }
73
-
74
- let normalizedForEntry = forEntry ;
75
- if ( forEntry && forEntry !== 'p5' && ! forEntry . startsWith ( 'p5.' ) ) {
76
- normalizedForEntry = 'p5.' + forEntry ;
27
+ const { module, submodule, forEntry } = getModuleInfo ( entry ) ;
28
+ const className = normalizeClassName ( forEntry || entry . memberof || 'p5' ) ;
29
+
30
+ switch ( entry . kind ) {
31
+ case 'class' :
32
+ organized . classes [ className ] = {
33
+ name : entry . name ,
34
+ description : extractDescription ( entry . description ) ,
35
+ params : ( entry . params || [ ] ) . map ( param => ( {
36
+ name : param . name ,
37
+ type : generateTypeFromTag ( param ) ,
38
+ optional : param . type ?. type === 'OptionalType'
39
+ } ) ) ,
40
+ module,
41
+ submodule,
42
+ extends : entry . tags ?. find ( tag => tag . title === 'extends' ) ?. name || null
43
+ } ; break ;
44
+ case 'function' :
45
+ case 'property' :
46
+ // Handle overloads
47
+ const overloads = entry . overloads ?. map ( overload => ( {
48
+ params : overload . params ,
49
+ returns : overload . returns ,
50
+ description : extractDescription ( overload . description )
51
+ } ) ) ;
52
+
53
+ organized . classitems . push ( {
54
+ name : entry . name ,
55
+ kind : entry . kind ,
56
+ description : extractDescription ( entry . description ) ,
57
+ params : ( entry . params || [ ] ) . map ( param => ( {
58
+ name : param . name ,
59
+ type : generateTypeFromTag ( param ) ,
60
+ optional : param . type ?. type === 'OptionalType'
61
+ } ) ) ,
62
+ returnType : entry . returns ?. [ 0 ] ? generateTypeFromTag ( entry . returns [ 0 ] ) : 'void' ,
63
+ module,
64
+ submodule,
65
+ class : className ,
66
+ isStatic : entry . path ?. [ 0 ] ?. scope === 'static' ,
67
+ overloads
68
+ } ) ; break ;
69
+ case 'constant' :
70
+ case 'typedef' :
71
+ organized . consts [ entry . name ] = {
72
+ name : entry . name ,
73
+ kind : entry . kind ,
74
+ description : extractDescription ( entry . description ) ,
75
+ // For constants, use P5.CONSTANT_NAME format
76
+ type : entry . kind === 'constant' ? `P5.${ entry . name . toUpperCase ( ) } ` : ( entry . type ? generateTypeFromTag ( entry ) : 'any' ) ,
77
+ module,
78
+ submodule,
79
+ class : forEntry || 'p5'
80
+ } ; break ;
77
81
}
78
-
79
- // Use memberof if available, fallback to forEntry, then default to 'p5'
80
- const className = normalizeClassName ( memberof || normalizedForEntry || 'p5' ) ;
81
-
82
- const isStatic = entry . path ?. [ 0 ] ?. scope === 'static' ;
83
- // Handle overloads
84
- const overloads = entry . overloads ?. map ( overload => ( {
85
- params : overload . params ,
86
- returns : overload . returns ,
87
- description : extractDescription ( overload . description )
88
- } ) ) ;
89
-
90
- organized . classitems . push ( {
91
- name : entry . name ,
92
- kind : entry . kind ,
93
- description : extractDescription ( entry . description ) ,
94
- params : ( entry . params || [ ] ) . map ( param => ( {
95
- name : param . name ,
96
- type : generateTypeFromTag ( param ) ,
97
- optional : param . type ?. type === 'OptionalType'
98
- } ) ) ,
99
- returnType : entry . returns ?. [ 0 ] ? generateTypeFromTag ( entry . returns [ 0 ] ) : 'void' ,
100
- module,
101
- submodule,
102
- class : className ,
103
- isStatic,
104
- overloads
105
- } ) ;
106
- }
107
- } ) ;
108
-
109
- // Process constants and typedefs
110
- allData . forEach ( entry => {
111
- if ( entry . kind === 'constant' || entry . kind === 'typedef' ) {
112
- const { module, submodule, forEntry } = getModuleInfo ( entry ) ;
113
- organized . consts [ entry . name ] = {
114
- name : entry . name ,
115
- kind : entry . kind ,
116
- description : extractDescription ( entry . description ) ,
117
- type : entry . type ? generateTypeFromTag ( entry ) : 'any' ,
118
- module,
119
- submodule,
120
- class : forEntry || 'p5'
121
- } ;
122
- }
123
- fs . writeFileSync ( "./consts.json" , JSON . stringify ( organized . consts , null , 2 ) , 'utf8' ) ;
124
- } ) ;
125
-
82
+ } ) ;
126
83
return organized ;
127
84
}
128
85
129
86
// Helper function to get module info
130
87
function getModuleInfo ( entry ) {
131
- const moduleTag = entry . tags ?. find ( tag => tag . title === 'module' ) ;
132
- const submoduleTag = entry . tags ?. find ( tag => tag . title === 'submodule' ) ;
133
- const forTag = entry . tags ?. find ( tag => tag . title === 'for' )
134
-
135
- return {
136
- module : moduleTag ?. name || 'p5' ,
137
- submodule : submoduleTag ?. description ,
138
- forEntry : forTag ?. description || entry . memberof
139
- } ;
88
+ return {
89
+ module : entry . tags ?. find ( tag => tag . title === 'module' ) ?. name || 'p5' ,
90
+ submodule : entry . tags ?. find ( tag => tag . title === 'submodule' ) ?. description || null ,
91
+ forEntry : entry . tags ?. find ( tag => tag . title === 'for' ) ?. description || entry . memberof
92
+ } ;
140
93
}
141
94
142
95
// Function to extract text from description object or string
143
96
function extractDescription ( desc ) {
144
97
if ( ! desc ) return '' ;
145
98
if ( typeof desc === 'string' ) return desc ;
146
99
if ( desc . children ) {
147
- return desc . children
148
- . map ( child => {
100
+ return desc . children . map ( child => {
149
101
if ( child . type === 'text' ) return child . value ;
150
102
if ( child . type === 'paragraph' ) return extractDescription ( child ) ;
151
- if ( child . type === 'inlineCode' ) return `\`${ child . value } \`` ;
152
- if ( child . type === 'code' ) return `\`${ child . value } \`` ;
103
+ if ( child . type === 'inlineCode' || child . type === 'code' ) return `\`${ child . value } \`` ;
153
104
return '' ;
154
105
} )
155
- . join ( '' )
156
- . trim ( )
157
- . replace ( / \n { 3 , } / g, '\n\n' ) ;
106
+ . join ( '' ) . trim ( ) . replace ( / \n { 3 , } / g, '\n\n' ) ;
158
107
}
159
108
return '' ;
160
109
}
@@ -301,7 +250,7 @@ function generateFunctionDeclaration(funcDoc) {
301
250
}
302
251
303
252
// Helper function to generate method declarations
304
- function generateMethodDeclarations ( item , isStatic = false ) {
253
+ function generateMethodDeclarations ( item , isStatic = false , isGlobal = false ) {
305
254
let output = '' ;
306
255
307
256
// Add JSDoc comment
@@ -425,11 +374,7 @@ function generateClassDeclaration(classDoc, organizedData) {
425
374
// Generate declaration file for a group of items
426
375
function generateDeclarationFile ( items , filePath , organizedData ) {
427
376
let output = '// This file is auto-generated from JSDoc documentation\n\n' ;
428
-
429
- // Add imports based on dependencies
430
377
const imports = new Set ( [ `import p5 from 'p5';` ] ) ;
431
-
432
- // Check for dependencies
433
378
const hasColorDependency = items . some ( item => {
434
379
const typeName = item . type ?. name ;
435
380
const desc = extractDescription ( item . description ) ;
@@ -563,7 +508,7 @@ function groupByFile(items) {
563
508
function generateAllDeclarationFiles ( ) {
564
509
// Organize all data first
565
510
const organizedData = organizeData ( data ) ;
566
-
511
+ generateCoreTypeDefinitions ( organizedData ) ;
567
512
// Group items by file
568
513
const fileGroups = groupByFile ( getAllEntries ( data ) ) ;
569
514
@@ -575,19 +520,113 @@ function generateAllDeclarationFiles() {
575
520
path . dirname ( relativePath ) ,
576
521
`${ parsedPath . name } .d.ts`
577
522
) ;
578
-
579
- // Generate the declaration file content
523
+
580
524
const declarationContent = generateDeclarationFile ( items , filePath , organizedData ) ;
581
-
582
- // Create directory if it doesn't exist
583
525
fs . mkdirSync ( path . dirname ( dtsPath ) , { recursive : true } ) ;
584
-
585
- // Write the declaration file
586
526
fs . writeFileSync ( dtsPath , declarationContent , 'utf8' ) ;
587
-
588
527
console . log ( `Generated ${ dtsPath } ` ) ;
589
528
} ) ;
590
529
}
591
530
531
+ function generateCoreTypeDefinitions ( organizedData ) {
532
+ // Generate p5.d.ts
533
+ let p5Output = '// This file is auto-generated from JSDoc documentation\n\n' ;
534
+
535
+ // Generate the p5 class
536
+ p5Output += `declare class p5 {\n` ;
537
+ p5Output += ` constructor(sketch?: (p: p5) => void, node?: HTMLElement, sync?: boolean);\n\n` ;
538
+
539
+ // Add instance methods
540
+ const instanceItems = organizedData . classitems . filter ( item =>
541
+ item . class === 'p5' && ! item . isStatic
542
+ ) ;
543
+ instanceItems . forEach ( item => {
544
+ p5Output += generateMethodDeclarations ( item , false ) ;
545
+ } ) ;
546
+
547
+ // Add static methods
548
+ const staticItems = organizedData . classitems . filter ( item =>
549
+ item . class === 'p5' && item . isStatic
550
+ ) ;
551
+ staticItems . forEach ( item => {
552
+ p5Output += generateMethodDeclarations ( item , true ) ;
553
+ } ) ;
554
+
555
+ // Add static constants
556
+ Object . values ( organizedData . consts ) . forEach ( constData => {
557
+ if ( constData . class === 'p5' ) {
558
+ if ( constData . description ) {
559
+ p5Output += ` /**\n * ${ constData . description } \n */\n` ;
560
+ }
561
+ if ( constData . kind === 'constant' ) {
562
+ p5Output += ` readonly ${ constData . name . toUpperCase ( ) } : ${ constData . type } ;\n\n` ;
563
+ } else {
564
+ p5Output += ` static ${ constData . name } : ${ constData . type } ;\n\n` ;
565
+ }
566
+ }
567
+ } ) ;
568
+
569
+ p5Output += `}\n\n` ;
570
+
571
+ // Add namespace for additional classes and types
572
+ p5Output += `declare namespace p5 {\n` ;
573
+
574
+ // Add type definitions
575
+ Object . values ( organizedData . consts ) . forEach ( constData => {
576
+ if ( constData . kind === 'typedef' ) {
577
+ if ( constData . description ) {
578
+ p5Output += ` /**\n * ${ constData . description } \n */\n` ;
579
+ }
580
+ p5Output += ` type ${ constData . name } = ${ constData . type } ;\n\n` ;
581
+ }
582
+ } ) ;
583
+
584
+ // Add other classes (like Graphics, Vector, etc)
585
+ Object . values ( organizedData . classes ) . forEach ( classDoc => {
586
+ if ( classDoc . name !== 'p5' ) {
587
+ p5Output += generateClassDeclaration ( classDoc , organizedData ) ;
588
+ }
589
+ } ) ;
590
+ p5Output += `}\n\n` ;
591
+
592
+ p5Output += `export default p5;\n` ;
593
+ p5Output += `export as namespace p5;\n` ;
594
+
595
+ // Generate global.d.ts
596
+ let globalOutput = '// This file is auto-generated from JSDoc documentation\n\n' ;
597
+ globalOutput += `import p5 from 'p5';\n\n` ;
598
+ globalOutput += `declare global {\n` ;
599
+ globalOutput += ` interface Window {\n` ;
600
+
601
+
602
+ // Add instance methods
603
+ instanceItems . forEach ( item => {
604
+ globalOutput += generateMethodDeclarations ( item ) ;
605
+ } ) ;
606
+
607
+ // Add constants to global scope
608
+ Object . values ( organizedData . consts ) . forEach ( constData => {
609
+ if ( constData . kind === 'constant' ) {
610
+ if ( constData . description ) {
611
+ globalOutput += ` /**\n * ${ constData . description } \n */\n` ;
612
+ }
613
+ globalOutput += ` readonly ${ constData . name . toUpperCase ( ) } : ${ constData . type } ;\n\n` ;
614
+ }
615
+ } ) ;
616
+
617
+ globalOutput += ` }\n` ;
618
+ globalOutput += `}\n\n` ;
619
+ globalOutput += `export {};\n` ;
620
+
621
+ // Create types directory if it doesn't exist
622
+ const typesDir = path . join ( process . cwd ( ) , 'types' ) ;
623
+ fs . mkdirSync ( typesDir , { recursive : true } ) ;
624
+
625
+ // Write the files
626
+ fs . writeFileSync ( path . join ( typesDir , 'p5.d.ts' ) , p5Output , 'utf8' ) ;
627
+ fs . writeFileSync ( path . join ( typesDir , 'global.d.ts' ) , globalOutput , 'utf8' ) ;
628
+ }
629
+
630
+
592
631
// Run the generator
593
632
generateAllDeclarationFiles ( ) ;
0 commit comments