@mintlify/scraping 4.0.906 → 4.0.908

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 (43) hide show
  1. package/__test__/sdk-docfx.test.ts +204 -0
  2. package/__test__/sdk-javadoc.test.ts +150 -0
  3. package/__test__/sdk-phpdoc.test.ts +134 -0
  4. package/__test__/sdk-sphinx.test.ts +84 -0
  5. package/__test__/sdk-typedoc.test.ts +138 -0
  6. package/bin/index.d.ts +3 -0
  7. package/bin/index.js +2 -0
  8. package/bin/index.js.map +1 -1
  9. package/bin/sdk/convert.d.ts +6 -0
  10. package/bin/sdk/convert.js +90 -0
  11. package/bin/sdk/convert.js.map +1 -0
  12. package/bin/sdk/converters/docfx.d.ts +2 -0
  13. package/bin/sdk/converters/docfx.js +402 -0
  14. package/bin/sdk/converters/docfx.js.map +1 -0
  15. package/bin/sdk/converters/javadoc.d.ts +2 -0
  16. package/bin/sdk/converters/javadoc.js +318 -0
  17. package/bin/sdk/converters/javadoc.js.map +1 -0
  18. package/bin/sdk/converters/phpdoc.d.ts +2 -0
  19. package/bin/sdk/converters/phpdoc.js +351 -0
  20. package/bin/sdk/converters/phpdoc.js.map +1 -0
  21. package/bin/sdk/converters/sphinx.d.ts +2 -0
  22. package/bin/sdk/converters/sphinx.js +267 -0
  23. package/bin/sdk/converters/sphinx.js.map +1 -0
  24. package/bin/sdk/converters/typedoc.d.ts +2 -0
  25. package/bin/sdk/converters/typedoc.js +318 -0
  26. package/bin/sdk/converters/typedoc.js.map +1 -0
  27. package/bin/sdk/generateSdkReference.d.ts +2 -0
  28. package/bin/sdk/generateSdkReference.js +20 -0
  29. package/bin/sdk/generateSdkReference.js.map +1 -0
  30. package/bin/sdk/types.d.ts +19 -0
  31. package/bin/sdk/types.js +2 -0
  32. package/bin/sdk/types.js.map +1 -0
  33. package/bin/tsconfig.build.tsbuildinfo +1 -1
  34. package/package.json +5 -4
  35. package/src/index.ts +3 -0
  36. package/src/sdk/convert.ts +101 -0
  37. package/src/sdk/converters/docfx.ts +491 -0
  38. package/src/sdk/converters/javadoc.ts +330 -0
  39. package/src/sdk/converters/phpdoc.ts +446 -0
  40. package/src/sdk/converters/sphinx.ts +277 -0
  41. package/src/sdk/converters/typedoc.ts +423 -0
  42. package/src/sdk/generateSdkReference.ts +25 -0
  43. package/src/sdk/types.ts +24 -0
