@openwebf/webf 0.22.5 → 0.22.8
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/dist/analyzer.js +117 -17
- package/dist/commands.js +25 -6
- package/dist/react.js +47 -2
- package/package.json +3 -1
- package/src/analyzer.ts +145 -10
- package/src/commands.ts +29 -5
- package/src/declaration.ts +2 -0
- package/src/react.ts +53 -4
- package/templates/react.component.tsx.tpl +57 -6
- package/test/union-types-jsdoc.test.ts +168 -0
- package/dist/analyzer_original.js +0 -467
package/dist/analyzer.js
CHANGED
|
@@ -37,12 +37,15 @@ exports.analyzer = analyzer;
|
|
|
37
37
|
exports.buildClassRelationship = buildClassRelationship;
|
|
38
38
|
exports.clearCaches = clearCaches;
|
|
39
39
|
const typescript_1 = __importStar(require("typescript"));
|
|
40
|
+
const tsdoc_1 = require("@microsoft/tsdoc");
|
|
40
41
|
const declaration_1 = require("./declaration");
|
|
41
42
|
const utils_1 = require("./utils");
|
|
42
43
|
// Cache for parsed source files to avoid re-parsing
|
|
43
44
|
const sourceFileCache = new Map();
|
|
44
45
|
// Cache for type conversions to avoid redundant processing
|
|
45
46
|
const typeConversionCache = new Map();
|
|
47
|
+
// TSDoc parser instance
|
|
48
|
+
const tsdocParser = new tsdoc_1.TSDocParser();
|
|
46
49
|
// Type mapping constants for better performance
|
|
47
50
|
const BASIC_TYPE_MAP = {
|
|
48
51
|
[typescript_1.default.SyntaxKind.StringKeyword]: declaration_1.FunctionArgumentType.dom_string,
|
|
@@ -72,7 +75,7 @@ function analyzer(blob, definedPropertyCollector, unionTypeCollector) {
|
|
|
72
75
|
blob.objects = sourceFile.statements
|
|
73
76
|
.map(statement => {
|
|
74
77
|
try {
|
|
75
|
-
return walkProgram(blob, statement, definedPropertyCollector, unionTypeCollector);
|
|
78
|
+
return walkProgram(blob, statement, sourceFile, definedPropertyCollector, unionTypeCollector);
|
|
76
79
|
}
|
|
77
80
|
catch (error) {
|
|
78
81
|
console.error(`Error processing statement in ${blob.source}:`, error);
|
|
@@ -106,6 +109,93 @@ function getInterfaceName(statement) {
|
|
|
106
109
|
}
|
|
107
110
|
return statement.name.escapedText;
|
|
108
111
|
}
|
|
112
|
+
function getJSDocComment(node, sourceFile) {
|
|
113
|
+
const sourceText = sourceFile.getFullText();
|
|
114
|
+
const nodeStart = node.getFullStart();
|
|
115
|
+
const nodePos = node.getStart(sourceFile);
|
|
116
|
+
// Get the text between full start and actual start (includes leading trivia)
|
|
117
|
+
const leadingText = sourceText.substring(nodeStart, nodePos);
|
|
118
|
+
// Find JSDoc comment in the leading text
|
|
119
|
+
const jsDocMatch = leadingText.match(/\/\*\*([\s\S]*?)\*\/\s*$/);
|
|
120
|
+
if (!jsDocMatch)
|
|
121
|
+
return undefined;
|
|
122
|
+
// Extract the full JSDoc comment including delimiters
|
|
123
|
+
const commentText = jsDocMatch[0];
|
|
124
|
+
const commentStartPos = nodeStart + leadingText.lastIndexOf(commentText);
|
|
125
|
+
// Create a TextRange for the comment
|
|
126
|
+
const textRange = tsdoc_1.TextRange.fromStringRange(sourceText, commentStartPos, commentStartPos + commentText.length);
|
|
127
|
+
// Parse the JSDoc comment using TSDoc
|
|
128
|
+
const parserContext = tsdocParser.parseRange(textRange);
|
|
129
|
+
const docComment = parserContext.docComment;
|
|
130
|
+
// For now, always use the raw comment to preserve all tags including @default
|
|
131
|
+
// TSDoc parser doesn't handle @default tags properly out of the box
|
|
132
|
+
// Fallback to raw comment if TSDoc parsing fails
|
|
133
|
+
const comment = jsDocMatch[1]
|
|
134
|
+
.split('\n')
|
|
135
|
+
.map(line => line.replace(/^\s*\*\s?/, ''))
|
|
136
|
+
.join('\n')
|
|
137
|
+
.trim();
|
|
138
|
+
return comment || undefined;
|
|
139
|
+
}
|
|
140
|
+
// Helper function to render TSDoc nodes to string
|
|
141
|
+
function renderDocNodes(nodes) {
|
|
142
|
+
return nodes.map(node => {
|
|
143
|
+
if (node.kind === 'PlainText') {
|
|
144
|
+
return node.text;
|
|
145
|
+
}
|
|
146
|
+
else if (node.kind === 'SoftBreak') {
|
|
147
|
+
return '\n';
|
|
148
|
+
}
|
|
149
|
+
else if (node.kind === 'Paragraph') {
|
|
150
|
+
return renderDocNodes(node.nodes);
|
|
151
|
+
}
|
|
152
|
+
return '';
|
|
153
|
+
}).join('').trim();
|
|
154
|
+
}
|
|
155
|
+
// Special function to get the first JSDoc comment in a file for the first interface
|
|
156
|
+
function getFirstInterfaceJSDoc(statement, sourceFile) {
|
|
157
|
+
// Find all interfaces in the file
|
|
158
|
+
const interfaces = [];
|
|
159
|
+
typescript_1.default.forEachChild(sourceFile, child => {
|
|
160
|
+
if (typescript_1.default.isInterfaceDeclaration(child)) {
|
|
161
|
+
interfaces.push(child);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
// If this is the first interface, check for a file-level JSDoc
|
|
165
|
+
if (interfaces.length > 0 && interfaces[0] === statement) {
|
|
166
|
+
const sourceText = sourceFile.getFullText();
|
|
167
|
+
const firstInterfacePos = statement.getFullStart();
|
|
168
|
+
// Get all text before the first interface
|
|
169
|
+
const textBeforeInterface = sourceText.substring(0, firstInterfacePos);
|
|
170
|
+
// Find the last JSDoc comment before the interface
|
|
171
|
+
const jsDocMatches = textBeforeInterface.match(/\/\*\*([\s\S]*?)\*\//g);
|
|
172
|
+
if (jsDocMatches && jsDocMatches.length > 0) {
|
|
173
|
+
const lastJsDoc = jsDocMatches[jsDocMatches.length - 1];
|
|
174
|
+
const commentStartPos = textBeforeInterface.lastIndexOf(lastJsDoc);
|
|
175
|
+
// Create a TextRange for the comment
|
|
176
|
+
const textRange = tsdoc_1.TextRange.fromStringRange(sourceText, commentStartPos, commentStartPos + lastJsDoc.length);
|
|
177
|
+
// Parse the JSDoc comment using TSDoc
|
|
178
|
+
const parserContext = tsdocParser.parseRange(textRange);
|
|
179
|
+
const docComment = parserContext.docComment;
|
|
180
|
+
// Extract the parsed content
|
|
181
|
+
if (docComment.summarySection) {
|
|
182
|
+
const summary = renderDocNodes(docComment.summarySection.nodes);
|
|
183
|
+
if (summary)
|
|
184
|
+
return summary;
|
|
185
|
+
}
|
|
186
|
+
// Fallback to raw comment
|
|
187
|
+
const comment = lastJsDoc
|
|
188
|
+
.replace(/^\/\*\*/, '')
|
|
189
|
+
.replace(/\*\/$/, '')
|
|
190
|
+
.split('\n')
|
|
191
|
+
.map(line => line.replace(/^\s*\*\s?/, ''))
|
|
192
|
+
.join('\n')
|
|
193
|
+
.trim();
|
|
194
|
+
return comment || undefined;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
109
199
|
function getHeritageType(heritage) {
|
|
110
200
|
if (!heritage.types.length)
|
|
111
201
|
return null;
|
|
@@ -210,11 +300,15 @@ function getParameterBaseType(type, mode) {
|
|
|
210
300
|
}
|
|
211
301
|
}
|
|
212
302
|
if (type.kind === typescript_1.default.SyntaxKind.LiteralType) {
|
|
213
|
-
// Handle literal types
|
|
303
|
+
// Handle literal types
|
|
214
304
|
const literalType = type;
|
|
215
305
|
if (literalType.literal.kind === typescript_1.default.SyntaxKind.NullKeyword) {
|
|
216
306
|
return declaration_1.FunctionArgumentType.null;
|
|
217
307
|
}
|
|
308
|
+
if (literalType.literal.kind === typescript_1.default.SyntaxKind.StringLiteral) {
|
|
309
|
+
// Return the string literal value itself
|
|
310
|
+
return literalType.literal.text;
|
|
311
|
+
}
|
|
218
312
|
return declaration_1.FunctionArgumentType.any;
|
|
219
313
|
}
|
|
220
314
|
return declaration_1.FunctionArgumentType.any;
|
|
@@ -379,10 +473,10 @@ function isParamsReadOnly(m) {
|
|
|
379
473
|
return false;
|
|
380
474
|
return m.modifiers.some(k => k.kind === typescript_1.default.SyntaxKind.ReadonlyKeyword);
|
|
381
475
|
}
|
|
382
|
-
function walkProgram(blob, statement, definedPropertyCollector, unionTypeCollector) {
|
|
476
|
+
function walkProgram(blob, statement, sourceFile, definedPropertyCollector, unionTypeCollector) {
|
|
383
477
|
switch (statement.kind) {
|
|
384
478
|
case typescript_1.default.SyntaxKind.InterfaceDeclaration:
|
|
385
|
-
return processInterfaceDeclaration(statement, blob, definedPropertyCollector, unionTypeCollector);
|
|
479
|
+
return processInterfaceDeclaration(statement, blob, sourceFile, definedPropertyCollector, unionTypeCollector);
|
|
386
480
|
case typescript_1.default.SyntaxKind.VariableStatement:
|
|
387
481
|
return processVariableStatement(statement, unionTypeCollector);
|
|
388
482
|
case typescript_1.default.SyntaxKind.TypeAliasDeclaration:
|
|
@@ -399,9 +493,13 @@ function processTypeAliasDeclaration(statement, blob) {
|
|
|
399
493
|
typeAlias.type = printer.printNode(typescript_1.default.EmitHint.Unspecified, statement.type, statement.getSourceFile());
|
|
400
494
|
return typeAlias;
|
|
401
495
|
}
|
|
402
|
-
function processInterfaceDeclaration(statement, blob, definedPropertyCollector, unionTypeCollector) {
|
|
496
|
+
function processInterfaceDeclaration(statement, blob, sourceFile, definedPropertyCollector, unionTypeCollector) {
|
|
403
497
|
const interfaceName = statement.name.escapedText.toString();
|
|
404
498
|
const obj = new declaration_1.ClassObject();
|
|
499
|
+
// Capture JSDoc comment for the interface
|
|
500
|
+
const directComment = getJSDocComment(statement, sourceFile);
|
|
501
|
+
const fileComment = getFirstInterfaceJSDoc(statement, sourceFile);
|
|
502
|
+
obj.documentation = directComment || fileComment;
|
|
405
503
|
// Process heritage clauses
|
|
406
504
|
if (statement.heritageClauses) {
|
|
407
505
|
const heritage = statement.heritageClauses[0];
|
|
@@ -420,40 +518,41 @@ function processInterfaceDeclaration(statement, blob, definedPropertyCollector,
|
|
|
420
518
|
}
|
|
421
519
|
// Process members in batches for better performance
|
|
422
520
|
const members = Array.from(statement.members);
|
|
423
|
-
processMembersBatch(members, obj, definedPropertyCollector, unionTypeCollector);
|
|
521
|
+
processMembersBatch(members, obj, sourceFile, definedPropertyCollector, unionTypeCollector);
|
|
424
522
|
declaration_1.ClassObject.globalClassMap[interfaceName] = obj;
|
|
425
523
|
return obj;
|
|
426
524
|
}
|
|
427
|
-
function processMembersBatch(members, obj, definedPropertyCollector, unionTypeCollector) {
|
|
525
|
+
function processMembersBatch(members, obj, sourceFile, definedPropertyCollector, unionTypeCollector) {
|
|
428
526
|
for (const member of members) {
|
|
429
527
|
try {
|
|
430
|
-
processMember(member, obj, definedPropertyCollector, unionTypeCollector);
|
|
528
|
+
processMember(member, obj, sourceFile, definedPropertyCollector, unionTypeCollector);
|
|
431
529
|
}
|
|
432
530
|
catch (error) {
|
|
433
531
|
console.error(`Error processing member:`, error);
|
|
434
532
|
}
|
|
435
533
|
}
|
|
436
534
|
}
|
|
437
|
-
function processMember(member, obj, definedPropertyCollector, unionTypeCollector) {
|
|
535
|
+
function processMember(member, obj, sourceFile, definedPropertyCollector, unionTypeCollector) {
|
|
438
536
|
switch (member.kind) {
|
|
439
537
|
case typescript_1.default.SyntaxKind.PropertySignature:
|
|
440
|
-
processPropertySignature(member, obj, definedPropertyCollector, unionTypeCollector);
|
|
538
|
+
processPropertySignature(member, obj, sourceFile, definedPropertyCollector, unionTypeCollector);
|
|
441
539
|
break;
|
|
442
540
|
case typescript_1.default.SyntaxKind.MethodSignature:
|
|
443
|
-
processMethodSignature(member, obj, unionTypeCollector);
|
|
541
|
+
processMethodSignature(member, obj, sourceFile, unionTypeCollector);
|
|
444
542
|
break;
|
|
445
543
|
case typescript_1.default.SyntaxKind.IndexSignature:
|
|
446
|
-
processIndexSignature(member, obj, unionTypeCollector);
|
|
544
|
+
processIndexSignature(member, obj, sourceFile, unionTypeCollector);
|
|
447
545
|
break;
|
|
448
546
|
case typescript_1.default.SyntaxKind.ConstructSignature:
|
|
449
|
-
processConstructSignature(member, obj, unionTypeCollector);
|
|
547
|
+
processConstructSignature(member, obj, sourceFile, unionTypeCollector);
|
|
450
548
|
break;
|
|
451
549
|
}
|
|
452
550
|
}
|
|
453
|
-
function processPropertySignature(member, obj, definedPropertyCollector, unionTypeCollector) {
|
|
551
|
+
function processPropertySignature(member, obj, sourceFile, definedPropertyCollector, unionTypeCollector) {
|
|
454
552
|
const prop = new declaration_1.PropsDeclaration();
|
|
455
553
|
prop.name = getPropName(member.name, prop);
|
|
456
554
|
prop.readonly = isParamsReadOnly(member);
|
|
555
|
+
prop.documentation = getJSDocComment(member, sourceFile);
|
|
457
556
|
definedPropertyCollector.properties.add(prop.name);
|
|
458
557
|
if (!member.type) {
|
|
459
558
|
console.warn(`Property ${prop.name} has no type annotation`);
|
|
@@ -491,10 +590,11 @@ function createAsyncProperty(prop, mode) {
|
|
|
491
590
|
};
|
|
492
591
|
return asyncProp;
|
|
493
592
|
}
|
|
494
|
-
function processMethodSignature(member, obj, unionTypeCollector) {
|
|
593
|
+
function processMethodSignature(member, obj, sourceFile, unionTypeCollector) {
|
|
495
594
|
var _a;
|
|
496
595
|
const f = new declaration_1.FunctionDeclaration();
|
|
497
596
|
f.name = getPropName(member.name);
|
|
597
|
+
f.documentation = getJSDocComment(member, sourceFile);
|
|
498
598
|
f.args = member.parameters.map(params => paramsNodeToArguments(params, unionTypeCollector));
|
|
499
599
|
if (member.type) {
|
|
500
600
|
const mode = new declaration_1.ParameterMode();
|
|
@@ -531,7 +631,7 @@ function createAsyncMethod(member, originalFunc, unionTypeCollector) {
|
|
|
531
631
|
};
|
|
532
632
|
return asyncFunc;
|
|
533
633
|
}
|
|
534
|
-
function processIndexSignature(member, obj, unionTypeCollector) {
|
|
634
|
+
function processIndexSignature(member, obj, sourceFile, unionTypeCollector) {
|
|
535
635
|
const prop = new declaration_1.IndexedPropertyDeclaration();
|
|
536
636
|
const modifier = member.modifiers;
|
|
537
637
|
prop.readonly = !!(modifier && modifier[0].kind === typescript_1.default.SyntaxKind.ReadonlyKeyword);
|
|
@@ -544,7 +644,7 @@ function processIndexSignature(member, obj, unionTypeCollector) {
|
|
|
544
644
|
prop.typeMode = mode;
|
|
545
645
|
obj.indexedProp = prop;
|
|
546
646
|
}
|
|
547
|
-
function processConstructSignature(member, obj, unionTypeCollector) {
|
|
647
|
+
function processConstructSignature(member, obj, sourceFile, unionTypeCollector) {
|
|
548
648
|
const c = new declaration_1.FunctionDeclaration();
|
|
549
649
|
c.name = 'constructor';
|
|
550
650
|
c.args = member.parameters.map(params => paramsNodeToArguments(params, unionTypeCollector));
|
package/dist/commands.js
CHANGED
|
@@ -317,6 +317,8 @@ function generateCommand(distPath, options) {
|
|
|
317
317
|
const hasTsConfig = fs_1.default.existsSync(tsConfigPath);
|
|
318
318
|
// Determine if we need to create a new project
|
|
319
319
|
const needsProjectCreation = !hasPackageJson || !hasGlobalDts || !hasTsConfig;
|
|
320
|
+
// Track if this is an existing project (has all required files)
|
|
321
|
+
const isExistingProject = hasPackageJson && hasGlobalDts && hasTsConfig;
|
|
320
322
|
let framework = options.framework;
|
|
321
323
|
let packageName = options.packageName;
|
|
322
324
|
// Validate and sanitize package name if provided
|
|
@@ -526,7 +528,7 @@ function generateCommand(distPath, options) {
|
|
|
526
528
|
// Handle npm publishing if requested via command line option
|
|
527
529
|
if (options.publishToNpm && framework) {
|
|
528
530
|
try {
|
|
529
|
-
yield buildAndPublishPackage(resolvedDistPath, options.npmRegistry);
|
|
531
|
+
yield buildAndPublishPackage(resolvedDistPath, options.npmRegistry, isExistingProject);
|
|
530
532
|
}
|
|
531
533
|
catch (error) {
|
|
532
534
|
console.error('\nError during npm publish:', error);
|
|
@@ -561,7 +563,7 @@ function generateCommand(distPath, options) {
|
|
|
561
563
|
}
|
|
562
564
|
}]);
|
|
563
565
|
try {
|
|
564
|
-
yield buildAndPublishPackage(resolvedDistPath, registryAnswer.registry || undefined);
|
|
566
|
+
yield buildAndPublishPackage(resolvedDistPath, registryAnswer.registry || undefined, isExistingProject);
|
|
565
567
|
}
|
|
566
568
|
catch (error) {
|
|
567
569
|
console.error('\nError during npm publish:', error);
|
|
@@ -652,17 +654,34 @@ function buildPackage(packagePath) {
|
|
|
652
654
|
}
|
|
653
655
|
});
|
|
654
656
|
}
|
|
655
|
-
function buildAndPublishPackage(
|
|
656
|
-
return __awaiter(this,
|
|
657
|
+
function buildAndPublishPackage(packagePath_1, registry_1) {
|
|
658
|
+
return __awaiter(this, arguments, void 0, function* (packagePath, registry, isExistingProject = false) {
|
|
657
659
|
const packageJsonPath = path_1.default.join(packagePath, 'package.json');
|
|
658
660
|
if (!fs_1.default.existsSync(packageJsonPath)) {
|
|
659
661
|
throw new Error(`No package.json found in ${packagePath}`);
|
|
660
662
|
}
|
|
661
|
-
|
|
663
|
+
let packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
662
664
|
const packageName = packageJson.name;
|
|
663
|
-
|
|
665
|
+
let packageVersion = packageJson.version;
|
|
664
666
|
// First, ensure dependencies are installed and build the package
|
|
665
667
|
yield buildPackage(packagePath);
|
|
668
|
+
// If this is an existing project, increment the patch version before publishing
|
|
669
|
+
if (isExistingProject) {
|
|
670
|
+
console.log(`\nIncrementing version for existing project...`);
|
|
671
|
+
const versionResult = (0, child_process_1.spawnSync)(NPM, ['version', 'patch', '--no-git-tag-version'], {
|
|
672
|
+
cwd: packagePath,
|
|
673
|
+
encoding: 'utf-8',
|
|
674
|
+
stdio: 'pipe'
|
|
675
|
+
});
|
|
676
|
+
if (versionResult.status !== 0) {
|
|
677
|
+
console.error('Failed to increment version:', versionResult.stderr);
|
|
678
|
+
throw new Error('Failed to increment version');
|
|
679
|
+
}
|
|
680
|
+
// Re-read package.json to get the new version
|
|
681
|
+
packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
682
|
+
packageVersion = packageJson.version;
|
|
683
|
+
console.log(`Version updated to ${packageVersion}`);
|
|
684
|
+
}
|
|
666
685
|
// Set registry if provided
|
|
667
686
|
if (registry) {
|
|
668
687
|
console.log(`\nUsing npm registry: ${registry}`);
|
package/dist/react.js
CHANGED
|
@@ -15,6 +15,9 @@ function readTemplate(name) {
|
|
|
15
15
|
return fs_1.default.readFileSync(path_1.default.join(__dirname, '../templates/' + name + '.tpl'), { encoding: 'utf-8' });
|
|
16
16
|
}
|
|
17
17
|
function generateReturnType(type) {
|
|
18
|
+
if ((0, utils_1.isUnionType)(type)) {
|
|
19
|
+
return type.value.map(v => `'${v.value}'`).join(' | ');
|
|
20
|
+
}
|
|
18
21
|
if ((0, utils_1.isPointerType)(type)) {
|
|
19
22
|
const pointerType = (0, utils_1.getPointerType)(type);
|
|
20
23
|
return pointerType;
|
|
@@ -79,6 +82,19 @@ function generateMethodDeclaration(method) {
|
|
|
79
82
|
var returnType = generateReturnType(method.returnType);
|
|
80
83
|
return `${methodName}(${args}): ${returnType};`;
|
|
81
84
|
}
|
|
85
|
+
function generateMethodDeclarationWithDocs(method, indent = '') {
|
|
86
|
+
let result = '';
|
|
87
|
+
if (method.documentation) {
|
|
88
|
+
result += `${indent}/**\n`;
|
|
89
|
+
const docLines = method.documentation.split('\n');
|
|
90
|
+
docLines.forEach(line => {
|
|
91
|
+
result += `${indent} * ${line}\n`;
|
|
92
|
+
});
|
|
93
|
+
result += `${indent} */\n`;
|
|
94
|
+
}
|
|
95
|
+
result += `${indent}${generateMethodDeclaration(method)}`;
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
82
98
|
function toReactEventName(name) {
|
|
83
99
|
const eventName = 'on-' + name;
|
|
84
100
|
return lodash_1.default.camelCase(eventName);
|
|
@@ -110,9 +126,13 @@ function generateReactComponent(blob, packageName, relativeDir) {
|
|
|
110
126
|
const events = classObjects.filter(object => {
|
|
111
127
|
return object.name.endsWith('Events');
|
|
112
128
|
});
|
|
129
|
+
const methods = classObjects.filter(object => {
|
|
130
|
+
return object.name.endsWith('Methods');
|
|
131
|
+
});
|
|
113
132
|
const others = classObjects.filter(object => {
|
|
114
133
|
return !object.name.endsWith('Properties')
|
|
115
|
-
&& !object.name.endsWith('Events')
|
|
134
|
+
&& !object.name.endsWith('Events')
|
|
135
|
+
&& !object.name.endsWith('Methods');
|
|
116
136
|
});
|
|
117
137
|
// Include type aliases
|
|
118
138
|
const typeAliasDeclarations = typeAliases.map(typeAlias => {
|
|
@@ -120,6 +140,19 @@ function generateReactComponent(blob, packageName, relativeDir) {
|
|
|
120
140
|
}).join('\n');
|
|
121
141
|
const dependencies = [
|
|
122
142
|
typeAliasDeclarations,
|
|
143
|
+
// Include Methods interfaces as dependencies
|
|
144
|
+
methods.map(object => {
|
|
145
|
+
const methodDeclarations = object.methods.map(method => {
|
|
146
|
+
return generateMethodDeclarationWithDocs(method, ' ');
|
|
147
|
+
}).join('\n');
|
|
148
|
+
let interfaceDoc = '';
|
|
149
|
+
if (object.documentation) {
|
|
150
|
+
interfaceDoc = `/**\n${object.documentation.split('\n').map(line => ` * ${line}`).join('\n')}\n */\n`;
|
|
151
|
+
}
|
|
152
|
+
return `${interfaceDoc}interface ${object.name} {
|
|
153
|
+
${methodDeclarations}
|
|
154
|
+
}`;
|
|
155
|
+
}).join('\n\n'),
|
|
123
156
|
others.map(object => {
|
|
124
157
|
const props = object.props.map(prop => {
|
|
125
158
|
if (prop.optional) {
|
|
@@ -135,7 +168,7 @@ interface ${object.name} {
|
|
|
135
168
|
].filter(Boolean).join('\n\n');
|
|
136
169
|
// Generate all components from this file
|
|
137
170
|
const components = [];
|
|
138
|
-
// Create a map of component names to their properties and
|
|
171
|
+
// Create a map of component names to their properties, events, and methods
|
|
139
172
|
const componentMap = new Map();
|
|
140
173
|
// Process all Properties interfaces
|
|
141
174
|
properties.forEach(prop => {
|
|
@@ -153,6 +186,14 @@ interface ${object.name} {
|
|
|
153
186
|
}
|
|
154
187
|
componentMap.get(componentName).events = event;
|
|
155
188
|
});
|
|
189
|
+
// Process all Methods interfaces
|
|
190
|
+
methods.forEach(method => {
|
|
191
|
+
const componentName = method.name.replace(/Methods$/, '');
|
|
192
|
+
if (!componentMap.has(componentName)) {
|
|
193
|
+
componentMap.set(componentName, {});
|
|
194
|
+
}
|
|
195
|
+
componentMap.get(componentName).methods = method;
|
|
196
|
+
});
|
|
156
197
|
// If we have multiple components, we need to generate a combined file
|
|
157
198
|
const componentEntries = Array.from(componentMap.entries());
|
|
158
199
|
if (componentEntries.length === 0) {
|
|
@@ -180,6 +221,7 @@ interface ${object.name} {
|
|
|
180
221
|
className: className,
|
|
181
222
|
properties: component.properties,
|
|
182
223
|
events: component.events,
|
|
224
|
+
methods: component.methods,
|
|
183
225
|
classObjectDictionary,
|
|
184
226
|
dependencies,
|
|
185
227
|
blob,
|
|
@@ -187,6 +229,7 @@ interface ${object.name} {
|
|
|
187
229
|
toWebFTagName,
|
|
188
230
|
generateReturnType,
|
|
189
231
|
generateMethodDeclaration,
|
|
232
|
+
generateMethodDeclarationWithDocs,
|
|
190
233
|
generateEventHandlerType,
|
|
191
234
|
getEventType,
|
|
192
235
|
});
|
|
@@ -214,6 +257,7 @@ interface ${object.name} {
|
|
|
214
257
|
className: className,
|
|
215
258
|
properties: component.properties,
|
|
216
259
|
events: component.events,
|
|
260
|
+
methods: component.methods,
|
|
217
261
|
classObjectDictionary,
|
|
218
262
|
dependencies: '', // Dependencies will be at the top
|
|
219
263
|
blob,
|
|
@@ -221,6 +265,7 @@ interface ${object.name} {
|
|
|
221
265
|
toWebFTagName,
|
|
222
266
|
generateReturnType,
|
|
223
267
|
generateMethodDeclaration,
|
|
268
|
+
generateMethodDeclarationWithDocs,
|
|
224
269
|
generateEventHandlerType,
|
|
225
270
|
getEventType,
|
|
226
271
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwebf/webf",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.8",
|
|
4
4
|
"description": "Command line tools for WebF",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"ts-jest": "^29.1.2"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
+
"@microsoft/tsdoc": "^0.15.1",
|
|
40
|
+
"@microsoft/tsdoc-config": "^0.17.1",
|
|
39
41
|
"commander": "^14.0.0",
|
|
40
42
|
"glob": "^10.3.10",
|
|
41
43
|
"inquirer": "^8.2.6",
|