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.
Files changed (37) hide show
  1. package/BuildEnv.js +0 -1
  2. package/build-program.js +4 -4
  3. package/build-stages.js +98 -281
  4. package/config-helpers.js +1 -1
  5. package/emit/mdx.js +311 -0
  6. package/emit/meta.js +62 -0
  7. package/index.d.ts +1 -42
  8. package/layers/build-metrics.js +1 -2
  9. package/layers/config-resolution.js +3 -5
  10. package/layers/type-environment.js +1 -2
  11. package/llms-program.js +3 -3
  12. package/markdown/helpers.js +10 -176
  13. package/observability/sinks/console-sink.js +0 -1
  14. package/observability/sinks/metrics-sink.js +0 -2
  15. package/package.json +6 -5
  16. package/path-derivation.js +1 -29
  17. package/plugin.js +2 -1
  18. package/prettier-formatter.js +27 -59
  19. package/remark-with-api.js +3 -2
  20. package/schemas/config.js +1 -18
  21. package/schemas/observability.js +0 -2
  22. package/schemas/performance.js +0 -1
  23. package/services/TwoslashCacheService.js +1 -1
  24. package/twoslash-transformer.js +14 -2
  25. package/code-post-processor.js +0 -38
  26. package/llms-processing.js +0 -270
  27. package/markdown/page-generators/class-page.js +0 -363
  28. package/markdown/page-generators/enum-page.js +0 -152
  29. package/markdown/page-generators/function-page.js +0 -127
  30. package/markdown/page-generators/index-pages.js +0 -25
  31. package/markdown/page-generators/interface-page.js +0 -310
  32. package/markdown/page-generators/namespace-page.js +0 -277
  33. package/markdown/page-generators/type-alias-page.js +0 -110
  34. package/markdown/page-generators/variable-page.js +0 -110
  35. package/markdown/prose-linker.js +0 -22
  36. package/twoslash-cache.js +0 -174
  37. package/twoslash-patterns.js +0 -87
