2023-05-24 02:53:53 +08:00
|
|
|
import { IndexTreeEvent, QueryProviderEvent } from "$sb/app_event.ts";
|
2022-10-14 21:11:33 +08:00
|
|
|
import { renderToText } from "$sb/lib/tree.ts";
|
2024-02-03 02:19:07 +08:00
|
|
|
import { applyQuery, liftAttributeFilter } from "$sb/lib/query.ts";
|
2023-10-03 21:24:07 +08:00
|
|
|
import { editor } from "$sb/syscalls.ts";
|
|
|
|
import { FileMeta } from "$sb/types.ts";
|
2023-08-30 03:17:29 +08:00
|
|
|
import { PromiseQueue } from "$sb/lib/async.ts";
|
2023-10-03 21:24:07 +08:00
|
|
|
import { ftsIndexPage, ftsSearch } from "./engine.ts";
|
2024-02-03 02:19:07 +08:00
|
|
|
import { evalQueryExpression } from "$sb/lib/query_expression.ts";
|
2022-05-16 21:09:36 +08:00
|
|
|
|
2022-09-02 21:41:40 +08:00
|
|
|
const searchPrefix = "🔍 ";
|
|
|
|
|
2023-08-30 03:17:29 +08:00
|
|
|
// Search indexing is prone to concurrency issues, so we queue all write operations
|
|
|
|
const promiseQueue = new PromiseQueue();
|
|
|
|
|
|
|
|
export function indexPage({ name, tree }: IndexTreeEvent) {
|
2023-05-24 02:53:53 +08:00
|
|
|
const text = renderToText(tree);
|
2023-08-30 03:17:29 +08:00
|
|
|
return promiseQueue.runInQueue(async () => {
|
|
|
|
// console.log("Now FTS indexing", name);
|
2023-10-03 21:24:07 +08:00
|
|
|
// await engine.deleteDocument(name);
|
|
|
|
await ftsIndexPage(name, text);
|
2023-08-30 03:17:29 +08:00
|
|
|
});
|
2022-06-28 20:14:15 +08:00
|
|
|
}
|
|
|
|
|
2022-05-16 21:09:36 +08:00
|
|
|
export async function queryProvider({
|
|
|
|
query,
|
|
|
|
}: QueryProviderEvent): Promise<any[]> {
|
2023-10-03 20:16:33 +08:00
|
|
|
const phraseFilter = liftAttributeFilter(query.filter, "phrase");
|
2022-05-16 21:09:36 +08:00
|
|
|
if (!phraseFilter) {
|
|
|
|
throw Error("No 'phrase' filter specified, this is mandatory");
|
|
|
|
}
|
2024-02-03 02:19:07 +08:00
|
|
|
const phrase = await evalQueryExpression(phraseFilter, {}, {}, {});
|
2023-10-03 20:16:33 +08:00
|
|
|
// console.log("Phrase", phrase);
|
2023-10-03 21:24:07 +08:00
|
|
|
let results: any[] = await ftsSearch(phrase);
|
2023-05-24 02:53:53 +08:00
|
|
|
|
|
|
|
// Patch the object to a format that users expect (translate id to name)
|
|
|
|
for (const r of results) {
|
|
|
|
r.name = r.id;
|
|
|
|
delete r.id;
|
|
|
|
}
|
2022-05-16 21:09:36 +08:00
|
|
|
|
2024-02-03 02:19:07 +08:00
|
|
|
results = await applyQuery(query, results, {}, {});
|
2022-05-16 21:09:36 +08:00
|
|
|
return results;
|
|
|
|
}
|
2022-05-17 17:53:17 +08:00
|
|
|
|
|
|
|
export async function searchCommand() {
|
2022-10-19 15:52:29 +08:00
|
|
|
const phrase = await editor.prompt("Search for: ");
|
2022-05-17 17:53:17 +08:00
|
|
|
if (phrase) {
|
2024-01-24 18:58:33 +08:00
|
|
|
await editor.navigate({ page: `${searchPrefix}${phrase}` });
|
2022-05-17 17:53:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-19 15:52:29 +08:00
|
|
|
export async function readFileSearch(
|
2022-10-12 17:47:13 +08:00
|
|
|
name: string,
|
2023-07-02 17:25:32 +08:00
|
|
|
): Promise<{ data: Uint8Array; meta: FileMeta }> {
|
2022-10-19 15:52:29 +08:00
|
|
|
const phrase = name.substring(
|
|
|
|
searchPrefix.length,
|
|
|
|
name.length - ".md".length,
|
|
|
|
);
|
2023-10-03 21:24:07 +08:00
|
|
|
const results = await ftsSearch(phrase);
|
2022-10-12 17:47:13 +08:00
|
|
|
const text = `# Search results for "${phrase}"\n${
|
|
|
|
results
|
2023-05-24 02:53:53 +08:00
|
|
|
.map((r) => `* [[${r.id}]] (score ${r.score})`)
|
|
|
|
.join("\n")
|
2022-10-12 17:47:13 +08:00
|
|
|
}
|
2023-05-24 02:53:53 +08:00
|
|
|
`;
|
2022-10-19 15:52:29 +08:00
|
|
|
|
2022-05-17 17:53:17 +08:00
|
|
|
return {
|
2023-07-02 17:25:32 +08:00
|
|
|
data: new TextEncoder().encode(text),
|
2022-05-17 17:53:17 +08:00
|
|
|
meta: {
|
|
|
|
name,
|
2022-10-19 15:52:29 +08:00
|
|
|
contentType: "text/markdown",
|
|
|
|
size: text.length,
|
2023-11-03 16:38:04 +08:00
|
|
|
created: 0,
|
2022-05-17 17:53:17 +08:00
|
|
|
lastModified: 0,
|
|
|
|
perm: "ro",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-05-24 02:53:53 +08:00
|
|
|
export function writeFileSearch(
|
|
|
|
name: string,
|
|
|
|
): FileMeta {
|
|
|
|
// Never actually writing this
|
|
|
|
return getFileMetaSearch(name);
|
|
|
|
}
|
|
|
|
|
2022-10-19 15:52:29 +08:00
|
|
|
export function getFileMetaSearch(name: string): FileMeta {
|
2022-05-17 17:53:17 +08:00
|
|
|
return {
|
|
|
|
name,
|
2022-10-19 15:52:29 +08:00
|
|
|
contentType: "text/markdown",
|
|
|
|
size: -1,
|
2023-11-03 16:38:04 +08:00
|
|
|
created: 0,
|
2022-05-17 17:53:17 +08:00
|
|
|
lastModified: 0,
|
|
|
|
perm: "ro",
|
|
|
|
};
|
|
|
|
}
|