From 290f849c64c9f198f09b592daa48ecdae957375f Mon Sep 17 00:00:00 2001 From: Radu Date: Fri, 24 Nov 2023 16:52:57 -0500 Subject: Support GFM using `remarked` and fix some bugs - This avoids edge cases in the primitive parser I wrote. - Add KaTeX stylesheet (cause of rendering issues, not Pronto). - Bundle with Webpack. --- page.ts | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 page.ts (limited to 'page.ts') diff --git a/page.ts b/page.ts new file mode 100644 index 0000000..6370553 --- /dev/null +++ b/page.ts @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only + +import "./public-path"; + +import * as lowlight from "lowlight"; +import latex from "highlight.js/lib/languages/latex"; +import rehypeHighlight from "rehype-highlight"; +import rehypeKatex from "rehype-katex"; +import rehypeSanitize from "rehype-sanitize"; +import rehypeStringify from "rehype-stringify"; +import remarkGfm from "remark-gfm"; +import remarkMath from "remark-math"; +import remarkParse from "remark-parse"; +import remarkRehype from "remark-rehype"; +import { unified } from "unified"; + +import "highlight.js/styles/default.min.css"; +import "katex/dist/katex.min.css"; + +import "./manifest.json"; +import "./styles.css"; + +(async () => { + console.log("ASAP: Loaded"); + + // Wait for message list to appear + const msgListCb = new MutationObserver(handleMsgList); + msgListCb.observe(document.body, { childList: true, subtree: true }); + handleMsgList(); + + function handleMsgList() { + const list = document.querySelector(".message-list"); + if (list) { + console.log("ASAP: Found message list"); + msgListCb.disconnect(); + // Monitor only message list for changes to reduce load + const msgCb = new MutationObserver(handleMsg); + msgCb.observe(list, { childList: true, subtree: true }); + handleMsg(); + } + } + + function handleMsg() { + const msgs = document.querySelectorAll( + ".message-parts-container:not(.zbyffrly-done), .parent-text:not(.zbyffrly-done)" + ); + msgs.forEach(async (msg) => { + msg.classList.add("zbyffrly-done"); + + // Replace all but '(edited)' indicator + let text = ""; + while (msg.firstChild) { + const node = msg.firstChild; + if (node instanceof HTMLElement && node.classList.contains("edited")) + break; + else { + msg.removeChild(node); + text += node.textContent!; + } + } + text = text.slice(0, -1); // Remove trailing space before potential '(edited)' + msg.innerHTML = (await toHtml(text)) + msg.innerHTML; + }); + } + + async function toHtml(s: string) { + return String( + await unified() + .use(remarkParse) + .use(remarkGfm) + .use(remarkMath) + .use(remarkRehype) + .use(rehypeSanitize, { required: { code: { class: "hljs" } } }) // Style unhighlighted code + .use(rehypeHighlight, { languages: { ...lowlight.common, latex } }) + .use(rehypeKatex, { macros: {} }) // Share macros within message + .use(rehypeStringify) + .process(s) + ); + } +})(); -- cgit v1.2.3