package/emit/mdx.js ADDED
@@ -0,0 +1,311 @@
1
+ import { Result } from "effect";
2
+ import { Blockquote, Code, Heading, InlineCode, Link, List, ListItem, Markdown, MdxJsxAttribute, MdxJsxAttributeValueExpression, MdxJsxFlowElement, MdxjsEsm, Paragraph, Root, Strong, Text } from "@effected/markdown";
3
+
4
+ //#region src/emit/mdx.ts
5
+ /** Serialize one flow node as its own document, without the trailing newline. */
6
+ function serialize(node) {
7
+ return Result.map(Markdown.stringifyResult(Root.make({ children: [node] })), (text) => text.replace(/\n$/, ""));
8
+ }
9
+ /** Serialize phrasing content to the one-line string a JSX prop or a table cell carries. */
10
+ function inlineText(children) {
11
+ if (children.length === 0) return Result.succeed("");
12
+ return serialize(Paragraph.make({ children: [...children] }));
13
+ }
14
+ const GENERICS = /<([A-Z][A-Za-z0-9_]*(?:\s+extends\s+[^,>\s][^,>]*)?(?:,\s*[A-Z][A-Za-z0-9_]*(?:\s+extends\s+[^,>\s][^,>]*)?)*)>/g;
15
+ /**
16
+ * {@link escapeMdxGenerics} as an mdast transform: a generic parameter list
17
+ * in a text run becomes an inline code node, and a raw-HTML node that IS a
18
+ * generic (`<T>` parses as an HTML tag) becomes one too. Code spans are
19
+ * already inline code and are left alone; container nodes are walked.
20
+ *
21
+ * @remarks
22
+ * Done on the tree rather than on the serialized string because the kit
23
+ * escapes a bare `<` in text (`Map\<K, V\>`) as it serializes, and the
24
+ * string-level regex would no longer see the generic. The two spellings are
25
+ * the same MDX; the tree form is what lets the kit own every byte.
26
+ */
27
+ function escapeGenericsInPhrasing(children) {
28
+ const out = [];
29
+ for (const node of children) if (node.type === "text") {
30
+ let last = 0;
31
+ for (const match of node.value.matchAll(GENERICS)) {
32
+ const index = match.index ?? 0;
33
+ if (index > last) out.push(Text.make({ value: node.value.slice(last, index) }));
34
+ out.push(InlineCode.make({ value: match[0] }));
35
+ last = index + match[0].length;
36
+ }
37
+ if (last === 0) out.push(node);
38
+ else if (last < node.value.length) out.push(Text.make({ value: node.value.slice(last) }));
39
+ } else if (node.type === "html" && new RegExp(`^${GENERICS.source}$`).test(node.value)) out.push(InlineCode.make({ value: node.value }));
40
+ else if (node.type === "link" || node.type === "strong" || node.type === "emphasis" || node.type === "delete") out.push({
41
+ ...node,
42
+ children: [...escapeGenericsInPhrasing(node.children)]
43
+ });
44
+ else out.push(node);
45
+ return out;
46
+ }
47
+ /** Phrasing content with generics escaped — the tree form of {@link escapeMdxGenerics}. */
48
+ function escapedPhrasing(children) {
49
+ return Result.succeed(escapeGenericsInPhrasing(children));
50
+ }
51
+ const text = (value) => Text.make({ value });
52
+ const paragraph = (children) => Paragraph.make({ children: [...children] });
53
+ const heading = (depth, value) => Heading.make({
54
+ depth,
55
+ children: [text(value)]
56
+ });
57
+ const code = (value) => InlineCode.make({ value });
58
+ const expression = (name, value) => MdxJsxAttribute.make({
59
+ name,
60
+ value: MdxJsxAttributeValueExpression.make({ value: JSON.stringify(value) })
61
+ });
62
+ const literal = (name, value) => MdxJsxAttribute.make({
63
+ name,
64
+ value
65
+ });
66
+ const element = (name, attributes, children = []) => MdxJsxFlowElement.make({
67
+ name,
68
+ attributes: [...attributes],
69
+ children: [...children]
70
+ });
71
+ var Body = class {
72
+ chunks = [];
73
+ failure;
74
+ push(node, trailing = "\n\n") {
75
+ if (this.failure) return;
76
+ const result = serialize(node);
77
+ if (Result.isFailure(result)) {
78
+ this.failure = result.failure;
79
+ return;
80
+ }
81
+ this.chunks.push({
82
+ text: result.success,
83
+ trailing
84
+ });
85
+ }
86
+ /** Push a heading. */
87
+ heading(depth, value) {
88
+ this.push(heading(depth, value));
89
+ }
90
+ pushResult(result, use) {
91
+ if (this.failure) return;
92
+ if (Result.isFailure(result)) {
93
+ this.failure = result.failure;
94
+ return;
95
+ }
96
+ use(result.success);
97
+ }
98
+ render() {
99
+ if (this.failure) return Result.fail(this.failure);
100
+ return Result.succeed(this.chunks.map((chunk) => chunk.text + chunk.trailing).join(""));
101
+ }
102
+ };
103
+ const RUNTIME = "rspress-plugin-api-extractor/runtime";
104
+ /** The component import lines each page kind carried. */
105
+ function importLines(kind) {
106
+ const lines = [`import { SourceCode } from "@rspress/core/theme";`];
107
+ if (kind === "enum") lines.push(`import { EnumMembersTable } from "${RUNTIME}";`);
108
+ else if (kind !== "namespace") lines.push(`import { ParametersTable } from "${RUNTIME}";`);
109
+ const components = kind === "class" || kind === "interface" ? "ApiSignature, ApiMember, ApiExample" : "ApiSignature, ApiExample";
110
+ lines.push(`import { ${components} } from "${RUNTIME}";`);
111
+ return lines.join("\n");
112
+ }
113
+ function parameterRows(rows, escapeGenerics) {
114
+ return Result.all(rows.map((row) => Result.map(inlineText(escapeGenerics ? escapeGenericsInPhrasing(row.description) : row.description), (description) => ({
115
+ name: row.name,
116
+ ...row.type !== void 0 ? { type: row.type } : {},
117
+ description
118
+ }))));
119
+ }
120
+ function enumRows(rows) {
121
+ return Result.all(rows.map((row) => Result.map(inlineText(row.description), (description) => ({
122
+ name: row.name,
123
+ ...row.value !== void 0 ? { value: row.value } : {},
124
+ description
125
+ }))));
126
+ }
127
+ /** The literal `memberName` a role fixes, or none when the member's own name is spent as an expression. */
128
+ function fixedMemberName(member) {
129
+ switch (member.role) {
130
+ case "constructor": return "constructor";
131
+ case "call-signature": return "Call Signature";
132
+ case "construct-signature": return "Construct Signature";
133
+ case "index-signature": return "Index Signature";
134
+ default: return;
135
+ }
136
+ }
137
+ /** Whether the role carried a `hasParameters` prop — constructors and methods, never properties or signatures. */
138
+ function carriesHasParameters(member) {
139
+ return member.role === "constructor" || member.role === "method" || member.role === "getter";
140
+ }
141
+ function emitMember(body, member, apiScope) {
142
+ body.pushResult(member.summary ? escapedPhrasing(member.summary) : Result.succeed(void 0), (summaryNodes) => {
143
+ body.pushResult(summaryNodes ? inlineText(summaryNodes) : Result.succeed(""), (summary) => {
144
+ const fixedName = fixedMemberName(member);
145
+ const attributes = [
146
+ expression("code", member.code.display),
147
+ expression("source", member.code.source),
148
+ expression("apiScope", apiScope),
149
+ fixedName !== void 0 ? literal("memberName", fixedName) : expression("memberName", member.name)
150
+ ];
151
+ if (summary) attributes.push(expression("summary", summary));
152
+ attributes.push(expression("id", member.anchor));
153
+ if (carriesHasParameters(member)) attributes.push(expression("hasParameters", member.parameters !== void 0));
154
+ body.push(element("ApiMember", attributes));
155
+ });
156
+ });
157
+ if (member.parameters !== void 0) body.pushResult(parameterRows(member.parameters, false), (rows) => {
158
+ body.push(element("ParametersTable", [expression("parameters", rows)]));
159
+ });
160
+ if (member.returns !== void 0) body.pushResult(escapedPhrasing(member.returns), (returns) => {
161
+ body.push(paragraph([
162
+ Strong.make({ children: [text("Returns:")] }),
163
+ text(" "),
164
+ ...returns
165
+ ]));
166
+ });
167
+ }
168
+ function emitBlock(body, block, page, options) {
169
+ const { apiScope } = options;
170
+ switch (block.kind) {
171
+ case "title":
172
+ body.heading(1, block.name);
173
+ if (block.deprecation !== void 0) body.pushResult(escapedPhrasing(block.deprecation), (message) => {
174
+ body.push(Blockquote.make({ children: [paragraph([
175
+ text("⚠️ "),
176
+ Strong.make({ children: [text("Deprecated:")] }),
177
+ text(" "),
178
+ ...message
179
+ ])] }));
180
+ });
181
+ if (block.releaseTag !== "Public") body.push(paragraph([code(block.releaseTag)]));
182
+ return;
183
+ case "prose":
184
+ if (block.role === "summary") {
185
+ for (const node of block.content) body.push(node);
186
+ return;
187
+ }
188
+ body.heading(2, block.role === "remarks" ? "Remarks" : "Returns");
189
+ for (const node of block.content) if (block.role === "returns" && node.type === "paragraph") body.pushResult(escapedPhrasing(node.children), (children) => body.push(paragraph(children)));
190
+ else body.push(node);
191
+ return;
192
+ case "available-from": {
193
+ const children = [text("Available from: ")];
194
+ block.entryPoints.forEach((entryPoint, index) => {
195
+ if (index > 0) children.push(text(", "));
196
+ children.push(code(entryPoint === "default" ? block.packageName : `${block.packageName}/${entryPoint}`));
197
+ });
198
+ body.push(paragraph(children));
199
+ return;
200
+ }
201
+ case "source-link": {
202
+ const children = [element("div", [literal("className", "api-docs-toolbar-left")], [element("SourceCode", [literal("href", block.href)])])];
203
+ if (options.llmsEnabled) children.push(element("div", [literal("className", "api-docs-toolbar-right")]));
204
+ body.push(element("div", [literal("className", "api-docs-toolbar")], children));
205
+ return;
206
+ }
207
+ case "signature": {
208
+ const attributes = [
209
+ expression("code", block.code.display),
210
+ expression("source", block.code.source),
211
+ expression("apiScope", apiScope)
212
+ ];
213
+ if (block.hasParameters !== void 0) attributes.push(expression("hasParameters", block.hasParameters));
214
+ if (block.hasMembers !== void 0) attributes.push(expression("hasMembers", block.hasMembers));
215
+ body.push(element("ApiSignature", attributes), block.hasMembers === true ? "\n" : "\n\n");
216
+ return;
217
+ }
218
+ case "base-class":
219
+ body.heading(2, "Base Class");
220
+ body.push(paragraph([
221
+ code(block.className),
222
+ text(" extends "),
223
+ code(block.baseName),
224
+ text(", a compiler-generated declaration that is not exported from "),
225
+ code(block.packageName),
226
+ text(".")
227
+ ]));
228
+ body.push(element("ApiSignature", [
229
+ expression("code", block.code.display),
230
+ expression("source", block.code.source),
231
+ expression("apiScope", apiScope)
232
+ ]));
233
+ return;
234
+ case "member-group":
235
+ body.heading(2, block.title);
236
+ for (const member of block.members) emitMember(body, member, apiScope);
237
+ return;
238
+ case "parameters":
239
+ body.pushResult(parameterRows(block.rows, true), (rows) => {
240
+ body.push(element("ParametersTable", [expression("parameters", rows)]));
241
+ });
242
+ return;
243
+ case "enum-members":
244
+ body.pushResult(enumRows(block.rows), (rows) => {
245
+ body.push(element("EnumMembersTable", [expression("members", rows)]));
246
+ });
247
+ return;
248
+ case "examples":
249
+ body.heading(2, "Examples");
250
+ for (const example of block.items) if (example.typeChecked) body.push(element("ApiExample", [
251
+ expression("code", example.code.display),
252
+ expression("source", example.code.source),
253
+ expression("apiScope", apiScope)
254
+ ]));
255
+ else body.push(Code.make({
256
+ value: example.code.display,
257
+ lang: example.language
258
+ }));
259
+ return;
260
+ case "see-also":
261
+ body.heading(2, "See Also");
262
+ body.pushResult(Result.all(block.references.map(escapedPhrasing)), (references) => {
263
+ body.push(List.make({
264
+ ordered: false,
265
+ spread: false,
266
+ children: references.map((reference) => ListItem.make({
267
+ spread: false,
268
+ children: [paragraph(reference)]
269
+ }))
270
+ }));
271
+ });
272
+ return;
273
+ case "member-index":
274
+ body.heading(2, block.title);
275
+ body.pushResult(Result.all(block.entries.map((entry) => entry.summary ? escapedPhrasing(entry.summary) : Result.succeed(void 0))), (summaries) => {
276
+ const items = block.entries.map((entry, index) => {
277
+ const children = [Link.make({
278
+ url: entry.route,
279
+ children: [text(entry.name)]
280
+ })];
281
+ const summary = summaries[index];
282
+ if (summary !== void 0) children.push(text(" - "), ...summary);
283
+ return ListItem.make({
284
+ spread: false,
285
+ children: [paragraph(children)]
286
+ });
287
+ });
288
+ body.push(List.make({
289
+ ordered: false,
290
+ spread: false,
291
+ children: items
292
+ }));
293
+ });
294
+ return;
295
+ }
296
+ }
297
+ /**
298
+ * Emit a page's MDX body: the component import lines followed by every
299
+ * block, joined as the generators joined them. No frontmatter — the adapter
300
+ * assembles that from the page facts, in the generate stage the snapshot
301
+ * hash is taken in.
302
+ */
303
+ function emitMdxBody(page, options) {
304
+ const body = new Body();
305
+ body.push(MdxjsEsm.make({ value: importLines(page.kind) }));
306
+ for (const block of page.blocks) emitBlock(body, block, page, options);
307
+ return body.render();
308
+ }
309
+
310
+ //#endregion
311
+ export { emitMdxBody };
package/emit/meta.js ADDED
@@ -0,0 +1,62 @@
1
+ import { emitFrontmatterBlock } from "@tsdoctor/model";
2
+
3
+ //#region src/emit/meta.ts
4
+ /**
5
+ * The RSPress navigation and landing-page emitters: the root and
6
+ * per-category `_meta.json` files rendered from a `@tsdoctor/pages`
7
+ * {@link NavTree}, and the `index.mdx` frontmatter rendered from an
8
+ * {@link IndexPage}.
9
+ *
10
+ * @remarks
11
+ * Pure functions of the IR. The renderer defaults (`collapsible` and
12
+ * `collapsed` true, `overviewHeaders` `[2]`) are RSPress sidebar policy the
13
+ * tree leaves to its consumer; the tab-indented JSON is the spelling the
14
+ * snapshot system compares an existing file against.
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+ /** The root `_meta.json` entries, one per category group that received a page. */
19
+ function rootMetaEntries(tree) {
20
+ return tree.groups.map((group) => ({
21
+ type: "dir",
22
+ name: group.category.folderName,
23
+ label: group.category.displayName,
24
+ collapsible: group.category.collapsible ?? true,
25
+ collapsed: group.category.collapsed ?? true,
26
+ overviewHeaders: group.category.overviewHeaders ?? [2]
27
+ }));
28
+ }
29
+ /** A category folder's `_meta.json` entries, in the tree's (label-sorted) order. */
30
+ function categoryMetaEntries(group) {
31
+ return group.pages.map((page) => ({
32
+ type: "file",
33
+ name: page.name,
34
+ label: page.label
35
+ }));
36
+ }
37
+ /** Serialize `_meta.json` entries the way the plugin always has: tab-indented JSON, no trailing newline. */
38
+ function renderMeta(entries) {
39
+ return JSON.stringify(entries, null, " ");
40
+ }
41
+ /** The root `_meta.json` text for an API. */
42
+ function renderRootMeta(tree) {
43
+ return renderMeta(rootMetaEntries(tree));
44
+ }
45
+ /** A category folder's `_meta.json` text. */
46
+ function renderCategoryMeta(group) {
47
+ return renderMeta(categoryMetaEntries(group));
48
+ }
49
+ /**
50
+ * The `index.mdx` text for an API: frontmatter only, with RSPress's
51
+ * `overview: true` so the page lists its category folders.
52
+ */
53
+ function emitIndexPage(index) {
54
+ return emitFrontmatterBlock({
55
+ title: index.title,
56
+ description: index.description,
57
+ overview: true
58
+ });
59
+ }
60
+
61
+ //#endregion
62
+ export { categoryMetaEntries, emitIndexPage, renderCategoryMeta, renderMeta, renderRootMeta, rootMetaEntries };
package/index.d.ts CHANGED
@@ -12,14 +12,6 @@ import "unified";
12
12
  import "vfile";
