chore(i18n): refactor and cleanup ()

* checkpoint

* finish

* docs
This commit is contained in:
Jacky Zhao 2024-02-04 20:57:10 -08:00 committed by GitHub
parent dff4b06313
commit 36e4cc41a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 326 additions and 211 deletions

View file

@ -9,6 +9,7 @@ function ArticleTitle({ fileData, displayClass }: QuartzComponentProps) {
return null
}
}
ArticleTitle.css = `
.article-title {
margin: 2rem 0 0 0;

View file

@ -1,7 +1,7 @@
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
import style from "./styles/backlinks.scss"
import { resolveRelative, simplifySlug } from "../util/path"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
import { classNames } from "../util/lang"
function Backlinks({ fileData, allFiles, displayClass, cfg }: QuartzComponentProps) {
@ -9,7 +9,7 @@ function Backlinks({ fileData, allFiles, displayClass, cfg }: QuartzComponentPro
const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug))
return (
<div class={classNames(displayClass, "backlinks")}>
<h3>{i18n(cfg.locale, "backlinks.backlinks")}</h3>
<h3>{i18n(cfg.locale).components.backlinks.title}</h3>
<ul class="overflow">
{backlinkFiles.length > 0 ? (
backlinkFiles.map((f) => (
@ -20,7 +20,7 @@ function Backlinks({ fileData, allFiles, displayClass, cfg }: QuartzComponentPro
</li>
))
) : (
<li>{i18n(cfg.locale, "backlinks.noBacklinksFound")}</li>
<li>{i18n(cfg.locale).components.backlinks.noBacklinksFound}</li>
)}
</ul>
</div>

View file

@ -4,7 +4,7 @@
import darkmodeScript from "./scripts/darkmode.inline"
import styles from "./styles/darkmode.scss"
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
import { classNames } from "../util/lang"
function Darkmode({ displayClass, cfg }: QuartzComponentProps) {
@ -23,7 +23,7 @@ function Darkmode({ displayClass, cfg }: QuartzComponentProps) {
style="enable-background:new 0 0 35 35"
xmlSpace="preserve"
>
<title>{i18n(cfg.locale, "darkmode.lightMode")}</title>
<title>{i18n(cfg.locale).components.themeToggle.darkMode}</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>
@ -39,7 +39,7 @@ function Darkmode({ displayClass, cfg }: QuartzComponentProps) {
style="enable-background:new 0 0 100 100"
xmlSpace="preserve"
>
<title>{i18n(cfg.locale, "darkmode.lightMode")}</title>
<title>{i18n(cfg.locale).components.themeToggle.lightMode}</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>

View file

@ -1,9 +1,10 @@
import { GlobalConfiguration } from "../cfg"
import { ValidLocale } from "../i18n"
import { QuartzPluginData } from "../plugins/vfile"
interface Props {
date: Date
locale?: string
locale?: ValidLocale
}
export type ValidDateType = keyof Required<QuartzPluginData>["dates"]
@ -17,7 +18,7 @@ export function getDate(cfg: GlobalConfiguration, data: QuartzPluginData): Date
return data.dates?.[cfg.defaultDateType]
}
export function formatDate(d: Date, locale = "en-US"): string {
export function formatDate(d: Date, locale: ValidLocale = "en-US"): string {
return d.toLocaleDateString(locale, {
year: "numeric",
month: "short",

View file

@ -6,10 +6,10 @@ import script from "./scripts/explorer.inline"
import { ExplorerNode, FileNode, Options } from "./ExplorerNode"
import { QuartzPluginData } from "../plugins/vfile"
import { classNames } from "../util/lang"
import { i18n } from "../i18n"
// Options interface defined in `ExplorerNode` to avoid circular dependency
const defaultOptions = {
title: "Explorer",
folderClickBehavior: "collapse",
folderDefaultState: "collapsed",
useSavedState: true,
@ -75,7 +75,7 @@ export default ((userOpts?: Partial<Options>) => {
jsonTree = JSON.stringify(folders)
}
function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
function Explorer({ cfg, allFiles, displayClass, fileData }: QuartzComponentProps) {
constructFileTree(allFiles)
return (
<div class={classNames(displayClass, "explorer")}>
@ -87,7 +87,7 @@ export default ((userOpts?: Partial<Options>) => {
data-savestate={opts.useSavedState}
data-tree={jsonTree}
>
<h1>{opts.title}</h1>
<h1>{opts.title ?? i18n(cfg.locale).components.explorer.title}</h1>
<svg
xmlns="http://www.w3.org/2000/svg"
width="14"

View file

@ -12,7 +12,7 @@ import {
type OrderEntries = "sort" | "filter" | "map"
export interface Options {
title: string
title?: string
folderDefaultState: "collapsed" | "open"
folderClickBehavior: "collapse" | "link"
useSavedState: boolean

View file

@ -1,7 +1,7 @@
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
import style from "./styles/footer.scss"
import { version } from "../../package.json"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
interface Options {
links: Record<string, string>
@ -15,8 +15,8 @@ export default ((opts?: Options) => {
<footer class={`${displayClass ?? ""}`}>
<hr />
<p>
{i18n(cfg.locale, "footer.createdWith")}{" "}
<a href="https://quartz.jzhao.xyz/">Quartz v{version}</a>, © {year}
{i18n(cfg.locale).components.footer.createdWith}{" "}
<a href="https://quartz.jzhao.xyz/">Quartz v{version}</a> © {year}
</p>
<ul>
{Object.entries(links).map(([text, link]) => (

View file

@ -2,7 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
// @ts-ignore
import script from "./scripts/graph.inline"
import style from "./styles/graph.scss"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
import { classNames } from "../util/lang"
export interface D3Config {
@ -59,7 +59,7 @@ export default ((opts?: GraphOptions) => {
const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph }
return (
<div class={classNames(displayClass, "graph")}>
<h3>{i18n(cfg.locale, "graph.graphView")}</h3>
<h3>{i18n(cfg.locale).components.graph.title}</h3>
<div class="graph-outer">
<div id="graph-container" data-cfg={JSON.stringify(localGraph)}></div>
<svg

View file

@ -1,13 +1,13 @@
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
import { FullSlug, _stripSlashes, joinSegments, pathToRoot } from "../util/path"
import { JSResourceToScriptElement } from "../util/resources"
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
export default (() => {
function Head({ cfg, fileData, externalResources }: QuartzComponentProps) {
const title = fileData.frontmatter?.title ?? i18n(cfg.locale, "head.untitled")
const title = fileData.frontmatter?.title ?? i18n(cfg.locale).propertyDefaults.title
const description =
fileData.description?.trim() ?? i18n(cfg.locale, "head.noDescriptionProvided")
fileData.description?.trim() ?? i18n(cfg.locale).propertyDefaults.description
const { css, js } = externalResources
const url = new URL(`https://${cfg.baseUrl ?? "example.com"}`)

