@mintlify/scraping 4.0.1230 → 4.0.1232
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/__test__/sdk-docfx.test.ts +133 -4
- package/__test__/sdk-navigation.test.ts +52 -0
- package/__test__/sdk-phpdoc.test.ts +44 -0
- package/__test__/sdk-sphinx.test.ts +3 -5
- package/__test__/sdk-typedoc.test.ts +50 -11
- package/bin/sdk/converters/docfx.js +44 -28
- package/bin/sdk/converters/docfx.js.map +1 -1
- package/bin/sdk/converters/go.js +8 -3
- package/bin/sdk/converters/go.js.map +1 -1
- package/bin/sdk/converters/javadoc.js +6 -2
- package/bin/sdk/converters/javadoc.js.map +1 -1
- package/bin/sdk/converters/phpdoc.js +31 -22
- package/bin/sdk/converters/phpdoc.js.map +1 -1
- package/bin/sdk/converters/sphinx.js +7 -4
- package/bin/sdk/converters/sphinx.js.map +1 -1
- package/bin/sdk/converters/typedoc.js +29 -7
- package/bin/sdk/converters/typedoc.js.map +1 -1
- package/bin/sdk/linked-tokens.d.ts +2 -1
- package/bin/sdk/linked-tokens.js +17 -7
- package/bin/sdk/linked-tokens.js.map +1 -1
- package/bin/sdk/navigation.d.ts +6 -0
- package/bin/sdk/navigation.js +22 -0
- package/bin/sdk/navigation.js.map +1 -0
- package/bin/sdk/types.d.ts +1 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/sdk/converters/docfx.ts +50 -37
- package/src/sdk/converters/go.ts +9 -4
- package/src/sdk/converters/javadoc.ts +9 -3
- package/src/sdk/converters/phpdoc.ts +33 -26
- package/src/sdk/converters/sphinx.ts +7 -4
- package/src/sdk/converters/typedoc.ts +23 -7
- package/src/sdk/linked-tokens.ts +25 -5
- package/src/sdk/navigation.ts +22 -0
- package/src/sdk/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/scraping",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1232",
|
|
4
4
|
"description": "Scrape documentation frameworks to Mintlify docs",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"optional": true
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "bd9ae94bb1b82d591ce385a24bba824f937bea7a"
|
|
91
91
|
}
|
|
@@ -3,7 +3,10 @@ import yaml from 'js-yaml';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
|
|
5
5
|
import { htmlToMdx } from '../convert.js';
|
|
6
|
-
import
|
|
6
|
+
import { identifierTokens, linkedTypeField } from '../linked-tokens.js';
|
|
7
|
+
import { inlineCode, linkedCode, responseField, truncate, type LinkedToken } from '../mdx.js';
|
|
8
|
+
import { nestNavGroups, type PathNavGroup } from '../navigation.js';
|
|
9
|
+
import type { SdkPage, SdkReference } from '../types.js';
|
|
7
10
|
|
|
8
11
|
type DocfxParameter = { id?: string; type?: string; description?: string };
|
|
9
12
|
type DocfxSyntax = {
|
|
@@ -82,7 +85,7 @@ export async function convertDocfx(sourcePath: string): Promise<SdkReference> {
|
|
|
82
85
|
];
|
|
83
86
|
|
|
84
87
|
const pages: SdkPage[] = [];
|
|
85
|
-
const groups:
|
|
88
|
+
const groups: PathNavGroup[] = [];
|
|
86
89
|
for (const namespace of namespaceOrder) {
|
|
87
90
|
const ordered = orderByToc(
|
|
88
91
|
typesByNamespace.get(namespace) ?? [],
|
|
@@ -91,12 +94,12 @@ export async function convertDocfx(sourcePath: string): Promise<SdkReference> {
|
|
|
91
94
|
const namespacePages = ordered.map((type) => renderer.renderPage(type));
|
|
92
95
|
pages.push(...namespacePages);
|
|
93
96
|
groups.push({
|
|
94
|
-
|
|
95
|
-
pages: namespacePages.map((page) => page.slug),
|
|
97
|
+
path: namespace ? namespace.split('.') : [],
|
|
98
|
+
group: { group: namespace || 'Reference', pages: namespacePages.map((page) => page.slug) },
|
|
96
99
|
});
|
|
97
100
|
}
|
|
98
101
|
|
|
99
|
-
return { pages, groups };
|
|
102
|
+
return { pages, groups: nestNavGroups(groups) };
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
async function loadManagedReferenceFiles(sourcePath: string): Promise<DocfxFile[]> {
|
|
@@ -270,7 +273,7 @@ class DocfxRenderer {
|
|
|
270
273
|
for (const member of this.members(item).filter((child) => child.type === 'Field')) {
|
|
271
274
|
const value = member.syntax?.content?.split('=')[1]?.trim() ?? '';
|
|
272
275
|
lines.push(
|
|
273
|
-
|
|
276
|
+
responseField(member.name ?? member.uid, value, false, this.prose(member.summary))
|
|
274
277
|
);
|
|
275
278
|
}
|
|
276
279
|
return lines;
|
|
@@ -292,16 +295,16 @@ class DocfxRenderer {
|
|
|
292
295
|
if (syntax.typeParameters?.length) {
|
|
293
296
|
lines.push(`${heading} Type Parameters`);
|
|
294
297
|
for (const param of syntax.typeParameters) {
|
|
295
|
-
lines.push(
|
|
298
|
+
lines.push(responseField(param.id ?? '', '', false, this.prose(param.description)));
|
|
296
299
|
}
|
|
297
300
|
}
|
|
298
301
|
if (syntax.parameters?.length) {
|
|
299
302
|
lines.push(`${heading} Parameters`);
|
|
300
303
|
for (const param of syntax.parameters) {
|
|
301
304
|
lines.push(
|
|
302
|
-
|
|
305
|
+
linkedTypeField(
|
|
303
306
|
param.id ?? '',
|
|
304
|
-
this.
|
|
307
|
+
this.typeTokens(param.type),
|
|
305
308
|
isOptionalParameter(param.id, syntax.content),
|
|
306
309
|
this.prose(param.description)
|
|
307
310
|
)
|
|
@@ -312,7 +315,10 @@ class DocfxRenderer {
|
|
|
312
315
|
if (returnType && returnType.toLowerCase() !== 'void') {
|
|
313
316
|
lines.push(`${heading} Returns`);
|
|
314
317
|
const description = this.prose(syntax.return?.description);
|
|
315
|
-
|
|
318
|
+
const linked =
|
|
319
|
+
linkedCode(this.typeTokens(syntax.return?.type)) ??
|
|
320
|
+
inlineCode(returnType.replace(/`/g, ''));
|
|
321
|
+
lines.push(`${linked}${description ? `\n\n${description}` : ''}`);
|
|
316
322
|
}
|
|
317
323
|
return lines;
|
|
318
324
|
}
|
|
@@ -325,24 +331,14 @@ class DocfxRenderer {
|
|
|
325
331
|
]
|
|
326
332
|
.filter(Boolean)
|
|
327
333
|
.join('\n\n');
|
|
328
|
-
return
|
|
334
|
+
return linkedTypeField(
|
|
329
335
|
member.name ?? member.uid,
|
|
330
|
-
this.
|
|
336
|
+
this.typeTokens(member.syntax?.return?.type),
|
|
331
337
|
isNullable(member.syntax?.content),
|
|
332
338
|
body
|
|
333
339
|
);
|
|
334
340
|
}
|
|
335
341
|
|
|
336
|
-
private responseField(name: string, type: string, optional: boolean, body?: string): string {
|
|
337
|
-
const typeAttr = type ? ` type=${this.jsxString(truncate(type, 80))}` : '';
|
|
338
|
-
const requiredAttr = optional ? '' : ' required';
|
|
339
|
-
return `<ResponseField name=${this.jsxString(name)}${typeAttr}${requiredAttr}>\n${indent(body || '')}\n</ResponseField>`;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
private jsxString(value: string): string {
|
|
343
|
-
return `{${JSON.stringify(value)}}`;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
342
|
private codeBlock(code: string, lang = 'csharp'): string {
|
|
347
343
|
return `\`\`\`${lang}\n${code}\n\`\`\``;
|
|
348
344
|
}
|
|
@@ -413,6 +409,25 @@ class DocfxRenderer {
|
|
|
413
409
|
return uid ? this.shortName(uid) : '';
|
|
414
410
|
}
|
|
415
411
|
|
|
412
|
+
private typeTokens(uid?: string): LinkedToken[] {
|
|
413
|
+
if (!uid) return [];
|
|
414
|
+
const source = uid
|
|
415
|
+
.replace(/(^|[^\w.])`+\d+/g, '$1')
|
|
416
|
+
.replace(/\{/g, '<')
|
|
417
|
+
.replace(/\}/g, '>');
|
|
418
|
+
const tokens = identifierTokens(
|
|
419
|
+
source,
|
|
420
|
+
/[A-Za-z_]\w*(?:`+\d+)?(?:\.[A-Za-z_]\w*(?:`+\d+)?)*/g,
|
|
421
|
+
(name, index) => {
|
|
422
|
+
const arity = genericArity(source, index + name.length);
|
|
423
|
+
const slug = this.slugByUid.get(arity ? `${name}\`${arity}` : name);
|
|
424
|
+
const text = name.replace(/`+\d+/g, '').split('.').at(-1) ?? name;
|
|
425
|
+
return { text, href: slug ? `/${slug}` : undefined };
|
|
426
|
+
}
|
|
427
|
+
);
|
|
428
|
+
return tokens.some((token) => token.href) ? tokens : [{ text: this.typeName(uid) }];
|
|
429
|
+
}
|
|
430
|
+
|
|
416
431
|
private firstSentence(summary?: string): string | undefined {
|
|
417
432
|
if (!summary) return undefined;
|
|
418
433
|
const text = decodeEntities(summary.replace(/<[^>]*>/g, ' '))
|
|
@@ -424,6 +439,19 @@ class DocfxRenderer {
|
|
|
424
439
|
}
|
|
425
440
|
}
|
|
426
441
|
|
|
442
|
+
function genericArity(text: string, start: number): number {
|
|
443
|
+
if (text[start] !== '<') return 0;
|
|
444
|
+
let depth = 0;
|
|
445
|
+
let arity = 1;
|
|
446
|
+
for (let index = start + 1; index < text.length; index += 1) {
|
|
447
|
+
const character = text[index];
|
|
448
|
+
if (character === '<') depth += 1;
|
|
449
|
+
else if (character === '>' && depth-- === 0) return arity;
|
|
450
|
+
else if (character === ',' && depth === 0) arity += 1;
|
|
451
|
+
}
|
|
452
|
+
return arity;
|
|
453
|
+
}
|
|
454
|
+
|
|
427
455
|
function byName(left: DocfxItem, right: DocfxItem): number {
|
|
428
456
|
return (left.name ?? '').localeCompare(right.name ?? '');
|
|
429
457
|
}
|
|
@@ -474,18 +502,3 @@ function isOptionalParameter(id?: string, content?: string): boolean {
|
|
|
474
502
|
function escapeRegExp(text: string): string {
|
|
475
503
|
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
476
504
|
}
|
|
477
|
-
|
|
478
|
-
function indent(text: string): string {
|
|
479
|
-
return text
|
|
480
|
-
.split('\n')
|
|
481
|
-
.map((line) => (line ? ` ${line}` : line))
|
|
482
|
-
.join('\n');
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
function truncate(text: string, max: number): string {
|
|
486
|
-
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
function escapeInlineCode(text: string): string {
|
|
490
|
-
return text.replace(/`/g, '');
|
|
491
|
-
}
|
package/src/sdk/converters/go.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
truncate,
|
|
23
23
|
type LinkedToken,
|
|
24
24
|
} from '../mdx.js';
|
|
25
|
+
import { nestNavGroups, type PathNavGroup } from '../navigation.js';
|
|
25
26
|
import { parseSdkReadme, unparseableMarkdown } from '../readme.js';
|
|
26
27
|
import type { SdkNavGroup, SdkPage, SdkPageTarget, SdkReference } from '../types.js';
|
|
27
28
|
|
|
@@ -194,14 +195,18 @@ export async function convertGo(sourcePath: string): Promise<SdkReference> {
|
|
|
194
195
|
const renderers = artifact.packages.map((pkg) => new GoRenderer(index, pkg));
|
|
195
196
|
|
|
196
197
|
const pages: SdkPage[] = [];
|
|
197
|
-
const groups:
|
|
198
|
-
for (const renderer of renderers) {
|
|
198
|
+
const groups: PathNavGroup[] = [];
|
|
199
|
+
for (const [position, renderer] of renderers.entries()) {
|
|
199
200
|
const packagePages = renderer.packagePages();
|
|
200
201
|
pages.push(...packagePages, ...renderer.memberPages());
|
|
201
|
-
|
|
202
|
+
const dir = artifact.packages[position]?.dir ?? '.';
|
|
203
|
+
groups.push({
|
|
204
|
+
path: dir === '.' ? [] : dir.split('/'),
|
|
205
|
+
group: { group: renderer.group, pages: packageEntries(packagePages) },
|
|
206
|
+
});
|
|
202
207
|
}
|
|
203
208
|
|
|
204
|
-
return { pages, groups };
|
|
209
|
+
return { pages, groups: nestNavGroups(groups) };
|
|
205
210
|
}
|
|
206
211
|
|
|
207
212
|
const KIND_GROUPS = [
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
trimTokens,
|
|
15
15
|
} from '../linked-tokens.js';
|
|
16
16
|
import { linkedCode, type LinkedToken } from '../mdx.js';
|
|
17
|
+
import { nestNavGroups } from '../navigation.js';
|
|
17
18
|
import type { SdkNavGroup, SdkPage, SdkReference } from '../types.js';
|
|
18
19
|
|
|
19
20
|
type JavadocKind = 'interface' | 'class' | 'enum' | 'record' | 'exception' | 'error' | 'annotation';
|
|
@@ -63,9 +64,14 @@ export async function convertJavadoc(sourcePath: string): Promise<SdkReference>
|
|
|
63
64
|
byPackage.set(type.pkg, siblings);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
const groups
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
const groups = nestNavGroups(
|
|
68
|
+
[...byPackage.entries()]
|
|
69
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
70
|
+
.map(([pkg, members]) => ({
|
|
71
|
+
path: pkg.split('.'),
|
|
72
|
+
group: { group: pkg, pages: packageEntries(members) },
|
|
73
|
+
}))
|
|
74
|
+
);
|
|
69
75
|
|
|
70
76
|
return { pages, groups };
|
|
71
77
|
}
|
|
@@ -3,7 +3,10 @@ import fse from 'fs-extra';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
|
|
5
5
|
import { markdownToMdx } from '../convert.js';
|
|
6
|
-
import
|
|
6
|
+
import { identifierTokens, linkedTypeField } from '../linked-tokens.js';
|
|
7
|
+
import { inlineCode, linkedCode, truncate, type LinkedToken } from '../mdx.js';
|
|
8
|
+
import { nestNavGroups, type PathNavGroup } from '../navigation.js';
|
|
9
|
+
import type { SdkPage, SdkReference } from '../types.js';
|
|
7
10
|
|
|
8
11
|
type DocTag = {
|
|
9
12
|
'@_name'?: string;
|
|
@@ -118,17 +121,20 @@ export async function convertPhpdoc(sourcePath: string): Promise<SdkReference> {
|
|
|
118
121
|
});
|
|
119
122
|
|
|
120
123
|
const pages: SdkPage[] = [];
|
|
121
|
-
const groups:
|
|
124
|
+
const groups: PathNavGroup[] = [];
|
|
122
125
|
for (const groupName of groupNames) {
|
|
123
126
|
const members = (byGroup.get(groupName) ?? []).sort((left, right) =>
|
|
124
127
|
left.name.localeCompare(right.name)
|
|
125
128
|
);
|
|
126
129
|
const groupPages = members.map((entry) => renderer.renderPage(entry));
|
|
127
130
|
pages.push(...groupPages);
|
|
128
|
-
groups.push({
|
|
131
|
+
groups.push({
|
|
132
|
+
path: members[0]?.namespace ?? [],
|
|
133
|
+
group: { group: groupName, pages: groupPages.map((page) => page.slug) },
|
|
134
|
+
});
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
return { pages, groups };
|
|
137
|
+
return { pages, groups: nestNavGroups(groups) };
|
|
132
138
|
}
|
|
133
139
|
|
|
134
140
|
function collectEntries(files: PhpFile[]): Entry[] {
|
|
@@ -229,7 +235,7 @@ class PhpdocRenderer {
|
|
|
229
235
|
]
|
|
230
236
|
.filter(Boolean)
|
|
231
237
|
.join('\n\n');
|
|
232
|
-
lines.push(
|
|
238
|
+
lines.push(linkedTypeField(constant.name ?? '', this.typeTokens(type), false, body));
|
|
233
239
|
}
|
|
234
240
|
}
|
|
235
241
|
|
|
@@ -254,7 +260,9 @@ class PhpdocRenderer {
|
|
|
254
260
|
]
|
|
255
261
|
.filter(Boolean)
|
|
256
262
|
.join('\n\n');
|
|
257
|
-
lines.push(
|
|
263
|
+
lines.push(
|
|
264
|
+
linkedTypeField(property.name ?? '', this.typeTokens(type), isNullable(type), body)
|
|
265
|
+
);
|
|
258
266
|
}
|
|
259
267
|
}
|
|
260
268
|
|
|
@@ -305,7 +313,7 @@ class PhpdocRenderer {
|
|
|
305
313
|
const body = paramTag?.['@_description']
|
|
306
314
|
? markdownToMdx(this.resolveInline(paramTag['@_description']))
|
|
307
315
|
: '';
|
|
308
|
-
lines.push(
|
|
316
|
+
lines.push(linkedTypeField(arg.name ?? '', this.typeTokens(type), optional, body));
|
|
309
317
|
}
|
|
310
318
|
}
|
|
311
319
|
|
|
@@ -315,7 +323,8 @@ class PhpdocRenderer {
|
|
|
315
323
|
const description = returnTag['@_description']
|
|
316
324
|
? `\n\n${markdownToMdx(this.resolveInline(returnTag['@_description']))}`
|
|
317
325
|
: '';
|
|
318
|
-
|
|
326
|
+
const returns = this.typeTokens(returnTag['@_type']);
|
|
327
|
+
lines.push(`${linkedCode(returns) ?? inlineCode(returnTag['@_type'])}${description}`);
|
|
319
328
|
}
|
|
320
329
|
|
|
321
330
|
const throwsTags = tagsOf(method.docblock, 'throws');
|
|
@@ -326,7 +335,7 @@ class PhpdocRenderer {
|
|
|
326
335
|
throwsTags
|
|
327
336
|
.map((tag) => {
|
|
328
337
|
const description = tag['@_description'] ? ` ${tag['@_description']}` : '';
|
|
329
|
-
return `-
|
|
338
|
+
return `- ${this.typeLink(tag['@_type'] ?? 'Exception')}${description}`;
|
|
330
339
|
})
|
|
331
340
|
.join('\n')
|
|
332
341
|
)
|
|
@@ -415,14 +424,23 @@ class PhpdocRenderer {
|
|
|
415
424
|
return truncate(sentence, 160);
|
|
416
425
|
}
|
|
417
426
|
|
|
418
|
-
private
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
427
|
+
private typeTokens(type: string): LinkedToken[] {
|
|
428
|
+
return identifierTokens(type, /\\?[A-Za-z_]\w*(?:\\[A-Za-z_]\w*)*/g, (name) => {
|
|
429
|
+
const slug = this.resolve(name);
|
|
430
|
+
return { text: name, href: slug ? `/${slug}` : undefined };
|
|
431
|
+
});
|
|
422
432
|
}
|
|
423
433
|
|
|
424
|
-
private
|
|
425
|
-
|
|
434
|
+
private typeLink(type: string): string {
|
|
435
|
+
const spans: LinkedToken[] = [];
|
|
436
|
+
for (const token of this.typeTokens(type)) {
|
|
437
|
+
const last = spans.at(-1);
|
|
438
|
+
if (last && !last.href && !token.href) last.text += token.text;
|
|
439
|
+
else spans.push({ ...token });
|
|
440
|
+
}
|
|
441
|
+
return spans
|
|
442
|
+
.map(({ text, href }) => (href ? `[${inlineCode(text)}](${href})` : inlineCode(text)))
|
|
443
|
+
.join('');
|
|
426
444
|
}
|
|
427
445
|
|
|
428
446
|
private codeBlock(code: string): string {
|
|
@@ -430,17 +448,6 @@ class PhpdocRenderer {
|
|
|
430
448
|
}
|
|
431
449
|
}
|
|
432
450
|
|
|
433
|
-
function indent(text: string): string {
|
|
434
|
-
return text
|
|
435
|
-
.split('\n')
|
|
436
|
-
.map((line) => (line ? ` ${line}` : line))
|
|
437
|
-
.join('\n');
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
function truncate(text: string, max: number): string {
|
|
441
|
-
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
451
|
function escapeInlineCode(text: string): string {
|
|
445
452
|
return text.replace(/`/g, '');
|
|
446
453
|
}
|
|
@@ -36,10 +36,13 @@ export async function convertSphinx(sourcePath: string): Promise<SdkReference> {
|
|
|
36
36
|
const docs = splitSphinxModules(await loadDocs(sourcePath));
|
|
37
37
|
const slugs = new Set(docs.map((doc) => doc.slug));
|
|
38
38
|
const anchors = collectAnchors(docs);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const pages = docs.map((doc) => renderPage(doc, slugs, anchors));
|
|
40
|
+
const [first, ...rest] = buildSphinxNavigation(docs);
|
|
41
|
+
const [overview, ...others] = first?.pages ?? [];
|
|
42
|
+
if (first?.group === 'Getting Started' && typeof overview === 'string' && !others.length) {
|
|
43
|
+
return { pages, groups: rest, overview };
|
|
44
|
+
}
|
|
45
|
+
return { pages, groups: first ? [first, ...rest] : [] };
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
type SphinxAnchors = Map<string, Map<string, string>>;
|
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
|
|
5
5
|
import { escapeMdxText, markdownToMdx, rewriteMdastLinks, stringifyMdast } from '../convert.js';
|
|
6
6
|
import { inlineCode, linkedCode, responseField, safeHref, truncate } from '../mdx.js';
|
|
7
|
+
import { nestNavGroups, type PathNavGroup } from '../navigation.js';
|
|
7
8
|
import { parseSdkReadme } from '../readme.js';
|
|
8
9
|
import type { SdkNavGroup, SdkPage, SdkPageTarget, SdkReference } from '../types.js';
|
|
9
10
|
|
|
@@ -166,9 +167,9 @@ export async function convertTypedoc(sourcePath: string): Promise<SdkReference>
|
|
|
166
167
|
const renderer = new TypedocRenderer(slugById);
|
|
167
168
|
const pages: SdkPage[] = [];
|
|
168
169
|
const groups: SdkNavGroup[] = [];
|
|
170
|
+
const moduleGroupById = new Map<number, PathNavGroup>();
|
|
169
171
|
|
|
170
172
|
for (const module of modules) {
|
|
171
|
-
const prefix = multiModule ? `${module.name} ` : '';
|
|
172
173
|
const declarations = collectDeclarations(module);
|
|
173
174
|
const kindGroups: SdkNavGroup[] = [];
|
|
174
175
|
for (const section of SECTIONS) {
|
|
@@ -196,11 +197,17 @@ export async function convertTypedoc(sourcePath: string): Promise<SdkReference>
|
|
|
196
197
|
}
|
|
197
198
|
const customGroups = hasCustomLayout(module) ? layoutGroups(module, slugById) : [];
|
|
198
199
|
const moduleGroups = customGroups.length ? customGroups : kindGroups;
|
|
199
|
-
|
|
200
|
+
if (multiModule) {
|
|
201
|
+
moduleGroupById.set(module.id, {
|
|
202
|
+
path: module.name.split('/'),
|
|
203
|
+
group: { group: module.name, pages: moduleGroups },
|
|
204
|
+
});
|
|
205
|
+
} else groups.push(...moduleGroups);
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
const overviewPages: SdkPage[] = [];
|
|
203
209
|
const overviewGroups: SdkNavGroup[] = [];
|
|
210
|
+
let projectOverview: string | undefined;
|
|
204
211
|
const reservedSlugs = new Set(pages.map((page) => page.slug.toLowerCase()));
|
|
205
212
|
const containers = [project, ...modules.filter((module) => module !== project)];
|
|
206
213
|
const overviews: { node: TypedocNode; slug: string }[] = [];
|
|
@@ -234,13 +241,22 @@ export async function convertTypedoc(sourcePath: string): Promise<SdkReference>
|
|
|
234
241
|
isProject ? undefined : project.name
|
|
235
242
|
);
|
|
236
243
|
overviewPages.push(overview);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
244
|
+
const moduleGroup = moduleGroupById.get(container.id)?.group;
|
|
245
|
+
if (isProject) projectOverview = slug;
|
|
246
|
+
else if (moduleGroup) moduleGroup.pages.unshift(slug);
|
|
247
|
+
else if (!projectOverview) projectOverview = slug;
|
|
248
|
+
else overviewGroups.push({ group: `${container.name} Overview`, pages: [slug] });
|
|
241
249
|
}
|
|
242
250
|
|
|
243
|
-
return {
|
|
251
|
+
return {
|
|
252
|
+
pages: [...overviewPages, ...pages],
|
|
253
|
+
groups: [
|
|
254
|
+
...overviewGroups,
|
|
255
|
+
...groups,
|
|
256
|
+
...nestNavGroups([...moduleGroupById.values()].filter(({ group }) => group.pages.length)),
|
|
257
|
+
],
|
|
258
|
+
...(projectOverview ? { overview: projectOverview } : {}),
|
|
259
|
+
};
|
|
244
260
|
}
|
|
245
261
|
|
|
246
262
|
function hasCustomLayout(container: TypedocNode): boolean {
|
package/src/sdk/linked-tokens.ts
CHANGED
|
@@ -78,14 +78,34 @@ export function topLevelDelimiter(
|
|
|
78
78
|
return -1;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
export function linkedTypeField(
|
|
81
|
+
export function linkedTypeField(
|
|
82
|
+
name: string,
|
|
83
|
+
tokens: LinkedToken[],
|
|
84
|
+
optional: boolean,
|
|
85
|
+
description?: string
|
|
86
|
+
): string {
|
|
82
87
|
const type = tokens.map((token) => token.text).join('');
|
|
83
88
|
const typeHref = tokens.length === 1 ? tokens[0]?.href : undefined;
|
|
84
|
-
let
|
|
89
|
+
let linked: string | undefined;
|
|
85
90
|
if (!typeHref || type.length > 80) {
|
|
86
|
-
|
|
87
|
-
if (linked) body = `**Type:** ${linked}`;
|
|
88
|
-
else if (type.length > 80) body = `**Type:** ${inlineCode(type)}`;
|
|
91
|
+
linked = linkedCode(tokens) ?? (type.length > 80 ? inlineCode(type) : undefined);
|
|
89
92
|
}
|
|
93
|
+
const body = [linked && `**Type:** ${linked}`, description].filter(Boolean).join('\n\n');
|
|
90
94
|
return responseField(name, type, optional, body, typeHref);
|
|
91
95
|
}
|
|
96
|
+
|
|
97
|
+
export function identifierTokens(
|
|
98
|
+
text: string,
|
|
99
|
+
identifier: RegExp,
|
|
100
|
+
link: (name: string, index: number) => LinkedToken
|
|
101
|
+
): LinkedToken[] {
|
|
102
|
+
const tokens: LinkedToken[] = [];
|
|
103
|
+
let cursor = 0;
|
|
104
|
+
for (const match of text.matchAll(identifier)) {
|
|
105
|
+
if (match.index > cursor) tokens.push({ text: text.slice(cursor, match.index) });
|
|
106
|
+
tokens.push(link(match[0], match.index));
|
|
107
|
+
cursor = match.index + match[0].length;
|
|
108
|
+
}
|
|
109
|
+
if (cursor < text.length) tokens.push({ text: text.slice(cursor) });
|
|
110
|
+
return tokens;
|
|
111
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SdkNavGroup } from './types.js';
|
|
2
|
+
|
|
3
|
+
export type PathNavGroup = { path: string[]; group: SdkNavGroup };
|
|
4
|
+
|
|
5
|
+
export function nestNavGroups(entries: PathNavGroup[]): SdkNavGroup[] {
|
|
6
|
+
const byPath = new Map<string, SdkNavGroup>();
|
|
7
|
+
const nested = entries.map(({ path, group }) => {
|
|
8
|
+
const copy = { ...group, pages: [...group.pages] };
|
|
9
|
+
if (path.length) byPath.set(path.join('\u0000'), copy);
|
|
10
|
+
return { path, group: copy };
|
|
11
|
+
});
|
|
12
|
+
const roots: SdkNavGroup[] = [];
|
|
13
|
+
for (const { path, group } of nested) {
|
|
14
|
+
let parent: SdkNavGroup | undefined;
|
|
15
|
+
for (let length = path.length - 1; length > 0 && !parent; length -= 1) {
|
|
16
|
+
parent = byPath.get(path.slice(0, length).join('\u0000'));
|
|
17
|
+
}
|
|
18
|
+
if (parent) parent.pages.push(group);
|
|
19
|
+
else roots.push(group);
|
|
20
|
+
}
|
|
21
|
+
return roots;
|
|
22
|
+
}
|