David Fischer
2024-02-14 6c8023463d0e4ea68be3216c454775fd87d3e370
Add support for image popovers (#854)

* feat(popover): Add support for images

* fix: run prettier

* feat(popover): use switch logic for content types & adjust styles

* feat(popover): Add content type data tag for popover-inner class
3 files modified
47 ■■■■ changed files
docs/features/popover previews.md 2 ●●●●● patch | view | raw | blame | history
quartz/components/scripts/popover.inline.ts 34 ●●●● patch | view | raw | blame | history
quartz/components/styles/popover.scss 11 ●●●●● patch | view | raw | blame | history
docs/features/popover previews.md
@@ -8,6 +8,8 @@
When [[creating components|creating your own components]], you can include this `popover-hint` class to also include it in the popover.
Similar to Obsidian, [[quartz layout.png|images referenced using wikilinks]] can also be viewed as popups.
## Configuration
- Remove popovers: set the `enablePopovers` field in `quartz.config.ts` to be `false`.
quartz/components/scripts/popover.inline.ts
@@ -37,9 +37,7 @@
  targetUrl.hash = ""
  targetUrl.search = ""
  const contents = await fetch(`${targetUrl}`)
    .then((res) => res.text())
    .catch((err) => {
  const response = await fetch(`${targetUrl}`).catch((err) => {
      console.error(err)
    })
@@ -48,18 +46,38 @@
    return
  }
  if (!contents) return
  const html = p.parseFromString(contents, "text/html")
  normalizeRelativeURLs(html, targetUrl)
  const elts = [...html.getElementsByClassName("popover-hint")]
  if (elts.length === 0) return
  if (!response) return
  const contentType = response.headers.get("Content-Type")
  const contentTypeCategory = contentType?.split("/")[0] ?? "text"
  const popoverElement = document.createElement("div")
  popoverElement.classList.add("popover")
  const popoverInner = document.createElement("div")
  popoverInner.classList.add("popover-inner")
  popoverElement.appendChild(popoverInner)
  popoverInner.dataset.contentType = contentTypeCategory
  switch (contentTypeCategory) {
    case "image":
      const img = document.createElement("img")
      response.blob().then((blob) => {
        img.src = URL.createObjectURL(blob)
      })
      img.alt = targetUrl.pathname
      popoverInner.appendChild(img)
      break
    default:
      const contents = await response.text()
      const html = p.parseFromString(contents, "text/html")
      normalizeRelativeURLs(html, targetUrl)
      const elts = [...html.getElementsByClassName("popover-hint")]
      if (elts.length === 0) return
  elts.forEach((elt) => popoverInner.appendChild(elt))
  }
  setPosition(popoverElement)
  link.appendChild(popoverElement)
quartz/components/styles/popover.scss
@@ -38,6 +38,17 @@
    white-space: normal;
  }
  & > .popover-inner[data-content-type="image"] {
    padding: 0;
    max-height: 100%;
    img {
      margin: 0;
      border-radius: 0;
      display: block;
    }
  }
  h1 {
    font-size: 1.5rem;
  }