@mintlify/scraping 4.0.1229 → 4.0.1230
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-javadoc.test.ts +69 -0
- package/bin/sdk/converters/javadoc.js +75 -2
- package/bin/sdk/converters/javadoc.js.map +1 -1
- package/bin/sdk/linked-tokens.d.ts +7 -0
- package/bin/sdk/linked-tokens.js +88 -0
- package/bin/sdk/linked-tokens.js.map +1 -0
- package/bin/sdk/sphinx-signatures.js +3 -85
- package/bin/sdk/sphinx-signatures.js.map +1 -1
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/sdk/converters/javadoc.ts +85 -2
- package/src/sdk/linked-tokens.ts +91 -0
- package/src/sdk/sphinx-signatures.ts +10 -81
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/scraping",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1230",
|
|
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": "e929a72c0d7dc12e955ca24554b1a3d6e6171bfa"
|
|
91
91
|
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import fse from 'fs-extra';
|
|
2
2
|
import type { Element, ElementContent, Root as HastRoot, RootContent } from 'hast';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
|
|
5
6
|
import { htmlToHast } from '../../pipeline/root.js';
|
|
6
7
|
import { removeHastComments } from '../../utils/hastComments.js';
|
|
7
8
|
import { hastToMdx, type RewriteLink } from '../convert.js';
|
|
9
|
+
import {
|
|
10
|
+
linkedTokens,
|
|
11
|
+
linkedTypeField,
|
|
12
|
+
sliceTokens,
|
|
13
|
+
topLevelDelimiter,
|
|
14
|
+
trimTokens,
|
|
15
|
+
} from '../linked-tokens.js';
|
|
16
|
+
import { linkedCode, type LinkedToken } from '../mdx.js';
|
|
8
17
|
import type { SdkNavGroup, SdkPage, SdkReference } from '../types.js';
|
|
9
18
|
|
|
10
19
|
type JavadocKind = 'interface' | 'class' | 'enum' | 'record' | 'exception' | 'error' | 'annotation';
|
|
@@ -239,11 +248,13 @@ function renderPage(
|
|
|
239
248
|
const anchors = collectDetailAnchors(kept);
|
|
240
249
|
const resolveHref = makeHrefResolver(type, slugByFile, anchors);
|
|
241
250
|
const signatures: string[] = [];
|
|
251
|
+
const types = new Map<string, string>();
|
|
252
|
+
const prefix = `MINTJAVADOC${randomUUID().replaceAll('-', '')}`;
|
|
242
253
|
for (const node of kept) {
|
|
243
254
|
pruneChrome(node);
|
|
244
255
|
unwrapLists(node);
|
|
245
256
|
resolveLinks(node, resolveHref);
|
|
246
|
-
signatures.push(...codifySignatures(node));
|
|
257
|
+
signatures.push(...codifySignatures(node, types, prefix));
|
|
247
258
|
}
|
|
248
259
|
|
|
249
260
|
const root: HastRoot = { type: 'root', children: kept as RootContent[] };
|
|
@@ -253,6 +264,8 @@ function renderPage(
|
|
|
253
264
|
.split(`\`\`\`\n${signature}\n\`\`\``)
|
|
254
265
|
.join(`\`\`\`java\n${signature}\n\`\`\``);
|
|
255
266
|
}
|
|
267
|
+
for (const [marker, replacement] of types)
|
|
268
|
+
content = content.replaceAll(marker, () => replacement);
|
|
256
269
|
|
|
257
270
|
return { slug: type.slug, title: type.name, description, tag, content, kind };
|
|
258
271
|
}
|
|
@@ -342,14 +355,21 @@ function unwrapLists(node: Element): void {
|
|
|
342
355
|
}
|
|
343
356
|
}
|
|
344
357
|
|
|
345
|
-
function codifySignatures(node: Element): string[] {
|
|
358
|
+
function codifySignatures(node: Element, types: Map<string, string>, prefix: string): string[] {
|
|
346
359
|
const signatures: string[] = [];
|
|
360
|
+
const markers = new Map<Element, string>();
|
|
347
361
|
visitElements(node, (el) => {
|
|
348
362
|
if (!hasClass(el, 'member-signature') && !hasClass(el, 'type-signature')) return;
|
|
349
363
|
const signature = textOf(el)
|
|
350
364
|
.replace(/\u00a0/g, ' ')
|
|
351
365
|
.trim();
|
|
352
366
|
signatures.push(signature);
|
|
367
|
+
const linked = signatureTypes(el);
|
|
368
|
+
if (linked) {
|
|
369
|
+
const marker = `${prefix}TYPES${types.size}END`;
|
|
370
|
+
types.set(marker, linked);
|
|
371
|
+
markers.set(el, marker);
|
|
372
|
+
}
|
|
353
373
|
el.tagName = 'pre';
|
|
354
374
|
el.properties = {};
|
|
355
375
|
el.children = [
|
|
@@ -361,9 +381,72 @@ function codifySignatures(node: Element): string[] {
|
|
|
361
381
|
},
|
|
362
382
|
];
|
|
363
383
|
});
|
|
384
|
+
insertMarkers(node, markers);
|
|
364
385
|
return signatures;
|
|
365
386
|
}
|
|
366
387
|
|
|
388
|
+
function insertMarkers(node: Element, markers: Map<Element, string>): void {
|
|
389
|
+
node.children = node.children.flatMap((child): ElementContent[] => {
|
|
390
|
+
if (child.type !== 'element') return [child];
|
|
391
|
+
insertMarkers(child, markers);
|
|
392
|
+
const marker = markers.get(child);
|
|
393
|
+
if (!marker) return [child];
|
|
394
|
+
return [
|
|
395
|
+
child,
|
|
396
|
+
{
|
|
397
|
+
type: 'element',
|
|
398
|
+
tagName: 'p',
|
|
399
|
+
properties: {},
|
|
400
|
+
children: [{ type: 'text', value: marker }],
|
|
401
|
+
},
|
|
402
|
+
];
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function signatureTypes(signature: Element): string | undefined {
|
|
407
|
+
const sections: string[] = [];
|
|
408
|
+
const parameters = findElement(signature, (el) => hasClass(el, 'parameters'));
|
|
409
|
+
const fields = parameters ? splitParameters(linkedTokens(parameters.children)) : [];
|
|
410
|
+
if (fields.some((field) => field.tokens.some((token) => token.href))) {
|
|
411
|
+
sections.push(
|
|
412
|
+
'**Parameters**',
|
|
413
|
+
...fields.map(({ name, tokens }) => linkedTypeField(name, tokens, false))
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
const returns = findElement(signature, (el) => hasClass(el, 'return-type'));
|
|
417
|
+
const returnLink = returns ? linkedCode(trimTokens(linkedTokens(returns.children))) : undefined;
|
|
418
|
+
if (returnLink) sections.push(`**${parameters ? 'Returns' : 'Type'}:** ${returnLink}`);
|
|
419
|
+
return sections.length ? sections.join('\n\n') : undefined;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
type JavadocParameter = { name: string; tokens: LinkedToken[] };
|
|
423
|
+
|
|
424
|
+
function splitParameters(tokens: LinkedToken[]): JavadocParameter[] {
|
|
425
|
+
const text = tokens.map((token) => token.text).join('');
|
|
426
|
+
const open = text.indexOf('(');
|
|
427
|
+
const close = text.lastIndexOf(')');
|
|
428
|
+
if (open === -1 || close <= open) return [];
|
|
429
|
+
const inner = sliceTokens(tokens, open + 1, close);
|
|
430
|
+
const list = inner.map((token) => token.text).join('');
|
|
431
|
+
const parameters: JavadocParameter[] = [];
|
|
432
|
+
let start = 0;
|
|
433
|
+
while (start <= list.length) {
|
|
434
|
+
const comma = topLevelDelimiter(list, ',', start, '<([{', '>)]}');
|
|
435
|
+
const end = comma === -1 ? list.length : comma;
|
|
436
|
+
const parameter = trimTokens(sliceTokens(inner, start, end));
|
|
437
|
+
const value = parameter.map((token) => token.text).join('');
|
|
438
|
+
const name = /([A-Za-z_$][\w$]*)$/.exec(value)?.[1];
|
|
439
|
+
if (name && value.length > name.length) {
|
|
440
|
+
parameters.push({
|
|
441
|
+
name,
|
|
442
|
+
tokens: trimTokens(sliceTokens(parameter, 0, value.length - name.length)),
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
start = end + 1;
|
|
446
|
+
}
|
|
447
|
+
return parameters;
|
|
448
|
+
}
|
|
449
|
+
|
|
367
450
|
function kindFromHeading(scope: Element | HastRoot): JavadocKind {
|
|
368
451
|
const heading = findElement(scope, (el) => el.tagName === 'h1');
|
|
369
452
|
const title = heading ? textOf(heading).trim() : '';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ElementContent } from 'hast';
|
|
2
|
+
|
|
3
|
+
import { inlineCode, linkedCode, responseField, safeHref, type LinkedToken } from './mdx.js';
|
|
4
|
+
|
|
5
|
+
export function linkedTokens(children: ElementContent[], href?: string): LinkedToken[] {
|
|
6
|
+
const tokens: LinkedToken[] = [];
|
|
7
|
+
for (const child of children) {
|
|
8
|
+
if (child.type === 'text') {
|
|
9
|
+
tokens.push({ text: child.value.replace(/\s+/g, ' '), href });
|
|
10
|
+
} else if (child.type === 'element') {
|
|
11
|
+
let nextHref = href;
|
|
12
|
+
if (child.tagName === 'a' && typeof child.properties.href === 'string') {
|
|
13
|
+
nextHref = safeHref(child.properties.href)?.replace(
|
|
14
|
+
/[\u0000-\u0020\u007f"'()[\]<>`{}\\]/g,
|
|
15
|
+
(character) => `%${character.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0')}`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
tokens.push(...linkedTokens(child.children, nextHref));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const merged: LinkedToken[] = [];
|
|
22
|
+
for (const token of tokens) {
|
|
23
|
+
const previous = merged.at(-1);
|
|
24
|
+
if (previous && previous.href === token.href) previous.text += token.text;
|
|
25
|
+
else merged.push({ ...token });
|
|
26
|
+
}
|
|
27
|
+
return merged;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function trimTokens(tokens: LinkedToken[]): LinkedToken[] {
|
|
31
|
+
const text = tokens.map((token) => token.text).join('');
|
|
32
|
+
return sliceTokens(tokens, text.length - text.trimStart().length, text.trimEnd().length);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function sliceTokens(tokens: LinkedToken[], start: number, end: number): LinkedToken[] {
|
|
36
|
+
const sliced: LinkedToken[] = [];
|
|
37
|
+
let offset = 0;
|
|
38
|
+
for (const token of tokens) {
|
|
39
|
+
const tokenEnd = offset + token.text.length;
|
|
40
|
+
if (tokenEnd > start && offset < end) {
|
|
41
|
+
sliced.push({
|
|
42
|
+
text: token.text.slice(Math.max(0, start - offset), end - offset),
|
|
43
|
+
href: token.href,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
offset = tokenEnd;
|
|
47
|
+
}
|
|
48
|
+
return sliced;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function topLevelDelimiter(
|
|
52
|
+
text: string,
|
|
53
|
+
delimiter: string,
|
|
54
|
+
start = 0,
|
|
55
|
+
opening = '([{',
|
|
56
|
+
closing = ')]}'
|
|
57
|
+
): number {
|
|
58
|
+
let depth = 0;
|
|
59
|
+
let quote: string | undefined;
|
|
60
|
+
let escaped = false;
|
|
61
|
+
for (let index = start; index < text.length; index += 1) {
|
|
62
|
+
const character = text[index] ?? '';
|
|
63
|
+
if (escaped) {
|
|
64
|
+
escaped = false;
|
|
65
|
+
} else if (quote) {
|
|
66
|
+
if (character === '\\') escaped = true;
|
|
67
|
+
else if (character === quote) quote = undefined;
|
|
68
|
+
} else if (character === '"' || character === "'") {
|
|
69
|
+
quote = character;
|
|
70
|
+
} else if (opening.includes(character)) {
|
|
71
|
+
depth += 1;
|
|
72
|
+
} else if (closing.includes(character)) {
|
|
73
|
+
depth = Math.max(0, depth - 1);
|
|
74
|
+
} else if (character === delimiter && depth === 0) {
|
|
75
|
+
return index;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return -1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function linkedTypeField(name: string, tokens: LinkedToken[], optional: boolean): string {
|
|
82
|
+
const type = tokens.map((token) => token.text).join('');
|
|
83
|
+
const typeHref = tokens.length === 1 ? tokens[0]?.href : undefined;
|
|
84
|
+
let body: string | undefined;
|
|
85
|
+
if (!typeHref || type.length > 80) {
|
|
86
|
+
const linked = linkedCode(tokens);
|
|
87
|
+
if (linked) body = `**Type:** ${linked}`;
|
|
88
|
+
else if (type.length > 80) body = `**Type:** ${inlineCode(type)}`;
|
|
89
|
+
}
|
|
90
|
+
return responseField(name, type, optional, body, typeHref);
|
|
91
|
+
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { hastToText } from '@mintlify/common';
|
|
2
|
-
import type { Element
|
|
2
|
+
import type { Element } from 'hast';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
linkedTokens,
|
|
6
|
+
linkedTypeField,
|
|
7
|
+
sliceTokens,
|
|
8
|
+
topLevelDelimiter,
|
|
9
|
+
trimTokens,
|
|
10
|
+
} from './linked-tokens.js';
|
|
11
|
+
import { inlineCode, linkedCode, type LinkedToken } from './mdx.js';
|
|
5
12
|
|
|
6
13
|
type DocumentedTypes = {
|
|
7
14
|
parameters: Map<string, LinkedToken[][]>;
|
|
@@ -47,15 +54,7 @@ function renderParameter(parameter: Element, documented: DocumentedTypes): strin
|
|
|
47
54
|
if (documented.parameters.get(name)?.some((type) => sameLinkedType(typeTokens, type))) {
|
|
48
55
|
return undefined;
|
|
49
56
|
}
|
|
50
|
-
|
|
51
|
-
const typeHref = typeTokens.length === 1 ? only?.href : undefined;
|
|
52
|
-
let body: string | undefined;
|
|
53
|
-
if (!typeHref || type.length > 80) {
|
|
54
|
-
const linked = linkedCode(typeTokens);
|
|
55
|
-
if (linked) body = `**Type:** ${linked}`;
|
|
56
|
-
else if (type.length > 80) body = `**Type:** ${inlineCode(type)}`;
|
|
57
|
-
}
|
|
58
|
-
return responseField(name, type, defaultStart !== -1 || name.startsWith('*'), body, typeHref);
|
|
57
|
+
return linkedTypeField(name, typeTokens, defaultStart !== -1 || name.startsWith('*'));
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
function documentedTypes(description: Element | undefined): DocumentedTypes {
|
|
@@ -147,76 +146,6 @@ function sameLinkedType(left: LinkedToken[], right: LinkedToken[]): boolean {
|
|
|
147
146
|
return key(left) === key(right);
|
|
148
147
|
}
|
|
149
148
|
|
|
150
|
-
function linkedTokens(children: ElementContent[], href?: string): LinkedToken[] {
|
|
151
|
-
const tokens: LinkedToken[] = [];
|
|
152
|
-
for (const child of children) {
|
|
153
|
-
if (child.type === 'text') {
|
|
154
|
-
tokens.push({ text: child.value.replace(/\s+/g, ' '), href });
|
|
155
|
-
} else if (child.type === 'element') {
|
|
156
|
-
let nextHref = href;
|
|
157
|
-
if (child.tagName === 'a' && typeof child.properties.href === 'string') {
|
|
158
|
-
nextHref = safeHref(child.properties.href)?.replace(
|
|
159
|
-
/[\u0000-\u0020\u007f"'()[\]<>`{}\\]/g,
|
|
160
|
-
(character) => `%${character.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0')}`
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
tokens.push(...linkedTokens(child.children, nextHref));
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
const merged: LinkedToken[] = [];
|
|
167
|
-
for (const token of tokens) {
|
|
168
|
-
const previous = merged.at(-1);
|
|
169
|
-
if (previous && previous.href === token.href) previous.text += token.text;
|
|
170
|
-
else merged.push({ ...token });
|
|
171
|
-
}
|
|
172
|
-
return merged;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
function trimTokens(tokens: LinkedToken[]): LinkedToken[] {
|
|
176
|
-
const text = tokens.map((token) => token.text).join('');
|
|
177
|
-
return sliceTokens(tokens, text.length - text.trimStart().length, text.trimEnd().length);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function sliceTokens(tokens: LinkedToken[], start: number, end: number): LinkedToken[] {
|
|
181
|
-
const sliced: LinkedToken[] = [];
|
|
182
|
-
let offset = 0;
|
|
183
|
-
for (const token of tokens) {
|
|
184
|
-
const tokenEnd = offset + token.text.length;
|
|
185
|
-
if (tokenEnd > start && offset < end) {
|
|
186
|
-
sliced.push({
|
|
187
|
-
text: token.text.slice(Math.max(0, start - offset), end - offset),
|
|
188
|
-
href: token.href,
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
offset = tokenEnd;
|
|
192
|
-
}
|
|
193
|
-
return sliced;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function topLevelDelimiter(text: string, delimiter: string): number {
|
|
197
|
-
let depth = 0;
|
|
198
|
-
let quote: string | undefined;
|
|
199
|
-
let escaped = false;
|
|
200
|
-
for (let index = 0; index < text.length; index += 1) {
|
|
201
|
-
const character = text[index];
|
|
202
|
-
if (escaped) {
|
|
203
|
-
escaped = false;
|
|
204
|
-
} else if (quote) {
|
|
205
|
-
if (character === '\\') escaped = true;
|
|
206
|
-
else if (character === quote) quote = undefined;
|
|
207
|
-
} else if (character === '"' || character === "'") {
|
|
208
|
-
quote = character;
|
|
209
|
-
} else if (character === '(' || character === '[' || character === '{') {
|
|
210
|
-
depth += 1;
|
|
211
|
-
} else if (character === ')' || character === ']' || character === '}') {
|
|
212
|
-
depth = Math.max(0, depth - 1);
|
|
213
|
-
} else if (character === delimiter && depth === 0) {
|
|
214
|
-
return index;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return -1;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
149
|
function findElements(node: Element, className: string): Element[] {
|
|
221
150
|
const elements: Element[] = [];
|
|
222
151
|
for (const child of node.children) {
|