silverbullet/plugs/index/header.ts

60 lines
1.6 KiB
TypeScript
Raw Normal View History

2024-02-29 22:23:05 +08:00
import { collectNodesMatching } from "$sb/lib/tree.ts";
import type { CompleteEvent, IndexTreeEvent } from "../../plug-api/types.ts";
import { ObjectValue } from "../../plug-api/types.ts";
2024-01-25 21:51:40 +08:00
import { indexObjects, queryObjects } from "./api.ts";
import { parsePageRef } from "$sb/lib/page_ref.ts";
2024-01-25 21:51:40 +08:00
type HeaderObject = ObjectValue<{
name: string;
page: string;
level: number;
pos: number;
}>;
export async function indexHeaders({ name: pageName, tree }: IndexTreeEvent) {
const headers: ObjectValue<HeaderObject>[] = [];
collectNodesMatching(tree, (t) => !!t.type?.startsWith("ATXHeading")).forEach(
(n) => {
const level = +n.type!.substring("ATXHeading".length);
const name = n.children![1].text!.trim();
headers.push({
ref: `${pageName}#${name}@${n.from}`,
tag: "header",
level,
name,
page: pageName,
pos: n.from!,
});
},
);
2024-01-25 23:05:48 +08:00
// console.log("Found", headers.length, "headers(s)");
2024-01-25 21:51:40 +08:00
await indexObjects(pageName, headers);
}
export async function headerComplete(completeEvent: CompleteEvent) {
2024-01-25 23:05:48 +08:00
const match = /\[\[([^\]$:#]*#[^\]]*)$/.exec(
2024-01-25 21:51:40 +08:00
completeEvent.linePrefix,
);
if (!match) {
return null;
}
const pageRef = parsePageRef(match[1]).page;
const allHeaders = await queryObjects<HeaderObject>("header", {
filter: ["=", ["attr", "page"], [
"string",
pageRef || completeEvent.pageName,
]],
}, 5);
return {
from: completeEvent.pos - match[1].length,
options: allHeaders.map((a) => ({
label: a.page === completeEvent.pageName
? `#${a.name}`
: a.ref.split("@")[0],
type: "header",
})),
};
}