using MarkdownRenderer to get HTML from markdown including Dataview inline query

Hello,

For a plugin that I am working on, i’d like to grap the HTML code resulting from the rendering of a markdown fragment, which includes an inline dataview query.

To be more precise my markdown fragment looks like: "**`=this.hostname**`". The generated HTML i’d expect from this is:

<p dir="auto"><strong><span class="dataview dataview-inline-query"><span>vm1</span></span></strong></p>

The function markdownToHTML I am using to render the markdown fragment is copied below (credit) :

export async function markdownToHtml(markdown: string, sourcePath?: string, app: App): Promise<string> {
  const component = new Component();
  component.load();
  const renderDiv = createDiv();
  await MarkdownRenderer.render(app, markdown, renderDiv, sourcePath ?? '', component);
  const html = renderDiv.getHTML();
  console.log("test - renderDiv");    // <-- identify in the console
  console.log(renderDiv);             // <-- (1) log the html element (object)
  console.log(renderDiv.getHTML());   // <-- (2) serialized html
  component.unload();
  return html;
}

Note the console.log statements and the screenshot below from the console as I am little puzzled by the result I am getting.

dev-console

As you may notice the console.log(renderDiv); statement (1) seems to render the fragment as expected (i.e including the result of the dataview inline query). However, serialising the exact same element to a HTML string: console.log(renderDiv.getHTML()); (2) returns the HTML representation of the markdown fragment without executing the inline query (see bottom line in the screenshot).

My question is if this is a bug (in the console?), or am I missing something?

Any help is much appreciated

Joost

I think that’s because console.log(renderDiv) writes an instance of the div to the console, which is transformed later on with Dataview MarkdownPostProcessor, so when in the console you expand that renderDiv variable, its content is already updated.

From the other hand, when you use renderDiv.getHTML(), it is executed BEFORE Dataview MarkdownPostProcessor and you are getting an old markup.

Thanks @mnaoumov, that was indeed what is going on.

Putting a small temporal delay (eg. 200 ms) seems to give the MarkdownPostProcessor enough time to do its thing, and gives me the HTML i expect,

However, is there a way to know when the MarkdownPostProcessors attached to the HTML element are done? I am considering creating a MarkdownPostProcessor with a high sortOrder (assuming that this will make it run last - i.e after dataview) that informs my plugin that it is safe to continue. Or do you happen to have a better suggestion?

Thanks again for your help!

1 Like

Hello,

With the ultimate objective to obtain the final HTML resulting from rendering a markdown fragment (that may including processing by a plugin, such as DataView), I’d like to find out when the MarkdownPostProcessors manipulating a given element have finished their work.

I proceeded as described in my previous post. I.e. use registerMarkdownPostProcessor with a (very) high a sortOrder' to register a callback function that would notify my plugin once all MarkdownPostProcessors` are done.

export default class MyPlugin extends Plugin {
	...
	async onload() {
		this.app.workspace.onLayoutReady(() => {
			this.registerMarkdownPostProcessor((element, context) => {
			console.log(element);            // this logs the element in a collapsible way
                                             // i.e. not necessarily representative for the
                                             // actual state of the element at time of logging 
			console.log(element.getHTML());  // this logs the element as it is at the time of 
                                             // logging  
		},9999);                             // It is assumed there are no MarkdownPostProcessor 
                                             // with a higher sortOrder 
		});
	}
}

I expected this would run after all other registered MarkdownPostProcessors (notably the ones from DataView that have a sortOrder of -100, and 100), but this unfortunately doesn’t seem to be the case judging from the output I get in the console (see screenshot below)

screenshot obsidian console

The collapsed element (on top) prints the element as I would like to have it. However, as pointed out by @mnaoumov in the post above this isn’t representative for the actual state of the element of the time of printing. Therefore, the bottom line prints the serialized element as it is at the time of logging. They should be the same, but obviously they aren’t.

My questions are:

  1. Does a high sortOrder (e.g. 9999) does indeed make the registered MarkdownPostProcessor run last (i.e. strictly after all MarkdownPostProcessor registered by other plugins, such as DataView)?
  2. Does MarkdownPostProcessor produce the final HTML, or is there another processing step/process in the Obsidian stack that can manipulate it?

Many thanks for your help!

joost