Skip to content

Obsidian Dataview

Dataview is a live index and query engine over your personal knowledge base. You can add metadata to your notes and query them with the Dataview Query Language to list, filter, sort or group your data. Dataview keeps your queries always up to date and makes data aggregation a breeze.

β€” Obsidian Dataview

Dataview is a plugin for Obsidian. There is a way, though, buiuld your own β€œDataview” for Astro. In order to do so one needs:

  • remark-code-hook, to cath all codeblocks with dataview language
  • Parse code as DQL (SQL-like language)
  • Translate (aka compile) DQL AST to BrainDB calls
  • Translate result to MDAST (or HTML)

Proof of concept

It will take time to repeat full functionality, so lets start with one simple case:

```dataview
TASK
```

Implementation

  1. Install BrainDB

  2. Install remark-code-hook

    Terminal window
    pnpm add @beoe/remark-code-hook
  3. Create remarkDataview

    src/plugins/remarkDataview.mjs
    import remarkCodeHook from "@beoe/remark-code-hook";
    export function remarkDataview(options) {
    const { bdb, ...rest } = options;
    return remarkCodeHook({
    ...rest,
    language: "dataview",
    code: ({ code }) => {
    if (code !== "TASK")
    throw new Error("PoC of Dataview - only TASK supported");
    return "Tasks will be here";
    },
    });
    }
  4. Configure Astro

    astro.config.mjs
    import { remarkDataview } from "./src/plugins/remarkDataview.mjs";
    export default defineConfig({
    markdown: {
    remarkPlugins: [[remarkDataview, { bdb }]],
    },
    });
  5. Use BrainDB to extract tsasks

    src/plugins/remarkDataview.mjs
    import remarkCodeHook from "@beoe/remark-code-hook";
    const list = (children) => ({
    type: "list",
    ordered: false,
    start: null,
    spread: false,
    children,
    });
    const listItem = (children, checked = null) => ({
    type: "listItem",
    spread: false,
    checked,
    children,
    });
    const paragraph = (children) => ({ type: "paragraph", children });
    const link = (children, url) => ({
    type: "link",
    title: null,
    url: url,
    children,
    });
    const text = (value) => ({ type: "text", value });
    export function remarkDataview(options) {
    const { bdb, ...rest } = options;
    return remarkCodeHook({
    ...rest,
    language: "dataview",
    code: ({ code }) => {
    if (code !== "TASK")
    throw new Error("PoC of Daview - only TASK supported");
    const grouped = {};
    bdb.tasksSync().forEach((task) => {
    const path = task.from().path();
    grouped[path] = grouped[path] || [];
    grouped[path].push(task);
    });
    return paragraph(
    Object.values(grouped)
    .flatMap((group) => {
    const doc = group[0].from();
    return [
    paragraph([link([text(doc.title())], doc.url())]),
    list(
    group.map((task) => listItem([task.ast()], task.checked()))
    ),
    ];
    })
    );
    },
    });
    }

Beyond proof of concept

For now this is PoC. For full version we need:

I tried to extract original DQL parser. Not sure about this approach though.

Example

This is an example of output πŸ‘‡

Content graph visualization

Euler diagram

  • Implement area-proportional diagram. Maybe edeap.
  • Try to implement it without headless browser

Faceted search

Icons for external links

  • One more idea is to add favicon of the target instead of β†—.

Last modified time

Link previews

  • handle non-html links (images, pdfs)

Social images autogenration

  • generate gradient based on tag colors

Pan and zoom for images

  • style pan-zoom buttons
  • create rehype plugin to wrap images into container (<figure class="beoe"></figure>), to avoid creating it on the client side

Table of contents

  • fix bug: it crashes if there are missing header levels, like h4 directly in h2
  • fix "snake" styles

Tag list

  • page for each tag
  • metadata for tags (color, icon)

Timelime diagram

  • removed Graphviz component from the repo need to use @beoe/astro-graphviz instead

Wikilinks

  • support anchors in wikilinks ([[page#anchor]], [[page#anchor|alias]])
  • check that anchors correspond to some header in target document
  • what about ambiguous links (bdb.documentsSync({ slug: permalink }).length > 1)?
  • image wikilinks (![[some.jpg]])