3 files added
10 files modified
| | |
| | | import { QuartzConfig } from "./quartz/cfg" |
| | | import * as Head from "./quartz/components/Head" |
| | | import * as Header from "./quartz/components/Header" |
| | | import Head from "./quartz/components/Head" |
| | | import Header from "./quartz/components/Header" |
| | | import { |
| | | ContentPage, |
| | | CreatedModifiedDate, |
| | |
| | | const transpiled = await esbuild.build({ |
| | | stdin: { |
| | | contents: text, |
| | | loader: 'ts', |
| | | sourcefile: path.relative(path.resolve('.'), args.path), |
| | | }, |
| | | write: false, |
| | |
| | | const server = http.createServer(async (req, res) => { |
| | | return serveHandler(req, res, { |
| | | public: output, |
| | | directoryListing: false |
| | | directoryListing: false, |
| | | }) |
| | | }) |
| | | server.listen(argv.port) |
| New file |
| | |
| | | import darkmodeScript from "./scripts/darkmode.inline" |
| | | import styles from '../styles/darkmode.scss' |
| | | |
| | | export default function Darkmode() { |
| | | return <div class="darkmode"> |
| | | <input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex={-1} /> |
| | | <label id="toggle-label-light" for="darkmode-toggle" tabIndex={-1}> |
| | | <svg |
| | | xmlns="http://www.w3.org/2000/svg" |
| | | xmlnsXlink="http://www.w3.org/1999/xlink" |
| | | version="1.1" |
| | | id="dayIcon" |
| | | x="0px" |
| | | y="0px" |
| | | viewBox="0 0 35 35" |
| | | style="enable-background:new 0 0 35 35;" |
| | | xmlSpace="preserve" |
| | | > |
| | | <title>Light mode</title> |
| | | <path |
| | | d="M6,17.5C6,16.672,5.328,16,4.5,16h-3C0.672,16,0,16.672,0,17.5 S0.672,19,1.5,19h3C5.328,19,6,18.328,6,17.5z M7.5,26c-0.414,0-0.789,0.168-1.061,0.439l-2,2C4.168,28.711,4,29.086,4,29.5 C4,30.328,4.671,31,5.5,31c0.414,0,0.789-0.168,1.06-0.44l2-2C8.832,28.289,9,27.914,9,27.5C9,26.672,8.329,26,7.5,26z M17.5,6 C18.329,6,19,5.328,19,4.5v-3C19,0.672,18.329,0,17.5,0S16,0.672,16,1.5v3C16,5.328,16.671,6,17.5,6z M27.5,9 c0.414,0,0.789-0.168,1.06-0.439l2-2C30.832,6.289,31,5.914,31,5.5C31,4.672,30.329,4,29.5,4c-0.414,0-0.789,0.168-1.061,0.44 l-2,2C26.168,6.711,26,7.086,26,7.5C26,8.328,26.671,9,27.5,9z M6.439,8.561C6.711,8.832,7.086,9,7.5,9C8.328,9,9,8.328,9,7.5 c0-0.414-0.168-0.789-0.439-1.061l-2-2C6.289,4.168,5.914,4,5.5,4C4.672,4,4,4.672,4,5.5c0,0.414,0.168,0.789,0.439,1.06 L6.439,8.561z M33.5,16h-3c-0.828,0-1.5,0.672-1.5,1.5s0.672,1.5,1.5,1.5h3c0.828,0,1.5-0.672,1.5-1.5S34.328,16,33.5,16z M28.561,26.439C28.289,26.168,27.914,26,27.5,26c-0.828,0-1.5,0.672-1.5,1.5c0,0.414,0.168,0.789,0.439,1.06l2,2 C28.711,30.832,29.086,31,29.5,31c0.828,0,1.5-0.672,1.5-1.5c0-0.414-0.168-0.789-0.439-1.061L28.561,26.439z M17.5,29 c-0.829,0-1.5,0.672-1.5,1.5v3c0,0.828,0.671,1.5,1.5,1.5s1.5-0.672,1.5-1.5v-3C19,29.672,18.329,29,17.5,29z M17.5,7 C11.71,7,7,11.71,7,17.5S11.71,28,17.5,28S28,23.29,28,17.5S23.29,7,17.5,7z M17.5,25c-4.136,0-7.5-3.364-7.5-7.5 c0-4.136,3.364-7.5,7.5-7.5c4.136,0,7.5,3.364,7.5,7.5C25,21.636,21.636,25,17.5,25z" |
| | | ></path> |
| | | </svg> |
| | | </label> |
| | | <label id="toggle-label-dark" for="darkmode-toggle" tabIndex={-1}> |
| | | <svg |
| | | xmlns="http://www.w3.org/2000/svg" |
| | | xmlnsXlink="http://www.w3.org/1999/xlink" |
| | | version="1.1" |
| | | id="nightIcon" |
| | | x="0px" |
| | | y="0px" |
| | | viewBox="0 0 100 100" |
| | | style="enable-background='new 0 0 100 100'" |
| | | xmlSpace="preserve" |
| | | > |
| | | <title>Dark mode</title> |
| | | <path |
| | | d="M96.76,66.458c-0.853-0.852-2.15-1.064-3.23-0.534c-6.063,2.991-12.858,4.571-19.655,4.571 C62.022,70.495,50.88,65.88,42.5,57.5C29.043,44.043,25.658,23.536,34.076,6.47c0.532-1.08,0.318-2.379-0.534-3.23 c-0.851-0.852-2.15-1.064-3.23-0.534c-4.918,2.427-9.375,5.619-13.246,9.491c-9.447,9.447-14.65,22.008-14.65,35.369 c0,13.36,5.203,25.921,14.65,35.368s22.008,14.65,35.368,14.65c13.361,0,25.921-5.203,35.369-14.65 c3.872-3.871,7.064-8.328,9.491-13.246C97.826,68.608,97.611,67.309,96.76,66.458z" |
| | | ></path> |
| | | </svg> |
| | | </label> |
| | | </div> |
| | | } |
| | | |
| | | Darkmode.beforeDOMLoaded = darkmodeScript |
| | | Darkmode.css = styles |
| | |
| | | externalResources: StaticResources |
| | | } |
| | | |
| | | export function Component({ title, description, slug, externalResources }: HeadProps) { |
| | | export default function Head({ title, description, slug, externalResources }: HeadProps) { |
| | | const { css, js } = externalResources |
| | | const baseDir = resolveToRoot(slug) |
| | | const iconPath = baseDir + "/static/icon.png" |
| | |
| | | import { resolveToRoot } from "../path" |
| | | import Darkmode from "./Darkmode" |
| | | import style from '../styles/header.scss' |
| | | |
| | | export interface HeaderProps { |
| | | title: string |
| | | slug: string |
| | | } |
| | | |
| | | export function Component({ title, slug }: HeaderProps) { |
| | | export default function Header({ title, slug }: HeaderProps) { |
| | | const baseDir = resolveToRoot(slug) |
| | | return <header> |
| | | <h1><a href={baseDir}>{title}</a></h1> |
| | | <div class="spacer"></div> |
| | | <Darkmode /> |
| | | </header> |
| | | } |
| | | |
| | | Header.beforeDOMLoaded = Darkmode.beforeDOMLoaded |
| | | Header.css = style + Darkmode.css |
| | |
| | | export default "Darkmode" |
| | | export default "Darkmode" |
| | | |
| | | console.log("HELLOOOO FROM CONSOLE") |
| | | const currentTheme = localStorage.getItem("theme") |
| | | const theme = |
| | | currentTheme ?? |
| | | (window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark") |
| | | |
| | | document.documentElement.setAttribute("saved-theme", theme) |
| | | |
| | | window.addEventListener("DOMContentLoaded", () => { |
| | | const toggleSwitch = document.querySelector("#darkmode-toggle") as HTMLInputElement |
| | | toggleSwitch.addEventListener("change", (e: any) => { |
| | | if (e.target.checked) { |
| | | document.documentElement.setAttribute("saved-theme", "dark") |
| | | localStorage.setItem("theme", "dark") |
| | | } else { |
| | | document.documentElement.setAttribute("saved-theme", "light") |
| | | localStorage.setItem("theme", "light") |
| | | } |
| | | }) |
| | | |
| | | if (theme === "dark") { |
| | | toggleSwitch.checked = true |
| | | } |
| | | }) |
| | |
| | | import { ComponentType } from "preact" |
| | | |
| | | export type QuartzComponent<Props> = { |
| | | Component: ComponentType<Props> |
| | | export type QuartzComponent<Props> = ComponentType<Props> & { |
| | | css?: string, |
| | | beforeDOMLoaded?: string, |
| | | afterDOMLoaded?: string, |
| | |
| | | |
| | | const title = file.data.frontmatter?.title |
| | | const doc = <html> |
| | | <Head.Component |
| | | <Head |
| | | title={title ?? "Untitled"} |
| | | description={file.data.description ?? "No description provided"} |
| | | slug={file.data.slug!} |
| | | externalResources={pageResources} /> |
| | | <body> |
| | | <div id="quartz-root" class="page"> |
| | | <Header.Component title={cfg.siteTitle} slug={file.data.slug!} /> |
| | | <Header title={cfg.siteTitle} slug={file.data.slug!} /> |
| | | <article> |
| | | {file.data.slug !== "index" && <h1>{title}</h1>} |
| | | {content} |
| | |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | p, ul, text, a, tr, td, li, ol, ul { |
| | | p, ul, text, a, tr, td, li, ol, ul, .katex { |
| | | color: var(--darkgray); |
| | | fill: var(--darkgray); |
| | | } |
| | |
| | | } |
| | | |
| | | blockquote { |
| | | margin-left: 0; |
| | | margin: 1rem 0; |
| | | border-left: 3px solid var(--secondary); |
| | | padding-left: 1rem; |
| | | transition: border-color 0.2s ease; |
| | |
| | | & > code { |
| | | background: none; |
| | | padding: 0; |
| | | font-size: 0.9rem; |
| | | font-size: 0.85rem; |
| | | counter-reset: line; |
| | | counter-increment: line 0; |
| | | display: grid; |
| | |
| | | border: 1px solid var(--border); |
| | | background-color: var(--bg); |
| | | border-radius: 5px; |
| | | padding: 0 0.7rem; |
| | | padding: 0 1rem; |
| | | |
| | | &[data-callout="note"] { |
| | | --color: #448aff; |
| New file |
| | |
| | | .darkmode { |
| | | float: right; |
| | | padding: 1rem; |
| | | min-width: 30px; |
| | | position: relative; |
| | | |
| | | @media all and (max-width: 450px) { |
| | | padding: 1rem; |
| | | } |
| | | |
| | | & > .toggle { |
| | | display: none; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | & svg { |
| | | cursor: pointer; |
| | | opacity: 0; |
| | | position: absolute; |
| | | width: 20px; |
| | | height: 20px; |
| | | top: calc(50% - 10px); |
| | | margin: 0 7px; |
| | | fill: var(--darkgray); |
| | | transition: opacity 0.1s ease; |
| | | } |
| | | } |
| | | |
| | | :root[saved-theme="dark"] .toggle ~ label { |
| | | & > #dayIcon { |
| | | opacity: 0; |
| | | } |
| | | & > #nightIcon { |
| | | opacity: 1; |
| | | } |
| | | } |
| | | |
| | | :root .toggle ~ label { |
| | | & > #dayIcon { |
| | | opacity: 1; |
| | | } |
| | | & > #nightIcon { |
| | | opacity: 0; |
| | | } |
| | | } |
| New file |
| | |
| | | header { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | margin: 1em 0 2em 0; |
| | | & > h1 { |
| | | margin: 0; |
| | | flex: auto; |
| | | } |
| | | } |