Skip to content

Commit b9ec9a7

Browse files
committed
Quartz sync: Jun 2, 2025, 2:25 AM
1 parent 6baec05 commit b9ec9a7

File tree

3 files changed

+66
-23
lines changed

3 files changed

+66
-23
lines changed

quartz/components/scripts/mindmap.inline.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { GlobalMindmapConfig, LocalMindmapConfig } from '../Mindmap'
44
import { Markmap, deriveOptions } from "markmap-view"
55
import { Toolbar } from "markmap-toolbar"
66
import { IPureNode } from 'markmap-common'
7+
import { h } from 'preact'
78

89
const externalIcon = `
910
<svg aria-hidden="true" class="external-icon" style="max-width:0.8em;max-height:0.8em; margin-left:0.2em;" viewBox="0 0 512 512">
@@ -29,6 +30,24 @@ const exitIcon = `
2930
d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/>
3031
</svg>`
3132

33+
function fixForeignObjectReplaceElementErrorInSafari(layout: HTMLElement) {
34+
layout.querySelectorAll("video, audio, iframe").forEach(el => {
35+
const src = el.getAttribute("data-src") ?? el.getAttribute("src") ?? el.querySelector("source")?.getAttribute("src")
36+
if (!src) return
37+
const type = el.getAttribute("data-type") ?? el.tagName.toLowerCase()
38+
const place = el.getAttribute("data-place") ?? "internal"
39+
40+
const a = Object.assign(document.createElement("a"), {
41+
href: src,
42+
target: "_blank",
43+
className: `media-fallback ${place}`,
44+
textContent: `${type} - ${src}`,
45+
})
46+
47+
el.parentElement?.replaceChild(a, el)
48+
a.style.display = "inline-block"
49+
})
50+
}
3251

3352
function renderMermaidInMindmap(svg: SVGSVGElement) {
3453
requestAnimationFrame(async () => {
@@ -164,7 +183,7 @@ function addExternalIcon(svg: SVGSVGElement) {
164183
})
165184
}
166185

167-
async function renderMindmap(mindmap: HTMLElement) {
186+
async function renderMindmap(mindmap: HTMLElement, isSafari = false) {
168187
removeAllChildren(mindmap)
169188

170189
if (!mindmap.dataset["mindmap"]) {
@@ -186,8 +205,9 @@ async function renderMindmap(mindmap: HTMLElement) {
186205

187206
renderToolbar(mindmap, mm, option)
188207
renderMermaidInMindmap(svg)
189-
addExternalIcon(svg)
190208
renderPopoverInMindmap()
209+
isSafari && fixForeignObjectReplaceElementErrorInSafari(mindmap)
210+
addExternalIcon(svg)
191211

192212
return () => {
193213
mindmap.innerHTML = ""
@@ -220,7 +240,7 @@ document.addEventListener("nav", async () => {
220240
const mindmapContainers = document.getElementsByClassName("mindmap-container")
221241
for (const container of mindmapContainers) {
222242
isSafari && container.classList.add("is-safari")
223-
localMindmapCleanups.push(await renderMindmap(container as HTMLElement))
243+
localMindmapCleanups.push(await renderMindmap(container as HTMLElement, isSafari))
224244
}
225245
}
226246

@@ -247,7 +267,7 @@ document.addEventListener("nav", async () => {
247267
registerEscapeHandler(container, hideGlobalMindmap)
248268
if (mindmapContainer) {
249269
isSafari && mindmapContainer.classList.add("is-safari")
250-
globalMindmapCleanups.push(await renderMindmap(mindmapContainer))
270+
globalMindmapCleanups.push(await renderMindmap(mindmapContainer, isSafari))
251271
}
252272
}
253273
}

quartz/components/styles/mindmap.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
img {
3131
margin-top: 1em;
3232
margin-bottom: 0;
33+
max-width: 300px;
3334
}
3435

3536
blockquote {
@@ -46,6 +47,24 @@
4647
}
4748
}
4849

50+
audio {
51+
width: 500px;
52+
}
53+
54+
video {
55+
width: 500px;
56+
height: auto;
57+
}
58+
59+
iframe.youtube {
60+
width: 500px;
61+
}
62+
63+
iframe.pdf {
64+
width: 960px;
65+
height: 540px;
66+
}
67+
4968
foreignObject,
5069
foreignObject * {
5170
user-select: none !important;

quartz/plugins/transformers/mindmap.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,21 @@ function wikilinkReplacement(currentSlug: FullSlug, transformOptions: TransformO
9191
const imageEmbedMatch = imageEmbedRegex.exec(displayText || "")
9292
const width = imageEmbedMatch?.groups?.width ? imageEmbedMatch?.groups?.width + "px" : "auto"
9393
const height = imageEmbedMatch?.groups?.height ? imageEmbedMatch?.groups?.height + "px" : "auto"
94-
return `<img src="${url}" alt="${fragment ?? displayText ?? link}" style="height:${height}; width:${width}; max-width: 640px;" />`
94+
return `<img src="${url}" alt="${fragment ?? displayText ?? link}" style="height:${height}; width:${width};" />`
95+
}
96+
else if (/\.(mp4|webm|ogv|avi|mov|flv|wmv|mkv|mpg|mpeg|m4v)$/.test(link)) {
97+
return `
98+
<video src="${url}" data-type="video" controls width="640px" height="360px"/>
99+
`
100+
} else if (/\.(mp3|wav|m4a|ogg|3gp|flac)$/.test(link)) {
101+
return `
102+
<audio src="${url}" data-type="audio" controls />
103+
`
104+
} else if (/\.(pdf)$/.test(link)) {
105+
return `
106+
<iframe src="${url}" class="pdf" data-type="pdf" />
107+
`
95108
}
96-
// else if (/\.(mp4|webm|ogv|avi|mov|flv|wmv|mkv|mpg|mpeg|m4v)$/.test(link)) {
97-
// return `
98-
// <video src="${url}" controls/>
99-
// `
100-
// } else if (/\.(mp3|wav|m4a|ogg|3gp|flac)$/.test(link)) {
101-
// return `<audio src="${url}" controls />`
102-
// } else if (/\.(pdf)$/.test(link)) {
103-
// return `<iframe src="${url}" class="pdf" />`
104-
// }
105109

106110
return `<a href="${url}" class="internal">${displayText || link}</a>`
107111
} else if (tag) {
@@ -117,16 +121,16 @@ function ytLinkReplacement() {
117121
const embedUrl = toYouTubeEmbedURL(match[1])
118122
if (embedUrl) {
119123
return `
120-
<a href="${embedUrl}" class="external" target="_blank" > ${match[1]}</a>
124+
<iframe
125+
data-type="youtube"
126+
data-place="external"
127+
data-src="${match[1]}"
128+
class="external-embed youtube"
129+
allow="fullscreen"
130+
frameborder="0"
131+
src="${embedUrl}">
132+
</iframe>
121133
`
122-
// return `
123-
// <iframe
124-
// class="external-embed youtube"
125-
// allow="fullscreen"
126-
// frameborder="0"
127-
// src="${embedUrl}">
128-
// </iframe>
129-
// `
130134
}
131135
}
132136
return match[0]

0 commit comments

Comments
 (0)