@doccov/sdk 0.8.0 → 0.9.0
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/index.js +121 -10
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3034,6 +3034,8 @@ function parseJSDocBlock(commentText) {
|
|
|
3034
3034
|
params: [],
|
|
3035
3035
|
throws: [],
|
|
3036
3036
|
examples: [],
|
|
3037
|
+
structuredExamples: [],
|
|
3038
|
+
seeAlso: [],
|
|
3037
3039
|
tags: [],
|
|
3038
3040
|
rawParamNames: []
|
|
3039
3041
|
};
|
|
@@ -3154,6 +3156,43 @@ function parseThrowsContent(content) {
|
|
|
3154
3156
|
description: processInlineLinks(remaining)
|
|
3155
3157
|
};
|
|
3156
3158
|
}
|
|
3159
|
+
function parseExampleContent(content) {
|
|
3160
|
+
const trimmed = content.trim();
|
|
3161
|
+
if (!trimmed)
|
|
3162
|
+
return null;
|
|
3163
|
+
const lines = trimmed.split(`
|
|
3164
|
+
`);
|
|
3165
|
+
let title;
|
|
3166
|
+
let description;
|
|
3167
|
+
let language;
|
|
3168
|
+
let codeStartIndex = 0;
|
|
3169
|
+
const firstLine = lines[0]?.trim() ?? "";
|
|
3170
|
+
const looksLikeCode = /^(import|const|let|var|function|class|export|async|await|if|for|while|return|\/\/|\/\*|\{|\[)/.test(firstLine);
|
|
3171
|
+
if (firstLine && !firstLine.startsWith("```") && !looksLikeCode) {
|
|
3172
|
+
title = firstLine;
|
|
3173
|
+
codeStartIndex = 1;
|
|
3174
|
+
}
|
|
3175
|
+
const codeBlockStart = lines.findIndex((l, i) => i >= codeStartIndex && l.trim().startsWith("```"));
|
|
3176
|
+
if (codeBlockStart !== -1) {
|
|
3177
|
+
const fenceMatch = lines[codeBlockStart].match(/```(\w+)?/);
|
|
3178
|
+
language = fenceMatch?.[1];
|
|
3179
|
+
if (codeBlockStart > codeStartIndex) {
|
|
3180
|
+
const descLines = lines.slice(codeStartIndex, codeBlockStart).filter((l) => l.trim());
|
|
3181
|
+
if (descLines.length > 0) {
|
|
3182
|
+
description = descLines.join(`
|
|
3183
|
+
`).trim();
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
const codeBlockEnd = lines.findIndex((l, i) => i > codeBlockStart && l.trim() === "```");
|
|
3187
|
+
const codeLines = codeBlockEnd === -1 ? lines.slice(codeBlockStart + 1) : lines.slice(codeBlockStart + 1, codeBlockEnd);
|
|
3188
|
+
const code2 = codeLines.join(`
|
|
3189
|
+
`);
|
|
3190
|
+
return { code: code2, title, description, language };
|
|
3191
|
+
}
|
|
3192
|
+
const code = lines.slice(codeStartIndex).join(`
|
|
3193
|
+
`).trim();
|
|
3194
|
+
return { code, title, language: "ts" };
|
|
3195
|
+
}
|
|
3157
3196
|
function findMatchingBrace(text, startIndex) {
|
|
3158
3197
|
if (text[startIndex] !== "{")
|
|
3159
3198
|
return -1;
|
|
@@ -3246,22 +3285,30 @@ function processTagContent(result, tag, content) {
|
|
|
3246
3285
|
if (example) {
|
|
3247
3286
|
result.examples.push(example);
|
|
3248
3287
|
}
|
|
3249
|
-
const
|
|
3288
|
+
const structuredExample = parseExampleContent(trimmedContent);
|
|
3289
|
+
if (structuredExample) {
|
|
3290
|
+
result.structuredExamples.push(structuredExample);
|
|
3291
|
+
}
|
|
3250
3292
|
result.tags.push({
|
|
3251
3293
|
name: "example",
|
|
3252
3294
|
text: example,
|
|
3253
|
-
language:
|
|
3295
|
+
language: structuredExample?.language
|
|
3254
3296
|
});
|
|
3255
3297
|
break;
|
|
3256
3298
|
}
|
|
3257
3299
|
case "see": {
|
|
3258
3300
|
const linkTargets = extractAllLinkTargets(trimmedContent);
|
|
3259
3301
|
for (const target of linkTargets) {
|
|
3302
|
+
result.seeAlso.push(target);
|
|
3260
3303
|
result.tags.push({ name: "link", text: target, reference: target });
|
|
3261
3304
|
result.tags.push({ name: "see", text: target, reference: target });
|
|
3262
3305
|
}
|
|
3263
3306
|
if (linkTargets.length === 0) {
|
|
3264
|
-
|
|
3307
|
+
const plainRef = trimmedContent.trim().split(/\s+/)[0];
|
|
3308
|
+
if (plainRef) {
|
|
3309
|
+
result.seeAlso.push(plainRef);
|
|
3310
|
+
}
|
|
3311
|
+
result.tags.push({ name: "see", text: trimmedContent, reference: plainRef || trimmedContent });
|
|
3265
3312
|
}
|
|
3266
3313
|
break;
|
|
3267
3314
|
}
|
|
@@ -3389,6 +3436,8 @@ function parseJSDocText(commentText) {
|
|
|
3389
3436
|
type: p.type
|
|
3390
3437
|
})),
|
|
3391
3438
|
examples: parsed.examples.length > 0 ? parsed.examples : undefined,
|
|
3439
|
+
structuredExamples: parsed.structuredExamples.length > 0 ? parsed.structuredExamples : undefined,
|
|
3440
|
+
seeAlso: parsed.seeAlso.length > 0 ? parsed.seeAlso : undefined,
|
|
3392
3441
|
tags: parsed.tags.length > 0 ? parsed.tags : undefined,
|
|
3393
3442
|
rawParamNames: parsed.rawParamNames
|
|
3394
3443
|
};
|
|
@@ -3528,6 +3577,23 @@ function extractPresentationMetadata(doc) {
|
|
|
3528
3577
|
}
|
|
3529
3578
|
|
|
3530
3579
|
// src/analysis/serializers/classes.ts
|
|
3580
|
+
function extractClassRelations(heritage, parsedDoc) {
|
|
3581
|
+
const relations = [];
|
|
3582
|
+
if (heritage.extends) {
|
|
3583
|
+
relations.push({ type: "extends", target: heritage.extends });
|
|
3584
|
+
}
|
|
3585
|
+
if (heritage.implements) {
|
|
3586
|
+
for (const impl of heritage.implements) {
|
|
3587
|
+
relations.push({ type: "implements", target: impl });
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
if (parsedDoc?.seeAlso) {
|
|
3591
|
+
for (const ref of parsedDoc.seeAlso) {
|
|
3592
|
+
relations.push({ type: "see-also", target: ref });
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
return relations;
|
|
3596
|
+
}
|
|
3531
3597
|
function serializeClass(declaration, symbol, context) {
|
|
3532
3598
|
const { checker, typeRegistry } = context;
|
|
3533
3599
|
const typeRefs = typeRegistry.getTypeRefs();
|
|
@@ -3539,6 +3605,7 @@ function serializeClass(declaration, symbol, context) {
|
|
|
3539
3605
|
const description = parsedDoc?.description ?? getJSDocComment(symbol, context.checker);
|
|
3540
3606
|
const metadata = extractPresentationMetadata(parsedDoc);
|
|
3541
3607
|
const decorators = extractDecorators(declaration);
|
|
3608
|
+
const relations = extractClassRelations(heritage, parsedDoc);
|
|
3542
3609
|
const exportEntry = {
|
|
3543
3610
|
id: symbol.getName(),
|
|
3544
3611
|
name: symbol.getName(),
|
|
@@ -3553,7 +3620,8 @@ function serializeClass(declaration, symbol, context) {
|
|
|
3553
3620
|
...heritage.implements && heritage.implements.length > 0 ? { implements: heritage.implements } : {},
|
|
3554
3621
|
tags: parsedDoc?.tags,
|
|
3555
3622
|
examples: parsedDoc?.examples,
|
|
3556
|
-
decorators
|
|
3623
|
+
decorators,
|
|
3624
|
+
related: relations.length > 0 ? relations : undefined
|
|
3557
3625
|
};
|
|
3558
3626
|
const typeDefinition = {
|
|
3559
3627
|
id: symbol.getName(),
|
|
@@ -3565,7 +3633,8 @@ function serializeClass(declaration, symbol, context) {
|
|
|
3565
3633
|
members: members.length > 0 ? members : undefined,
|
|
3566
3634
|
...heritage.extends ? { extends: heritage.extends } : {},
|
|
3567
3635
|
...heritage.implements && heritage.implements.length > 0 ? { implements: heritage.implements } : {},
|
|
3568
|
-
tags: parsedDoc?.tags
|
|
3636
|
+
tags: parsedDoc?.tags,
|
|
3637
|
+
related: relations.length > 0 ? relations : undefined
|
|
3569
3638
|
};
|
|
3570
3639
|
return {
|
|
3571
3640
|
exportEntry,
|
|
@@ -3888,6 +3957,22 @@ function serializeCallSignatures(signatures, symbol, context, parsedDoc) {
|
|
|
3888
3957
|
};
|
|
3889
3958
|
});
|
|
3890
3959
|
}
|
|
3960
|
+
function extractFunctionRelations(declaration, checker, parsedDoc) {
|
|
3961
|
+
const relations = [];
|
|
3962
|
+
if (declaration.type && ts2.isTypeReferenceNode(declaration.type)) {
|
|
3963
|
+
const typeName = declaration.type.typeName.getText();
|
|
3964
|
+
const builtIns = ["Promise", "Array", "Map", "Set", "Record", "Partial", "Required", "Pick", "Omit"];
|
|
3965
|
+
if (!builtIns.includes(typeName)) {
|
|
3966
|
+
relations.push({ type: "returns", target: typeName });
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
if (parsedDoc?.seeAlso) {
|
|
3970
|
+
for (const ref of parsedDoc.seeAlso) {
|
|
3971
|
+
relations.push({ type: "see-also", target: ref });
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
return relations;
|
|
3975
|
+
}
|
|
3891
3976
|
function serializeFunctionExport(declaration, symbol, context) {
|
|
3892
3977
|
const { checker } = context;
|
|
3893
3978
|
const funcSymbol = checker.getSymbolAtLocation(declaration.name || declaration);
|
|
@@ -3896,6 +3981,7 @@ function serializeFunctionExport(declaration, symbol, context) {
|
|
|
3896
3981
|
const metadata = extractPresentationMetadata(parsedDoc);
|
|
3897
3982
|
const type = checker.getTypeAtLocation(declaration.name || declaration);
|
|
3898
3983
|
const callSignatures = type.getCallSignatures();
|
|
3984
|
+
const relations = extractFunctionRelations(declaration, checker, parsedDoc);
|
|
3899
3985
|
return {
|
|
3900
3986
|
id: symbol.getName(),
|
|
3901
3987
|
name: symbol.getName(),
|
|
@@ -3906,7 +3992,8 @@ function serializeFunctionExport(declaration, symbol, context) {
|
|
|
3906
3992
|
description,
|
|
3907
3993
|
source: getSourceLocation(declaration),
|
|
3908
3994
|
examples: parsedDoc?.examples,
|
|
3909
|
-
tags: parsedDoc?.tags
|
|
3995
|
+
tags: parsedDoc?.tags,
|
|
3996
|
+
related: relations.length > 0 ? relations : undefined
|
|
3910
3997
|
};
|
|
3911
3998
|
}
|
|
3912
3999
|
|
|
@@ -3994,6 +4081,25 @@ function serializeInterfaceMembers(declaration, checker, typeRefs, referencedTyp
|
|
|
3994
4081
|
}
|
|
3995
4082
|
return members;
|
|
3996
4083
|
}
|
|
4084
|
+
function extractInterfaceRelations(declaration, parsedDoc) {
|
|
4085
|
+
const relations = [];
|
|
4086
|
+
if (declaration.heritageClauses) {
|
|
4087
|
+
for (const clause of declaration.heritageClauses) {
|
|
4088
|
+
if (clause.token === ts2.SyntaxKind.ExtendsKeyword) {
|
|
4089
|
+
for (const type of clause.types) {
|
|
4090
|
+
const typeName = type.expression.getText();
|
|
4091
|
+
relations.push({ type: "extends", target: typeName });
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
if (parsedDoc?.seeAlso) {
|
|
4097
|
+
for (const ref of parsedDoc.seeAlso) {
|
|
4098
|
+
relations.push({ type: "see-also", target: ref });
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
return relations;
|
|
4102
|
+
}
|
|
3997
4103
|
function serializeInterface(declaration, symbol, context) {
|
|
3998
4104
|
const { checker, typeRegistry } = context;
|
|
3999
4105
|
const parsedDoc = parseJSDocComment(symbol, checker);
|
|
@@ -4003,6 +4109,7 @@ function serializeInterface(declaration, symbol, context) {
|
|
|
4003
4109
|
const typeRefs = typeRegistry.getTypeRefs();
|
|
4004
4110
|
const typeParameters = serializeTypeParameterDeclarations(declaration.typeParameters, checker, referencedTypes);
|
|
4005
4111
|
const members = serializeInterfaceMembers(declaration, checker, typeRefs, referencedTypes);
|
|
4112
|
+
const relations = extractInterfaceRelations(declaration, parsedDoc);
|
|
4006
4113
|
const exportEntry = {
|
|
4007
4114
|
id: symbol.getName(),
|
|
4008
4115
|
name: symbol.getName(),
|
|
@@ -4014,7 +4121,8 @@ function serializeInterface(declaration, symbol, context) {
|
|
|
4014
4121
|
members,
|
|
4015
4122
|
typeParameters,
|
|
4016
4123
|
tags: parsedDoc?.tags,
|
|
4017
|
-
examples: parsedDoc?.examples
|
|
4124
|
+
examples: parsedDoc?.examples,
|
|
4125
|
+
related: relations.length > 0 ? relations : undefined
|
|
4018
4126
|
};
|
|
4019
4127
|
const schema = interfaceToSchema(declaration, checker, typeRefs, referencedTypes);
|
|
4020
4128
|
const typeDefinition = {
|
|
@@ -4026,7 +4134,8 @@ function serializeInterface(declaration, symbol, context) {
|
|
|
4026
4134
|
members,
|
|
4027
4135
|
description,
|
|
4028
4136
|
source: getSourceLocation(declaration),
|
|
4029
|
-
tags: parsedDoc?.tags
|
|
4137
|
+
tags: parsedDoc?.tags,
|
|
4138
|
+
related: relations.length > 0 ? relations : undefined
|
|
4030
4139
|
};
|
|
4031
4140
|
return {
|
|
4032
4141
|
exportEntry,
|
|
@@ -5206,7 +5315,9 @@ function generateAssertionFix(drift, exportEntry) {
|
|
|
5206
5315
|
const oldValue = oldValueMatch?.[1];
|
|
5207
5316
|
if (!oldValue)
|
|
5208
5317
|
return null;
|
|
5209
|
-
const
|
|
5318
|
+
const oldExampleCode = typeof oldExample === "string" ? oldExample : oldExample.code;
|
|
5319
|
+
const updatedCode = oldExampleCode.replace(new RegExp(`//\\s*=>\\s*${escapeRegex(oldValue)}`, "g"), `// => ${newValue}`);
|
|
5320
|
+
const updatedExample = typeof oldExample === "string" ? updatedCode : { ...oldExample, code: updatedCode };
|
|
5210
5321
|
const updatedExamples = [...examples];
|
|
5211
5322
|
updatedExamples[exampleIndex] = updatedExample;
|
|
5212
5323
|
return {
|
|
@@ -5538,7 +5649,7 @@ function serializeJSDoc(patch, indent = "") {
|
|
|
5538
5649
|
}
|
|
5539
5650
|
lines.push(tagLine);
|
|
5540
5651
|
}
|
|
5541
|
-
if (patch.deprecated && patch.deprecated
|
|
5652
|
+
if (patch.deprecated && typeof patch.deprecated === "string") {
|
|
5542
5653
|
lines.push(`@deprecated ${patch.deprecated}`);
|
|
5543
5654
|
}
|
|
5544
5655
|
if (patch.examples) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doccov/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "DocCov SDK - Documentation coverage and drift detection for TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"dist"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@openpkg-ts/spec": "^0.
|
|
42
|
+
"@openpkg-ts/spec": "^0.7.0",
|
|
43
43
|
"@vercel/sandbox": "^1.0.3",
|
|
44
44
|
"mdast": "^3.0.0",
|
|
45
45
|
"remark-mdx": "^3.1.0",
|