@@ -0,0 +1,138 @@
1
+ import { mkdtemp, rm, writeFile } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { describe, expect, it, beforeEach, afterEach } from 'vitest';
5
+
6
+ import { convertTypedoc } from '../src/sdk/converters/typedoc.js';
7
+
8
+ const project = {
9
+ id: 0,
10
+ name: '@auth0/example',
11
+ kind: 1,
12
+ children: [
13
+ {
14
+ id: 1,
15
+ name: 'Client',
16
+ kind: 128,
17
+ comment: {
18
+ summary: [
19
+ { kind: 'text', text: 'A client for the [API](https://example.com). Second sentence.' },
20
+ ],
21
+ },
22
+ children: [
23
+ {
24
+ id: 2,
25
+ name: 'constructor',
26
+ kind: 512,
27
+ signatures: [
28
+ {
29
+ id: 3,
30
+ name: 'new Client',
31
+ kind: 16384,
32
+ parameters: [
33
+ {
34
+ id: 4,
35
+ name: 'options',
36
+ kind: 32768,
37
+ type: { type: 'reference', name: 'ClientOptions' },
38
+ comment: { summary: [{ kind: 'text', text: 'The options.' }] },
39
+ },
40
+ ],
41
+ type: { type: 'reference', name: 'Client', target: 1 },
42
+ },
43
+ ],
44
+ },
45
+ {
46
+ id: 5,
47
+ name: 'token',
48
+ kind: 1024,
49
+ flags: { isOptional: true },
50
+ type: {
51
+ type: 'union',
52
+ types: [
53
+ { type: 'intrinsic', name: 'string' },
54
+ { type: 'intrinsic', name: 'undefined' },
55
+ ],
56
+ },
57
+ comment: { summary: [{ kind: 'text', text: 'The current token.' }] },
58
+ },
59
+ {
60
+ id: 6,
61
+ name: 'login',
62
+ kind: 2048,
63
+ signatures: [
64
+ {
65
+ id: 7,
66
+ name: 'login',
67
+ kind: 4096,
68
+ comment: {
69
+ summary: [
70
+ { kind: 'text', text: 'Logs in. See ' },
71
+ { kind: 'inline-tag', text: 'ClientOptions', target: 8 },
72
+ ],
73
+ },
74
+ type: {
75
+ type: 'reference',
76
+ name: 'Promise',
77
+ typeArguments: [{ type: 'intrinsic', name: 'void' }],
78
+ },
79
+ },
80
+ ],
81
+ },
82
+ ],
83
+ },
84
+ {
85
+ id: 8,
86
+ name: 'ClientOptions',
87
+ kind: 256,
88
+ children: [
89
+ {
90
+ id: 9,
91
+ name: 'domain',
92
+ kind: 1024,
93
+ type: { type: 'intrinsic', name: 'string' },
94
+ },
95
+ ],
96
+ },
97
+ { id: 10, name: 'hidden', kind: 64, flags: { isPrivate: true }, signatures: [] },
98
+ ],
99
+ };
100
+
101
+ describe('convertTypedoc', () => {
102
+ let directory: string;
103
+
104
+ beforeEach(async () => {
105
+ directory = await mkdtemp(path.join(os.tmpdir(), 'typedoc-'));
106
+ });
107
+
108
+ afterEach(async () => {
109
+ await rm(directory, { recursive: true, force: true });
110
+ });
111
+
112
+ it('converts a typedoc project into pages and groups', async () => {
113
+ const artifact = path.join(directory, 'typedoc.json');
114
+ await writeFile(artifact, JSON.stringify(project));
115
+
116
+ const reference = await convertTypedoc(artifact);
117
+
118
+ expect(reference.groups).toEqual([
119
+ { group: 'Classes', pages: ['classes/Client'] },
120
+ { group: 'Interfaces', pages: ['interfaces/ClientOptions'] },
121
+ ]);
122
+
123
+ const client = reference.pages.find((page) => page.slug === 'classes/Client');
124
+ expect(client).toBeDefined();
125
+ expect(client?.title).toBe('Client');
126
+ expect(client?.tag).toBe('CLASS');
127
+ expect(client?.description).toBe('A client for the API.');
128
+ expect(client?.content).toContain('## Constructor');
129
+ expect(client?.content).toContain('new Client(options: ClientOptions): Client');
130
+ expect(client?.content).toContain(
131
+ '<ResponseField name={"options"} type={"ClientOptions"} required>'
132
+ );
133
+ expect(client?.content).toContain('<ResponseField name={"token"} type={"string | undefined"}>');
134
+ expect(client?.content).toContain('### login()');
135
+ expect(client?.content).toContain('[ClientOptions](/interfaces/ClientOptions)');
136
+ expect(client?.content).not.toContain('hidden');
137
+ });
138
+ });
package/bin/index.d.ts CHANGED
@@ -12,3 +12,6 @@ export { getErrorMessage } from './utils/errors.js';
12
12
  export { checkUrl } from './utils/url.js';
13
13
  export { FINAL_SUCCESS_MESSAGE } from './constants.js';
14
14
  export { parseGraphqlSdl } from './graphql/parseGraphqlSdl.js';
