rspress-plugin-api-extractor 0.14.0 → 0.15.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/BuildEnv.js +0 -1
- package/build-program.js +4 -4
- package/build-stages.js +98 -281
- package/config-helpers.js +1 -1
- package/emit/mdx.js +311 -0
- package/emit/meta.js +62 -0
- package/index.d.ts +1 -42
- package/layers/build-metrics.js +1 -2
- package/layers/config-resolution.js +3 -5
- package/layers/type-environment.js +1 -2
- package/llms-program.js +3 -3
- package/markdown/helpers.js +10 -176
- package/observability/sinks/console-sink.js +0 -1
- package/observability/sinks/metrics-sink.js +0 -2
- package/package.json +6 -5
- package/path-derivation.js +1 -29
- package/plugin.js +2 -1
- package/prettier-formatter.js +27 -59
- package/remark-with-api.js +3 -2
- package/schemas/config.js +1 -18
- package/schemas/observability.js +0 -2
- package/schemas/performance.js +0 -1
- package/services/TwoslashCacheService.js +1 -1
- package/twoslash-transformer.js +14 -2
- package/code-post-processor.js +0 -38
- package/llms-processing.js +0 -270
- package/markdown/page-generators/class-page.js +0 -363
- package/markdown/page-generators/enum-page.js +0 -152
- package/markdown/page-generators/function-page.js +0 -127
- package/markdown/page-generators/index-pages.js +0 -25
- package/markdown/page-generators/interface-page.js +0 -310
- package/markdown/page-generators/namespace-page.js +0 -277
- package/markdown/page-generators/type-alias-page.js +0 -110
- package/markdown/page-generators/variable-page.js +0 -110
- package/markdown/prose-linker.js +0 -22
- package/twoslash-cache.js +0 -174
- package/twoslash-patterns.js +0 -87
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, stripTwoslashDirectives } from "../helpers.js";
|
|
2
|
-
import { linkProse } from "../prose-linker.js";
|
|
3
|
-
import { ApiItems, Tsdoc } from "@tsdoctor/model";
|
|
4
|
-
|
|
5
|
-
//#region src/markdown/page-generators/enum-page.ts
|
|
6
|
-
/**
|
|
7
|
-
* Generates MDX documentation pages for TypeScript enums.
|
|
8
|
-
*
|
|
9
|
-
* This class transforms API Extractor enum models into rich MDX documentation
|
|
10
|
-
* pages with syntax-highlighted signatures, member tables, and cross-linked
|
|
11
|
-
* type references.
|
|
12
|
-
*
|
|
13
|
-
* **Page Structure:**
|
|
14
|
-
* 1. Frontmatter with title, description, and Open Graph metadata
|
|
15
|
-
* 2. Component imports
|
|
16
|
-
* 3. Page title (H1) and summary
|
|
17
|
-
* 4. Optional deprecation warning and release tag badge
|
|
18
|
-
* 5. Source code link toolbar
|
|
19
|
-
* 6. Enum signature block
|
|
20
|
-
* 7. Members table (Name, Value, Description)
|
|
21
|
-
* 8. Examples section with Twoslash-enabled code blocks
|
|
22
|
-
* 9. See Also references
|
|
23
|
-
*
|
|
24
|
-
* **Relationships:**
|
|
25
|
-
* - Created and invoked by {@link ApiExtractorPlugin} during page generation
|
|
26
|
-
* - Uses `Signature.format` from `@tsdoctor/model` for formatting type signatures
|
|
27
|
-
* - Uses the `Tsdoc` / `ApiItems` modules from `@tsdoctor/model` for extracting documentation
|
|
28
|
-
* - Uses the per-build prose linker (`linkProse`) for adding type reference links
|
|
29
|
-
*
|
|
30
|
-
* @see {@link TypeAliasPageGenerator} for type alias documentation
|
|
31
|
-
* @see {@link VariablePageGenerator} for variable/constant documentation
|
|
32
|
-
*/
|
|
33
|
-
var EnumPageGenerator = class {
|
|
34
|
-
/**
|
|
35
|
-
* Generate a markdown page for an enum
|
|
36
|
-
*
|
|
37
|
-
* @param apiScope - API scope identifier for VFS lookup
|
|
38
|
-
*/
|
|
39
|
-
async generate(apiEnum, baseRoute, packageName, singularName, apiScope, apiName, sourceConfig, suppressExampleErrors, llmsPlugin, availableFrom) {
|
|
40
|
-
const shouldSuppressErrors = suppressExampleErrors ?? true;
|
|
41
|
-
const name = apiEnum.displayName;
|
|
42
|
-
const summary = Tsdoc.summary(apiEnum) || "No description available.";
|
|
43
|
-
const releaseTag = Tsdoc.releaseTag(apiEnum);
|
|
44
|
-
let content = generateFrontmatter(name, summary, singularName, apiName);
|
|
45
|
-
content += `import { SourceCode } from "@rspress/core/theme";\n`;
|
|
46
|
-
content += `import { EnumMembersTable } from "rspress-plugin-api-extractor/runtime";\n`;
|
|
47
|
-
content += `import { ApiSignature, ApiExample } from "rspress-plugin-api-extractor/runtime";\n\n`;
|
|
48
|
-
content += `# ${name}\n\n`;
|
|
49
|
-
const deprecation = Tsdoc.deprecation(apiEnum);
|
|
50
|
-
if (deprecation) {
|
|
51
|
-
const message = escapeMdxGenerics(linkProse(deprecation.message));
|
|
52
|
-
content += `> ⚠️ **Deprecated:** ${message}\n\n`;
|
|
53
|
-
}
|
|
54
|
-
if (releaseTag !== "Public") content += `\`${releaseTag}\`\n\n`;
|
|
55
|
-
content += `${summary}\n\n`;
|
|
56
|
-
content += generateAvailableFrom(packageName, availableFrom);
|
|
57
|
-
const sourceLink = ApiItems.sourceLink(apiEnum, sourceConfig);
|
|
58
|
-
if (sourceLink) {
|
|
59
|
-
content += `<div className="api-docs-toolbar">\n`;
|
|
60
|
-
content += ` <div className="api-docs-toolbar-left">\n`;
|
|
61
|
-
content += ` <SourceCode href="${sourceLink}" />\n`;
|
|
62
|
-
content += ` </div>\n`;
|
|
63
|
-
if (llmsPlugin?.enabled) {
|
|
64
|
-
content += ` <div className="api-docs-toolbar-right">\n`;
|
|
65
|
-
content += ` </div>\n`;
|
|
66
|
-
}
|
|
67
|
-
content += `</div>\n\n`;
|
|
68
|
-
}
|
|
69
|
-
const skeleton = this.generateEnumSkeleton(apiEnum);
|
|
70
|
-
const hasMembers = apiEnum.members.length > 0;
|
|
71
|
-
if (skeleton) {
|
|
72
|
-
const displayCode = stripTwoslashDirectives(skeleton);
|
|
73
|
-
const signatureNewlines = hasMembers ? "\n" : "\n\n";
|
|
74
|
-
content += `<ApiSignature code={${JSON.stringify(displayCode)}} source={${JSON.stringify(skeleton)}} apiScope={${JSON.stringify(apiScope)}} hasMembers={${hasMembers}} />${signatureNewlines}`;
|
|
75
|
-
}
|
|
76
|
-
if (hasMembers) {
|
|
77
|
-
const membersData = apiEnum.members.map((member) => {
|
|
78
|
-
const memberItem = member;
|
|
79
|
-
const memberSummary = Tsdoc.summary(member) || "";
|
|
80
|
-
let value;
|
|
81
|
-
if (memberItem.excerpt?.text) {
|
|
82
|
-
const excerptText = memberItem.excerpt.text.trim();
|
|
83
|
-
const equalsIndex = excerptText.indexOf("=");
|
|
84
|
-
if (equalsIndex !== -1) value = excerptText.substring(equalsIndex + 1).trim().replace(/,\s*$/, "");
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
name: member.displayName,
|
|
88
|
-
value,
|
|
89
|
-
description: linkProse(memberSummary)
|
|
90
|
-
};
|
|
91
|
-
});
|
|
92
|
-
content += `<EnumMembersTable members={${JSON.stringify(membersData)}} />\n\n`;
|
|
93
|
-
}
|
|
94
|
-
const examples = Tsdoc.examples(apiEnum);
|
|
95
|
-
if (examples.length > 0) {
|
|
96
|
-
content += `## Examples\n\n`;
|
|
97
|
-
for (const example of examples) {
|
|
98
|
-
const prepared = prepareExampleCode(example, name, packageName, shouldSuppressErrors);
|
|
99
|
-
const formattedCode = await formatExampleCode(prepared.code, prepared.language, {
|
|
100
|
-
api: packageName,
|
|
101
|
-
blockType: "example"
|
|
102
|
-
});
|
|
103
|
-
if (prepared.isTypeScript) {
|
|
104
|
-
const displayCode = stripTwoslashDirectives(formattedCode);
|
|
105
|
-
content += `<ApiExample code={${JSON.stringify(displayCode)}} source={${JSON.stringify(formattedCode)}} apiScope={${JSON.stringify(apiScope)}} />\n\n`;
|
|
106
|
-
} else content += `\`\`\`${prepared.language}\n${formattedCode}\n\`\`\`\n\n`;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
const seeReferences = Tsdoc.seeReferences(apiEnum);
|
|
110
|
-
if (seeReferences.length > 0) {
|
|
111
|
-
content += `## See Also\n\n`;
|
|
112
|
-
for (const reference of seeReferences) {
|
|
113
|
-
const refText = escapeMdxGenerics(linkProse(reference.text));
|
|
114
|
-
content += `- ${refText}\n`;
|
|
115
|
-
}
|
|
116
|
-
content += `\n`;
|
|
117
|
-
}
|
|
118
|
-
return {
|
|
119
|
-
routePath: `${baseRoute}/enum/${name.toLowerCase()}`,
|
|
120
|
-
content
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Generate a complete enum skeleton showing all members
|
|
125
|
-
*/
|
|
126
|
-
generateEnumSkeleton(apiEnum) {
|
|
127
|
-
const lines = [];
|
|
128
|
-
const enumName = apiEnum.displayName;
|
|
129
|
-
lines.push(`enum ${enumName} {`);
|
|
130
|
-
const members = apiEnum.members;
|
|
131
|
-
for (let i = 0; i < members.length; i++) {
|
|
132
|
-
const member = members[i];
|
|
133
|
-
const memberItem = member;
|
|
134
|
-
let memberLine = ` ${member.displayName}`;
|
|
135
|
-
if (memberItem.excerpt?.text) {
|
|
136
|
-
const excerptText = memberItem.excerpt.text.trim();
|
|
137
|
-
const equalsIndex = excerptText.indexOf("=");
|
|
138
|
-
if (equalsIndex !== -1) {
|
|
139
|
-
const value = excerptText.substring(equalsIndex + 1).trim().replace(/,\s*$/, "");
|
|
140
|
-
memberLine += ` = ${value}`;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (i < members.length - 1) memberLine += ",";
|
|
144
|
-
lines.push(memberLine);
|
|
145
|
-
}
|
|
146
|
-
lines.push("}");
|
|
147
|
-
return lines.join("\n");
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
//#endregion
|
|
152
|
-
export { EnumPageGenerator };
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
2
|
-
import { linkProse } from "../prose-linker.js";
|
|
3
|
-
import { ApiItems, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
4
|
-
|
|
5
|
-
//#region src/markdown/page-generators/function-page.ts
|
|
6
|
-
/**
|
|
7
|
-
* Generates MDX documentation pages for TypeScript/JavaScript functions.
|
|
8
|
-
*
|
|
9
|
-
* This class transforms API Extractor function models into rich MDX documentation
|
|
10
|
-
* pages with syntax-highlighted signatures and cross-linked type references.
|
|
11
|
-
*
|
|
12
|
-
* **Page Structure:**
|
|
13
|
-
* 1. Frontmatter with title, description, and Open Graph metadata
|
|
14
|
-
* 2. Component imports
|
|
15
|
-
* 3. Page title (H1) and summary
|
|
16
|
-
* 4. Optional deprecation warning and release tag badge
|
|
17
|
-
* 5. Source code link toolbar
|
|
18
|
-
* 6. Function signature block
|
|
19
|
-
* 7. Parameters documentation
|
|
20
|
-
* 8. Returns documentation
|
|
21
|
-
* 9. Examples section with Twoslash-enabled code blocks
|
|
22
|
-
* 10. See Also references
|
|
23
|
-
*
|
|
24
|
-
* **Relationships:**
|
|
25
|
-
* - Created and invoked by {@link ApiExtractorPlugin} during page generation
|
|
26
|
-
* - Uses `Signature.format` from `@tsdoctor/model` for formatting type signatures
|
|
27
|
-
* - Uses the `Tsdoc` / `ApiItems` modules from `@tsdoctor/model` for extracting documentation
|
|
28
|
-
* - Uses the per-build prose linker (`linkProse`) for adding type reference links
|
|
29
|
-
*
|
|
30
|
-
* @see {@link ClassPageGenerator} for class documentation
|
|
31
|
-
* @see {@link TypeAliasPageGenerator} for type alias documentation
|
|
32
|
-
*/
|
|
33
|
-
var FunctionPageGenerator = class {
|
|
34
|
-
/**
|
|
35
|
-
* Generate a markdown page for a function
|
|
36
|
-
*
|
|
37
|
-
* @param apiScope - API scope identifier for VFS lookup
|
|
38
|
-
*/
|
|
39
|
-
async generate(apiFunction, baseRoute, packageName, singularName, apiScope, apiName, sourceConfig, suppressExampleErrors, llmsPlugin, availableFrom) {
|
|
40
|
-
const shouldSuppressErrors = suppressExampleErrors ?? true;
|
|
41
|
-
const name = apiFunction.displayName;
|
|
42
|
-
const summary = Tsdoc.summary(apiFunction) || "No description available.";
|
|
43
|
-
const releaseTag = Tsdoc.releaseTag(apiFunction);
|
|
44
|
-
let content = generateFrontmatter(name, summary, singularName, apiName);
|
|
45
|
-
content += `import { SourceCode } from "@rspress/core/theme";\n`;
|
|
46
|
-
content += `import { ParametersTable } from "rspress-plugin-api-extractor/runtime";\n`;
|
|
47
|
-
content += `import { ApiSignature, ApiExample } from "rspress-plugin-api-extractor/runtime";\n\n`;
|
|
48
|
-
content += `# ${name}\n\n`;
|
|
49
|
-
const deprecation = Tsdoc.deprecation(apiFunction);
|
|
50
|
-
if (deprecation) {
|
|
51
|
-
const message = escapeMdxGenerics(linkProse(deprecation.message));
|
|
52
|
-
content += `> ⚠️ **Deprecated:** ${message}\n\n`;
|
|
53
|
-
}
|
|
54
|
-
if (releaseTag !== "Public") content += `\`${releaseTag}\`\n\n`;
|
|
55
|
-
content += `${summary}\n\n`;
|
|
56
|
-
content += generateAvailableFrom(packageName, availableFrom);
|
|
57
|
-
const sourceLink = ApiItems.sourceLink(apiFunction, sourceConfig);
|
|
58
|
-
if (sourceLink) {
|
|
59
|
-
content += `<div className="api-docs-toolbar">\n`;
|
|
60
|
-
content += ` <div className="api-docs-toolbar-left">\n`;
|
|
61
|
-
content += ` <SourceCode href="${sourceLink}" />\n`;
|
|
62
|
-
content += ` </div>\n`;
|
|
63
|
-
if (llmsPlugin?.enabled) {
|
|
64
|
-
content += ` <div className="api-docs-toolbar-right">\n`;
|
|
65
|
-
content += ` </div>\n`;
|
|
66
|
-
}
|
|
67
|
-
content += `</div>\n\n`;
|
|
68
|
-
}
|
|
69
|
-
const params = Tsdoc.params(apiFunction);
|
|
70
|
-
const hasParameters = params.length > 0;
|
|
71
|
-
if (apiFunction.excerpt.text) {
|
|
72
|
-
const signature = Signature.format(apiFunction.excerpt).trim();
|
|
73
|
-
let signatureWithImports = signature;
|
|
74
|
-
const apiPackage = apiFunction.getAssociatedPackage?.();
|
|
75
|
-
if (apiPackage) {
|
|
76
|
-
const imports = new TypeReferenceExtractor(apiPackage, packageName).extractImportsForApiItem(apiFunction);
|
|
77
|
-
signatureWithImports = prependHiddenImports(signature, imports);
|
|
78
|
-
}
|
|
79
|
-
const displayCode = stripTwoslashDirectives(signatureWithImports);
|
|
80
|
-
content += `<ApiSignature code={${JSON.stringify(displayCode)}} source={${JSON.stringify(signatureWithImports)}} apiScope={${JSON.stringify(apiScope)}} hasParameters={${hasParameters}} />\n\n`;
|
|
81
|
-
}
|
|
82
|
-
if (hasParameters) {
|
|
83
|
-
const parametersData = params.map((param) => ({
|
|
84
|
-
name: param.name,
|
|
85
|
-
type: param.type,
|
|
86
|
-
description: escapeMdxGenerics(linkProse(param.description))
|
|
87
|
-
}));
|
|
88
|
-
content += `<ParametersTable parameters={${JSON.stringify(parametersData)}} />\n\n`;
|
|
89
|
-
}
|
|
90
|
-
const returns = Tsdoc.returns(apiFunction);
|
|
91
|
-
if (returns) {
|
|
92
|
-
const description = escapeMdxGenerics(linkProse(returns.description));
|
|
93
|
-
content += `## Returns\n\n${description}\n\n`;
|
|
94
|
-
}
|
|
95
|
-
const examples = Tsdoc.examples(apiFunction);
|
|
96
|
-
if (examples.length > 0) {
|
|
97
|
-
content += `## Examples\n\n`;
|
|
98
|
-
for (const example of examples) {
|
|
99
|
-
const prepared = prepareExampleCode(example, name, packageName, shouldSuppressErrors);
|
|
100
|
-
const formattedCode = await formatExampleCode(prepared.code, prepared.language, {
|
|
101
|
-
api: packageName,
|
|
102
|
-
blockType: "example"
|
|
103
|
-
});
|
|
104
|
-
if (prepared.isTypeScript) {
|
|
105
|
-
const displayCode = stripTwoslashDirectives(formattedCode);
|
|
106
|
-
content += `<ApiExample code={${JSON.stringify(displayCode)}} source={${JSON.stringify(formattedCode)}} apiScope={${JSON.stringify(apiScope)}} />\n\n`;
|
|
107
|
-
} else content += `\`\`\`${prepared.language}\n${formattedCode}\n\`\`\`\n\n`;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const seeReferences = Tsdoc.seeReferences(apiFunction);
|
|
111
|
-
if (seeReferences.length > 0) {
|
|
112
|
-
content += `## See Also\n\n`;
|
|
113
|
-
for (const reference of seeReferences) {
|
|
114
|
-
const refText = escapeMdxGenerics(linkProse(reference.text));
|
|
115
|
-
content += `- ${refText}\n`;
|
|
116
|
-
}
|
|
117
|
-
content += `\n`;
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
routePath: `${baseRoute}/function/${name.toLowerCase()}`,
|
|
121
|
-
content
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
//#endregion
|
|
127
|
-
export { FunctionPageGenerator };
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { emitFrontmatterBlock } from "@tsdoctor/model";
|
|
2
|
-
|
|
3
|
-
//#region src/markdown/page-generators/index-pages.ts
|
|
4
|
-
/**
|
|
5
|
-
* Generator for main API index page with only frontmatter (no content)
|
|
6
|
-
*/
|
|
7
|
-
var MainIndexPageGenerator = class {
|
|
8
|
-
/**
|
|
9
|
-
* Generate the main API index page
|
|
10
|
-
*/
|
|
11
|
-
generate(packageName, baseRoute, _categoryCounts) {
|
|
12
|
-
const content = emitFrontmatterBlock({
|
|
13
|
-
title: "API Reference",
|
|
14
|
-
description: `Auto-generated API documentation for ${packageName}`,
|
|
15
|
-
overview: true
|
|
16
|
-
});
|
|
17
|
-
return {
|
|
18
|
-
routePath: `${baseRoute}/index`,
|
|
19
|
-
content
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
export { MainIndexPageGenerator };
|
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
import { escapeMdxGenerics, formatExampleCode, generateAvailableFrom, generateFrontmatter, prepareExampleCode, prependHiddenImports, stripTwoslashDirectives } from "../helpers.js";
|
|
2
|
-
import { linkProse } from "../prose-linker.js";
|
|
3
|
-
import { ApiItems, Routes, Signature, Tsdoc, TypeReferenceExtractor } from "@tsdoctor/model";
|
|
4
|
-
|
|
5
|
-
//#region src/markdown/page-generators/interface-page.ts
|
|
6
|
-
/**
|
|
7
|
-
* Generates MDX documentation pages for TypeScript interfaces.
|
|
8
|
-
*
|
|
9
|
-
* This class transforms API Extractor interface models into rich MDX documentation
|
|
10
|
-
* pages with syntax-highlighted signatures, cross-linked type references, and
|
|
11
|
-
* interactive features.
|
|
12
|
-
*
|
|
13
|
-
* **Page Structure:**
|
|
14
|
-
* 1. Frontmatter with title, description, and Open Graph metadata
|
|
15
|
-
* 2. Component imports (SourceCode, ParametersTable, ApiSignature, etc.)
|
|
16
|
-
* 3. Page title (H1) and summary
|
|
17
|
-
* 4. Optional deprecation warning and release tag badge
|
|
18
|
-
* 5. Source code link toolbar
|
|
19
|
-
* 6. Full interface signature block showing all members
|
|
20
|
-
* 7. Member sections: Call Signatures, Construct Signatures, Index Signatures, Properties, Methods
|
|
21
|
-
* 8. Examples section with Twoslash-enabled code blocks
|
|
22
|
-
* 9. See Also references
|
|
23
|
-
*
|
|
24
|
-
* **Interface-Specific Features:**
|
|
25
|
-
* - Handles type parameters (generics) in interface declarations
|
|
26
|
-
* - Supports call signatures for callable interfaces
|
|
27
|
-
* - Supports construct signatures for constructable interfaces
|
|
28
|
-
* - Supports index signatures for dictionary-like interfaces
|
|
29
|
-
* - Handles extends clauses for interface inheritance
|
|
30
|
-
*
|
|
31
|
-
* **Relationships:**
|
|
32
|
-
* - Created and invoked by {@link ApiExtractorPlugin} during page generation
|
|
33
|
-
* - Uses `Signature.format` from `@tsdoctor/model` for formatting type signatures
|
|
34
|
-
* - Uses the `Tsdoc` / `ApiItems` modules from `@tsdoctor/model` for extracting documentation
|
|
35
|
-
* - Uses the per-build prose linker (`linkProse`) for adding type reference links
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```ts
|
|
39
|
-
* const generator = new InterfacePageGenerator();
|
|
40
|
-
* const { routePath, content } = await generator.generate(
|
|
41
|
-
* apiInterface,
|
|
42
|
-
* "/api/my-package",
|
|
43
|
-
* "my-package",
|
|
44
|
-
* "Interface",
|
|
45
|
-
* "My Package",
|
|
46
|
-
* sourceConfig,
|
|
47
|
-
* true, // suppressExampleErrors
|
|
48
|
-
* undefined, // llmsPlugin
|
|
49
|
-
* "claude-binary-plugin", // apiScope
|
|
50
|
-
* );
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @see {@link ClassPageGenerator} for class documentation
|
|
54
|
-
* @see {@link TypeAliasPageGenerator} for type alias documentation
|
|
55
|
-
*/
|
|
56
|
-
var InterfacePageGenerator = class {
|
|
57
|
-
/**
|
|
58
|
-
* Generate a markdown page for an interface
|
|
59
|
-
*
|
|
60
|
-
* @param apiScope - API scope identifier for VFS lookup
|
|
61
|
-
*/
|
|
62
|
-
async generate(apiInterface, baseRoute, packageName, singularName, apiScope, apiName, sourceConfig, suppressExampleErrors, llmsPlugin, availableFrom) {
|
|
63
|
-
const shouldSuppressErrors = suppressExampleErrors ?? true;
|
|
64
|
-
const name = apiInterface.displayName;
|
|
65
|
-
const summary = Tsdoc.summary(apiInterface) || "No description available.";
|
|
66
|
-
const releaseTag = Tsdoc.releaseTag(apiInterface);
|
|
67
|
-
let content = generateFrontmatter(name, summary, singularName, apiName);
|
|
68
|
-
content += `import { SourceCode } from "@rspress/core/theme";\n`;
|
|
69
|
-
content += `import { ParametersTable } from "rspress-plugin-api-extractor/runtime";\n`;
|
|
70
|
-
content += `import { ApiSignature, ApiMember, ApiExample } from "rspress-plugin-api-extractor/runtime";\n\n`;
|
|
71
|
-
content += `# ${name}\n\n`;
|
|
72
|
-
const deprecation = Tsdoc.deprecation(apiInterface);
|
|
73
|
-
if (deprecation) {
|
|
74
|
-
const message = escapeMdxGenerics(linkProse(deprecation.message));
|
|
75
|
-
content += `> ⚠️ **Deprecated:** ${message}\n\n`;
|
|
76
|
-
}
|
|
77
|
-
if (releaseTag !== "Public") content += `\`${releaseTag}\`\n\n`;
|
|
78
|
-
content += `${summary}\n\n`;
|
|
79
|
-
content += generateAvailableFrom(packageName, availableFrom);
|
|
80
|
-
const sourceLink = ApiItems.sourceLink(apiInterface, sourceConfig);
|
|
81
|
-
if (sourceLink) {
|
|
82
|
-
content += `<div className="api-docs-toolbar">\n`;
|
|
83
|
-
content += ` <div className="api-docs-toolbar-left">\n`;
|
|
84
|
-
content += ` <SourceCode href="${sourceLink}" />\n`;
|
|
85
|
-
content += ` </div>\n`;
|
|
86
|
-
if (llmsPlugin?.enabled) {
|
|
87
|
-
content += ` <div className="api-docs-toolbar-right">\n`;
|
|
88
|
-
content += ` </div>\n`;
|
|
89
|
-
}
|
|
90
|
-
content += `</div>\n\n`;
|
|
91
|
-
}
|
|
92
|
-
const skeleton = this.generateInterfaceSkeletonWithTwoslash(apiInterface, packageName);
|
|
93
|
-
const displayCode = stripTwoslashDirectives(skeleton);
|
|
94
|
-
content += `<ApiSignature code={${JSON.stringify(displayCode)}} source={${JSON.stringify(skeleton)}} apiScope={${JSON.stringify(apiScope)}} />\n\n`;
|
|
95
|
-
const callSignatures = apiInterface.members.filter((m) => m.kind === "CallSignature");
|
|
96
|
-
if (callSignatures.length > 0) {
|
|
97
|
-
content += `## Call Signatures\n\n`;
|
|
98
|
-
for (const callSig of callSignatures) {
|
|
99
|
-
const callSigSummary = Tsdoc.summary(callSig);
|
|
100
|
-
const callSigId = Routes.memberAnchor("call-signature");
|
|
101
|
-
const callSigItem = callSig;
|
|
102
|
-
if (callSigItem.excerpt?.text) {
|
|
103
|
-
const memberSignature = Signature.format(callSigItem.excerpt).trim();
|
|
104
|
-
const skeletonWithContext = this.generateInterfaceMemberWithContext(apiInterface, callSig, packageName);
|
|
105
|
-
const summaryMd = callSigSummary ? escapeMdxGenerics(linkProse(callSigSummary)) : void 0;
|
|
106
|
-
content += `<ApiMember code={${JSON.stringify(memberSignature)}} source={${JSON.stringify(skeletonWithContext)}} apiScope={${JSON.stringify(apiScope)}} memberName="Call Signature"${summaryMd ? ` summary={${JSON.stringify(summaryMd)}}` : ""} id={${JSON.stringify(callSigId)}} />\n\n`;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const constructSignatures = apiInterface.members.filter((m) => m.kind === "ConstructSignature");
|
|
111
|
-
if (constructSignatures.length > 0) {
|
|
112
|
-
content += `## Construct Signatures\n\n`;
|
|
113
|
-
for (const constructSig of constructSignatures) {
|
|
114
|
-
const constructSigSummary = Tsdoc.summary(constructSig);
|
|
115
|
-
const constructSigId = Routes.memberAnchor("construct-signature");
|
|
116
|
-
const constructSigItem = constructSig;
|
|
117
|
-
if (constructSigItem.excerpt?.text) {
|
|
118
|
-
const memberSignature = Signature.format(constructSigItem.excerpt).trim();
|
|
119
|
-
const skeletonWithContext = this.generateInterfaceMemberWithContext(apiInterface, constructSig, packageName);
|
|
120
|
-
const summaryMd = constructSigSummary ? escapeMdxGenerics(linkProse(constructSigSummary)) : void 0;
|
|
121
|
-
content += `<ApiMember code={${JSON.stringify(memberSignature)}} source={${JSON.stringify(skeletonWithContext)}} apiScope={${JSON.stringify(apiScope)}} memberName="Construct Signature"${summaryMd ? ` summary={${JSON.stringify(summaryMd)}}` : ""} id={${JSON.stringify(constructSigId)}} />\n\n`;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const indexSignatures = apiInterface.members.filter((m) => m.kind === "IndexSignature");
|
|
126
|
-
if (indexSignatures.length > 0) {
|
|
127
|
-
content += `## Index Signature\n\n`;
|
|
128
|
-
for (const indexSig of indexSignatures) {
|
|
129
|
-
const indexSigSummary = Tsdoc.summary(indexSig);
|
|
130
|
-
const indexSigId = Routes.memberAnchor("index-signature");
|
|
131
|
-
const indexSigItem = indexSig;
|
|
132
|
-
if (indexSigItem.excerpt?.text) {
|
|
133
|
-
const memberSignature = Signature.format(indexSigItem.excerpt).trim();
|
|
134
|
-
const skeletonWithContext = this.generateInterfaceMemberWithContext(apiInterface, indexSig, packageName);
|
|
135
|
-
const summaryMd = indexSigSummary ? escapeMdxGenerics(linkProse(indexSigSummary)) : void 0;
|
|
136
|
-
content += `<ApiMember code={${JSON.stringify(memberSignature)}} source={${JSON.stringify(skeletonWithContext)}} apiScope={${JSON.stringify(apiScope)}} memberName="Index Signature"${summaryMd ? ` summary={${JSON.stringify(summaryMd)}}` : ""} id={${JSON.stringify(indexSigId)}} />\n\n`;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
const properties = apiInterface.members.filter((m) => m.kind === "PropertySignature");
|
|
141
|
-
if (properties.length > 0) {
|
|
142
|
-
content += `## Properties\n\n`;
|
|
143
|
-
for (const prop of properties) {
|
|
144
|
-
const propSummary = Tsdoc.summary(prop);
|
|
145
|
-
const propId = Routes.memberAnchor(prop.displayName);
|
|
146
|
-
const propItem = prop;
|
|
147
|
-
if (propItem.excerpt?.text) {
|
|
148
|
-
const memberSignature = Signature.format(propItem.excerpt).trim();
|
|
149
|
-
const skeletonWithContext = this.generateInterfaceMemberWithContext(apiInterface, prop, packageName);
|
|
150
|
-
const summaryMd = propSummary ? escapeMdxGenerics(linkProse(propSummary)) : void 0;
|
|
151
|
-
content += `<ApiMember code={${JSON.stringify(memberSignature)}} source={${JSON.stringify(skeletonWithContext)}} apiScope={${JSON.stringify(apiScope)}} memberName={${JSON.stringify(prop.displayName)}}${summaryMd ? ` summary={${JSON.stringify(summaryMd)}}` : ""} id={${JSON.stringify(propId)}} />\n\n`;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
const methods = apiInterface.members.filter((m) => m.kind === "MethodSignature");
|
|
156
|
-
if (methods.length > 0) {
|
|
157
|
-
content += `## Methods\n\n`;
|
|
158
|
-
for (const method of methods) {
|
|
159
|
-
const methodSummary = Tsdoc.summary(method);
|
|
160
|
-
const methodId = Routes.memberAnchor(method.displayName);
|
|
161
|
-
const methodItem = method;
|
|
162
|
-
if (methodItem.excerpt?.text) {
|
|
163
|
-
const memberSignature = Signature.format(methodItem.excerpt).trim();
|
|
164
|
-
const skeletonWithContext = this.generateInterfaceMemberWithContext(apiInterface, method, packageName);
|
|
165
|
-
const hasParameters = Tsdoc.params(method).length > 0;
|
|
166
|
-
const summaryMd = methodSummary ? escapeMdxGenerics(linkProse(methodSummary)) : void 0;
|
|
167
|
-
content += `<ApiMember code={${JSON.stringify(memberSignature)}} source={${JSON.stringify(skeletonWithContext)}} apiScope={${JSON.stringify(apiScope)}} memberName={${JSON.stringify(method.displayName)}}${summaryMd ? ` summary={${JSON.stringify(summaryMd)}}` : ""} id={${JSON.stringify(methodId)}} hasParameters={${hasParameters}} />\n\n`;
|
|
168
|
-
}
|
|
169
|
-
const params = Tsdoc.params(method);
|
|
170
|
-
if (params.length > 0) content += `<ParametersTable parameters={${JSON.stringify(params.map((p) => ({
|
|
171
|
-
name: p.name,
|
|
172
|
-
type: p.type,
|
|
173
|
-
description: linkProse(p.description)
|
|
174
|
-
})))}} />\n\n`;
|
|
175
|
-
const returns = Tsdoc.returns(method);
|
|
176
|
-
if (returns) {
|
|
177
|
-
const description = escapeMdxGenerics(linkProse(returns.description));
|
|
178
|
-
content += `**Returns:** ${description}\n\n`;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const examples = Tsdoc.examples(apiInterface);
|
|
183
|
-
if (examples.length > 0) {
|
|
184
|
-
content += `## Examples\n\n`;
|
|
185
|
-
for (const example of examples) {
|
|
186
|
-
const prepared = prepareExampleCode(example, name, packageName, shouldSuppressErrors);
|
|
187
|
-
const formattedCode = await formatExampleCode(prepared.code, prepared.language, {
|
|
188
|
-
api: packageName,
|
|
189
|
-
blockType: "example"
|
|
190
|
-
});
|
|
191
|
-
if (prepared.isTypeScript) {
|
|
192
|
-
const displayCode = stripTwoslashDirectives(formattedCode);
|
|
193
|
-
content += `<ApiExample code={${JSON.stringify(displayCode)}} source={${JSON.stringify(formattedCode)}} apiScope={${JSON.stringify(apiScope)}} />\n\n`;
|
|
194
|
-
} else content += `\`\`\`${prepared.language}\n${formattedCode}\n\`\`\`\n\n`;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
const seeReferences = Tsdoc.seeReferences(apiInterface);
|
|
198
|
-
if (seeReferences.length > 0) {
|
|
199
|
-
content += `## See Also\n\n`;
|
|
200
|
-
for (const reference of seeReferences) {
|
|
201
|
-
const refText = escapeMdxGenerics(linkProse(reference.text));
|
|
202
|
-
content += `- ${refText}\n`;
|
|
203
|
-
}
|
|
204
|
-
content += `\n`;
|
|
205
|
-
}
|
|
206
|
-
return {
|
|
207
|
-
routePath: `${baseRoute}/interface/${name.toLowerCase()}`,
|
|
208
|
-
content
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Generate an interface member signature with full interface context
|
|
213
|
-
* Includes hidden imports with cut directive for external type resolution
|
|
214
|
-
* Uses the simplified approach: 3 lines (interface opening, member, closing)
|
|
215
|
-
*/
|
|
216
|
-
generateInterfaceMemberWithContext(apiInterface, targetMember, packageName) {
|
|
217
|
-
const interfaceName = apiInterface.displayName;
|
|
218
|
-
const inheritance = ApiItems.inheritance(apiInterface);
|
|
219
|
-
let declaration = `interface ${interfaceName}`;
|
|
220
|
-
if (apiInterface.typeParameters && apiInterface.typeParameters.length > 0) {
|
|
221
|
-
const typeParams = apiInterface.typeParameters.map((tp) => tp.name).join(", ");
|
|
222
|
-
declaration += `<${typeParams}>`;
|
|
223
|
-
}
|
|
224
|
-
if (inheritance.extends && inheritance.extends.length > 0) declaration += ` extends ${inheritance.extends.join(", ")}`;
|
|
225
|
-
declaration += " {";
|
|
226
|
-
const memberItem = targetMember;
|
|
227
|
-
const memberSignature = memberItem.excerpt?.text ? Signature.format(memberItem.excerpt).trim() : "";
|
|
228
|
-
const skeleton = `${declaration}\n${memberSignature}\n}`;
|
|
229
|
-
const apiPackage = apiInterface.getAssociatedPackage?.();
|
|
230
|
-
if (apiPackage) {
|
|
231
|
-
const imports = new TypeReferenceExtractor(apiPackage, packageName).extractImportsForApiItem(targetMember);
|
|
232
|
-
return prependHiddenImports(skeleton, imports);
|
|
233
|
-
}
|
|
234
|
-
return skeleton;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Generate an interface skeleton for signature blocks
|
|
238
|
-
* Includes hidden imports with cut directive for external type resolution
|
|
239
|
-
*/
|
|
240
|
-
generateInterfaceSkeletonWithTwoslash(apiInterface, packageName) {
|
|
241
|
-
const skeleton = this.generateInterfaceSkeleton(apiInterface);
|
|
242
|
-
const apiPackage = apiInterface.getAssociatedPackage?.();
|
|
243
|
-
if (apiPackage) {
|
|
244
|
-
const imports = new TypeReferenceExtractor(apiPackage, packageName).extractImportsForApiItem(apiInterface);
|
|
245
|
-
return prependHiddenImports(skeleton, imports);
|
|
246
|
-
}
|
|
247
|
-
return skeleton;
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Generate a complete interface skeleton showing all members
|
|
251
|
-
*/
|
|
252
|
-
generateInterfaceSkeleton(apiInterface) {
|
|
253
|
-
const lines = [];
|
|
254
|
-
const interfaceName = apiInterface.displayName;
|
|
255
|
-
const inheritance = ApiItems.inheritance(apiInterface);
|
|
256
|
-
let declaration = `interface ${interfaceName}`;
|
|
257
|
-
if (apiInterface.typeParameters && apiInterface.typeParameters.length > 0) {
|
|
258
|
-
const typeParams = apiInterface.typeParameters.map((tp) => tp.name).join(", ");
|
|
259
|
-
declaration += `<${typeParams}>`;
|
|
260
|
-
}
|
|
261
|
-
if (inheritance.extends && inheritance.extends.length > 0) declaration += ` extends ${inheritance.extends.join(", ")}`;
|
|
262
|
-
declaration += " {";
|
|
263
|
-
lines.push(declaration);
|
|
264
|
-
const callSignatures = apiInterface.members.filter((m) => m.kind === "CallSignature");
|
|
265
|
-
if (callSignatures.length > 0) for (const callSig of callSignatures) {
|
|
266
|
-
const callSigItem = callSig;
|
|
267
|
-
if (callSigItem.excerpt?.text) {
|
|
268
|
-
const signature = Signature.format(callSigItem.excerpt).trim();
|
|
269
|
-
lines.push(` ${signature}`);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
const constructSignatures = apiInterface.members.filter((m) => m.kind === "ConstructSignature");
|
|
273
|
-
if (constructSignatures.length > 0) for (const constructSig of constructSignatures) {
|
|
274
|
-
const constructSigItem = constructSig;
|
|
275
|
-
if (constructSigItem.excerpt?.text) {
|
|
276
|
-
const signature = Signature.format(constructSigItem.excerpt).trim();
|
|
277
|
-
lines.push(` ${signature}`);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
const indexSignatures = apiInterface.members.filter((m) => m.kind === "IndexSignature");
|
|
281
|
-
if (indexSignatures.length > 0) for (const indexSig of indexSignatures) {
|
|
282
|
-
const indexSigItem = indexSig;
|
|
283
|
-
if (indexSigItem.excerpt?.text) {
|
|
284
|
-
const signature = Signature.format(indexSigItem.excerpt).trim();
|
|
285
|
-
lines.push(` ${signature}`);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
const properties = apiInterface.members.filter((m) => m.kind === "PropertySignature");
|
|
289
|
-
if (properties.length > 0) for (const prop of properties) {
|
|
290
|
-
const propItem = prop;
|
|
291
|
-
if (propItem.excerpt?.text) {
|
|
292
|
-
const signature = Signature.format(propItem.excerpt).trim();
|
|
293
|
-
lines.push(` ${signature}`);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
const methods = apiInterface.members.filter((m) => m.kind === "MethodSignature");
|
|
297
|
-
if (methods.length > 0) for (const method of methods) {
|
|
298
|
-
const methodItem = method;
|
|
299
|
-
if (methodItem.excerpt?.text) {
|
|
300
|
-
const signature = Signature.format(methodItem.excerpt).trim();
|
|
301
|
-
lines.push(` ${signature}`);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
lines.push("}");
|
|
305
|
-
return lines.join("\n");
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
//#endregion
|
|
310
|
-
export { InterfacePageGenerator };
|