Skip to content

Commit 6560d8d

Browse files
committed
adding all methods to global.d.ts and p5.d.ts
1 parent d10e150 commit 6560d8d

File tree

1 file changed

+166
-127
lines changed

1 file changed

+166
-127
lines changed

utils/generate-types.js

Lines changed: 166 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const organized = {
1212
consts: {}
1313
};
1414

15-
// Add this helper function at the top with other helpers
1615
function normalizeClassName(className) {
1716
if (!className || className === 'p5') return 'p5';
1817
return className.startsWith('p5.') ? className : `p5.${className}`;
@@ -25,136 +24,86 @@ function organizeData(data) {
2524

2625
// Process modules first
2726
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;
7781
}
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+
});
12683
return organized;
12784
}
12885

12986
// Helper function to get module info
13087
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+
};
14093
}
14194

14295
// Function to extract text from description object or string
14396
function extractDescription(desc) {
14497
if (!desc) return '';
14598
if (typeof desc === 'string') return desc;
14699
if (desc.children) {
147-
return desc.children
148-
.map(child => {
100+
return desc.children.map(child => {
149101
if (child.type === 'text') return child.value;
150102
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}\``;
153104
return '';
154105
})
155-
.join('')
156-
.trim()
157-
.replace(/\n{3,}/g, '\n\n');
106+
.join('').trim().replace(/\n{3,}/g, '\n\n');
158107
}
159108
return '';
160109
}
@@ -301,7 +250,7 @@ function generateFunctionDeclaration(funcDoc) {
301250
}
302251

303252
// Helper function to generate method declarations
304-
function generateMethodDeclarations(item, isStatic = false) {
253+
function generateMethodDeclarations(item, isStatic = false, isGlobal = false) {
305254
let output = '';
306255

307256
// Add JSDoc comment
@@ -425,11 +374,7 @@ function generateClassDeclaration(classDoc, organizedData) {
425374
// Generate declaration file for a group of items
426375
function generateDeclarationFile(items, filePath, organizedData) {
427376
let output = '// This file is auto-generated from JSDoc documentation\n\n';
428-
429-
// Add imports based on dependencies
430377
const imports = new Set([`import p5 from 'p5';`]);
431-
432-
// Check for dependencies
433378
const hasColorDependency = items.some(item => {
434379
const typeName = item.type?.name;
435380
const desc = extractDescription(item.description);
@@ -563,7 +508,7 @@ function groupByFile(items) {
563508
function generateAllDeclarationFiles() {
564509
// Organize all data first
565510
const organizedData = organizeData(data);
566-
511+
generateCoreTypeDefinitions(organizedData);
567512
// Group items by file
568513
const fileGroups = groupByFile(getAllEntries(data));
569514

@@ -575,19 +520,113 @@ function generateAllDeclarationFiles() {
575520
path.dirname(relativePath),
576521
`${parsedPath.name}.d.ts`
577522
);
578-
579-
// Generate the declaration file content
523+
580524
const declarationContent = generateDeclarationFile(items, filePath, organizedData);
581-
582-
// Create directory if it doesn't exist
583525
fs.mkdirSync(path.dirname(dtsPath), { recursive: true });
584-
585-
// Write the declaration file
586526
fs.writeFileSync(dtsPath, declarationContent, 'utf8');
587-
588527
console.log(`Generated ${dtsPath}`);
589528
});
590529
}
591530

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+
592631
// Run the generator
593632
generateAllDeclarationFiles();

0 commit comments

Comments
 (0)