diff --git a/plugs/index/builtins.ts b/plugs/index/builtins.ts index 49fe15c..7eaa750 100644 --- a/plugs/index/builtins.ts +++ b/plugs/index/builtins.ts @@ -53,6 +53,11 @@ export const builtins: Record> = { inDirective: "boolean", asTemplate: "boolean", }, + paragraph: { + text: "string", + page: "string", + pos: "number", + }, }; export async function loadBuiltinsIntoIndex() { diff --git a/plugs/index/index.plug.yaml b/plugs/index/index.plug.yaml index 488da23..ff5f1f3 100644 --- a/plugs/index/index.plug.yaml +++ b/plugs/index/index.plug.yaml @@ -86,6 +86,11 @@ functions: events: - page:index + indexParagraphs: + path: "./paragraph.ts:indexParagraphs" + events: + - page:index + # Backlinks indexLinks: path: "./page_links.ts:indexLinks" diff --git a/plugs/index/paragraph.ts b/plugs/index/paragraph.ts new file mode 100644 index 0000000..9619e68 --- /dev/null +++ b/plugs/index/paragraph.ts @@ -0,0 +1,51 @@ +import type { IndexTreeEvent } from "$sb/app_event.ts"; +import { indexObjects } from "./api.ts"; +import { renderToText, traverseTree, traverseTreeAsync } from "$sb/lib/tree.ts"; +import { extractAttributes } from "$sb/lib/attribute.ts"; + +/** ParagraphObject An index object for the top level text nodes */ +export type ParagraphObject = { + ref: string; + tags: string[]; + text: string; + page: string; + pos: number; +} & Record; + +export async function indexParagraphs({ name: page, tree }: IndexTreeEvent) { + const objects: ParagraphObject[] = []; + + await traverseTreeAsync(tree, async (p) => { + // only search directly under document + // Paragraph nodes also appear under block elements + if (p.type == "Document") return false; // continue traversal if p is Document + if (p.type != "Paragraph") return true; + + const tags = new Set(["paragraph"]); + // tag the paragraph with any hashtags inside it + traverseTree(p, (e) => { + if (e.type == "Hashtag") { + tags.add(e.children![0].text!.substring(1)); + return true; + } + + return false; + }); + + const attrs = await extractAttributes(p, false); + const pos = p.from!; + objects.push({ + ref: `${page}@${pos}`, + text: renderToText(p), + tags: [...tags.values()], + page, + pos, + ...attrs, + }); + + // stop on every element except document, including paragraphs + return true; + }); + + await indexObjects(page, objects); +}