View file

@ -1,9 +1,10 @@
import { pathToRoot } from "../util/path"
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
import { classNames } from "../util/lang"
import { i18n } from "../i18n"
function PageTitle({ fileData, cfg, displayClass }: QuartzComponentProps) {
const title = cfg?.pageTitle ?? "Untitled Quartz"
const title = cfg?.pageTitle ?? i18n(cfg.locale).propertyDefaults.title
const baseDir = pathToRoot(fileData.slug!)
return (
<h1 class={classNames(displayClass, "page-title")}>

View file

@ -5,11 +5,11 @@ import { byDateAndAlphabetical } from "./PageList"
import style from "./styles/recentNotes.scss"
import { Date, getDate } from "./Date"
import { GlobalConfiguration } from "../cfg"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
import { classNames } from "../util/lang"
interface Options {
title: string
title?: string
limit: number
linkToMore: SimpleSlug | false
filter: (f: QuartzPluginData) => boolean
@ -17,7 +17,6 @@ interface Options {
}
const defaultOptions = (cfg: GlobalConfiguration): Options => ({
title: "Recent Notes",
limit: 3,
linkToMore: false,
filter: () => true,
@ -31,10 +30,10 @@ export default ((userOpts?: Partial<Options>) => {
const remaining = Math.max(0, pages.length - opts.limit)
return (
<div class={classNames(displayClass, "recent-notes")}>
<h3>{opts.title}</h3>
<h3>{opts.title ?? i18n(cfg.locale).components.recentNotes.title}</h3>
<ul class="recent-ul">
{pages.slice(0, opts.limit).map((page) => {
const title = page.frontmatter?.title
const title = page.frontmatter?.title ?? i18n(cfg.locale).propertyDefaults.title
const tags = page.frontmatter?.tags ?? []
return (
@ -72,11 +71,7 @@ export default ((userOpts?: Partial<Options>) => {
{opts.linkToMore && remaining > 0 && (
<p>
<a href={resolveRelative(fileData.slug!, opts.linkToMore)}>
{" "}
{i18n(cfg.locale, "recentNotes.seeRemainingMore", {
remaining: remaining.toString(),
})}{" "}
{i18n(cfg.locale).components.recentNotes.seeRemainingMore({ remaining })}
</a>
</p>
)}

View file

@ -3,7 +3,7 @@ import style from "./styles/search.scss"
// @ts-ignore
import script from "./scripts/search.inline"
import { classNames } from "../util/lang"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
export interface SearchOptions {
enablePreview: boolean
@ -16,11 +16,11 @@ const defaultOptions: SearchOptions = {
export default ((userOpts?: Partial<SearchOptions>) => {
function Search({ displayClass, cfg }: QuartzComponentProps) {
const opts = { ...defaultOptions, ...userOpts }
const searchPlaceholder = i18n(cfg.locale).components.search.searchBarPlaceholder
return (
<div class={classNames(displayClass, "search")}>
<div id="search-icon">
<p>{i18n(cfg.locale, "search")}</p>
<p>{i18n(cfg.locale).components.search.title}</p>
<div></div>
<svg
tabIndex={0}
@ -44,8 +44,8 @@ export default ((userOpts?: Partial<SearchOptions>) => {
id="search-bar"
name="search"
type="text"
aria-label="Search for something"
placeholder="Search for something"
aria-label={searchPlaceholder}
placeholder={searchPlaceholder}
/>
<div id="search-layout" data-preview={opts.enablePreview}></div>
</div>

View file

@ -5,7 +5,7 @@ import { classNames } from "../util/lang"
// @ts-ignore
import script from "./scripts/toc.inline"
import { i18n } from "../i18n/i18next"
import { i18n } from "../i18n"
interface Options {
layout: "modern" | "legacy"
@ -23,7 +23,7 @@ function TableOfContents({ fileData, displayClass, cfg }: QuartzComponentProps)
return (
<div class={classNames(displayClass, "toc")}>
<button type="button" id="toc" class={fileData.collapseToc ? "collapsed" : ""}>
<h3>{i18n(cfg.locale, "tableOfContent")}</h3>
<h3>{i18n(cfg.locale).components.tableOfContents.title}</h3>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
@ -63,7 +63,7 @@ function LegacyTableOfContents({ fileData, cfg }: QuartzComponentProps) {
return (
<details id="toc" open={!fileData.collapseToc}>
<summary>
<h3>{i18n(cfg.locale, "tableOfContent")}</h3>
<h3>{i18n(cfg.locale).components.tableOfContents.title}</h3>
</summary>
<ul>
{fileData.toc.map((tocEntry) => (

View file

@ -1,11 +1,11 @@
import { i18n } from "../../i18n/i18next"
import { i18n } from "../../i18n"
import { QuartzComponentConstructor, QuartzComponentProps } from "../types"
function NotFound({ cfg }: QuartzComponentProps) {
return (
<article class="popover-hint">
<h1>404</h1>
<p>{i18n(cfg.locale, "404")}</p>
<p>{i18n(cfg.locale).pages.error.notFound}</p>
</article>
)
}

View file

@ -5,9 +5,8 @@ import style from "../styles/listPage.scss"
import { PageList } from "../PageList"
import { _stripSlashes, simplifySlug } from "../../util/path"
import { Root } from "hast"
import { pluralize } from "../../util/lang"
import { htmlToJsx } from "../../util/jsx"
import { i18n } from "../../i18n/i18next"
import { i18n } from "../../i18n"
interface FolderContentOptions {
/**
@ -54,8 +53,9 @@ export default ((opts?: Partial<FolderContentOptions>) => {
<div class="page-listing">
{options.showFolderCount && (
<p>
{pluralize(allPagesInFolder.length, i18n(cfg.locale, "common.item"))}{" "}
{i18n(cfg.locale, "folderContent.underThisFolder")}.
{i18n(cfg.locale).pages.folderContent.itemsUnderFolder({
count: allPagesInFolder.length,
})}
</p>
)}
<div>

View file

@ -4,9 +4,8 @@ import { PageList } from "../PageList"
import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path"
import { QuartzPluginData } from "../../plugins/vfile"
import { Root } from "hast"
import { pluralize } from "../../util/lang"
import { htmlToJsx } from "../../util/jsx"
import { i18n } from "../../i18n/i18next"
import { i18n } from "../../i18n"
const numPages = 10
function TagContent(props: QuartzComponentProps) {
@ -44,10 +43,7 @@ function TagContent(props: QuartzComponentProps) {
<article>
<p>{content}</p>
</article>
<p>
{i18n(cfg.locale, "tagContent.found")} {tags.length}{" "}
{i18n(cfg.locale, "tagContent.totalTags")}.
</p>
<p>{i18n(cfg.locale).pages.tagContent.totalTags({ count: tags.length })}</p>
<div>
{tags.map((tag) => {
const pages = tagItemMap.get(tag)!
@ -68,10 +64,12 @@ function TagContent(props: QuartzComponentProps) {
{content && <p>{content}</p>}
<div class="page-listing">
<p>
{pluralize(pages.length, i18n(cfg.locale, "common.item"))}{" "}
{i18n(cfg.locale, "tagContent.withThisTag")}.{" "}
{pages.length > numPages &&
`${i18n(cfg.locale, "tagContent.showingFirst")} ${numPages}.`}
{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}
{pages.length > numPages && (
<span>
{i18n(cfg.locale).pages.tagContent.showingFirst({ count: numPages })}
</span>
)}
</p>
<PageList limit={numPages} {...listProps} />
</div>
@ -92,10 +90,7 @@ function TagContent(props: QuartzComponentProps) {
<div class={classes}>
<article>{content}</article>
<div class="page-listing">
<p>
{pluralize(pages.length, i18n(cfg.locale, "common.item"))}{" "}
{i18n(cfg.locale, "tagContent.withThisTag")}.
</p>
<p>{i18n(cfg.locale).pages.tagContent.itemsUnderTag({ count: pages.length })}</p>
<div>
<PageList {...listProps} />
</div>

View file

@ -7,6 +7,8 @@ import { FullSlug, RelativeURL, joinSegments, normalizeHastElement } from "../ut
import { visit } from "unist-util-visit"
import { Root, Element, ElementContent } from "hast"
import { QuartzPluginData } from "../plugins/vfile"
import { GlobalConfiguration } from "../cfg"
import { i18n } from "../i18n"
interface RenderComponents {
head: QuartzComponent
@ -63,6 +65,7 @@ function getOrComputeFileIndex(allFiles: QuartzPluginData[]): Map<FullSlug, Quar
}
export function renderPage(
cfg: GlobalConfiguration,
slug: FullSlug,
componentData: QuartzComponentProps,
components: RenderComponents,
@ -136,7 +139,9 @@ export function renderPage(
type: "element",
tagName: "a",
properties: { href: inner.properties?.href, class: ["internal"] },
children: [{ type: "text", value: `Link to original` }],
children: [
{ type: "text", value: i18n(cfg.locale).components.transcludes.linkToOriginal },
],
},
]
} else if (page.htmlAst) {
@ -147,7 +152,14 @@ export function renderPage(
tagName: "h1",
properties: {},
children: [
{ type: "text", value: page.frontmatter?.title ?? `Transclude of ${page.slug}` },
{
type: "text",
value:
page.frontmatter?.title ??
i18n(cfg.locale).components.transcludes.transcludeOf({
targetSlug: page.slug!,
}),
},
],
},
...(page.htmlAst.children as ElementContent[]).map((child) =>
@ -157,7 +169,9 @@ export function renderPage(
type: "element",
tagName: "a",
properties: { href: inner.properties?.href, class: ["internal"] },
children: [{ type: "text", value: `Link to original` }],
children: [
{ type: "text", value: i18n(cfg.locale).components.transcludes.linkToOriginal },
],
},
]
}