13
13
  import "react";
14
14
  //#region src/schemas/config.d.ts
15
- /**
16
- * Verbosity level for plugin build output.
17
- *
18
- * @public
19
- */
20
- declare const LogLevel: Schema.Literals<readonly ["none", "info", "verbose", "debug", "warn", "error"]>;
21
- /** @public */
22
- type LogLevel = typeof LogLevel.Type;
23
15
  /**
24
16
  * Configuration for a single documentation category (e.g. Classes, Functions).
25
17
  *
@@ -34,8 +26,6 @@ declare const CategoryConfig: Schema.Struct<{
34
26
  readonly folderName: Schema.String;
35
27
  /** API item kinds included in this category. */
36
28
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
37
- /** TSDoc modifier tag that marks items for this category. */
38
- readonly tsdocModifier: Schema.optional<Schema.String>;
39
29
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
40
30
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
41
31
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -90,8 +80,6 @@ declare const VersionConfig: Schema.Struct<{
90
80
  readonly folderName: Schema.String;
91
81
  /** API item kinds included in this category. */
92
82
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
93
- /** TSDoc modifier tag that marks items for this category. */
94
- readonly tsdocModifier: Schema.optional<Schema.String>;
95
83
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
96
84
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
97
85
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -110,8 +98,6 @@ declare const VersionConfig: Schema.Struct<{
110
98
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
111
99
  readonly name: Schema.String;
112
100
  readonly version: Schema.String;
113
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
114
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
115
101
  }>>>>;
116
102
  /** Auto-detect external packages from `package.json` dependency fields. */
117
103
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -176,8 +162,6 @@ declare const SingleApiConfig: Schema.Struct<{
176
162
  readonly folderName: Schema.String;
177
163
  /** API item kinds included in this category. */
178
164
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
179
- /** TSDoc modifier tag that marks items for this category. */
180
- readonly tsdocModifier: Schema.optional<Schema.String>;
181
165
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
182
166
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
183
167
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -196,8 +180,6 @@ declare const SingleApiConfig: Schema.Struct<{
196
180
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
197
181
  readonly name: Schema.String;
198
182
  readonly version: Schema.String;
199
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
200
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
201
183
  }>>>>;
202
184
  /** Auto-detect external packages from `package.json` dependency fields. */
203
185
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -241,8 +223,6 @@ declare const SingleApiConfig: Schema.Struct<{
241
223
  readonly folderName: Schema.String;
242
224
  /** API item kinds included in this category. */
243
225
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
244
- /** TSDoc modifier tag that marks items for this category. */
245
- readonly tsdocModifier: Schema.optional<Schema.String>;
246
226
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
247
227
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
248
228
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -261,8 +241,6 @@ declare const SingleApiConfig: Schema.Struct<{
261
241
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
262
242
  readonly name: Schema.String;
263
243
  readonly version: Schema.String;
264
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
265
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
266
244
  }>>>>;
267
245
  /** Auto-detect external packages from `package.json` dependency fields. */
268
246
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -330,8 +308,6 @@ declare const MultiApiConfig: Schema.Struct<{
330
308
  readonly folderName: Schema.String;
331
309
  /** API item kinds included in this category. */
332
310
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
333
- /** TSDoc modifier tag that marks items for this category. */
334
- readonly tsdocModifier: Schema.optional<Schema.String>;
335
311
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
336
312
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
337
313
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -350,8 +326,6 @@ declare const MultiApiConfig: Schema.Struct<{
350
326
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
351
327
  readonly name: Schema.String;
352
328
  readonly version: Schema.String;
353
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
354
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
355
329
  }>>>>;
356
330
  /** Auto-detect external packages from `package.json` dependency fields. */
357
331
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -442,8 +416,6 @@ declare const PluginOptions: Schema.Struct<{
442
416
  readonly folderName: Schema.String;
443
417
  /** API item kinds included in this category. */
444
418
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
445
- /** TSDoc modifier tag that marks items for this category. */
446
- readonly tsdocModifier: Schema.optional<Schema.String>;
447
419
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
448
420
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
449
421
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -462,8 +434,6 @@ declare const PluginOptions: Schema.Struct<{
462
434
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
463
435
  readonly name: Schema.String;
464
436
  readonly version: Schema.String;
465
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
466
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
467
437
  }>>>>;
468
438
  /** Auto-detect external packages from `package.json` dependency fields. */
469
439
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -507,8 +477,6 @@ declare const PluginOptions: Schema.Struct<{
507
477
  readonly folderName: Schema.String;
508
478
  /** API item kinds included in this category. */
509
479
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
510
- /** TSDoc modifier tag that marks items for this category. */
511
- readonly tsdocModifier: Schema.optional<Schema.String>;
512
480
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
513
481
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
514
482
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -527,8 +495,6 @@ declare const PluginOptions: Schema.Struct<{
527
495
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
528
496
  readonly name: Schema.String;
529
497
  readonly version: Schema.String;
530
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
531
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
532
498
  }>>>>;
533
499
  /** Auto-detect external packages from `package.json` dependency fields. */
534
500
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -590,8 +556,6 @@ declare const PluginOptions: Schema.Struct<{
590
556
  readonly folderName: Schema.String;
591
557
  /** API item kinds included in this category. */
592
558
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
593
- /** TSDoc modifier tag that marks items for this category. */
594
- readonly tsdocModifier: Schema.optional<Schema.String>;
595
559
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
596
560
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
597
561
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -610,8 +574,6 @@ declare const PluginOptions: Schema.Struct<{
610
574
  readonly externalPackages: Schema.optional<Schema.mutable<Schema.$Array<Schema.Struct<{
611
575
  readonly name: Schema.String;
612
576
  readonly version: Schema.String;
613
- readonly tsconfig: Schema.optional<Schema.declare<string | URL | ((...args: Array<unknown>) => unknown), string | URL | ((...args: Array<unknown>) => unknown)>>;
614
- readonly compilerOptions: Schema.optional<Schema.Unknown>;
615
577
  }>>>>;
616
578
  /** Auto-detect external packages from `package.json` dependency fields. */
617
579
  readonly autoDetectDependencies: Schema.optional<Schema.Struct<{
@@ -677,8 +639,6 @@ declare const PluginOptions: Schema.Struct<{
677
639
  readonly folderName: Schema.String;
678
640
  /** API item kinds included in this category. */
679
641
  readonly itemKinds: Schema.optional<Schema.mutable<Schema.$Array<Schema.declare<ApiItemKind, ApiItemKind>>>>;
680
- /** TSDoc modifier tag that marks items for this category. */
681
- readonly tsdocModifier: Schema.optional<Schema.String>;
682
642
  /** Whether the sidebar section is collapsible. Defaults to `true`. */
683
643
  readonly collapsible: Schema.withDecodingDefault<Schema.Boolean, never>;
684
644
  /** Whether the sidebar section starts collapsed. Defaults to `true`. */
@@ -710,7 +670,6 @@ declare const PluginOptions: Schema.Struct<{
710
670
  readonly slowPageGeneration: Schema.withDecodingDefault<Schema.Number, never>;
711
671
  readonly slowApiLoad: Schema.withDecodingDefault<Schema.Number, never>;
712
672
  readonly slowFileOperation: Schema.withDecodingDefault<Schema.Number, never>;
713
- readonly slowHttpRequest: Schema.withDecodingDefault<Schema.Number, never>;
714
673
  readonly slowDbOperation: Schema.withDecodingDefault<Schema.Number, never>;
715
674
  }>>;
716
675
  }>>;
@@ -936,5 +895,5 @@ declare function resolveServeConfig(options?: ServeOptions): ResolvedServeConfig
936
895
  */
937
896
  declare function serve(options?: ServeOptions): Promise<void>;
938
897
  //#endregion
939
- export { ApiExtractorPlugin, type PluginOptions as ApiExtractorPluginOptions, type BaseRoute, type CategoryConfig, DEFAULT_CATEGORIES, type DirInfo, type FromDirOptions, type LoadedModel, type LogLevel, type MultiApiConfig, type OpenGraphImageConfig, type OpenGraphImageMetadata, type OpenGraphMetadata, type ResolvedServeConfig, type ServeMode, type ServeOptions, type SingleApiConfig, type SourceConfig, type VersionConfig, isServerReady, resolveServeConfig, serve };
898
+ export { ApiExtractorPlugin, type PluginOptions as ApiExtractorPluginOptions, type BaseRoute, type CategoryConfig, DEFAULT_CATEGORIES, type DirInfo, type FromDirOptions, type LoadedModel, type MultiApiConfig, type OpenGraphImageConfig, type OpenGraphImageMetadata, type OpenGraphMetadata, type ResolvedServeConfig, type ServeMode, type ServeOptions, type SingleApiConfig, type SourceConfig, type VersionConfig, isServerReady, resolveServeConfig, serve };
940
899
  //# sourceMappingURL=index.d.ts.map
@@ -81,8 +81,7 @@ const BuildMetrics = {
81
81
  phaseTimeMs: Metric.counter("phase.time.ms"),
82
82
  vfsFiles: Metric.counter("vfs.files"),
83
83
  importsPrepended: Metric.counter("imports.prepended"),
84
- twoslashDiagnostics: Metric.counter("twoslash.diagnostics"),
85
- configDefaultsApplied: Metric.counter("config.defaults.applied")
84
+ twoslashDiagnostics: Metric.counter("twoslash.diagnostics")
86
85
  };
87
86
 
88
87
  //#endregion
@@ -4,22 +4,22 @@ import { PluginEvent } from "../observability/events.js";
4
4
  import { emit, wantsLevel } from "../observability/EventBus.js";
5
5
  import { withPhase } from "../observability/spans.js";
6
6
  import { normalizeThemeConfig } from "../markdown/shiki-utils.js";
7
- import { apiScopeOf, deriveOutputPaths, normalizeBaseRoute, unscopedName } from "../path-derivation.js";
8
7
  import { classifyApiConfig, extractAutoDetectedPackages, isVersionConfig, mergeLlmsPluginConfig, validateExternalPackages } from "../config-utils.js";
9
8
  import { CategoryResolver } from "../category-resolver.js";
10
9
  import { ConfigValidationError } from "../errors.js";
11
10
  import { loadApiModel, loadPackageJson, loadVersionModel } from "../model-loader.js";
11
+ import { deriveOutputPaths } from "../path-derivation.js";
12
12
  import { DEFAULT_CATEGORIES } from "../schemas/config.js";
13
13
  import { PluginConfig } from "../services/PluginConfig.js";
14
14
  import { TypeRegistryService } from "../services/TypeRegistryService.js";
15
15
  import { emitVfsPayloadEvents, mergeApiResult } from "./api-results.js";
16
16
  import { mergeExternalTypes } from "./external-types.js";
17
17
  import { registerTypeEnvironments, resolveTsConfigTyped } from "./type-environment.js";
18
- import path from "node:path";
18
+ import { apiScopeOf, normalizeBaseRoute, unscopedName } from "@tsdoctor/pages";
19
19
  import { Effect, Metric } from "effect";
20
+ import { ApiExtractedPackage, TypeReferenceExtractor } from "@tsdoctor/model";
20
21
  import { deriveSiteUrl } from "@tsdoctor/seo";
21
22
  import { hashContent } from "@tsdoctor/snapshot";
22
- import { ApiExtractedPackage, TypeReferenceExtractor } from "@tsdoctor/model";
23
23
  import { PackageManifest } from "@effected/package-json";
24
24
 
25
25
  //#region src/layers/config-resolution.ts
@@ -261,7 +261,6 @@ const makeConfigService = Effect.gen(function* () {
261
261
  ...resolvedLlms != null ? { llmsPlugin: resolvedLlms } : {},
262
262
  ...siteUrl != null ? { siteUrl } : {},
263
263
  ...resolvedOgImage != null ? { ogImage: resolvedOgImage } : {},
264
- docsDir: path.dirname(outputDir),
265
264
  ...docsRoot != null ? { docsRoot } : {},
266
265
  ...resolvedTheme != null ? { theme: resolvedTheme } : {}
267
266
  }
@@ -343,7 +342,6 @@ const makeConfigService = Effect.gen(function* () {
343
342
  ...resolvedLlms != null ? { llmsPlugin: resolvedLlms } : {},
344
343
  ...siteUrl != null ? { siteUrl } : {},
345
344
  ...resolvedOgImage != null ? { ogImage: resolvedOgImage } : {},
346
- docsDir: path.dirname(outputDir),
347
345
  ...docsRoot != null ? { docsRoot } : {},
348
346
  ...resolvedTheme != null ? { theme: resolvedTheme } : {}
349
347
  }
@@ -2,10 +2,9 @@ import { PluginEvent } from "../observability/events.js";
2
2
  import { emit } from "../observability/EventBus.js";
3
3
  import { TwoslashEnvironments } from "../services/TwoslashEnvironments.js";
4
4
  import { ConfigValidationError } from "../errors.js";
5
- import { twoslashEnvHash } from "../twoslash-cache.js";
6
5
  import { TwoslashCacheService } from "../services/TwoslashCacheService.js";
7
6
  import { Effect } from "effect";
8
- import { resolveTypeScriptConfig } from "@tsdoctor/vfs";
7
+ import { resolveTypeScriptConfig, twoslashEnvHash } from "@tsdoctor/vfs";
9
8
  import ts from "typescript";
10
9
 
11
10
  //#region src/layers/type-environment.ts
package/llms-program.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { PluginEvent } from "./observability/events.js";
2
2
  import { emit } from "./observability/EventBus.js";
3
- import { filterLlmsFullTxt, filterLlmsTxt, generatePackageLlmsFullTxt, generatePackageLlmsTxt, generateStructuredLlmsTxt, parseLlmsTxtLine } from "./llms-processing.js";
4
3
  import path from "node:path";
4
+ import { filterLlmsFullTxt, filterLlmsTxt, generatePackageLlmsFullTxt, generatePackageLlmsTxt, generateStructuredLlmsTxt, parseLlmsTxtLine } from "@tsdoctor/pages";
5
5
  import { Effect, FileSystem } from "effect";
6
6
 
7
7
  //#region src/llms-program.ts
8
8
  /**
9
9
  * Effect program for post-processing LLMs text files in afterBuild.
10
10
  *
11
- * Wires the pure processing functions from llms-processing.ts into the
11
+ * Wires the pure processing functions from @tsdoctor/pages into the
12
12
  * plugin lifecycle, handling file I/O via the core `effect` FileSystem service.
13
13
  *
14
14
  * Responsibilities:
@@ -89,7 +89,7 @@ function buildPackagePointers(buildResults, prefix, packageRoutes) {
89
89
  * Collect API page entries from the global llms.txt for a specific package.
90
90
  *
91
91
  * Parses the global llms.txt to find entries whose URLs match this package's
92
- * generated API routes, building the LlmsTxtEntry array for per-package files.
92
+ * generated API routes, building the `LlmsTxtEntry` array for per-package files.
93
93
  */
94
94
  function collectApiEntries(globalLlmsTxtContent, result) {
95
95
  const base = result.baseRoute.endsWith("/") ? result.baseRoute : `${result.baseRoute}/`;