diff --git a/src/codeblocks/MDRC.ts b/src/codeblocks/MDRC.ts index 7762bbc2..a7a2b73e 100644 --- a/src/codeblocks/MDRC.ts +++ b/src/codeblocks/MDRC.ts @@ -9,6 +9,7 @@ export class CodeblockMDRC extends MarkdownRenderChild { source: string; plugin: BreadcrumbsPlugin; component: CodeblockTree | CodeblockMermaid | undefined; + id: string; constructor( plugin: BreadcrumbsPlugin, @@ -17,12 +18,26 @@ export class CodeblockMDRC extends MarkdownRenderChild { ) { super(containerEl); + this.id = window.crypto.randomUUID(); + this.plugin = plugin; this.source = source; } + async update(): Promise { + log.debug("CodeblockMDRC.update"); + if (this.component) { + try { + this.component.update(); + } catch (e) { + log.error("failed to update codeblock", e); + } + } + } + async onload(): Promise { log.debug("CodeblockMDRC.load"); + Codeblocks.register_codeblock(this); const { parsed, errors } = Codeblocks.parse_source( this.plugin, @@ -65,6 +80,7 @@ export class CodeblockMDRC extends MarkdownRenderChild { onunload(): void { log.debug("CodeblockMDRC.unload"); + Codeblocks.unregister_codeblock(this); this.component?.$destroy(); } diff --git a/src/codeblocks/index.ts b/src/codeblocks/index.ts index fb7d56c3..75d8e845 100644 --- a/src/codeblocks/index.ts +++ b/src/codeblocks/index.ts @@ -12,6 +12,7 @@ import type BreadcrumbsPlugin from "src/main"; import { get_all_hierarchy_fields } from "src/utils/hierarchies"; import { Mermaid } from "src/utils/mermaid"; import { quote_join } from "src/utils/strings"; +import { CodeblockMDRC } from "src/codeblocks/MDRC"; // TODO: parseYaml @@ -316,8 +317,27 @@ const resolve_options = ( parsed, ); +const active_codeblocks: Map = new Map(); + +const register_codeblock = (codeBlock: CodeblockMDRC) => { + active_codeblocks.set(codeBlock.id, codeBlock); +} + +const unregister_codeblock = (codeBlock: CodeblockMDRC) => { + active_codeblocks.delete(codeBlock.id); +} + +const update_codeblocks = () => { + for (const codeBlock of active_codeblocks.values()) { + void codeBlock.update(); + } +} + export const Codeblocks = { FIELDS, parse_source, resolve_options, + register_codeblock, + unregister_codeblock, + update_codeblocks, }; diff --git a/src/components/codeblocks/CodeblockMermaid.svelte b/src/components/codeblocks/CodeblockMermaid.svelte index 621f3140..52e84723 100644 --- a/src/components/codeblocks/CodeblockMermaid.svelte +++ b/src/components/codeblocks/CodeblockMermaid.svelte @@ -13,11 +13,17 @@ import { Paths } from "src/utils/paths"; import { wrap_in_codeblock } from "src/utils/strings"; import CodeblockErrors from "./CodeblockErrors.svelte"; + import type { BCEdge } from "src/graph/MyMultiGraph"; export let plugin: BreadcrumbsPlugin; export let options: ICodeblock["Options"]; export let errors: BreadcrumbsError[]; + // this is an exposed function that we can call from the outside to update the codeblock + export const update = () => { + all_paths = get_all_paths(); + } + const base_traversal = ({ hierarchy_i, }: { @@ -36,26 +42,36 @@ }), ); - const all_paths = - $active_file_store && plugin.graph.hasNode($active_file_store.path) - ? options.merge_hierarchies - ? base_traversal({ hierarchy_i: undefined }) - : plugin.settings.hierarchies - .map((_hierarchy, hierarchy_i) => - base_traversal({ hierarchy_i }), - ) - .flat() - : []; - - const sliced = all_paths.map((path) => + const get_all_paths = () => { + if ($active_file_store && plugin.graph.hasNode($active_file_store.path)) { + if (options.merge_hierarchies) { + return base_traversal({ hierarchy_i: undefined }); + } else { + return plugin.settings.hierarchies + .map((_hierarchy, hierarchy_i) => + base_traversal({ hierarchy_i }) + ) + .flat(); + } + } else { + return []; + } + } + + let all_paths = get_all_paths(); + + let sliced: BCEdge[][]; + $: sliced = all_paths.map((path) => path.slice(options.depth[0], options.depth[1]), ); - const flat_unique = remove_duplicates_by(sliced.flat(), (e) => e.id); + let flat_unique: BCEdge[][]; + $: flat_unique = remove_duplicates_by(sliced.flat(), (e) => e.id); const sort = get_edge_sorter(options.sort, plugin.graph); - const mermaid = wrap_in_codeblock( + let mermaid: string; + $: mermaid = wrap_in_codeblock( Mermaid.from_edges(flat_unique.sort(sort), { click: { method: "class" }, renderer: options.mermaid_renderer, @@ -91,17 +107,26 @@ }), "mermaid", ); - log.debug(mermaid); - - const render_mermaid = (node: HTMLElement) => { - MarkdownRenderer.render( - plugin.app, - mermaid, - node, - $active_file_store?.path ?? "", - plugin, - ); - }; + $: log.debug(mermaid); + + let mermaid_element: HTMLElement | undefined; + + // we need to pass both the mermaid string and the target element, so that it re-renders when the mermaid string changes + // and for the initial render the target element is undefined, so we need to check for that + const render_mermaid = (mermaid_str: string, target_el: HTMLElement | undefined) => { + if (target_el) { + target_el.empty(); + MarkdownRenderer.render( + plugin.app, + mermaid_str, + target_el, + $active_file_store?.path ?? "", + plugin, + ) + } + } + + $: render_mermaid(mermaid, mermaid_element);
@@ -119,7 +144,7 @@
{:else}

No paths found.

diff --git a/src/components/codeblocks/CodeblockTree.svelte b/src/components/codeblocks/CodeblockTree.svelte index 016653e5..4b9c2f60 100644 --- a/src/components/codeblocks/CodeblockTree.svelte +++ b/src/components/codeblocks/CodeblockTree.svelte @@ -8,11 +8,17 @@ import FlatEdgeList from "../FlatEdgeList.svelte"; import NestedEdgeList from "../NestedEdgeList.svelte"; import CodeblockErrors from "./CodeblockErrors.svelte"; + import type { BCEdge } from "src/graph/MyMultiGraph"; export let plugin: BreadcrumbsPlugin; export let options: ICodeblock["Options"]; export let errors: BreadcrumbsError[]; + // this is an exposed function that we can call from the outside to update the codeblock + export const update = () => { + all_paths = get_all_paths(); + } + const base_traversal = ({ hierarchy_i, }: { @@ -31,18 +37,26 @@ }), ); - const all_paths = - $active_file_store && plugin.graph.hasNode($active_file_store.path) - ? options.merge_hierarchies - ? base_traversal({ hierarchy_i: undefined }) - : plugin.settings.hierarchies - .map((_hierarchy, hierarchy_i) => - base_traversal({ hierarchy_i }), - ) - .flat() - : []; + const get_all_paths = () => { + if ($active_file_store && plugin.graph.hasNode($active_file_store.path)) { + if (options.merge_hierarchies) { + return base_traversal({ hierarchy_i: undefined }); + } else { + return plugin.settings.hierarchies + .map((_hierarchy, hierarchy_i) => + base_traversal({ hierarchy_i }) + ) + .flat(); + } + } else { + return []; + } + } + + let all_paths = get_all_paths(); - const sliced = all_paths.map((path) => + let sliced: BCEdge[][]; + $: sliced = all_paths.map((path) => path.slice(options.depth[0], options.depth[1]), ); diff --git a/src/main.ts b/src/main.ts index 2d06c51d..75bddf94 100644 --- a/src/main.ts +++ b/src/main.ts @@ -26,6 +26,7 @@ import { get_all_hierarchy_fields } from "./utils/hierarchies"; import { deep_merge_objects } from "./utils/objects"; import { redraw_page_views } from "./views/page"; import { TreeView } from "./views/tree"; +import { Codeblocks } from "src/codeblocks"; export default class BreadcrumbsPlugin extends Plugin { settings!: BreadcrumbsSettings; @@ -201,16 +202,17 @@ export default class BreadcrumbsPlugin extends Plugin { (leaf) => new TreeView(leaf, this), ); - // Codeblocks - this.registerMarkdownCodeBlockProcessor( - "breadcrumbs", - (source, el, ctx) => { - const mdrc = new CodeblockMDRC(this, el, source); - ctx.addChild(mdrc); - }, - ); }); + // Codeblocks + this.registerMarkdownCodeBlockProcessor( + "breadcrumbs", + (source, el, ctx) => { + const mdrc = new CodeblockMDRC(this, el, source); + ctx.addChild(mdrc); + }, + ); + // Commands this.addCommand({ id: "breadcrumbs:rebuild-graph", @@ -343,6 +345,7 @@ export default class BreadcrumbsPlugin extends Plugin { rebuild_graph?: boolean; active_file_store?: boolean; redraw_page_views?: boolean; + redraw_codeblocks?: boolean; }) => { log.debug( "refresh >", @@ -404,6 +407,10 @@ export default class BreadcrumbsPlugin extends Plugin { if (options?.redraw_page_views !== false) { redraw_page_views(this); } + + if (options?.redraw_codeblocks !== false) { + Codeblocks.update_codeblocks(); + } }; // SOURCE: https://docs.obsidian.md/Plugins/User+interface/Views