mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-18 19:30:27 +08:00
Share code block enhancement between renderers
The copy button and syntax highlighting setup for code blocks moves out of the Markdown component, so other document renderers can reuse it.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { toDom } from "hast-util-to-dom";
|
|
||||||
import { mount, tick, unmount } from "svelte";
|
import { mount, tick, unmount } from "svelte";
|
||||||
|
|
||||||
|
import { enhanceCodeBlocks } from "@app/lib/codeBlocks";
|
||||||
import { decodeEmbed, embedPreviewKind, retinaWidth } from "@app/lib/embeds";
|
import { decodeEmbed, embedPreviewKind, retinaWidth } from "@app/lib/embeds";
|
||||||
import { parseFrontmatter } from "@app/lib/frontmatter";
|
import { parseFrontmatter } from "@app/lib/frontmatter";
|
||||||
import { invoke } from "@app/lib/invoke";
|
import { invoke } from "@app/lib/invoke";
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
} from "@app/lib/markdown";
|
} from "@app/lib/markdown";
|
||||||
import { parseEntityHref } from "@app/lib/mentions";
|
import { parseEntityHref } from "@app/lib/mentions";
|
||||||
import { isOid } from "@app/lib/radUri";
|
import { isOid } from "@app/lib/radUri";
|
||||||
import { highlight } from "@app/lib/syntax";
|
|
||||||
import { scrollIntoView, twemoji } from "@app/lib/utils";
|
import { scrollIntoView, twemoji } from "@app/lib/utils";
|
||||||
|
|
||||||
import Icon from "@app/components/Icon.svelte";
|
import Icon from "@app/components/Icon.svelte";
|
||||||
@@ -333,39 +332,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces code blocks in the background with highlighted code.
|
enhanceCodeBlocks(container);
|
||||||
const prefix = "language-";
|
|
||||||
const nodes = Array.from(container.querySelectorAll("pre code"));
|
|
||||||
|
|
||||||
const treeChanges: Promise<void>[] = [];
|
|
||||||
|
|
||||||
for (const node of nodes) {
|
|
||||||
const preElement = node.parentElement as HTMLElement;
|
|
||||||
const copyButton = document.createElement("radicle-clipboard");
|
|
||||||
copyButton.setAttribute("text", node.textContent || "");
|
|
||||||
const preWrapper = document.createElement("div");
|
|
||||||
preWrapper.classList.add("pre-wrapper");
|
|
||||||
preElement.parentNode?.insertBefore(preWrapper, preElement);
|
|
||||||
preWrapper.appendChild(preElement);
|
|
||||||
preWrapper.appendChild(copyButton);
|
|
||||||
|
|
||||||
const className = Array.from(node.classList).find(name =>
|
|
||||||
name.startsWith(prefix),
|
|
||||||
);
|
|
||||||
if (!className) continue;
|
|
||||||
|
|
||||||
treeChanges.push(
|
|
||||||
highlight(node.textContent ?? "", className.slice(prefix.length))
|
|
||||||
.then(tree => {
|
|
||||||
if (tree) {
|
|
||||||
node.replaceChildren(toDom(tree, { fragment: true }));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(e => console.warn("Not able to highlight code block", e)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Promise.allSettled(treeChanges);
|
|
||||||
|
|
||||||
if (!scrolledToHash && window.location.hash) {
|
if (!scrolledToHash && window.location.hash) {
|
||||||
scrollIntoView(window.location.hash.substring(1));
|
scrollIntoView(window.location.hash.substring(1));
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { toDom } from "hast-util-to-dom";
|
||||||
|
|
||||||
|
import { highlight } from "@app/lib/syntax";
|
||||||
|
|
||||||
|
const languagePrefix = "language-";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a copy button to every `pre code` block in `container` and replaces
|
||||||
|
* the blocks that name a language with highlighted code in the background.
|
||||||
|
*/
|
||||||
|
export function enhanceCodeBlocks(container: HTMLElement) {
|
||||||
|
for (const node of container.querySelectorAll("pre code")) {
|
||||||
|
const preElement = node.parentElement as HTMLElement;
|
||||||
|
const copyButton = document.createElement("radicle-clipboard");
|
||||||
|
copyButton.setAttribute("text", node.textContent || "");
|
||||||
|
const preWrapper = document.createElement("div");
|
||||||
|
preWrapper.classList.add("pre-wrapper");
|
||||||
|
preElement.parentNode?.insertBefore(preWrapper, preElement);
|
||||||
|
preWrapper.appendChild(preElement);
|
||||||
|
preWrapper.appendChild(copyButton);
|
||||||
|
|
||||||
|
const className = Array.from(node.classList).find(name =>
|
||||||
|
name.startsWith(languagePrefix),
|
||||||
|
);
|
||||||
|
if (!className) continue;
|
||||||
|
|
||||||
|
highlight(node.textContent ?? "", className.slice(languagePrefix.length))
|
||||||
|
.then(tree => {
|
||||||
|
if (tree) {
|
||||||
|
node.replaceChildren(toDom(tree, { fragment: true }));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => console.warn("Not able to highlight code block", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user