Skip to content

Commit 9c0dae4

Browse files
committed
feat: add content/documentation/ to search index, rough PoC
1 parent 69afb01 commit 9c0dae4

File tree

2 files changed

+86
-7
lines changed

2 files changed

+86
-7
lines changed

build/src/php/FileGenerator/Application/ApiSearchGenerator.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,19 @@ public function generateSearchIndex(): array
5151
}
5252

5353
$result[] = [
54+
'id' => 'api_' . $fn->fnName(),
5455
'fnName' => $fn->fnName(),
5556
'fnSignature' => $fn->fnSignature(),
5657
'desc' => $this->formatDescription($fn->description()),
5758
'anchor' => $anchor,
59+
'type' => 'api',
5860
];
5961
}
6062

63+
// Add documentation files to search index
64+
$documentationItems = $this->generateDocumentationSearchItems();
65+
$result = array_merge($result, $documentationItems);
66+
6167
return $result;
6268
}
6369

@@ -68,4 +74,61 @@ private function formatDescription(string $desc): string
6874
{
6975
return preg_replace('/\[(.*?)\]\((.*?)\)/', '<i>$1</i>', $desc);
7076
}
77+
78+
/**
79+
* Generate search index items for documentation files
80+
*
81+
* @return array<array{id: string, title: string, content: string, url: string, type: string}>
82+
*/
83+
private function generateDocumentationSearchItems(): array
84+
{
85+
$result = [];
86+
$documentationPath = __DIR__ . '/../../../../../content/documentation';
87+
88+
if (!is_dir($documentationPath)) {
89+
error_log("Documentation path not found: " . $documentationPath);
90+
return [];
91+
}
92+
93+
$files = scandir($documentationPath);
94+
if ($files === false) {
95+
error_log("Could not scan documentation directory: " . $documentationPath);
96+
return [];
97+
}
98+
99+
foreach ($files as $file) {
100+
if (pathinfo($file, PATHINFO_EXTENSION) !== 'md' || $file === '_index.md') {
101+
continue;
102+
}
103+
104+
$filePath = $documentationPath . '/' . $file;
105+
$content = file_get_contents($filePath);
106+
107+
// Extract title from frontmatter
108+
$title = pathinfo($file, PATHINFO_FILENAME);
109+
if (preg_match('/title = "([^"]+)"/', $content, $matches)) {
110+
$title = $matches[1];
111+
}
112+
113+
// Remove frontmatter
114+
$content = preg_replace('/\+\+\+.*?\+\+\+/s', '', $content);
115+
116+
// Remove markdown formatting and clean content
117+
$content = preg_replace('/[#`*\[\]()]/', ' ', $content);
118+
$content = preg_replace('/\s+/', ' ', trim($content));
119+
120+
// Limit content length for search index
121+
$content = substr($content, 0, 500);
122+
123+
$result[] = [
124+
'id' => 'doc_' . pathinfo($file, PATHINFO_FILENAME),
125+
'title' => $title,
126+
'content' => $content,
127+
'url' => '/documentation/' . pathinfo($file, PATHINFO_FILENAME),
128+
'type' => 'documentation',
129+
];
130+
}
131+
132+
return $result;
133+
}
71134
}

static/search.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ function initSearch() {
109109
const index = elasticlunr(function () {
110110
this.addField("fnName");
111111
this.addField("desc");
112-
this.setRef("anchor");
112+
this.addField("title");
113+
this.addField("content");
114+
this.setRef("id");
113115
elasticlunr.stopWordFilter.stopWords = {};
114116
elasticlunr.Pipeline.registerFunction(elasticlunr.trimmer, "trimmer");
115117
elasticlunr.tokenizer.seperator = /[\s~~]+/;
@@ -174,10 +176,12 @@ function showResults(index) {
174176
}
175177

176178
const options = {
177-
bool: "AND",
179+
bool: "OR",
178180
fields: {
179181
fnName: {boost: 3},
182+
title: {boost: 2},
180183
desc: {boost: 1},
184+
content: {boost: 1}
181185
},
182186
expand: true
183187
};
@@ -188,6 +192,7 @@ function showResults(index) {
188192
fnSignature: "",
189193
desc: "Cannot provide any Phel symbol. Try something else",
190194
anchor: "#",
195+
type: "api"
191196
};
192197

193198
createMenuItem(emptyResult, null);
@@ -215,11 +220,22 @@ function createMenuItem(result, index) {
215220
}
216221

217222
function formatSearchResultItem(item) {
218-
return `<a href="/documentation/api/#${item.anchor}">`
219-
+ `<div class="search-results__item">${item.fnName} `
220-
+ `<small class="fn-signature">${item.fnSignature}</small>`
221-
+ `<span class="desc">${item.desc}</span>`
222-
+ `</div></a>`;
223+
if (item.type === "documentation") {
224+
return `<a href="${item.url}">`
225+
+ `<div class="search-results__item">`
226+
+ `<span class="result-type">Documentation</span>`
227+
+ `<strong>${item.title}</strong>`
228+
+ `<span class="desc">${item.content}</span>`
229+
+ `</div></a>`;
230+
} else {
231+
return `<a href="/documentation/api/#${item.anchor}">`
232+
+ `<div class="search-results__item">`
233+
+ `<span class="result-type">API</span>`
234+
+ `${item.fnName} `
235+
+ `<small class="fn-signature">${item.fnSignature}</small>`
236+
+ `<span class="desc">${item.desc}</span>`
237+
+ `</div></a>`;
238+
}
223239
}
224240

225241
function removeSelectedClassFromSearchResult() {

0 commit comments

Comments
 (0)