Jacky Zhao
2023-06-17 cb89cce183215f6a8edcb6d166875e2982586002
basic left,right layout
9 files modified
106 ■■■■■ changed files
quartz.config.ts 11 ●●●● patch | view | raw | blame | history
quartz/components/TagList.tsx 2 ●●● patch | view | raw | blame | history
quartz/components/scripts/callout.inline.ts 26 ●●●● patch | view | raw | blame | history
quartz/components/scripts/toc.inline.ts 13 ●●●●● patch | view | raw | blame | history
quartz/components/styles/darkmode.scss 4 ●●●● patch | view | raw | blame | history
quartz/plugins/emitters/contentPage.tsx 20 ●●●● patch | view | raw | blame | history
quartz/plugins/transformers/ofm.ts 2 ●●●●● patch | view | raw | blame | history
quartz/styles/base.scss 23 ●●●●● patch | view | raw | blame | history
quartz/styles/callouts.scss 5 ●●●● patch | view | raw | blame | history
quartz.config.ts
@@ -59,15 +59,16 @@
      Plugin.ContentPage({
        head: Component.Head(),
        header: [Component.PageTitle(), Component.Spacer(), Component.Darkmode()],
        body: [
        beforeBody: [
          Component.ArticleTitle(),
          Component.ReadingTime(),
          Component.TagList(),
          Component.TableOfContents(),
          Component.Content()
        ],
        left: [],
        right: [],
        left: [
          Component.TableOfContents(),
        ],
        right: [
        ],
        footer: []
      }),
      Plugin.ContentIndex(), // you can exclude this if you don't plan on using popovers, graph, or backlinks,
quartz/components/TagList.tsx
@@ -6,7 +6,7 @@
  const tags = fileData.frontmatter?.tags
  const slug = fileData.slug!
  const baseDir = resolveToRoot(slug)
  if (tags) {
  if (tags && tags.length > 0) {
    return <ul class="tags">{tags.map(tag => {
      const display = `#${tag}`
      const linkDest = baseDir + `/tags/${slugAnchor(tag)}`
quartz/components/scripts/callout.inline.ts
@@ -6,19 +6,21 @@
  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`, () => {
function setupCallout() {
  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)
    if (title) {
      title.removeEventListener(`click`, toggleCallout)
      title.addEventListener(`click`, toggleCallout)
      const collapsed = div.classList.contains(`is-collapsed`)
      const height = collapsed ? title.scrollHeight : div.scrollHeight
      div.style.maxHeight = height + `px`
    }
  }
})
}
document.addEventListener(`nav`, setupCallout)
window.addEventListener(`resize`, setupCallout)
quartz/components/scripts/toc.inline.ts
@@ -14,19 +14,24 @@
  }
})
function toggleCollapsible(this: HTMLElement) {
function toggleToc(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", () => {
function setupToc() {
  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)
  toc.removeEventListener("click", toggleToc)
  toc.addEventListener("click", toggleToc)
}
window.addEventListener("resize", setupToc)
document.addEventListener("nav", () => {
  setupToc()
  // update toc entry highlighting
  observer.disconnect()
quartz/components/styles/darkmode.scss
@@ -4,10 +4,6 @@
  min-width: 30px;
  position: relative;
  @media all and (max-width: 450px) {
    padding: 1rem;
  }
  & > .toggle {
    display: none;
    box-sizing: border-box;
quartz/plugins/emitters/contentPage.tsx
@@ -6,11 +6,12 @@
import HeaderConstructor from "../../components/Header"
import { QuartzComponentProps } from "../../components/types"
import BodyConstructor from "../../components/Body"
import ContentConstructor from "../../components/Content"
interface Options {
  head: QuartzComponent
  header: QuartzComponent[],
  body: QuartzComponent[],
  beforeBody: QuartzComponent[],
  left: QuartzComponent[],
  right: QuartzComponent[],
  footer: QuartzComponent[],
@@ -21,14 +22,15 @@
    throw new Error("ContentPage must be initialized with options specifiying the components to use")
  }
  const { head: Head, header, body } = opts
  const { head: Head, header, beforeBody, left, right, footer } = opts
  const Header = HeaderConstructor()
  const Body = BodyConstructor()
  const Content = ContentConstructor()
  return {
    name: "ContentPage",
    getQuartzComponents() {
      return [opts.head, Header, Body, ...opts.header, ...opts.body, ...opts.left, ...opts.right, ...opts.footer]
      return [opts.head, Header, Body, ...opts.header, ...opts.beforeBody, ...opts.left, ...opts.right, ...opts.footer]
    },
    async emit(_contentDir, cfg, content, resources, emit): Promise<string[]> {
      const fps: string[] = []
@@ -59,9 +61,19 @@
              <Header {...componentData} >
                {header.map(HeaderComponent => <HeaderComponent {...componentData} />)}
              </Header>
              {beforeBody.map(BodyComponent => <BodyComponent {...componentData} />)}
              <Body {...componentData}>
                {body.map(BodyComponent => <BodyComponent {...componentData} />)}
                <div class="left">
                  {left.map(BodyComponent => <BodyComponent {...componentData} />)}
                </div>
                <div class="center">
                  <Content {...componentData} />
                </div>
                <div class="right">
                  {right.map(BodyComponent => <BodyComponent {...componentData} />)}
                </div>
              </Body>
            </div>
          </body>
          {pageResources.js.filter(resource => resource.loadTime === "afterDOMReady").map(res => JSResourceToScriptElement(res))}
quartz/plugins/transformers/ofm.ts
@@ -300,8 +300,6 @@
        })
      }
      console.log(js)
      return { js }
    }
  }
quartz/styles/base.scss
@@ -51,8 +51,31 @@
  padding: 4rem 30vw;
  margin: 0 auto;
  max-width: 1000px;
  position: relative;
  & .left, & .right {
    position: fixed;
    padding: 0 4rem 0 6rem;
    max-width: 30vw;
    box-sizing: border-box;
    top: 10rem;
  }
  & .left {
    left: 0;
  }
  & .right {
    right: 0;
  }
  @media all and (max-width: 1200px) {
    padding: 25px 5vw;
    & .left, & .right {
      padding: 0;
      max-width: none;
      position: initial;
    }
  }
  & p {
quartz/styles/callouts.scss
@@ -8,6 +8,10 @@
    overflow-y: hidden;
  transition: max-height 0.3s ease;
  & > *:nth-child(2) {
    margin-top: 0;
  }
    &[data-callout="note"] {
      --color: #448aff;
      --border: #448aff22;
@@ -74,7 +78,6 @@
    align-items: center;
    gap: 5px;
    padding: 1rem 0;
    margin-bottom: -1rem;
    color: var(--color);
    & .fold {