Skip to content

Commit 8f2d8dd

Browse files
committed
fix(app): duplicate markdown
1 parent 3b5b21a commit 8f2d8dd

1 file changed

Lines changed: 65 additions & 83 deletions

File tree

packages/ui/src/components/markdown.tsx

Lines changed: 65 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -103,68 +103,76 @@ function setCopyState(button: HTMLButtonElement, labels: CopyLabels, copied: boo
103103
button.setAttribute("data-tooltip", labels.copy)
104104
}
105105

106-
function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
107-
const timeouts = new Map<HTMLButtonElement, ReturnType<typeof setTimeout>>()
108-
109-
const updateLabel = (button: HTMLButtonElement) => {
110-
const copied = button.getAttribute("data-copied") === "true"
111-
setCopyState(button, labels, copied)
112-
}
113-
114-
const ensureWrapper = (block: HTMLPreElement) => {
115-
const parent = block.parentElement
116-
if (!parent) return
117-
const wrapped = parent.getAttribute("data-component") === "markdown-code"
118-
if (wrapped) {
119-
const buttons = Array.from(parent.querySelectorAll('[data-slot="markdown-copy-button"]')).filter(
120-
(el): el is HTMLButtonElement => el instanceof HTMLButtonElement,
121-
)
122-
123-
if (buttons.length === 0) {
124-
parent.appendChild(createCopyButton(labels))
125-
return
126-
}
127-
128-
for (const button of buttons.slice(1)) {
129-
button.remove()
130-
}
131-
132-
return
133-
}
106+
function ensureCodeWrapper(block: HTMLPreElement, labels: CopyLabels) {
107+
const parent = block.parentElement
108+
if (!parent) return
109+
const wrapped = parent.getAttribute("data-component") === "markdown-code"
110+
if (!wrapped) {
134111
const wrapper = document.createElement("div")
135112
wrapper.setAttribute("data-component", "markdown-code")
136113
parent.replaceChild(wrapper, block)
137114
wrapper.appendChild(block)
138115
wrapper.appendChild(createCopyButton(labels))
116+
return
139117
}
140118

141-
const markCodeLinks = () => {
142-
const codeNodes = Array.from(root.querySelectorAll(":not(pre) > code"))
143-
for (const code of codeNodes) {
144-
const href = codeUrl(code.textContent ?? "")
145-
const parentLink =
146-
code.parentElement instanceof HTMLAnchorElement && code.parentElement.classList.contains("external-link")
147-
? code.parentElement
148-
: null
149-
150-
if (!href) {
151-
if (parentLink) parentLink.replaceWith(code)
152-
continue
153-
}
119+
const buttons = Array.from(parent.querySelectorAll('[data-slot="markdown-copy-button"]')).filter(
120+
(el): el is HTMLButtonElement => el instanceof HTMLButtonElement,
121+
)
154122

155-
if (parentLink) {
156-
parentLink.href = href
157-
continue
158-
}
123+
if (buttons.length === 0) {
124+
parent.appendChild(createCopyButton(labels))
125+
return
126+
}
127+
128+
for (const button of buttons.slice(1)) {
129+
button.remove()
130+
}
131+
}
132+
133+
function markCodeLinks(root: HTMLDivElement) {
134+
const codeNodes = Array.from(root.querySelectorAll(":not(pre) > code"))
135+
for (const code of codeNodes) {
136+
const href = codeUrl(code.textContent ?? "")
137+
const parentLink =
138+
code.parentElement instanceof HTMLAnchorElement && code.parentElement.classList.contains("external-link")
139+
? code.parentElement
140+
: null
141+
142+
if (!href) {
143+
if (parentLink) parentLink.replaceWith(code)
144+
continue
145+
}
159146

160-
const link = document.createElement("a")
161-
link.href = href
162-
link.className = "external-link"
163-
link.target = "_blank"
164-
link.rel = "noopener noreferrer"
165-
code.parentNode?.replaceChild(link, code)
166-
link.appendChild(code)
147+
if (parentLink) {
148+
parentLink.href = href
149+
continue
167150
}
151+
152+
const link = document.createElement("a")
153+
link.href = href
154+
link.className = "external-link"
155+
link.target = "_blank"
156+
link.rel = "noopener noreferrer"
157+
code.parentNode?.replaceChild(link, code)
158+
link.appendChild(code)
159+
}
160+
}
161+
162+
function decorate(root: HTMLDivElement, labels: CopyLabels) {
163+
const blocks = Array.from(root.querySelectorAll("pre"))
164+
for (const block of blocks) {
165+
ensureCodeWrapper(block, labels)
166+
}
167+
markCodeLinks(root)
168+
}
169+
170+
function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
171+
const timeouts = new Map<HTMLButtonElement, ReturnType<typeof setTimeout>>()
172+
173+
const updateLabel = (button: HTMLButtonElement) => {
174+
const copied = button.getAttribute("data-copied") === "true"
175+
setCopyState(button, labels, copied)
168176
}
169177

170178
const handleClick = async (event: MouseEvent) => {
@@ -186,11 +194,7 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
186194
timeouts.set(button, timeout)
187195
}
188196

189-
const blocks = Array.from(root.querySelectorAll("pre"))
190-
for (const block of blocks) {
191-
ensureWrapper(block)
192-
}
193-
markCodeLinks()
197+
decorate(root, labels)
194198

195199
const buttons = Array.from(root.querySelectorAll('[data-slot="markdown-copy-button"]'))
196200
for (const button of buttons) {
@@ -207,20 +211,6 @@ function setupCodeCopy(root: HTMLDivElement, labels: CopyLabels) {
207211
}
208212
}
209213

210-
function wrapCodeBlocks(root: HTMLDivElement) {
211-
const blocks = Array.from(root.querySelectorAll("pre"))
212-
for (const block of blocks) {
213-
const parent = block.parentElement
214-
if (!parent) continue
215-
const wrapped = parent.getAttribute("data-component") === "markdown-code"
216-
if (wrapped) continue
217-
const wrapper = document.createElement("div")
218-
wrapper.setAttribute("data-component", "markdown-code")
219-
parent.replaceChild(wrapper, block)
220-
wrapper.appendChild(block)
221-
}
222-
}
223-
224214
function touch(key: string, value: Entry) {
225215
cache.delete(key)
226216
cache.set(key, value)
@@ -284,23 +274,15 @@ export function Markdown(
284274

285275
const temp = document.createElement("div")
286276
temp.innerHTML = content
287-
wrapCodeBlocks(temp)
277+
decorate(temp, {
278+
copy: i18n.t("ui.message.copy"),
279+
copied: i18n.t("ui.message.copied"),
280+
})
288281

289282
morphdom(container, temp, {
290283
childrenOnly: true,
291284
onBeforeElUpdated: (fromEl, toEl) => {
292285
if (fromEl.isEqualNode(toEl)) return false
293-
294-
const fromWrapped = fromEl.getAttribute("data-component") === "markdown-code"
295-
const toWrapped = toEl.getAttribute("data-component") === "markdown-code"
296-
if (fromWrapped && toWrapped) {
297-
const fromPre = fromEl.querySelector("pre")
298-
const toPre = toEl.querySelector("pre")
299-
if (fromPre && toPre && !fromPre.isEqualNode(toPre)) {
300-
morphdom(fromPre, toPre)
301-
}
302-
return false
303-
}
304286
return true
305287
},
306288
})

0 commit comments

Comments
 (0)