-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformatters.ts
More file actions
99 lines (88 loc) · 3.5 KB
/
formatters.ts
File metadata and controls
99 lines (88 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import type { TypeInferenceResult } from "./search-index";
import type { AnchorIndex, DocEntry } from "./types";
/**
* Formats search results into a human-readable string.
* @param results - Matched documentation entries.
* @param query - The original search query.
* @param version - Python version searched.
* @param fallbackUsed - Whether type inference fallback was used.
* @param typeInference - Type inference result when fallback was used.
* @returns Formatted string listing results or a no-results message.
*/
export function formatSearchResults(
results: DocEntry[],
query: string,
version: string,
fallbackUsed?: boolean,
typeInference?: TypeInferenceResult,
): string {
if (!results.length) {
let message = `No results found for "${query}" in Python ${version} docs.`;
if (typeInference && typeInference.inferredTypes.length > 0) {
message += `\n\nSuggested types based on your query:\n`;
message += typeInference.inferredTypes.map((t) => ` - ${t}`).join("\n");
if (typeInference.alternativeTypes.length > 0) {
message += `\n\nAlternative types:\n`;
message += typeInference.alternativeTypes.map((t) => ` - ${t}`).join("\n");
}
}
return message;
}
const lines: string[] = [
`Found ${results.length} result(s) for "${query}" in Python ${version} docs.`,
];
if (fallbackUsed && typeInference) {
lines.push("");
lines.push("⚠️ Original search returned no results. Used type inference to find matches.");
lines.push(` Inferred types: ${typeInference.inferredTypes.join(", ")}`);
}
lines.push("");
lines.push(...results.map((r) => `- ${r.name} [${r.type}] -> ${r.path}`));
lines.push("");
lines.push("Use fetch_python_doc with the path to get the full documentation.");
return lines.join("\n");
}
/**
* Formats a documentation page for display with pagination support.
* Handles anchor navigation when specified, showing the relevant section
* or listing available anchors if not found.
* @param markdown - Full markdown content of the page.
* @param path - Documentation path.
* @param version - Python version.
* @param fromCache - Whether content was served from cache.
* @param offset - Character offset for pagination.
* @param limit - Maximum characters to return.
* @param anchorIndex - Index of anchors in the document.
* @param anchor - Optional anchor to navigate to.
* @returns Formatted document string with header and pagination hints.
*/
export function formatDocument(
markdown: string,
path: string,
version: string,
fromCache: boolean,
offset: number,
limit: number,
anchorIndex: AnchorIndex,
anchor?: string,
): string {
const header = `# Python ${version}: ${path} ${fromCache ? "(cached)" : "(fetched)"}\n\n`;
if (anchor) {
const found = anchorIndex.anchors.find((a) => a.name === anchor);
if (found) {
return `${header}**Section:** ${anchor}\n\n${markdown.slice(found.startOffset, found.endOffset)}`;
}
const available = anchorIndex.anchors.map((a) => ` - ${a.name}: ${a.heading}`).join("\n");
return (
`${header}⚠️ **Anchor "${anchor}" not found.**\n\n` +
`Available anchors:\n${available || " (none)"}\n\n` +
markdown.slice(offset, offset + limit)
);
}
const end = Math.min(offset + limit, markdown.length);
const content = markdown.slice(offset, end);
if (end < anchorIndex.totalLength) {
return `${header}${content}\n\n---\nMore content available. Use offset=${end} to continue reading.`;
}
return `${header}${content}`;
}