0

I want to parse markdown in the browser and do that ansyc, so nothing "hangs". However, the unified parse function is only synchronous. So, how to parse Markdown without blocking the browser/UI?

My code:

import { unified } from "unified";
import remarkParse from "remark-parse";

const tree = unified().use(remarkParse).parse(markdown);
stefan.at.kotlin
  • 15,347
  • 38
  • 147
  • 270

3 Answers3

2

For non-blocking browser scripts you could take a look at Service Workers. See the docs for details. With workers, there will no (or close-to) changes in the code. It you need to pass information between the primary page and the worker you need to pass so-called messages between each of them (postMessage/onmessage, see examples on the mentioned docs page).

tl;dr: Web Workers are background threads for js code that's running aside of the default js cycle of the tab (also possible if the tab is closed).

boppy
  • 1,753
  • 12
  • 10
1

You can use the process method provided by unified, which returns a Promise.

import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";

const parseMarkdown = async (markdown) => {
  const result = await unified()
    .use(remarkParse)
    .use(remarkRehype)
    .use(rehypeStringify)
    .process(markdown);

  return result.toString();
};

(async () => {
  const markdown = "# Hello, World!";
  const html = await parseMarkdown(markdown);
  console.log(html);
})();

Define an async function parseMarkdown that takes a markdown string as input. use unified with remarkParse, remarkRehype, and rehypeStringify to process the markdown asynchronously inside the function. The process method returns a Promise, which we can await to get the result. Now convert the result to a string with the toString() method.

You can then use an async immediately invoked function expression (IIFE) to call the parseMarkdown function.

(async () => {
  const markdown = "# Hello, World!";
  const html = await parseMarkdown(markdown);
  console.log(html);
})();
0

You could use worker that parses Markdown in another thread using postMessage:

index.js (main file):

let mdParseWorker = new Worker("./worker.js");

mdParseWorker.onmessage = e => {
  let tree = e.data;
  // Do something with tree
}

mdParseWorker.postMessage(markdown, "*")

worker.js:

import { unified } from "unified";
import remarkParse from "remark-parse";

onmessage = e => {
  let tree = unified().use(remarkParse).parse(e.data);
  self.postMessage(tree, "*");
}
MfyDev
  • 439
  • 1
  • 12