collapsible toc
This commit is contained in:
		
							
								
								
									
										2
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -5,7 +5,7 @@ declare module '*.scss' {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// dom custom event
 | 
					// dom custom event
 | 
				
			||||||
interface CustomEventMap {
 | 
					interface CustomEventMap {
 | 
				
			||||||
  "spa_nav": CustomEvent<{ url: string }>;
 | 
					  "nav": CustomEvent<{ url: string }>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
declare global {
 | 
					declare global {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,9 +4,9 @@ import clipboardStyle from './styles/clipboard.scss'
 | 
				
			|||||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
					import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Body({ children }: QuartzComponentProps) {
 | 
					function Body({ children }: QuartzComponentProps) {
 | 
				
			||||||
  return <article>
 | 
					  return <div id="quartz-body">
 | 
				
			||||||
    {children}
 | 
					    {children}
 | 
				
			||||||
  </article>
 | 
					  </div>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Body.afterDOMLoaded = clipboardScript
 | 
					Body.afterDOMLoaded = clipboardScript
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import { toJsxRuntime } from "hast-util-to-jsx-runtime"
 | 
				
			|||||||
function Content({ tree }: QuartzComponentProps) {
 | 
					function Content({ tree }: QuartzComponentProps) {
 | 
				
			||||||
  // @ts-ignore (preact makes it angry)
 | 
					  // @ts-ignore (preact makes it angry)
 | 
				
			||||||
  const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: 'html' })
 | 
					  const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: 'html' })
 | 
				
			||||||
  return content
 | 
					  return <article>{content}</article>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default (() => Content) satisfies QuartzComponentConstructor
 | 
					export default (() => Content) satisfies QuartzComponentConstructor
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,9 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 | 
				
			|||||||
import legacyStyle from "./styles/legacyToc.scss"
 | 
					import legacyStyle from "./styles/legacyToc.scss"
 | 
				
			||||||
import modernStyle from "./styles/toc.scss"
 | 
					import modernStyle from "./styles/toc.scss"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// @ts-ignore
 | 
				
			||||||
 | 
					import script from "./scripts/toc.inline"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Options {
 | 
					interface Options {
 | 
				
			||||||
  layout: 'modern' | 'legacy'
 | 
					  layout: 'modern' | 'legacy'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -10,56 +13,49 @@ const defaultOptions: Options = {
 | 
				
			|||||||
  layout: 'modern'
 | 
					  layout: 'modern'
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default ((opts?: Partial<Options>) => {
 | 
					function TableOfContents({ fileData }: QuartzComponentProps) {
 | 
				
			||||||
  const layout = opts?.layout ?? defaultOptions.layout
 | 
					 | 
				
			||||||
  function TableOfContents({ fileData }: QuartzComponentProps) {
 | 
					 | 
				
			||||||
  if (!fileData.toc) {
 | 
					  if (!fileData.toc) {
 | 
				
			||||||
    return null
 | 
					    return null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return <details class="toc" open>
 | 
					  return <>
 | 
				
			||||||
      <summary><h3>Table of Contents</h3></summary>
 | 
					    <button type="button" id="toc">
 | 
				
			||||||
 | 
					      <h3>Table of Contents</h3>
 | 
				
			||||||
 | 
					      <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>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <div id="toc-content">
 | 
				
			||||||
 | 
					      <ul>
 | 
				
			||||||
 | 
					        {fileData.toc.map(tocEntry => <li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
 | 
				
			||||||
 | 
					          <a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>{tocEntry.text}</a>
 | 
				
			||||||
 | 
					        </li>)}
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					TableOfContents.css = modernStyle
 | 
				
			||||||
 | 
					TableOfContents.afterDOMLoaded = script
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function LegacyTableOfContents({ fileData }: QuartzComponentProps) {
 | 
				
			||||||
 | 
					  if (!fileData.toc) {
 | 
				
			||||||
 | 
					    return null
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return <details id="toc" open>
 | 
				
			||||||
 | 
					    <summary>
 | 
				
			||||||
 | 
					      <h3>Table of Contents</h3>
 | 
				
			||||||
 | 
					    </summary>
 | 
				
			||||||
    <ul>
 | 
					    <ul>
 | 
				
			||||||
      {fileData.toc.map(tocEntry => <li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
 | 
					      {fileData.toc.map(tocEntry => <li key={tocEntry.slug} class={`depth-${tocEntry.depth}`}>
 | 
				
			||||||
        <a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>{tocEntry.text}</a>
 | 
					        <a href={`#${tocEntry.slug}`} data-for={tocEntry.slug}>{tocEntry.text}</a>
 | 
				
			||||||
      </li>)}
 | 
					      </li>)}
 | 
				
			||||||
    </ul>
 | 
					    </ul>
 | 
				
			||||||
  </details>
 | 
					  </details>
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  TableOfContents.css = layout === "modern" ? modernStyle : legacyStyle
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (layout === "modern") {
 | 
					 | 
				
			||||||
    TableOfContents.afterDOMLoaded = `
 | 
					 | 
				
			||||||
const bufferPx = 150
 | 
					 | 
				
			||||||
const observer = new IntersectionObserver(entries => {
 | 
					 | 
				
			||||||
  for (const entry of entries) {
 | 
					 | 
				
			||||||
    const slug = entry.target.id
 | 
					 | 
				
			||||||
    const tocEntryElement = document.querySelector(\`a[data-for="$\{slug\}"]\`)
 | 
					 | 
				
			||||||
    const windowHeight = entry.rootBounds?.height
 | 
					 | 
				
			||||||
    if (windowHeight && tocEntryElement) {
 | 
					 | 
				
			||||||
      if (entry.boundingClientRect.y < windowHeight) {
 | 
					 | 
				
			||||||
        tocEntryElement.classList.add("in-view")
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        tocEntryElement.classList.remove("in-view")
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function init() {
 | 
					 | 
				
			||||||
  const headers = document.querySelectorAll("h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]")
 | 
					 | 
				
			||||||
  headers.forEach(header => observer.observe(header))
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					LegacyTableOfContents.css = legacyStyle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
init()
 | 
					export default ((opts?: Partial<Options>) => {
 | 
				
			||||||
 | 
					  const layout = opts?.layout ?? defaultOptions.layout
 | 
				
			||||||
document.addEventListener("spa_nav", (e) => {
 | 
					  return layout === "modern" ? TableOfContents : LegacyTableOfContents
 | 
				
			||||||
  observer.disconnect()
 | 
					 | 
				
			||||||
  init()
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return TableOfContents
 | 
					 | 
				
			||||||
}) satisfies QuartzComponentConstructor
 | 
					}) satisfies QuartzComponentConstructor
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,9 @@ const svgCopy =
 | 
				
			|||||||
const svgCheck =
 | 
					const svgCheck =
 | 
				
			||||||
  '<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true"><path fill-rule="evenodd" fill="rgb(63, 185, 80)" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path></svg>'
 | 
					  '<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true"><path fill-rule="evenodd" fill="rgb(63, 185, 80)" d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"></path></svg>'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const els = document.getElementsByTagName("pre")
 | 
					document.addEventListener("nav", () => {
 | 
				
			||||||
for (let i = 0; i < els.length; i++) {
 | 
					  const els = document.getElementsByTagName("pre")
 | 
				
			||||||
 | 
					  for (let i = 0; i < els.length; i++) {
 | 
				
			||||||
    const codeBlock = els[i].getElementsByTagName("code")[0]
 | 
					    const codeBlock = els[i].getElementsByTagName("code")[0]
 | 
				
			||||||
    const source = codeBlock.innerText.replace(/\n\n/g, "\n")
 | 
					    const source = codeBlock.innerText.replace(/\n\n/g, "\n")
 | 
				
			||||||
    const button = document.createElement("button")
 | 
					    const button = document.createElement("button")
 | 
				
			||||||
@@ -26,4 +27,5 @@ for (let i = 0; i < els.length; i++) {
 | 
				
			|||||||
      )
 | 
					      )
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    els[i].prepend(button)
 | 
					    els[i].prepend(button)
 | 
				
			||||||
}
 | 
					  }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,7 @@ const getOpts = ({ target }: Event): { url: URL, scroll?: boolean } | undefined
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function notifyNav(slug: string) {
 | 
					function notifyNav(slug: string) {
 | 
				
			||||||
  const event = new CustomEvent("spa_nav", { detail: { slug } })
 | 
					  const event = new CustomEvent("nav", { detail: { slug } })
 | 
				
			||||||
  document.dispatchEvent(event)
 | 
					  document.dispatchEvent(event)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,6 +96,7 @@ function createRouter() {
 | 
				
			|||||||
      return
 | 
					      return
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return new class Router {
 | 
					  return new class Router {
 | 
				
			||||||
    go(pathname: string) {
 | 
					    go(pathname: string) {
 | 
				
			||||||
      const url = new URL(pathname, window.location.toString())
 | 
					      const url = new URL(pathname, window.location.toString())
 | 
				
			||||||
@@ -113,6 +114,7 @@ function createRouter() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
createRouter()
 | 
					createRouter()
 | 
				
			||||||
 | 
					notifyNav(document.body.dataset.slug!)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!customElements.get('route-announcer')) {
 | 
					if (!customElements.get('route-announcer')) {
 | 
				
			||||||
  const attrs = {
 | 
					  const attrs = {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										35
									
								
								quartz/components/scripts/toc.inline.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								quartz/components/scripts/toc.inline.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					const bufferPx = 150
 | 
				
			||||||
 | 
					const observer = new IntersectionObserver(entries => {
 | 
				
			||||||
 | 
					  for (const entry of entries) {
 | 
				
			||||||
 | 
					    const slug = entry.target.id
 | 
				
			||||||
 | 
					    const tocEntryElement = document.querySelector(`a[data-for="${slug}"]`)
 | 
				
			||||||
 | 
					    const windowHeight = entry.rootBounds?.height
 | 
				
			||||||
 | 
					    if (windowHeight && tocEntryElement) {
 | 
				
			||||||
 | 
					      if (entry.boundingClientRect.y < windowHeight) {
 | 
				
			||||||
 | 
					        tocEntryElement.classList.add("in-view")
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        tocEntryElement.classList.remove("in-view")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toggleCollapsible(this: HTMLElement) {
 | 
				
			||||||
 | 
					  this.classList.toggle("collapsed")
 | 
				
			||||||
 | 
					  const content = this.nextElementSibling as HTMLElement
 | 
				
			||||||
 | 
					  content.classList.toggle("collapsed")
 | 
				
			||||||
 | 
					  content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					document.addEventListener("nav", () => {
 | 
				
			||||||
 | 
					  const toc = document.getElementById("toc")!
 | 
				
			||||||
 | 
					  const content = toc.nextElementSibling as HTMLElement
 | 
				
			||||||
 | 
					  content.style.maxHeight = content.scrollHeight + "px"
 | 
				
			||||||
 | 
					  toc.removeEventListener("click", toggleCollapsible)
 | 
				
			||||||
 | 
					  toc.addEventListener("click", toggleCollapsible)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // update toc entry highlighting
 | 
				
			||||||
 | 
					  observer.disconnect()
 | 
				
			||||||
 | 
					  const headers = document.querySelectorAll("h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]")
 | 
				
			||||||
 | 
					  headers.forEach(header => observer.observe(header))
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
details.toc {
 | 
					details#toc {
 | 
				
			||||||
  & summary {
 | 
					  & summary {
 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,21 +1,35 @@
 | 
				
			|||||||
details.toc {
 | 
					button#toc {
 | 
				
			||||||
  & summary {
 | 
					  background-color: transparent;
 | 
				
			||||||
 | 
					  border: none;
 | 
				
			||||||
 | 
					  text-align: left;
 | 
				
			||||||
  cursor: pointer;
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  color: var(--dark);
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    list-style: none;
 | 
					  & h3 {
 | 
				
			||||||
    &::marker, &::-webkit-details-marker {
 | 
					    font-size: 1rem;
 | 
				
			||||||
      display: none;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    & > * {
 | 
					 | 
				
			||||||
    display: inline-block;
 | 
					    display: inline-block;
 | 
				
			||||||
    margin: 0;
 | 
					    margin: 0;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    & > h3 {
 | 
					  & .fold {
 | 
				
			||||||
      font-size: 1rem;
 | 
					    margin-left: 0.5rem; 
 | 
				
			||||||
 | 
					    transition: transform 0.3s ease;
 | 
				
			||||||
 | 
					    opacity: 0.8;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.collapsed .fold {
 | 
				
			||||||
 | 
					    transform: rotateZ(-90deg)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					#toc-content {
 | 
				
			||||||
 | 
					  list-style: none;
 | 
				
			||||||
 | 
					  overflow: hidden;
 | 
				
			||||||
 | 
					  max-height: none;
 | 
				
			||||||
 | 
					  transition: max-height 0.3s ease;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  & ul {
 | 
					  & ul {
 | 
				
			||||||
    list-style: none;
 | 
					    list-style: none;
 | 
				
			||||||
@@ -37,3 +51,4 @@ details.toc {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => {
 | 
				
			|||||||
  return {
 | 
					  return {
 | 
				
			||||||
    name: "ContentPage",
 | 
					    name: "ContentPage",
 | 
				
			||||||
    getQuartzComponents() {
 | 
					    getQuartzComponents() {
 | 
				
			||||||
      return [opts.head, Header, ...opts.header, ...opts.body]
 | 
					      return [opts.head, Header, Body, ...opts.header, ...opts.body, ...opts.left, ...opts.right, ...opts.footer]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    async emit(_contentDir, cfg, content, resources, emit): Promise<string[]> {
 | 
					    async emit(_contentDir, cfg, content, resources, emit): Promise<string[]> {
 | 
				
			||||||
      const fps: string[] = []
 | 
					      const fps: string[] = []
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,10 +33,6 @@ export function emitComponentResources(cfg: GlobalConfiguration, resources: Stat
 | 
				
			|||||||
    afterDOMLoaded: []
 | 
					    afterDOMLoaded: []
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (cfg.enableSPA) {
 | 
					 | 
				
			||||||
    componentResources.afterDOMLoaded.push(spaRouterScript)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (const component of allComponents) {
 | 
					  for (const component of allComponents) {
 | 
				
			||||||
    const { css, beforeDOMLoaded, afterDOMLoaded } = component
 | 
					    const { css, beforeDOMLoaded, afterDOMLoaded } = component
 | 
				
			||||||
    if (css) {
 | 
					    if (css) {
 | 
				
			||||||
@@ -50,6 +46,15 @@ export function emitComponentResources(cfg: GlobalConfiguration, resources: Stat
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (cfg.enableSPA) {
 | 
				
			||||||
 | 
					    componentResources.afterDOMLoaded.push(spaRouterScript)
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    componentResources.afterDOMLoaded.push(`
 | 
				
			||||||
 | 
					      const event = new CustomEvent("nav", { detail: { slug: document.body.dataset.slug } })
 | 
				
			||||||
 | 
					      document.dispatchEvent(event)`
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  emit({
 | 
					  emit({
 | 
				
			||||||
    slug: "index",
 | 
					    slug: "index",
 | 
				
			||||||
    ext: ".css",
 | 
					    ext: ".css",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,8 @@ export const Katex: QuartzTransformerPlugin = () => ({
 | 
				
			|||||||
      }]
 | 
					      }]
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  externalResources: {
 | 
					  externalResources() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
      css: [
 | 
					      css: [
 | 
				
			||||||
        // base css
 | 
					        // base css
 | 
				
			||||||
        "https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css",
 | 
					        "https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css",
 | 
				
			||||||
@@ -28,4 +29,5 @@ export const Katex: QuartzTransformerPlugin = () => ({
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ import { slugify } from "../../path"
 | 
				
			|||||||
import rehypeRaw from "rehype-raw"
 | 
					import rehypeRaw from "rehype-raw"
 | 
				
			||||||
import { visit } from "unist-util-visit"
 | 
					import { visit } from "unist-util-visit"
 | 
				
			||||||
import path from "path"
 | 
					import path from "path"
 | 
				
			||||||
 | 
					import { JSResource } from "../../resources"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface Options {
 | 
					export interface Options {
 | 
				
			||||||
  highlight: boolean
 | 
					  highlight: boolean
 | 
				
			||||||
@@ -235,6 +236,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
 | 
				
			|||||||
                node.children.splice(0, 1, ...blockquoteContent)
 | 
					                node.children.splice(0, 1, ...blockquoteContent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // add properties to base blockquote
 | 
					                // add properties to base blockquote
 | 
				
			||||||
 | 
					                // TODO: add the js to actually support collapsing callout
 | 
				
			||||||
                node.data = {
 | 
					                node.data = {
 | 
				
			||||||
                  hProperties: {
 | 
					                  hProperties: {
 | 
				
			||||||
                    ...(node.data?.hProperties ?? {}),
 | 
					                    ...(node.data?.hProperties ?? {}),
 | 
				
			||||||
@@ -270,16 +272,19 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
 | 
				
			|||||||
    htmlPlugins() {
 | 
					    htmlPlugins() {
 | 
				
			||||||
      return [rehypeRaw]
 | 
					      return [rehypeRaw]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    externalResources: {
 | 
					    externalResources() {
 | 
				
			||||||
      js: [{
 | 
					      const mermaidScript: JSResource = {
 | 
				
			||||||
        script: `
 | 
					        script: `
 | 
				
			||||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
 | 
					          import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
 | 
				
			||||||
mermaid.initialize({ startOnLoad: true });
 | 
					          mermaid.initialize({ startOnLoad: true });
 | 
				
			||||||
          `,
 | 
					          `,
 | 
				
			||||||
        loadTime: 'afterDOMReady',
 | 
					        loadTime: 'afterDOMReady',
 | 
				
			||||||
        moduleType: 'module',
 | 
					        moduleType: 'module',
 | 
				
			||||||
        contentType: 'inline'
 | 
					        contentType: 'inline'
 | 
				
			||||||
      }]
 | 
					      }
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        js: opts.mermaid ? [mermaidScript] : []
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ export type QuartzTransformerPluginInstance = {
 | 
				
			|||||||
  name: string
 | 
					  name: string
 | 
				
			||||||
  markdownPlugins(): PluggableList
 | 
					  markdownPlugins(): PluggableList
 | 
				
			||||||
  htmlPlugins(): PluggableList
 | 
					  htmlPlugins(): PluggableList
 | 
				
			||||||
  externalResources?: Partial<StaticResources>
 | 
					  externalResources?(): Partial<StaticResources>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type QuartzFilterPlugin<Options extends OptionType = undefined> = (opts?: Options) => QuartzFilterPluginInstance 
 | 
					export type QuartzFilterPlugin<Options extends OptionType = undefined> = (opts?: Options) => QuartzFilterPluginInstance 
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user