diff --git a/quartz/components/ArticleTitle.tsx b/quartz/components/ArticleTitle.tsx index a52b2a4..2484c94 100644 --- a/quartz/components/ArticleTitle.tsx +++ b/quartz/components/ArticleTitle.tsx @@ -1,9 +1,10 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" +import { classNames } from "../util/lang" function ArticleTitle({ fileData, displayClass }: QuartzComponentProps) { const title = fileData.frontmatter?.title if (title) { - return <h1 class={`article-title ${displayClass ?? ""}`}>{title}</h1> + return <h1 class={classNames(displayClass, "article-title")}>{title}</h1> } else { return null } diff --git a/quartz/components/Backlinks.tsx b/quartz/components/Backlinks.tsx index c4172ce..d5bdc0b 100644 --- a/quartz/components/Backlinks.tsx +++ b/quartz/components/Backlinks.tsx @@ -1,12 +1,13 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/backlinks.scss" import { resolveRelative, simplifySlug } from "../util/path" +import { classNames } from "../util/lang" function Backlinks({ fileData, allFiles, displayClass }: QuartzComponentProps) { const slug = simplifySlug(fileData.slug!) const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug)) return ( - <div class={`backlinks ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "backlinks")}> <h3>Backlinks</h3> <ul class="overflow"> {backlinkFiles.length > 0 ? ( diff --git a/quartz/components/Breadcrumbs.tsx b/quartz/components/Breadcrumbs.tsx index 182d9d6..3875f5e 100644 --- a/quartz/components/Breadcrumbs.tsx +++ b/quartz/components/Breadcrumbs.tsx @@ -2,6 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import breadcrumbsStyle from "./styles/breadcrumbs.scss" import { FullSlug, SimpleSlug, resolveRelative } from "../util/path" import { QuartzPluginData } from "../plugins/vfile" +import { classNames } from "../util/lang" type CrumbData = { displayName: string @@ -113,7 +114,7 @@ export default ((opts?: Partial<BreadcrumbOptions>) => { } return ( - <nav class={`breadcrumb-container ${displayClass ?? ""}`} aria-label="breadcrumbs"> + <nav class={classNames(displayClass, "breadcrumb-container")} aria-label="breadcrumbs"> {crumbs.map((crumb, index) => ( <div class="breadcrumb-element"> <a href={crumb.path}>{crumb.displayName}</a> diff --git a/quartz/components/ContentMeta.tsx b/quartz/components/ContentMeta.tsx index 5337fee..6cd083e 100644 --- a/quartz/components/ContentMeta.tsx +++ b/quartz/components/ContentMeta.tsx @@ -1,6 +1,7 @@ import { formatDate, getDate } from "./Date" import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import readingTime from "reading-time" +import { classNames } from "../util/lang" interface ContentMetaOptions { /** @@ -33,7 +34,7 @@ export default ((opts?: Partial<ContentMetaOptions>) => { segments.push(timeTaken) } - return <p class={`content-meta ${displayClass ?? ""}`}>{segments.join(", ")}</p> + return <p class={classNames(displayClass, "content-meta")}>{segments.join(", ")}</p> } else { return null } diff --git a/quartz/components/Darkmode.tsx b/quartz/components/Darkmode.tsx index f1a7d08..6d10bb9 100644 --- a/quartz/components/Darkmode.tsx +++ b/quartz/components/Darkmode.tsx @@ -4,10 +4,11 @@ import darkmodeScript from "./scripts/darkmode.inline" import styles from "./styles/darkmode.scss" import { QuartzComponentConstructor, QuartzComponentProps } from "./types" +import { classNames } from "../util/lang" function Darkmode({ displayClass }: QuartzComponentProps) { return ( - <div class={`darkmode ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "darkmode")}> <input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex={-1} /> <label id="toggle-label-light" for="darkmode-toggle" tabIndex={-1}> <svg diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index fdfff23..e964c5a 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -5,6 +5,7 @@ import explorerStyle from "./styles/explorer.scss" import script from "./scripts/explorer.inline" import { ExplorerNode, FileNode, Options } from "./ExplorerNode" import { QuartzPluginData } from "../plugins/vfile" +import { classNames } from "../util/lang" // Options interface defined in `ExplorerNode` to avoid circular dependency const defaultOptions = { @@ -77,7 +78,7 @@ export default ((userOpts?: Partial<Options>) => { function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) { constructFileTree(allFiles) return ( - <div class={`explorer ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "explorer")}> <button type="button" id="explorer" diff --git a/quartz/components/Graph.tsx b/quartz/components/Graph.tsx index 0c2647f..756a46b 100644 --- a/quartz/components/Graph.tsx +++ b/quartz/components/Graph.tsx @@ -2,6 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" // @ts-ignore import script from "./scripts/graph.inline" import style from "./styles/graph.scss" +import { classNames } from "../util/lang" export interface D3Config { drag: boolean @@ -56,7 +57,7 @@ export default ((opts?: GraphOptions) => { const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph } const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph } return ( - <div class={`graph ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "graph")}> <h3>Graph View</h3> <div class="graph-outer"> <div id="graph-container" data-cfg={JSON.stringify(localGraph)}></div> diff --git a/quartz/components/PageTitle.tsx b/quartz/components/PageTitle.tsx index 81d80d1..fb1660a 100644 --- a/quartz/components/PageTitle.tsx +++ b/quartz/components/PageTitle.tsx @@ -1,11 +1,12 @@ import { pathToRoot } from "../util/path" import { QuartzComponentConstructor, QuartzComponentProps } from "./types" +import { classNames } from "../util/lang" function PageTitle({ fileData, cfg, displayClass }: QuartzComponentProps) { const title = cfg?.pageTitle ?? "Untitled Quartz" const baseDir = pathToRoot(fileData.slug!) return ( - <h1 class={`page-title ${displayClass ?? ""}`}> + <h1 class={classNames(displayClass, "page-title")}> <a href={baseDir}>{title}</a> </h1> ) diff --git a/quartz/components/RecentNotes.tsx b/quartz/components/RecentNotes.tsx index 9a53ad7..81b354d 100644 --- a/quartz/components/RecentNotes.tsx +++ b/quartz/components/RecentNotes.tsx @@ -5,6 +5,7 @@ import { byDateAndAlphabetical } from "./PageList" import style from "./styles/recentNotes.scss" import { Date, getDate } from "./Date" import { GlobalConfiguration } from "../cfg" +import { classNames } from "../util/lang" interface Options { title: string @@ -28,7 +29,7 @@ export default ((userOpts?: Partial<Options>) => { const pages = allFiles.filter(opts.filter).sort(opts.sort) const remaining = Math.max(0, pages.length - opts.limit) return ( - <div class={`recent-notes ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "recent-notes")}> <h3>{opts.title}</h3> <ul class="recent-ul"> {pages.slice(0, opts.limit).map((page) => { diff --git a/quartz/components/Search.tsx b/quartz/components/Search.tsx index 9c1852d..92684ae 100644 --- a/quartz/components/Search.tsx +++ b/quartz/components/Search.tsx @@ -2,11 +2,12 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/search.scss" // @ts-ignore import script from "./scripts/search.inline" +import { classNames } from "../util/lang" export default (() => { function Search({ displayClass }: QuartzComponentProps) { return ( - <div class={`search ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "search")}> <div id="search-icon"> <p>Search</p> <div></div> diff --git a/quartz/components/Spacer.tsx b/quartz/components/Spacer.tsx index 8359111..5288752 100644 --- a/quartz/components/Spacer.tsx +++ b/quartz/components/Spacer.tsx @@ -1,7 +1,8 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" +import { classNames } from "../util/lang" function Spacer({ displayClass }: QuartzComponentProps) { - return <div class={`spacer ${displayClass ?? ""}`}></div> + return <div class={classNames(displayClass, "spacer")}></div> } export default (() => Spacer) satisfies QuartzComponentConstructor diff --git a/quartz/components/TableOfContents.tsx b/quartz/components/TableOfContents.tsx index 1c55f07..167c837 100644 --- a/quartz/components/TableOfContents.tsx +++ b/quartz/components/TableOfContents.tsx @@ -1,6 +1,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types" import legacyStyle from "./styles/legacyToc.scss" import modernStyle from "./styles/toc.scss" +import { classNames } from "../util/lang" // @ts-ignore import script from "./scripts/toc.inline" @@ -19,7 +20,7 @@ function TableOfContents({ fileData, displayClass }: QuartzComponentProps) { } return ( - <div class={`toc ${displayClass ?? ""}`}> + <div class={classNames(displayClass, "toc")}> <button type="button" id="toc" class={fileData.collapseToc ? "collapsed" : ""}> <h3>Table of Contents</h3> <svg diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx index b39b199..e5dd1a3 100644 --- a/quartz/components/TagList.tsx +++ b/quartz/components/TagList.tsx @@ -1,12 +1,13 @@ import { pathToRoot, slugTag } from "../util/path" import { QuartzComponentConstructor, QuartzComponentProps } from "./types" +import { classNames } from "../util/lang" function TagList({ fileData, displayClass }: QuartzComponentProps) { const tags = fileData.frontmatter?.tags const baseDir = pathToRoot(fileData.slug!) if (tags && tags.length > 0) { return ( - <ul class={`tags ${displayClass ?? ""}`}> + <ul class={classNames(displayClass, "tags")}> {tags.map((tag) => { const display = `#${tag}` const linkDest = baseDir + `/tags/${slugTag(tag)}` diff --git a/quartz/util/lang.ts b/quartz/util/lang.ts index 5211b5d..31e8c02 100644 --- a/quartz/util/lang.ts +++ b/quartz/util/lang.ts @@ -9,3 +9,13 @@ export function pluralize(count: number, s: string): string { export function capitalize(s: string): string { return s.substring(0, 1).toUpperCase() + s.substring(1) } + +export function classNames( + displayClass?: "mobile-only" | "desktop-only", + ...classes: string[] +): string { + if (displayClass) { + classes.push(displayClass) + } + return classes.join(" ") +}