15
+ export { generateSdkReference } from './sdk/generateSdkReference.js';
16
+ export { htmlToMdx, hastToMdx, markdownToMdx } from './sdk/convert.js';
17
+ export type { SdkFormat, SdkPage, SdkNavGroup, SdkReference, SdkConverter } from './sdk/types.js';
package/bin/index.js CHANGED
@@ -12,4 +12,6 @@ export { getErrorMessage } from './utils/errors.js';
12
12
  export { checkUrl } from './utils/url.js';
13
13
  export { FINAL_SUCCESS_MESSAGE } from './constants.js';
14
14
  export { parseGraphqlSdl } from './graphql/parseGraphqlSdl.js';
15
+ export { generateSdkReference } from './sdk/generateSdkReference.js';
16
+ export { htmlToMdx, hastToMdx, markdownToMdx } from './sdk/convert.js';
15
17
  //# sourceMappingURL=index.js.map
package/bin/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAC;AACnG,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,kCAAkC,EAAE,MAAM,kDAAkD,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAC;AACnG,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,kCAAkC,EAAE,MAAM,kDAAkD,CAAC;AAEtG,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Root as HastRoot } from 'hast';
2
+ export type RewriteLink = (href: string) => string | undefined;
3
+ export declare function hastToMdx(fragment: HastRoot, rewriteLink?: RewriteLink): string;
4
+ export declare function htmlToMdx(html: string, rewriteLink?: RewriteLink): string;
5
+ export declare function markdownToMdx(markdown: string): string;
6
+ export declare function escapeMdxText(text: string): string;
@@ -0,0 +1,90 @@
1
+ import remarkGfm from 'remark-gfm';
2
+ import remarkMdx from 'remark-mdx';
3
+ import remarkParse from 'remark-parse';
4
+ import remarkStringify from 'remark-stringify';
5
+ import { unified } from 'unified';
6
+ import { visit } from 'unist-util-visit';
7
+ import { convertHeaderLinksToText } from '../components/link.js';
8
+ import { createCallout, createCodeGroup, createTabs } from '../customComponents/create.js';
9
+ import { rehypeToRemarkCustomComponents } from '../customComponents/plugin.js';
10
+ import { selectiveRehypeRemark } from '../customComponents/selective.js';
11
+ import { htmlToHast } from '../pipeline/root.js';
12
+ import { unifiedRemoveBreaks } from '../utils/breaks.js';
13
+ import { unifiedRemoveClassNames } from '../utils/className.js';
14
+ import { unifiedRemoveCopyButtons } from '../utils/copyButton.js';
15
+ import { framework } from '../utils/detectFramework.js';
16
+ import { remarkRemoveEmptyEmphases } from '../utils/emptyEmphasis.js';
17
+ import { unifiedRemoveEmptyParagraphs } from '../utils/emptyParagraphs.js';
18
+ import { remarkProperlyFormatEmphasis } from '../utils/formatEmphasis.js';
19
+ import { removeHastComments } from '../utils/hastComments.js';
20
+ import { remarkSpaceListsOut } from '../utils/lists.js';
21
+ import { unifiedRemoveNestedRoots } from '../utils/nestedRoots.js';
22
+ import { unifiedRemovePositions } from '../utils/position.js';
23
+ const rehypeRewriteLinks = (rewriteLink) => () => (tree) => {
24
+ visit(tree, 'element', (node) => {
25
+ if (node.tagName !== 'a' || typeof node.properties?.href !== 'string')
26
+ return;
27
+ const rewritten = rewriteLink(node.properties.href);
28
+ if (rewritten === undefined) {
29
+ delete node.properties.href;
30
+ }
31
+ else {
32
+ node.properties.href = rewritten;
33
+ }
34
+ });
35
+ };
36
+ export function hastToMdx(fragment, rewriteLink) {
37
+ const originalVendor = framework.vendor;
38
+ framework.vendor ??= 'gitbook';
39
+ try {
40
+ return runHastToMdx(fragment, rewriteLink);
41
+ }
42
+ finally {
43
+ framework.vendor = originalVendor;
44
+ }
45
+ }
46
+ function runHastToMdx(fragment, rewriteLink) {
47
+ const processor = unified().use(unifiedRemoveBreaks).use(unifiedRemoveCopyButtons);
48
+ if (rewriteLink)
49
+ processor.use(rehypeRewriteLinks(rewriteLink));
50
+ const mdastTree = processor
51
+ .use(createCallout)
52
+ .use(createCodeGroup)
53
+ .use(createTabs)
54
+ .use(unifiedRemoveClassNames)
55
+ .use(unifiedRemoveEmptyParagraphs)
56
+ .use(unifiedRemovePositions)
57
+ .use(selectiveRehypeRemark)
58
+ .use(rehypeToRemarkCustomComponents)
59
+ .use(convertHeaderLinksToText)
60
+ .use(unifiedRemoveNestedRoots)
61
+ .use(remarkSpaceListsOut)
62
+ .use(remarkRemoveEmptyEmphases)
63
+ .use(remarkProperlyFormatEmphasis)
64
+ // @ts-expect-error hast root is transformed to mdast by the plugin chain
65
+ .runSync(fragment);
66
+ return stringifyMdast(mdastTree);
67
+ }
68
+ export function htmlToMdx(html, rewriteLink) {
69
+ const hast = htmlToHast(html);
70
+ removeHastComments(hast);
71
+ return hastToMdx(hast, rewriteLink);
72
+ }
73
+ export function markdownToMdx(markdown) {
74
+ const mdastTree = unified().use(remarkParse).use(remarkGfm).parse(markdown);
75
+ visit(mdastTree, 'html', (node) => {
76
+ node.type = 'text';
77
+ node.value = node.value.replace(/<[^>]*>/g, '');
78
+ });
79
+ return stringifyMdast(mdastTree);
80
+ }
81
+ function stringifyMdast(tree) {
82
+ const result = unified().use(remarkMdx).use(remarkGfm).use(remarkStringify).stringify(tree);
83
+ return String(result)
84
+ .replace(/\n{3,}/g, '\n\n')
85
+ .trim();
86
+ }
87
+ export function escapeMdxText(text) {
88
+ return markdownToMdx(text.replace(/\r\n/g, '\n'));
89
+ }
90
+ //# sourceMappingURL=convert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/sdk/convert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { SdkReference } from '../types.js';
2
+ export declare function convertDocfx(sourcePath: string): Promise<SdkReference>;
@@ -0,0 +1,402 @@
1
+ import fse from 'fs-extra';
2
+ import yaml from 'js-yaml';
3
+ import path from 'node:path';
4
+ import { htmlToMdx } from '../convert.js';
5
+ const PAGE_TAGS = {
6
+ Class: 'CLASS',
7
+ Interface: 'INTERFACE',
8
+ Enum: 'ENUM',
9
+ Struct: 'STRUCT',
10
+ Delegate: 'DELEGATE',
11
+ };
12
+ export async function convertDocfx(sourcePath) {
13
+ const files = await loadManagedReferenceFiles(sourcePath);
14
+ const itemsByUid = new Map();
15
+ const namesByUid = new Map();
16
+ for (const file of files) {
17
+ for (const item of file.items ?? []) {
18
+ if (!item.uid)
19
+ continue;
20
+ itemsByUid.set(item.uid, item);
21
+ if (item.name)
22
+ namesByUid.set(item.uid, item.name);
23
+ }
24
+ for (const reference of file.references ?? []) {
25
+ if (reference.uid && reference.name && !namesByUid.has(reference.uid)) {
26
+ namesByUid.set(reference.uid, reference.name);
27
+ }
28
+ }
29
+ }
30
+ const types = [...itemsByUid.values()]
31
+ .filter((item) => item.type !== undefined && item.type in PAGE_TAGS)
32
+ .sort((left, right) => (left.name ?? '').localeCompare(right.name ?? ''));
33
+ const namespaceSlug = namespaceSlugs([...new Set(types.map((type) => type.namespace ?? ''))].sort());
34
+ const slugByUid = new Map();
35
+ for (const type of types) {
36
+ slugByUid.set(type.uid, path.posix.join(namespaceSlug.get(type.namespace ?? '') ?? '', slugify(type.name ?? type.uid)));
37
+ }
38
+ const renderer = new DocfxRenderer(slugByUid, namesByUid, itemsByUid);
39
+ const { tocNamespaces, tocOrder } = await loadToc(sourcePath);
40
+ const typesByNamespace = new Map();
41
+ for (const type of types) {
42
+ const namespace = type.namespace ?? '';
43
+ typesByNamespace.set(namespace, [...(typesByNamespace.get(namespace) ?? []), type]);
44
+ }
45
+ const namespaceOrder = [
46
+ ...tocNamespaces.filter((namespace) => typesByNamespace.has(namespace)),
47
+ ...[...typesByNamespace.keys()]
48
+ .filter((namespace) => !tocNamespaces.includes(namespace))
49
+ .sort(),
50
+ ];
51
+ const pages = [];
52
+ const groups = [];
53
+ for (const namespace of namespaceOrder) {
54
+ const ordered = orderByToc(typesByNamespace.get(namespace) ?? [], tocOrder.get(namespace) ?? []);
55
+ const namespacePages = ordered.map((type) => renderer.renderPage(type));
56
+ pages.push(...namespacePages);
57
+ groups.push({
58
+ group: namespace || 'Reference',
59
+ pages: namespacePages.map((page) => page.slug),
60
+ });
61
+ }
62
+ return { pages, groups };
63
+ }
64
+ async function loadManagedReferenceFiles(sourcePath) {
65
+ const entries = await fse.readdir(sourcePath);
66
+ const files = [];
67
+ for (const entry of entries.filter((name) => /\.ya?ml$/.test(name)).sort()) {
68
+ const raw = await fse.readFile(path.join(sourcePath, entry), 'utf8');
69
+ if (!raw.startsWith('### YamlMime:ManagedReference'))
70
+ continue;
71
+ const parsed = yaml.load(raw);
72
+ if (parsed && typeof parsed === 'object')
73
+ files.push(parsed);
74
+ }
75
+ return files;
76
+ }
77
+ async function loadToc(sourcePath) {
78
+ const tocNamespaces = [];
79
+ const tocOrder = new Map();
80
+ const tocPath = path.join(sourcePath, 'toc.yml');
81
+ if (!(await fse.pathExists(tocPath)))
82
+ return { tocNamespaces, tocOrder };
83
+ const parsed = yaml.load(await fse.readFile(tocPath, 'utf8'));
84
+ const collect = (nodes) => {
85
+ for (const node of nodes) {
86
+ if (node.type === 'Namespace' && node.uid !== undefined) {
87
+ tocNamespaces.push(node.uid);
88
+ tocOrder.set(node.uid, (node.items ?? [])
89
+ .map((child) => child.uid)
90
+ .filter((uid) => typeof uid === 'string'));
91
+ }
92
+ if (node.items)
93
+ collect(node.items);
94
+ }
95
+ };
96
+ collect(parsed?.items ?? []);
97
+ return { tocNamespaces, tocOrder };
98
+ }
99
+ function orderByToc(types, order) {
100
+ const rank = new Map(order.map((uid, index) => [uid, index]));
101
+ return [...types].sort((left, right) => {
102
+ const leftRank = rank.get(left.uid);
103
+ const rightRank = rank.get(right.uid);
104
+ if (leftRank !== undefined && rightRank !== undefined)
105
+ return leftRank - rightRank;
106
+ if (leftRank !== undefined)
107
+ return -1;
108
+ if (rightRank !== undefined)
109
+ return 1;
110
+ return (left.name ?? '').localeCompare(right.name ?? '');
111
+ });
112
+ }
113
+ function namespaceSlugs(namespaces) {
114
+ const parts = namespaces.map((namespace) => namespace.split('.'));
115
+ let common = parts[0] ?? [];
116
+ for (const segments of parts.slice(1)) {
117
+ let index = 0;
118
+ while (index < common.length && common[index] === segments[index])
119
+ index += 1;
120
+ common = common.slice(0, index);
121
+ }
122
+ const slugs = new Map();
123
+ const used = new Set();
124
+ for (const [index, namespace] of namespaces.entries()) {
125
+ const segments = parts[index] ?? [];
126
+ const rest = segments.slice(common.length);
127
+ const base = slugify((rest.length ? rest : segments.slice(-1)).join('-'));
128
+ let slug = used.has(base) ? slugify(segments.join('-')) : base;
129
+ for (let suffix = 2; used.has(slug); suffix += 1) {
130
+ slug = `${slugify(segments.join('-'))}-${suffix}`;
131
+ }
132
+ used.add(slug);
133
+ slugs.set(namespace, slug);
134
+ }
135
+ return slugs;
136
+ }
137
+ function slugify(name) {
138
+ return (name
139
+ .toLowerCase()
140
+ .replace(/`+\d*/g, '')
141
+ .replace(/[^a-z0-9-_.]+/g, '-')
142
+ .replace(/^-+|-+$/g, '') || 'item');
143
+ }
144
+ class DocfxRenderer {
145
+ constructor(slugByUid, namesByUid, itemsByUid) {
146
+ this.slugByUid = slugByUid;
147
+ this.namesByUid = namesByUid;
148
+ this.itemsByUid = itemsByUid;
149
+ }
150
+ renderPage(item) {
151
+ const lines = [this.prose(item.summary)];
152
+ if (item.syntax?.content)
153
+ lines.push(this.codeBlock(item.syntax.content));
154
+ lines.push(this.prose(item.remarks));
155
+ lines.push(...(item.example ?? []).map((example) => this.renderExample(example)));
156
+ switch (item.type) {
157
+ case 'Enum':
158
+ lines.push(...this.renderEnum(item));
159
+ break;
160
+ case 'Delegate':
161
+ lines.push(...this.renderSignatureDetails(item.syntax, 2));
162
+ break;
163
+ default:
164
+ lines.push(...this.renderTypeMembers(item));
165
+ }
166
+ return {
167
+ slug: this.slugByUid.get(item.uid) ?? slugify(item.name ?? item.uid),
168
+ title: item.name ?? item.uid,
169
+ description: this.firstSentence(item.summary),
170
+ tag: PAGE_TAGS[item.type ?? ''],
171
+ content: lines.filter(Boolean).join('\n\n'),
172
+ };
173
+ }
174
+ members(item) {
175
+ return (item.children ?? [])
176
+ .map((uid) => this.itemsByUid.get(uid))
177
+ .filter((member) => member !== undefined);
178
+ }
179
+ renderTypeMembers(item) {
180
+ const members = this.members(item);
181
+ const lines = [];
182
+ const constructors = members.filter((member) => member.type === 'Constructor');
183
+ const fields = members.filter((member) => member.type === 'Field').sort(byName);
184
+ const properties = members
185
+ .filter((member) => member.type === 'Property' || member.type === 'Event')
186
+ .sort(byName);
187
+ const methods = members.filter((member) => member.type === 'Method' || member.type === 'Operator');
188
+ if (constructors.length) {
189
+ lines.push('## Constructors');
190
+ for (const ctor of constructors)
191
+ lines.push(...this.renderMember(ctor, 3));
192
+ }
193
+ if (fields.length) {
194
+ lines.push('## Fields');
195
+ for (const field of fields)
196
+ lines.push(this.memberField(field));
197
+ }
198
+ if (properties.length) {
199
+ lines.push('## Properties');
200
+ for (const property of properties)
201
+ lines.push(this.memberField(property));
202
+ }
203
+ if (methods.length) {
204
+ lines.push('## Methods');
205
+ const grouped = new Map();
206
+ for (const method of methods) {
207
+ const base = baseName(method.name ?? method.uid);
208
+ grouped.set(base, [...(grouped.get(base) ?? []), method]);
209
+ }
210
+ for (const [name, overloads] of [...grouped.entries()].sort(([left], [right]) => left.localeCompare(right))) {
211
+ lines.push(`### ${name}()`);
212
+ for (const overload of overloads)
213
+ lines.push(...this.renderMember(overload, 4));
214
+ }
215
+ }
216
+ return lines;
217
+ }
218
+ renderEnum(item) {
219
+ const lines = ['## Members'];
220
+ for (const member of this.members(item).filter((child) => child.type === 'Field')) {
221
+ const value = member.syntax?.content?.split('=')[1]?.trim() ?? '';
222
+ lines.push(this.responseField(member.name ?? member.uid, value, false, this.prose(member.summary)));
223
+ }
224
+ return lines;
225
+ }
226
+ renderMember(member, depth) {
227
+ const lines = [];
228
+ if (member.syntax?.content)
229
+ lines.push(this.codeBlock(member.syntax.content));
230
+ lines.push(this.prose(member.summary), this.prose(member.remarks));
231
+ lines.push(...(member.example ?? []).map((example) => this.renderExample(example)));
232
+ lines.push(...this.renderSignatureDetails(member.syntax, depth));
233
+ return lines.filter(Boolean);
234
+ }
235
+ renderSignatureDetails(syntax, depth) {
236
+ if (!syntax)
237
+ return [];
238
+ const lines = [];
239
+ const heading = '#'.repeat(depth);
240
+ if (syntax.typeParameters?.length) {
241
+ lines.push(`${heading} Type Parameters`);
242
+ for (const param of syntax.typeParameters) {
243
+ lines.push(this.responseField(param.id ?? '', '', false, this.prose(param.description)));
244
+ }
245
+ }
246
+ if (syntax.parameters?.length) {
247
+ lines.push(`${heading} Parameters`);
248
+ for (const param of syntax.parameters) {
249
+ lines.push(this.responseField(param.id ?? '', this.typeName(param.type), isOptionalParameter(param.id, syntax.content), this.prose(param.description)));
250
+ }
251
+ }
252
+ const returnType = this.typeName(syntax.return?.type);
253
+ if (returnType && returnType.toLowerCase() !== 'void') {
254
+ lines.push(`${heading} Returns`);
255
+ const description = this.prose(syntax.return?.description);
256
+ lines.push(`\`${escapeInlineCode(returnType)}\`${description ? `\n\n${description}` : ''}`);
257
+ }
258
+ return lines;
259
+ }
260
+ memberField(member) {
261
+ const body = [
262
+ this.prose(member.summary),
263
+ this.prose(member.remarks),
264
+ ...(member.example ?? []).map((example) => this.renderExample(example)),
265
+ ]
266
+ .filter(Boolean)
267
+ .join('\n\n');
268
+ return this.responseField(member.name ?? member.uid, this.typeName(member.syntax?.return?.type), isNullable(member.syntax?.content), body);
269
+ }
270
+ responseField(name, type, optional, body) {
271
+ const typeAttr = type ? ` type=${this.jsxString(truncate(type, 80))}` : '';
272
+ const requiredAttr = optional ? '' : ' required';
273
+ return `<ResponseField name=${this.jsxString(name)}${typeAttr}${requiredAttr}>\n${indent(body || '')}\n</ResponseField>`;
274
+ }
275
+ jsxString(value) {
276
+ return `{${JSON.stringify(value)}}`;
277
+ }
278
+ codeBlock(code, lang = 'csharp') {
279
+ return `\`\`\`${lang}\n${code}\n\`\`\``;
280
+ }
281
+ renderExample(example) {
282
+ if (/<[a-z][^>]*>/i.test(example))
283
+ return this.prose(example);
284
+ return this.codeBlock(decodeEntities(example));
285
+ }
286
+ prose(html) {
287
+ if (!html)
288
+ return '';
289
+ const resolved = this.inlineCodeSpans(this.resolveXrefs(html));
290
+ return resolved
291
+ .split(/(<pre[^>]*>[\s\S]*?<\/pre>)/g)
292
+ .map((segment, index) => index % 2 === 1 ? this.preToCodeBlock(segment) : htmlToMdx(segment))
293
+ .filter(Boolean)
294
+ .join('\n\n');
295
+ }
296
+ preToCodeBlock(segment) {
297
+ const lang = /class="lang(?:uage)?-([\w-]+)"/.exec(segment)?.[1] ?? 'csharp';
298
+ const code = decodeEntities(segment.replace(/<[^>]+>/g, '')).replace(/^\n+|\n+$/g, '');
299
+ return this.codeBlock(code, lang);
300
+ }
301
+ resolveXrefs(html) {
302
+ return html.replace(/<xref\s[^>]*?(?:href|uid)="([^"]+)"[^>]*>([\s\S]*?)<\/xref>/g, (_, href, text) => {
303
+ const uid = decodeUid(href);
304
+ const label = text.trim() || escapeHtml(this.shortName(uid));
305
+ const slug = this.slugForUid(uid);
306
+ return slug ? `<a href="/${slug}">${label}</a>` : `<code>${label}</code>`;
307
+ });
308
+ }
309
+ inlineCodeSpans(html) {
310
+ return html
311
+ .split(/(<pre[\s\S]*?<\/pre>|<code[\s\S]*?<\/code>)/g)
312
+ .map((segment, index) => index % 2 === 1
313
+ ? segment
314
+ : segment.replace(/`([^`\n]+)`/g, (_, code) => `<code>${escapeHtml(code)}</code>`))
315
+ .join('');
316
+ }
317
+ slugForUid(uid) {
318
+ const direct = this.slugByUid.get(uid);
319
+ if (direct)
320
+ return direct;
321
+ const parent = this.itemsByUid.get(uid)?.parent ??
322
+ uid
323
+ .replace(/\(.*\)$/, '')
324
+ .replace(/\*$/, '')
325
+ .replace(/\.[^.]*$/, '');
326
+ return parent ? this.slugByUid.get(parent) : undefined;
327
+ }
328
+ shortName(uid) {
329
+ return this.namesByUid.get(uid) ?? shortNameFromUid(uid);
330
+ }
331
+ typeName(uid) {
332
+ return uid ? this.shortName(uid) : '';
333
+ }
334
+ firstSentence(summary) {
335
+ if (!summary)
336
+ return undefined;
337
+ const text = decodeEntities(summary.replace(/<[^>]*>/g, ' '))
338
+ .replace(/\s+/g, ' ')
339
+ .trim();
340
+ if (!text)
341
+ return undefined;
342
+ const sentence = text.split(/(?<=\.)\s/)[0] ?? text;
343
+ return truncate(sentence, 160);
344
+ }
345
+ }
346
+ function byName(left, right) {
347
+ return (left.name ?? '').localeCompare(right.name ?? '');
348
+ }
349
+ function baseName(name) {
350
+ return name.split(/[(<]/)[0]?.trim() || name;
351
+ }
352
+ function shortNameFromUid(uid) {
353
+ return uid
354
+ .replace(/`+\d+/g, '')
355
+ .replace(/\{/g, '<')
356
+ .replace(/\}/g, '>')
357
+ .replace(/[A-Za-z_][A-Za-z0-9_.]*/g, (dotted) => dotted.split('.').at(-1) ?? dotted);
358
+ }
359
+ function decodeUid(href) {
360
+ try {
361
+ return decodeEntities(decodeURIComponent(href));
362
+ }
363
+ catch {
364
+ return decodeEntities(href);
365
+ }
366
+ }
367
+ function decodeEntities(text) {
368
+ return text
369
+ .replace(/&lt;/g, '<')
370
+ .replace(/&gt;/g, '>')
371
+ .replace(/&quot;/g, '"')
372
+ .replace(/&#39;/g, "'")
373
+ .replace(/&nbsp;/g, ' ')
374
+ .replace(/&amp;/g, '&');
375
+ }
376
+ function escapeHtml(text) {
377
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
378
+ }
379
+ function isNullable(content) {
380
+ return content !== undefined && /\?\s+\w+\s*[{;=]/.test(content);
381
+ }
382
+ function isOptionalParameter(id, content) {
383
+ if (!id || !content)
384
+ return false;
385
+ return new RegExp(`\\b${escapeRegExp(id)}\\s*=`).test(content);
386
+ }
387
+ function escapeRegExp(text) {
388
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
389
+ }
390
+ function indent(text) {
391
+ return text
392
+ .split('\n')
393
+ .map((line) => (line ? ` ${line}` : line))
394
+ .join('\n');
395
+ }
396
+ function truncate(text, max) {
397
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
398
+ }
399
+ function escapeInlineCode(text) {
400
+ return text.replace(/`/g, '');
401
+ }
402
+ //# sourceMappingURL=docfx.js.map