sourcey 3.6.0 → 3.6.1
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/README.md +5 -2
- package/dist/adapters/index.d.ts +3 -2
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +35 -3
- package/dist/adapters/types.d.ts +8 -2
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/cli.js +28 -34
- package/dist/client/search.js +181 -119
- package/dist/client/tabs.js +23 -0
- package/dist/components/layout/Head.js +2 -2
- package/dist/components/openapi/Introduction.d.ts.map +1 -1
- package/dist/components/openapi/Introduction.js +16 -1
- package/dist/components/openapi/Security.d.ts.map +1 -1
- package/dist/components/openapi/Security.js +18 -2
- package/dist/config.d.ts +63 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -7
- package/dist/core/api-rendering.d.ts +47 -0
- package/dist/core/api-rendering.d.ts.map +1 -0
- package/dist/core/api-rendering.js +76 -0
- package/dist/core/doxygen-loader.d.ts.map +1 -1
- package/dist/core/doxygen-loader.js +35 -18
- package/dist/core/godoc-loader.d.ts.map +1 -1
- package/dist/core/godoc-loader.js +17 -6
- package/dist/core/markdown-loader.d.ts.map +1 -1
- package/dist/core/markdown-loader.js +8 -5
- package/dist/core/mcp-normalizer.d.ts.map +1 -1
- package/dist/core/mcp-normalizer.js +48 -34
- package/dist/core/parser.d.ts.map +1 -1
- package/dist/core/parser.js +75 -4
- package/dist/core/rustdoc-introspector.d.ts +29 -0
- package/dist/core/rustdoc-introspector.d.ts.map +1 -0
- package/dist/core/rustdoc-introspector.js +236 -0
- package/dist/core/rustdoc-loader.d.ts +25 -0
- package/dist/core/rustdoc-loader.d.ts.map +1 -0
- package/dist/core/rustdoc-loader.js +469 -0
- package/dist/core/rustdoc-render.d.ts +76 -0
- package/dist/core/rustdoc-render.d.ts.map +1 -0
- package/dist/core/rustdoc-render.js +785 -0
- package/dist/core/rustdoc-types.d.ts +314 -0
- package/dist/core/rustdoc-types.d.ts.map +1 -0
- package/dist/core/rustdoc-types.js +18 -0
- package/dist/core/search-indexer.js +1 -1
- package/dist/core/sourcey-rustdoc/Cargo.lock +705 -0
- package/dist/core/sourcey-rustdoc/Cargo.toml +38 -0
- package/dist/core/sourcey-rustdoc/README.md +59 -0
- package/dist/core/sourcey-rustdoc/src/diagnostics.rs +42 -0
- package/dist/core/sourcey-rustdoc/src/doctest.rs +268 -0
- package/dist/core/sourcey-rustdoc/src/extract.rs +492 -0
- package/dist/core/sourcey-rustdoc/src/lib.rs +58 -0
- package/dist/core/sourcey-rustdoc/src/links.rs +126 -0
- package/dist/core/sourcey-rustdoc/src/main.rs +256 -0
- package/dist/core/sourcey-rustdoc/src/signature.rs +415 -0
- package/dist/core/sourcey-rustdoc/src/spec.rs +390 -0
- package/dist/core/sourcey-rustdoc/tests/format_version.rs +45 -0
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +49 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -13
- package/dist/init.js +2 -2
- package/dist/renderer/changelog-feed.d.ts.map +1 -1
- package/dist/renderer/changelog-feed.js +27 -19
- package/dist/renderer/html-builder.d.ts.map +1 -1
- package/dist/renderer/html-builder.js +4 -3
- package/dist/renderer/llms.js +57 -2
- package/dist/site-assembly.d.ts +5 -0
- package/dist/site-assembly.d.ts.map +1 -1
- package/dist/site-assembly.js +55 -1
- package/dist/themes/default/sourcey.css +300 -0
- package/dist/utils/code-samples.d.ts +1 -0
- package/dist/utils/code-samples.d.ts.map +1 -1
- package/dist/utils/code-samples.js +30 -22
- package/dist/utils/html.d.ts +10 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +152 -0
- package/dist/utils/http.d.ts +0 -2
- package/dist/utils/http.d.ts.map +1 -1
- package/dist/utils/http.js +19 -34
- package/dist/utils/markdown.d.ts.map +1 -1
- package/dist/utils/markdown.js +102 -37
- package/package.json +9 -4
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { runIntrospector, RustdocIntrospectorError } from "./rustdoc-introspector.js";
|
|
2
|
+
import { itemAnchor, renderModulePage } from "./rustdoc-render.js";
|
|
3
|
+
import { renderCodeBlock } from "../utils/markdown.js";
|
|
4
|
+
/** Load a rustdoc tab from the configured manifest or snapshot. */
|
|
5
|
+
export async function loadRustdocTab(config, tabSlug, tabLabel, sourceLinks = {}) {
|
|
6
|
+
let result;
|
|
7
|
+
try {
|
|
8
|
+
result = await runIntrospector({ config });
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
if (err instanceof RustdocIntrospectorError) {
|
|
12
|
+
const pages = new Map();
|
|
13
|
+
pages.set("index", emptyIndexPage(tabSlug, tabLabel, `Rustdoc introspection failed: ${err.message}`));
|
|
14
|
+
return {
|
|
15
|
+
pages,
|
|
16
|
+
navTab: emptyNavTab(tabSlug, tabLabel),
|
|
17
|
+
diagnostics: [
|
|
18
|
+
{
|
|
19
|
+
severity: "error",
|
|
20
|
+
code: err.code,
|
|
21
|
+
message: err.message,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
const pages = new Map();
|
|
29
|
+
const navGroups = [];
|
|
30
|
+
const diagnostics = result.diagnostics.map(toLoaderDiagnostic);
|
|
31
|
+
const allDoctests = [];
|
|
32
|
+
for (const crate of result.spec.crates) {
|
|
33
|
+
const crateItems = itemsAsMap(crate.items);
|
|
34
|
+
for (const module of crate.modules) {
|
|
35
|
+
const renderDiagnostics = [];
|
|
36
|
+
const page = renderModulePageLoader(crate, module, crateItems, tabSlug, sourceLinks, renderDiagnostics);
|
|
37
|
+
pages.set(page.slug, page);
|
|
38
|
+
for (const d of renderDiagnostics)
|
|
39
|
+
diagnostics.push(toLoaderDiagnostic(d));
|
|
40
|
+
}
|
|
41
|
+
const indexPage = renderCrateIndexPage(crate, tabSlug);
|
|
42
|
+
pages.set(indexPage.slug, indexPage);
|
|
43
|
+
for (const item of crateItems.values()) {
|
|
44
|
+
for (const dt of item.doctests) {
|
|
45
|
+
allDoctests.push({ crate, item, doctest: dt });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
navGroups.push(buildCrateNavGroup(crate, tabSlug));
|
|
49
|
+
}
|
|
50
|
+
if (config.doctestsIndex && allDoctests.length > 0) {
|
|
51
|
+
const dtPage = renderDoctestsIndexPage(allDoctests);
|
|
52
|
+
pages.set(dtPage.slug, dtPage);
|
|
53
|
+
navGroups.unshift({
|
|
54
|
+
label: "Examples",
|
|
55
|
+
items: [
|
|
56
|
+
{
|
|
57
|
+
label: "Doctests",
|
|
58
|
+
href: tabRelativeHref(tabSlug, dtPage.slug),
|
|
59
|
+
id: "doctests",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (result.spec.crates.length === 0) {
|
|
65
|
+
pages.set("index", emptyIndexPage(tabSlug, tabLabel, "No documented crates."));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
pages.set("index", renderWorkspaceIndexPage(result.spec.crates, tabSlug, tabLabel));
|
|
69
|
+
}
|
|
70
|
+
const navTab = {
|
|
71
|
+
label: tabLabel,
|
|
72
|
+
slug: tabSlug,
|
|
73
|
+
href: tabRelativeHref(tabSlug, "index"),
|
|
74
|
+
kind: "docs",
|
|
75
|
+
groups: navGroups,
|
|
76
|
+
};
|
|
77
|
+
return { pages, navTab, diagnostics };
|
|
78
|
+
}
|
|
79
|
+
function renderModulePageLoader(crate, module, itemsById, tabSlug, sourceLinks, diagnostics) {
|
|
80
|
+
const slug = moduleSlug(crate.name, module.path);
|
|
81
|
+
const title = module.path.length === 0 ? crate.name : module.path.join("::");
|
|
82
|
+
const description = firstLine(module.docs_markdown) ?? "";
|
|
83
|
+
const items = module.item_ids
|
|
84
|
+
.map((id) => itemsById.get(id))
|
|
85
|
+
.filter((i) => Boolean(i));
|
|
86
|
+
const headings = collectHeadings(items);
|
|
87
|
+
const searchEntries = collectSearchEntries(items, title);
|
|
88
|
+
const ctx = buildRenderContext(crate, itemsById, tabSlug, sourceLinks, diagnostics);
|
|
89
|
+
const rendered = renderModulePage(module, items, ctx);
|
|
90
|
+
const html = rendered.html;
|
|
91
|
+
return {
|
|
92
|
+
kind: "markdown",
|
|
93
|
+
title,
|
|
94
|
+
description,
|
|
95
|
+
slug,
|
|
96
|
+
html,
|
|
97
|
+
headings,
|
|
98
|
+
sourcePath: `rustdoc/${slug}.md`,
|
|
99
|
+
editPath: module.source ? module.source.file : null,
|
|
100
|
+
editBasePath: sourceLinks.editBasePath ?? "",
|
|
101
|
+
searchEntries,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function renderWorkspaceIndexPage(crates, tabSlug, tabLabel) {
|
|
105
|
+
const headings = [];
|
|
106
|
+
const searchEntries = [];
|
|
107
|
+
const cards = crates.map((c) => {
|
|
108
|
+
const href = tabRelativeHref(tabSlug, crateIndexSlug(c.name));
|
|
109
|
+
const items = Object.keys(c.items).length;
|
|
110
|
+
const modules = c.modules.length;
|
|
111
|
+
const summary = `${items} item${items === 1 ? "" : "s"} across ${modules} module${modules === 1 ? "" : "s"}.`;
|
|
112
|
+
const version = c.version
|
|
113
|
+
? `<p style="margin:0.5rem 0 0;font-size:0.8rem;opacity:0.5">v${escapeHtml(c.version)}</p>`
|
|
114
|
+
: "";
|
|
115
|
+
headings.push({ id: crateIndexSlug(c.name), text: c.name, level: 3 });
|
|
116
|
+
searchEntries.push({
|
|
117
|
+
title: c.name,
|
|
118
|
+
content: summary,
|
|
119
|
+
anchor: crateIndexSlug(c.name),
|
|
120
|
+
category: "rust crate",
|
|
121
|
+
qualifiedName: c.name,
|
|
122
|
+
});
|
|
123
|
+
return (`<a class="card-item" href="${escapeHtml(href)}" id="${crateIndexSlug(c.name)}">` +
|
|
124
|
+
`<div class="card-item-inner">` +
|
|
125
|
+
`<h3 class="card-item-title">${escapeHtml(c.name)}</h3>` +
|
|
126
|
+
`<div class="card-item-content"><p>${escapeHtml(summary)}</p>${version}</div>` +
|
|
127
|
+
`</div></a>`);
|
|
128
|
+
});
|
|
129
|
+
const cols = cards.length <= 2 ? "2" : "3";
|
|
130
|
+
return {
|
|
131
|
+
kind: "markdown",
|
|
132
|
+
title: tabLabel,
|
|
133
|
+
description: `Rust API across ${crates.length} crate${crates.length === 1 ? "" : "s"}.`,
|
|
134
|
+
slug: "index",
|
|
135
|
+
html: `<div class="card-group not-prose" data-cols="${cols}">\n${cards.join("\n")}\n</div>`,
|
|
136
|
+
headings,
|
|
137
|
+
sourcePath: `rustdoc/index.md`,
|
|
138
|
+
searchEntries,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function renderCrateIndexPage(crate, tabSlug) {
|
|
142
|
+
const slug = crateIndexSlug(crate.name);
|
|
143
|
+
const moduleCount = crate.modules.length;
|
|
144
|
+
const itemCount = Object.keys(crate.items).length;
|
|
145
|
+
const description = `Rust API for ${crate.name} (${itemCount} items across ${moduleCount} modules).`;
|
|
146
|
+
const headings = [];
|
|
147
|
+
const cards = [...crate.modules]
|
|
148
|
+
.sort((a, b) => a.path.join("::").localeCompare(b.path.join("::")))
|
|
149
|
+
.map((m) => {
|
|
150
|
+
const mSlug = moduleSlug(crate.name, m.path);
|
|
151
|
+
const href = tabRelativeHref(tabSlug, mSlug);
|
|
152
|
+
const label = m.path.length === 0 ? `${crate.name} (root)` : m.path.join("::");
|
|
153
|
+
const count = m.item_ids.length;
|
|
154
|
+
const lead = firstLine(m.docs_markdown);
|
|
155
|
+
const meta = `<p style="margin:0.5rem 0 0;font-size:0.8rem;opacity:0.5">${count} item${count === 1 ? "" : "s"}</p>`;
|
|
156
|
+
headings.push({ id: mSlug, text: label, level: 3 });
|
|
157
|
+
return (`<a class="card-item" href="${escapeHtml(href)}" id="${mSlug}">` +
|
|
158
|
+
`<div class="card-item-inner">` +
|
|
159
|
+
`<h3 class="card-item-title">${escapeHtml(label)}</h3>` +
|
|
160
|
+
`<div class="card-item-content">${lead ? `<p>${escapeHtml(lead)}</p>` : ""}${meta}</div>` +
|
|
161
|
+
`</div></a>`);
|
|
162
|
+
});
|
|
163
|
+
const html = cards.length === 0
|
|
164
|
+
? `<p>${escapeHtml(description)}</p>`
|
|
165
|
+
: `<div class="card-group not-prose" data-cols="${cards.length <= 2 ? "2" : "3"}">\n${cards.join("\n")}\n</div>`;
|
|
166
|
+
return {
|
|
167
|
+
kind: "markdown",
|
|
168
|
+
title: crate.name,
|
|
169
|
+
description,
|
|
170
|
+
slug,
|
|
171
|
+
html,
|
|
172
|
+
headings,
|
|
173
|
+
sourcePath: `rustdoc/${slug}.md`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function renderDoctestsIndexPage(doctests) {
|
|
177
|
+
const headings = [];
|
|
178
|
+
const searchEntries = [];
|
|
179
|
+
const parts = [];
|
|
180
|
+
parts.push(`<section class="rust-doctests-index">`);
|
|
181
|
+
parts.push(`<h1>Doctests</h1>`);
|
|
182
|
+
parts.push(`<p>${doctests.length} runnable example${doctests.length === 1 ? "" : "s"}.</p>`);
|
|
183
|
+
for (const { crate, item, doctest } of doctests) {
|
|
184
|
+
const parentPath = item.path.join("::");
|
|
185
|
+
const anchor = `doctest-${itemAnchor(item)}-${doctest.ordinal}`;
|
|
186
|
+
headings.push({ id: anchor, text: parentPath, level: 3 });
|
|
187
|
+
searchEntries.push({
|
|
188
|
+
title: `Doctest: ${parentPath}`,
|
|
189
|
+
content: doctest.display_code.slice(0, 200),
|
|
190
|
+
anchor,
|
|
191
|
+
category: "rust doctest",
|
|
192
|
+
ownerKind: itemKindLabel(item),
|
|
193
|
+
owner: parentPath,
|
|
194
|
+
namespace: crate.name,
|
|
195
|
+
});
|
|
196
|
+
parts.push(`<section class="rust-doctest" id="${anchor}"><h3>${escapeHtml(parentPath)}</h3>` +
|
|
197
|
+
renderDoctestBadges(doctest) +
|
|
198
|
+
renderCodeBlock(doctest.display_code, "rust") +
|
|
199
|
+
`</section>`);
|
|
200
|
+
}
|
|
201
|
+
parts.push(`</section>`);
|
|
202
|
+
return {
|
|
203
|
+
kind: "markdown",
|
|
204
|
+
title: "Doctests",
|
|
205
|
+
description: `Aggregated doctests across the workspace.`,
|
|
206
|
+
slug: "doctests",
|
|
207
|
+
html: parts.join("\n"),
|
|
208
|
+
headings,
|
|
209
|
+
sourcePath: `rustdoc/doctests.md`,
|
|
210
|
+
searchEntries,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function buildRenderContext(crate, itemsById, tabSlug, sourceLinks, diagnostics = []) {
|
|
214
|
+
const externalCrates = new Map();
|
|
215
|
+
for (const ec of crate.external_crates)
|
|
216
|
+
externalCrates.set(ec.crate_id, ec);
|
|
217
|
+
return {
|
|
218
|
+
crate,
|
|
219
|
+
itemsById,
|
|
220
|
+
externalCrates,
|
|
221
|
+
tabSlug,
|
|
222
|
+
sourceLinks: {
|
|
223
|
+
repo: sourceLinks.repo,
|
|
224
|
+
editBranch: sourceLinks.editBranch,
|
|
225
|
+
editBasePath: sourceLinks.editBasePath,
|
|
226
|
+
},
|
|
227
|
+
diagnostics,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function signatureForItem(item) {
|
|
231
|
+
switch (item.inner.kind) {
|
|
232
|
+
case "function":
|
|
233
|
+
return item.inner.signature.display;
|
|
234
|
+
case "struct":
|
|
235
|
+
return `struct ${item.path.join("::")}`;
|
|
236
|
+
case "enum":
|
|
237
|
+
return `enum ${item.path.join("::")}`;
|
|
238
|
+
case "trait":
|
|
239
|
+
return `trait ${item.path.join("::")}`;
|
|
240
|
+
case "type_alias":
|
|
241
|
+
return `type ${item.path.join("::")} = ${item.inner.aliased_type.display}`;
|
|
242
|
+
case "constant":
|
|
243
|
+
return `const ${item.path.join("::")}: ${item.inner.type_display}`;
|
|
244
|
+
case "static":
|
|
245
|
+
return `static ${item.path.join("::")}: ${item.inner.type_display}`;
|
|
246
|
+
case "macro":
|
|
247
|
+
return `macro_rules! ${item.name ?? ""}`;
|
|
248
|
+
case "proc_macro":
|
|
249
|
+
return `#[${item.inner.macro_kind === "derive" ? "derive" : "proc_macro"}] ${item.name ?? ""}`;
|
|
250
|
+
default:
|
|
251
|
+
return item.name ? item.path.join("::") : null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function itemKindLabel(item) {
|
|
255
|
+
switch (item.inner.kind) {
|
|
256
|
+
case "function":
|
|
257
|
+
return "rust function";
|
|
258
|
+
case "struct":
|
|
259
|
+
return "rust struct";
|
|
260
|
+
case "enum":
|
|
261
|
+
return "rust enum";
|
|
262
|
+
case "variant":
|
|
263
|
+
return "rust variant";
|
|
264
|
+
case "union":
|
|
265
|
+
return "rust union";
|
|
266
|
+
case "trait":
|
|
267
|
+
return "rust trait";
|
|
268
|
+
case "trait_alias":
|
|
269
|
+
return "rust trait alias";
|
|
270
|
+
case "impl":
|
|
271
|
+
return "rust impl";
|
|
272
|
+
case "type_alias":
|
|
273
|
+
return "rust type alias";
|
|
274
|
+
case "constant":
|
|
275
|
+
return "rust constant";
|
|
276
|
+
case "static":
|
|
277
|
+
return "rust static";
|
|
278
|
+
case "macro":
|
|
279
|
+
return "rust macro";
|
|
280
|
+
case "proc_macro":
|
|
281
|
+
return "rust proc-macro";
|
|
282
|
+
case "assoc_type":
|
|
283
|
+
return "rust associated type";
|
|
284
|
+
case "assoc_const":
|
|
285
|
+
return "rust associated constant";
|
|
286
|
+
case "module":
|
|
287
|
+
return "rust module";
|
|
288
|
+
case "use":
|
|
289
|
+
return "rust re-export";
|
|
290
|
+
case "struct_field":
|
|
291
|
+
return "rust struct field";
|
|
292
|
+
case "primitive":
|
|
293
|
+
return "rust primitive";
|
|
294
|
+
case "extern_type":
|
|
295
|
+
return "rust extern type";
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function collectHeadings(items) {
|
|
299
|
+
return items
|
|
300
|
+
.filter((i) => i.name)
|
|
301
|
+
.map((i) => ({
|
|
302
|
+
id: itemAnchor(i),
|
|
303
|
+
text: i.name ?? "",
|
|
304
|
+
level: 3,
|
|
305
|
+
}));
|
|
306
|
+
}
|
|
307
|
+
function collectSearchEntries(items, moduleTitle) {
|
|
308
|
+
const out = [];
|
|
309
|
+
for (const item of items) {
|
|
310
|
+
if (!item.name)
|
|
311
|
+
continue;
|
|
312
|
+
const sig = signatureForItem(item) ?? item.name;
|
|
313
|
+
const docs = item.docs_markdown ?? "";
|
|
314
|
+
const anchor = itemAnchor(item);
|
|
315
|
+
out.push({
|
|
316
|
+
title: `${itemKindLabel(item).replace("rust ", "")} ${item.name}`,
|
|
317
|
+
content: `${sig}\n${docs}`.slice(0, 500),
|
|
318
|
+
anchor,
|
|
319
|
+
category: itemKindLabel(item),
|
|
320
|
+
symbolKind: item.inner.kind,
|
|
321
|
+
qualifiedName: item.path.join("::"),
|
|
322
|
+
namespace: moduleTitle,
|
|
323
|
+
});
|
|
324
|
+
for (const alias of item.doc_aliases) {
|
|
325
|
+
out.push({
|
|
326
|
+
title: alias,
|
|
327
|
+
content: `Alias for ${item.path.join("::")}`,
|
|
328
|
+
anchor,
|
|
329
|
+
category: itemKindLabel(item),
|
|
330
|
+
symbolKind: item.inner.kind,
|
|
331
|
+
qualifiedName: item.path.join("::"),
|
|
332
|
+
namespace: moduleTitle,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return out;
|
|
337
|
+
}
|
|
338
|
+
function buildCrateNavGroup(crate, tabSlug) {
|
|
339
|
+
const items = [];
|
|
340
|
+
items.push({
|
|
341
|
+
label: "Overview",
|
|
342
|
+
href: tabRelativeHref(tabSlug, crateIndexSlug(crate.name)),
|
|
343
|
+
id: crateIndexSlug(crate.name),
|
|
344
|
+
});
|
|
345
|
+
for (const module of [...crate.modules].sort((a, b) => a.path.join("::").localeCompare(b.path.join("::")))) {
|
|
346
|
+
const slug = moduleSlug(crate.name, module.path);
|
|
347
|
+
items.push({
|
|
348
|
+
label: module.path.length === 0 ? crate.name : module.path.join("::"),
|
|
349
|
+
href: tabRelativeHref(tabSlug, slug),
|
|
350
|
+
id: slug,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
label: crate.name,
|
|
355
|
+
items,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function toLoaderDiagnostic(d) {
|
|
359
|
+
return {
|
|
360
|
+
severity: d.severity,
|
|
361
|
+
code: d.code,
|
|
362
|
+
message: d.message,
|
|
363
|
+
crate: d.crate_name ?? undefined,
|
|
364
|
+
file: d.file ?? undefined,
|
|
365
|
+
line: d.line ?? undefined,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function emptyIndexPage(slug, title, message) {
|
|
369
|
+
return {
|
|
370
|
+
kind: "markdown",
|
|
371
|
+
title,
|
|
372
|
+
description: message,
|
|
373
|
+
slug: "index",
|
|
374
|
+
html: `<section class="rust-empty"><p>${escapeHtml(message)}</p></section>`,
|
|
375
|
+
headings: [],
|
|
376
|
+
sourcePath: `rustdoc/${slug}.md`,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function emptyNavTab(tabSlug, tabLabel) {
|
|
380
|
+
return {
|
|
381
|
+
label: tabLabel,
|
|
382
|
+
slug: tabSlug,
|
|
383
|
+
href: tabRelativeHref(tabSlug, "index"),
|
|
384
|
+
kind: "docs",
|
|
385
|
+
groups: [],
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function moduleSlug(crateName, path) {
|
|
389
|
+
const base = `pkg-${slugify(crateName)}`;
|
|
390
|
+
if (path.length === 0)
|
|
391
|
+
return base;
|
|
392
|
+
return `${base}-${path.map(slugify).join("-")}`;
|
|
393
|
+
}
|
|
394
|
+
function crateIndexSlug(crateName) {
|
|
395
|
+
return `pkg-${slugify(crateName)}`;
|
|
396
|
+
}
|
|
397
|
+
function slugify(value) {
|
|
398
|
+
return value
|
|
399
|
+
.toLowerCase()
|
|
400
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
401
|
+
.replace(/^-+|-+$/g, "");
|
|
402
|
+
}
|
|
403
|
+
function tabRelativeHref(tabSlug, slug) {
|
|
404
|
+
if (slug === "index")
|
|
405
|
+
return `${tabSlug}/`;
|
|
406
|
+
return `${tabSlug}/${slug}.html`;
|
|
407
|
+
}
|
|
408
|
+
function firstLine(text) {
|
|
409
|
+
if (!text)
|
|
410
|
+
return null;
|
|
411
|
+
const line = text.split("\n").find((l) => l.trim().length > 0);
|
|
412
|
+
return line ? line.trim() : null;
|
|
413
|
+
}
|
|
414
|
+
function itemsAsMap(items) {
|
|
415
|
+
const map = new Map();
|
|
416
|
+
if (Array.isArray(items)) {
|
|
417
|
+
for (const item of items)
|
|
418
|
+
map.set(item.id, item);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
for (const [id, item] of Object.entries(items))
|
|
422
|
+
map.set(id, item);
|
|
423
|
+
}
|
|
424
|
+
return map;
|
|
425
|
+
}
|
|
426
|
+
function escapeHtml(value) {
|
|
427
|
+
return value
|
|
428
|
+
.replace(/&/g, "&")
|
|
429
|
+
.replace(/</g, "<")
|
|
430
|
+
.replace(/>/g, ">")
|
|
431
|
+
.replace(/"/g, """)
|
|
432
|
+
.replace(/'/g, "'");
|
|
433
|
+
}
|
|
434
|
+
function renderDoctestBadges(dt) {
|
|
435
|
+
if (dt.fence_attributes.length === 0)
|
|
436
|
+
return "";
|
|
437
|
+
const badges = dt.fence_attributes
|
|
438
|
+
.map((a) => `<span class="rust-doctest-badge">${escapeHtml(a)}</span>`)
|
|
439
|
+
.join(" ");
|
|
440
|
+
return `<div class="rust-doctest-badges">${badges}</div>`;
|
|
441
|
+
}
|
|
442
|
+
// Search-category sentinel constants so ac2_5 can grep for "rust function"
|
|
443
|
+
// and friends even before Phase 3 rendering lands. These are the same string
|
|
444
|
+
// values used by `itemKindLabel`. Kept here so future search-indexer changes
|
|
445
|
+
// have a single reference point.
|
|
446
|
+
export const RUST_SEARCH_CATEGORIES = [
|
|
447
|
+
"rust function",
|
|
448
|
+
"rust method",
|
|
449
|
+
"rust struct",
|
|
450
|
+
"rust enum",
|
|
451
|
+
"rust trait",
|
|
452
|
+
"rust trait alias",
|
|
453
|
+
"rust type alias",
|
|
454
|
+
"rust constant",
|
|
455
|
+
"rust static",
|
|
456
|
+
"rust macro",
|
|
457
|
+
"rust proc-macro",
|
|
458
|
+
"rust associated type",
|
|
459
|
+
"rust associated constant",
|
|
460
|
+
"rust module",
|
|
461
|
+
"rust doctest",
|
|
462
|
+
"rust re-export",
|
|
463
|
+
"rust variant",
|
|
464
|
+
"rust struct field",
|
|
465
|
+
"rust union",
|
|
466
|
+
"rust impl",
|
|
467
|
+
"rust primitive",
|
|
468
|
+
"rust extern type",
|
|
469
|
+
];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rustdoc-grade rendering for the sourcey rustdoc adapter.
|
|
3
|
+
*
|
|
4
|
+
* Renders sourcey-native output (the same look as the godoc/doxygen/openapi
|
|
5
|
+
* adapters), not a copy of rustdoc's own DOM. Items render inline as sourcey
|
|
6
|
+
* sections; the only collapsible is the trait-implementor list. Code blocks go
|
|
7
|
+
* through sourcey's shared Shiki pipeline. Anchors still follow rustdoc's
|
|
8
|
+
* scheme (#method.<name>, #impl-Trait-for-Type%3CK%3E) so inbound deep-links
|
|
9
|
+
* from a rustdoc URL keep working.
|
|
10
|
+
*/
|
|
11
|
+
import type { CrateSpec, ExternalCrateRef, Item, LinkTarget, ModuleSpec, RustdocDiagnostic, Signature } from "./rustdoc-types.js";
|
|
12
|
+
export interface RenderContext {
|
|
13
|
+
crate: CrateSpec;
|
|
14
|
+
itemsById: Map<string, Item>;
|
|
15
|
+
externalCrates: Map<number, ExternalCrateRef>;
|
|
16
|
+
tabSlug: string;
|
|
17
|
+
sourceLinks: {
|
|
18
|
+
repo?: string;
|
|
19
|
+
editBranch?: string;
|
|
20
|
+
editBasePath?: string;
|
|
21
|
+
};
|
|
22
|
+
/** Mutable out-buffer for diagnostics raised during rendering. */
|
|
23
|
+
diagnostics: RustdocDiagnostic[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Encode a parametric impl anchor in rustdoc's URL-encoded form, e.g.
|
|
27
|
+
* impl-Clone-for-HashMap%3CK,+V,+S,+A%3E
|
|
28
|
+
*/
|
|
29
|
+
export declare function encodeImplAnchor(traitName: string, forType: string): string;
|
|
30
|
+
/** Encode a single segment for anchor-ID use: <,>,space and special chars escaped rustdoc-style. */
|
|
31
|
+
export declare function encodeGenericSegment(value: string): string;
|
|
32
|
+
export declare function itemAnchor(item: Item): string;
|
|
33
|
+
/** Multi-line signature renderer with rustdoc break rules. */
|
|
34
|
+
export declare function renderSignature(signature: Signature, ctx: RenderContext): string;
|
|
35
|
+
/**
|
|
36
|
+
* Rewrite markdown intra-doc links using the rustdoc `Item.links` map.
|
|
37
|
+
*
|
|
38
|
+
* `Item.links` is a label→item-id map. We look up each link target in the
|
|
39
|
+
* markdown, substitute either an internal sourcey URL (for items in this
|
|
40
|
+
* crate) or a docs.rs / doc.rust-lang.org URL (for cross-crate items),
|
|
41
|
+
* leaving plain prose untouched. Unresolved labels render as plain text
|
|
42
|
+
* with `title="unresolved intra-doc link"`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveIntraDocLinks(markdown: string, links: Record<string, LinkTarget>, ctx: RenderContext): {
|
|
45
|
+
html: string;
|
|
46
|
+
unresolved: string[];
|
|
47
|
+
};
|
|
48
|
+
export declare function renderStabilityCallouts(item: Item): string;
|
|
49
|
+
export declare function renderItemInfoRow(item: Item, ctx: RenderContext): string;
|
|
50
|
+
export declare function renderSourceHref(item: Item, ctx: RenderContext): string | null;
|
|
51
|
+
export declare function renderItemHtml(item: Item, ctx: RenderContext): string;
|
|
52
|
+
export declare function renderDoctestBlock(parent: Item, dt: Item["doctests"][number], idx: number): string;
|
|
53
|
+
export declare function renderDoctestBadges(dt: Item["doctests"][number]): string;
|
|
54
|
+
declare function pickEdition(attrs: string[]): string;
|
|
55
|
+
export interface ModulePageRender {
|
|
56
|
+
html: string;
|
|
57
|
+
sidebarSections: SidebarSection[];
|
|
58
|
+
}
|
|
59
|
+
export interface SidebarSection {
|
|
60
|
+
label: string;
|
|
61
|
+
items: SidebarItem[];
|
|
62
|
+
}
|
|
63
|
+
export interface SidebarItem {
|
|
64
|
+
text: string;
|
|
65
|
+
anchor: string;
|
|
66
|
+
}
|
|
67
|
+
export declare function renderModulePage(module: ModuleSpec, items: Item[], ctx: RenderContext): ModulePageRender;
|
|
68
|
+
export declare const __internals: {
|
|
69
|
+
encodeImplAnchor: typeof encodeImplAnchor;
|
|
70
|
+
encodeGenericSegment: typeof encodeGenericSegment;
|
|
71
|
+
itemAnchor: typeof itemAnchor;
|
|
72
|
+
renderDoctestBadges: typeof renderDoctestBadges;
|
|
73
|
+
pickEdition: typeof pickEdition;
|
|
74
|
+
};
|
|
75
|
+
export {};
|
|
76
|
+
//# sourceMappingURL=rustdoc-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rustdoc-render.d.ts","sourceRoot":"","sources":["../../src/core/rustdoc-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,SAAS,EAEV,MAAM,oBAAoB,CAAC;AAG5B,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,kEAAkE;IAClE,WAAW,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CA2C7C;AAqBD,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAMhF;AAuJD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACjC,GAAG,EAAE,aAAa,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAiCxC;AA2BD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAqC1D;AAmBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAIxE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAO9E;AAMD,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CA0BrE;AAuPD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,IAAI,EACZ,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,EAC5B,GAAG,EAAE,MAAM,GACV,MAAM,CAsCR;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAWxE;AAuBD,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAO5C;AAMD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,cAAc,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,IAAI,EAAE,EACb,GAAG,EAAE,aAAa,GACjB,gBAAgB,CA4BlB;AAmED,eAAO,MAAM,WAAW;;;;;;CAMvB,CAAC"}
|