@fragno-dev/cli 0.1.13 → 0.1.15

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.
@@ -0,0 +1,121 @@
1
+ interface SearchResult {
2
+ id: string;
3
+ type: "page" | "heading" | "text";
4
+ content: string;
5
+ breadcrumbs?: string[];
6
+ contentWithHighlights?: Array<{
7
+ type: string;
8
+ content: string;
9
+ styles?: { highlight?: boolean };
10
+ }>;
11
+ url: string;
12
+ }
13
+
14
+ interface MergedResult {
15
+ url: string;
16
+ urlWithMd: string;
17
+ fullUrl: string;
18
+ fullUrlWithMd: string;
19
+ title?: string;
20
+ breadcrumbs?: string[];
21
+ type: "page" | "heading" | "text";
22
+ sections: Array<{
23
+ content: string;
24
+ type: "page" | "heading" | "text";
25
+ }>;
26
+ }
27
+
28
+ /**
29
+ * Merge search results by URL, grouping sections and content under each URL (without hash)
30
+ */
31
+ export function mergeResultsByUrl(results: SearchResult[], baseUrl: string): MergedResult[] {
32
+ const mergedMap = new Map<string, MergedResult>();
33
+
34
+ for (const result of results) {
35
+ // Strip hash to get base URL for merging
36
+ const baseUrlWithoutHash = result.url.split("#")[0];
37
+ const existing = mergedMap.get(baseUrlWithoutHash);
38
+
39
+ if (existing) {
40
+ // Add this result as a section
41
+ existing.sections.push({
42
+ content: result.content,
43
+ type: result.type,
44
+ });
45
+ } else {
46
+ // Create new merged result
47
+ const urlWithMd = `${baseUrlWithoutHash}.md`;
48
+
49
+ const fullUrl = `https://${baseUrl}${baseUrlWithoutHash}`;
50
+ const fullUrlWithMd = `https://${baseUrl}${urlWithMd}`;
51
+
52
+ mergedMap.set(baseUrlWithoutHash, {
53
+ url: baseUrlWithoutHash,
54
+ urlWithMd,
55
+ fullUrl,
56
+ fullUrlWithMd,
57
+ title: result.type === "page" ? result.content : undefined,
58
+ breadcrumbs: result.breadcrumbs,
59
+ type: result.type,
60
+ sections: [
61
+ {
62
+ content: result.content,
63
+ type: result.type,
64
+ },
65
+ ],
66
+ });
67
+ }
68
+ }
69
+
70
+ return Array.from(mergedMap.values());
71
+ }
72
+
73
+ /**
74
+ * Format merged results as markdown
75
+ */
76
+ export function formatAsMarkdown(mergedResults: MergedResult[]): string {
77
+ const lines: string[] = [];
78
+
79
+ for (const result of mergedResults) {
80
+ // Title (use first section content if it's a page, or just use content)
81
+ const title = result.title || result.sections[0]?.content || "Untitled";
82
+ lines.push(`## Page: '${title}'`);
83
+ // Breadcrumbs
84
+ if (result.breadcrumbs && result.breadcrumbs.length > 0) {
85
+ lines.push(" " + result.breadcrumbs.join(" > "));
86
+ lines.push("");
87
+ }
88
+
89
+ // Both URLs
90
+ lines.push("URLs:");
91
+ lines.push(` - ${result.fullUrl}`);
92
+ lines.push(` - ${result.fullUrlWithMd}`);
93
+ lines.push("");
94
+
95
+ // Show all sections found on this page
96
+ if (result.sections.length > 1) {
97
+ lines.push("Relevant sections:");
98
+ for (let i = 0; i < result.sections.length; i++) {
99
+ const section = result.sections[i];
100
+ // Skip the first section if it's just the page title repeated
101
+ if (i === 0 && result.type === "page" && section.content === result.title) {
102
+ continue;
103
+ }
104
+ lines.push(` - ${section.content}`);
105
+ }
106
+ lines.push("");
107
+ }
108
+
109
+ lines.push("---");
110
+ lines.push("");
111
+ }
112
+
113
+ return lines.join("\n");
114
+ }
115
+
116
+ /**
117
+ * Format merged results as JSON
118
+ */
119
+ export function formatAsJson(mergedResults: MergedResult[]): string {
120
+ return JSON.stringify(mergedResults, null, 2);
121
+ }