From 8b682f08f3a4849238b95a5b958c652ced4c50bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Trzci=C5=84ski?= Date: Fri, 29 Nov 2024 15:29:35 +0100 Subject: [PATCH] [#69560] add url mapping --- src/hooks/markdownUrlMapping.js | 19 +++++++++++++++++++ src/hooks/useText.js | 6 ++++-- src/mystState.js | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/hooks/markdownUrlMapping.js diff --git a/src/hooks/markdownUrlMapping.js b/src/hooks/markdownUrlMapping.js new file mode 100644 index 0000000..e7cb3b5 --- /dev/null +++ b/src/hooks/markdownUrlMapping.js @@ -0,0 +1,19 @@ +import markdownIt from "markdown-it"; + +const mappedAttrs = ["src", "href"]; + +const mapToken = (token, mapFunc) => { + for (const attrName of mappedAttrs) { + const attr = token.attrGet(attrName); + if (attr) token.attrSet(attrName, mapFunc(token.tag, attr)); + } +}; + +export function markdownItMapUrls(/** @type {markdownIt} */ md) { + md.core.ruler.after("inline", "map_urls", (state) => { + for (const token of state.tokens) { + mapToken(token, state.env.mapUrl); + token.children?.forEach?.((c) => mapToken(c, state.env.mapUrl)); + } + }); +} diff --git a/src/hooks/useText.js b/src/hooks/useText.js index f936ef4..21c4d7c 100644 --- a/src/hooks/useText.js +++ b/src/hooks/useText.js @@ -14,6 +14,7 @@ import { MystState } from "../mystState"; import { useComputed } from "@preact/signals"; import markdownCheckboxes from "markdown-it-checkbox"; import { colonFencedBlocks } from "./markdownFence"; +import { markdownItMapUrls } from "./markdownUrlMapping"; const countOccurences = (str, pattern) => (str?.match(pattern) || []).length; @@ -112,6 +113,7 @@ export const useText = ({ preview }) => { .use(markdownSourceMap) .use(checkLinks) .use(colonFencedBlocks) + .use(markdownItMapUrls) .use(markdownCheckboxes); if (options.backslashLineBreak.value) md.use(backslashLineBreakPlugin); @@ -187,14 +189,14 @@ export const useText = ({ preview }) => { const html = lookup[hash] || - purify.sanitize(markdown.value.render(md, { chunkId, startLine, lineMap, view: editorView.value }), { + purify.sanitize(markdown.value.render(md, { chunkId, startLine, lineMap, view: editorView.value, mapUrl: options.mapUrl.value }), { // Taken from Mermaid JS settings: https://github.com/mermaid-js/mermaid/blob/dd0304387e85fc57a9ebb666f89ef788c012c2c5/packages/mermaid/src/mermaidAPI.ts#L50 ADD_TAGS: ["foreignobject"], ADD_ATTR: ["dominant-baseline"], }); return { md, hash, id: chunkId, html }; }), - [markdown.value, options.id.value], + [markdown.value, options.id.value, options.mapUrl.value], ); useEffect(() => readyToRender && updateHtmlChunks({ newMarkdown: text }), [readyToRender]); diff --git a/src/mystState.js b/src/mystState.js index 01408f0..96e08d8 100644 --- a/src/mystState.js +++ b/src/mystState.js @@ -51,6 +51,7 @@ const defaults = { parent: null, syncScroll: false, unfoldedHeadings: null, + mapUrl: (tag, url) => url, }; export function createMystState(/** @type {typeof defaults} */ opts) {