From 63eb99e0d348e28df20cce1f64607c4ea049e372 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Sat, 2 Mar 2024 13:54:31 +0100 Subject: [PATCH] Fixes #771 --- plugs/index/header.ts | 72 ++++++++++++++++++++++++++++------------- website/Space Script.md | 2 +- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/plugs/index/header.ts b/plugs/index/header.ts index fb080f5c..61fe46a7 100644 --- a/plugs/index/header.ts +++ b/plugs/index/header.ts @@ -1,34 +1,62 @@ -import { collectNodesMatching } from "$sb/lib/tree.ts"; +import { + collectNodesMatching, + collectNodesOfType, + renderToText, +} from "$sb/lib/tree.ts"; import type { CompleteEvent, IndexTreeEvent } from "../../plug-api/types.ts"; import { ObjectValue } from "../../plug-api/types.ts"; import { indexObjects, queryObjects } from "./api.ts"; import { parsePageRef } from "$sb/lib/page_ref.ts"; +import { extractAttributes } from "$sb/lib/attribute.ts"; -type HeaderObject = ObjectValue<{ - name: string; - page: string; - level: number; - pos: number; -}>; +type HeaderObject = ObjectValue< + { + name: string; + page: string; + level: number; + pos: number; + } & Record +>; export async function indexHeaders({ name: pageName, tree }: IndexTreeEvent) { const headers: ObjectValue[] = []; - 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!, - }); - }, - ); - // console.log("Found", headers.length, "headers(s)"); + for ( + const n of collectNodesMatching( + tree, + (t) => !!t.type?.startsWith("ATXHeading"), + ) + ) { + const level = +n.type!.substring("ATXHeading".length); + const tags = new Set(); + + collectNodesOfType(n, "Hashtag").forEach((h) => { + // Push tag to the list, removing the initial # + tags.add(h.children![0].text!.substring(1)); + h.children = []; + }); + + // Extract attributes and remove from tree + const extractedAttributes = await extractAttributes( + ["header", ...tags], + n, + true, + ); + const name = n.children!.slice(1).map(renderToText).join("").trim(); + + headers.push({ + ref: `${pageName}#${name}@${n.from}`, + tag: "header", + tags: [...tags], + level, + name, + page: pageName, + pos: n.from!, + ...extractedAttributes, + }); + } + + console.log("Found", headers, "headers(s)"); await indexObjects(pageName, headers); } diff --git a/website/Space Script.md b/website/Space Script.md index 8b957578..1abb0f01 100644 --- a/website/Space Script.md +++ b/website/Space Script.md @@ -140,7 +140,7 @@ SilverBullet indexes various types of content as [[Objects]]. There are various The `silverbullet.registerAttributeExtractor` API takes two arguments: * `def` with currently just one option: - * `tags`: Array of tags this extractor should be applied to, could be a built-in tag such as `item`, `page` or `task`, but also any custom tags you define. + * `tags`: Array of tags this extractor should be applied to, could be a built-in tag such as `item`, `page`, `paragraph`, `header`, or `task`, but also any custom tags you define. * `callback`: the callback function to invoke (can be `async` or not). This callback is passed the following arguments: * `text`: the text of the object to extract attributes for * return value: an object of attribute mappings, possibly overriding built-in ones.