fix(app): duplicate markdown

This commit is contained in:
adamelmore
2026-02-23 09:54:26 -06:00
parent 3b5b21a91e
commit 8f2d8dd47a

View File

@@ -103,6 +103,70 @@ function setCopyState(button: HTMLButtonElement, labels: CopyLabels, copied: boo
button.setAttribute("data-tooltip", labels.copy)
}
function ensureCodeWrapper(block: HTMLPreElement, labels: CopyLabels) {
const parent = block.parentElement
if (!parent) return
const wrapped = parent.getAttribute("data-component") === "markdown-code"
if (!wrapped) {
const wrapper = document.createElement("div")
wrapper.setAttribute("data-component", "markdown-code")
parent.replaceChild(wrapper, block)
wrapper.appendChild(block)
wrapper.appendChild(createCopyButton(labels))
return
}
const buttons = Array.from(parent.querySelectorAll('[data-slot="markdown-copy-button"]')).filter(
(el): el is HTMLButtonElement => el instanceof HTMLButtonElement,
)
if (buttons.length === 0) {
parent.appendChild(createCopyButton(labels))
return
}
for (const button of buttons.slice(1)) {
button.remove()
}
}
function markCodeLinks(root: HTMLDivElement) {
const codeNodes = Array.from(root.querySelectorAll(":not(pre) > code"))
for (const code of codeNodes) {
const href = codeUrl(code.textContent ?? "")
const parentLink =
code.parentElement instanceof HTMLAnchorElement && code.parentElement.classList.contains("external-link")
? code.parentElement
: null
if (!href) {
if (parentLink) parentLink.replaceWith(code)
continue
}
if (parentLink) {
parentLink.href = href
continue
}
const link = document.createElement("a")
link.href = href
link.className = "external-link"
link.target = "_blank"
link.rel = "noopener noreferrer"
code.parentNode?.replaceChild(link, code)
link.appendChild(code)
}
}
function decorate(root: HTMLDivElement, labels: CopyLabels) {
const blocks = Array.from(root.querySelectorAll("pre"))
for (const block of blocks) {
ensureCodeWrapper(block, labels)
}
markCodeLinks(root)
}
function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
const timeouts = new Map<HTMLButtonElement, ReturnType<typeof setTimeout>>()
@@ -111,62 +175,6 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
setCopyState(button, labels, copied)
}
const ensureWrapper = (block: HTMLPreElement) => {
const parent = block.parentElement
if (!parent) return
const wrapped = parent.getAttribute("data-component") === "markdown-code"
if (wrapped) {
const buttons = Array.from(parent.querySelectorAll('[data-slot="markdown-copy-button"]')).filter(
(el): el is HTMLButtonElement => el instanceof HTMLButtonElement,
)
if (buttons.length === 0) {
parent.appendChild(createCopyButton(labels))
return
}
for (const button of buttons.slice(1)) {
button.remove()
}
return
}
const wrapper = document.createElement("div")
wrapper.setAttribute("data-component", "markdown-code")
parent.replaceChild(wrapper, block)
wrapper.appendChild(block)
wrapper.appendChild(createCopyButton(labels))
}
const markCodeLinks = () => {
const codeNodes = Array.from(root.querySelectorAll(":not(pre) > code"))
for (const code of codeNodes) {
const href = codeUrl(code.textContent ?? "")
const parentLink =
code.parentElement instanceof HTMLAnchorElement && code.parentElement.classList.contains("external-link")
? code.parentElement
: null
if (!href) {
if (parentLink) parentLink.replaceWith(code)
continue
}
if (parentLink) {
parentLink.href = href
continue
}
const link = document.createElement("a")
link.href = href
link.className = "external-link"
link.target = "_blank"
link.rel = "noopener noreferrer"
code.parentNode?.replaceChild(link, code)
link.appendChild(code)
}
}
const handleClick = async (event: MouseEvent) => {
const target = event.target
if (!(target instanceof Element)) return
@@ -186,11 +194,7 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
timeouts.set(button, timeout)
}
const blocks = Array.from(root.querySelectorAll("pre"))
for (const block of blocks) {
ensureWrapper(block)
}
markCodeLinks()
decorate(root, labels)
const buttons = Array.from(root.querySelectorAll('[data-slot="markdown-copy-button"]'))
for (const button of buttons) {
@@ -207,20 +211,6 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
}
}
function wrapCodeBlocks(root: HTMLDivElement) {
const blocks = Array.from(root.querySelectorAll("pre"))
for (const block of blocks) {
const parent = block.parentElement
if (!parent) continue
const wrapped = parent.getAttribute("data-component") === "markdown-code"
if (wrapped) continue
const wrapper = document.createElement("div")
wrapper.setAttribute("data-component", "markdown-code")
parent.replaceChild(wrapper, block)
wrapper.appendChild(block)
}
}
function touch(key: string, value: Entry) {
cache.delete(key)
cache.set(key, value)
@@ -284,23 +274,15 @@ export function Markdown(
const temp = document.createElement("div")
temp.innerHTML = content
wrapCodeBlocks(temp)
decorate(temp, {
copy: i18n.t("ui.message.copy"),
copied: i18n.t("ui.message.copied"),
})
morphdom(container, temp, {
childrenOnly: true,
onBeforeElUpdated: (fromEl, toEl) => {
if (fromEl.isEqualNode(toEl)) return false
const fromWrapped = fromEl.getAttribute("data-component") === "markdown-code"
const toWrapped = toEl.getAttribute("data-component") === "markdown-code"
if (fromWrapped && toWrapped) {
const fromPre = fromEl.querySelector("pre")
const toPre = toEl.querySelector("pre")
if (fromPre && toPre && !fromPre.isEqualNode(toPre)) {
morphdom(fromPre, toPre)
}
return false
}
return true
},
})