| quartz/components/scripts/callout.inline.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/index.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/transformers/ofm.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/styles/callouts.scss | ●●●●● patch | view | raw | blame | history |
quartz/components/scripts/callout.inline.ts
New file @@ -0,0 +1,24 @@ function toggleCallout(this: HTMLElement) { const outerBlock = this.parentElement! this.classList.toggle(`is-collapsed`) const collapsed = this.classList.contains(`is-collapsed`) const height = collapsed ? this.scrollHeight : outerBlock.scrollHeight outerBlock.style.maxHeight = height + `px` } function setupCallout(div: HTMLElement) { const collapsed = div.classList.contains(`is-collapsed`) const title = div.firstElementChild! const height = collapsed ? title.scrollHeight : div.scrollHeight div.style.maxHeight = height + `px` } document.addEventListener(`nav`, () => { const collapsible = document.getElementsByClassName(`callout is-collapsible`) as HTMLCollectionOf<HTMLElement> for (const div of collapsible) { const title = div.firstElementChild setupCallout(div) title?.removeEventListener(`click`, toggleCallout) title?.addEventListener(`click`, toggleCallout) } }) quartz/plugins/index.ts
@@ -83,7 +83,7 @@ } for (const transformer of plugins.transformers) { const res = transformer.externalResources const res = transformer.externalResources ? transformer.externalResources() : {} if (res?.js) { staticResources.js = staticResources.js.concat(res.js) } quartz/plugins/transformers/ofm.ts
@@ -7,6 +7,8 @@ import { visit } from "unist-util-visit" import path from "path" import { JSResource } from "../../resources" // @ts-ignore import calloutScript from "../../components/scripts/callout.inline.ts" export interface Options { highlight: boolean @@ -210,6 +212,10 @@ const defaultState = collapseChar === "-" ? "collapsed" : "expanded" const title = match.input.slice(calloutDirective.length).trim() || capitalize(calloutType) const toggleIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="fold"> <polyline points="6 9 12 15 18 9"></polyline> </svg>` const titleNode: HTML = { type: "html", value: `<div @@ -217,6 +223,7 @@ > <div class="callout-icon">${callouts[canonicalizeCallout(calloutType)]}</div> <div class="callout-title-inner">${title}</div> ${collapse ? toggleIcon : ""} </div>` } @@ -228,7 +235,6 @@ type: 'text', value: remainingText, }] }) } @@ -236,7 +242,6 @@ node.children.splice(0, 1, ...blockquoteContent) // add properties to base blockquote // TODO: add the js to actually support collapsing callout node.data = { hProperties: { ...(node.data?.hProperties ?? {}), @@ -273,7 +278,18 @@ return [rehypeRaw] }, externalResources() { const mermaidScript: JSResource = { const js: JSResource[] = [] if (opts.callouts) { js.push({ script: calloutScript, loadTime: 'afterDOMReady', contentType: 'inline' }) } if (opts.mermaid) { js.push({ script: ` import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs'; mermaid.initialize({ startOnLoad: true }); @@ -281,10 +297,12 @@ loadTime: 'afterDOMReady', moduleType: 'module', contentType: 'inline' }) } return { js: opts.mermaid ? [mermaidScript] : [] } console.log(js) return { js } } } } quartz/styles/callouts.scss
@@ -5,6 +5,8 @@ background-color: var(--bg); border-radius: 5px; padding: 0 1rem; overflow-y: hidden; transition: max-height 0.3s ease; &[data-callout="note"] { --color: #448aff; @@ -71,8 +73,20 @@ display: flex; align-items: center; gap: 5px; margin: 1rem 0; padding: 1rem 0; margin-bottom: -1rem; color: var(--color); & .fold { margin-left: 0.5rem; transition: transform 0.3s ease; opacity: 0.8; cursor: pointer; } &.is-collapsed .fold { transform: rotateZ(-90deg) } } .callout-icon {