feat: add defaultDateType config
| | |
| | | - This should also include the subpath if you are [[hosting]] on GitHub pages without a custom domain. For example, if my repository is `jackyzha0/quartz`, GitHub pages would deploy to `https://jackyzha0.github.io/quartz` and the `baseUrl` would be `jackyzha0.github.io/quartz` |
| | | - Note that Quartz 4 will avoid using this as much as possible and use relative URLs whenever it can to make sure your site works no matter _where_ you end up actually deploying it. |
| | | - `ignorePatterns`: a list of [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) patterns that Quartz should ignore and not search through when looking for files inside the `content` folder. See [[private pages]] for more details. |
| | | - `defaultDateType`: whether to use created, modified, or published as the default date to display on pages and page listings. |
| | | - `theme`: configure how the site looks. |
| | | - `typography`: what fonts to use. Any font available on [Google Fonts](https://fonts.google.com/) works here. |
| | | - `header`: Font to use for headers |
| | |
| | | }, |
| | | baseUrl: "quartz.jzhao.xyz", |
| | | ignorePatterns: ["private", "templates"], |
| | | defaultDateType: "created", |
| | | theme: { |
| | | typography: { |
| | | header: "Schibsted Grotesk", |
| | |
| | | import { ValidDateType } from "./components/Date" |
| | | import { QuartzComponent } from "./components/types" |
| | | import { PluginTypes } from "./plugins/types" |
| | | import { Theme } from "./util/theme" |
| | |
| | | analytics: Analytics |
| | | /** Glob patterns to not search */ |
| | | ignorePatterns: string[] |
| | | /** Whether to use created, modified, or published as the default type of date */ |
| | | defaultDateType: ValidDateType |
| | | /** Base URL to use for CNAME files, sitemaps, and RSS feeds that require an absolute URL. |
| | | * Quartz will avoid using this as much as possible and use relative URLs most of the time |
| | | */ |
| | |
| | | import { formatDate } from "./Date" |
| | | import { formatDate, getDate } from "./Date" |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "./types" |
| | | import readingTime from "reading-time" |
| | | |
| | | export default (() => { |
| | | function ContentMetadata({ fileData }: QuartzComponentProps) { |
| | | function ContentMetadata({ cfg, fileData }: QuartzComponentProps) { |
| | | const text = fileData.text |
| | | if (text) { |
| | | const segments: string[] = [] |
| | | const { text: timeTaken, words: _words } = readingTime(text) |
| | | if (fileData.dates?.modified) { |
| | | segments.push(formatDate(fileData.dates.modified)) |
| | | |
| | | if (fileData.dates) { |
| | | segments.push(formatDate(getDate(cfg, fileData)!)) |
| | | } |
| | | |
| | | segments.push(timeTaken) |
| | |
| | | import { GlobalConfiguration } from "../cfg" |
| | | import { QuartzPluginData } from "../plugins/vfile" |
| | | |
| | | interface Props { |
| | | date: Date |
| | | } |
| | | |
| | | export type ValidDateType = keyof Required<QuartzPluginData>["dates"] |
| | | |
| | | export function getDate(cfg: GlobalConfiguration, data: QuartzPluginData): Date | undefined { |
| | | return data.dates?.[cfg.defaultDateType] |
| | | } |
| | | |
| | | export function formatDate(d: Date): string { |
| | | return d.toLocaleDateString("en-US", { |
| | | year: "numeric", |
| | |
| | | import { FullSlug, resolveRelative } from "../util/path" |
| | | import { QuartzPluginData } from "../plugins/vfile" |
| | | import { Date } from "./Date" |
| | | import { Date, getDate } from "./Date" |
| | | import { QuartzComponentProps } from "./types" |
| | | import { GlobalConfiguration } from "../cfg" |
| | | |
| | | export function byDateAndAlphabetical(f1: QuartzPluginData, f2: QuartzPluginData): number { |
| | | export function byDateAndAlphabetical( |
| | | cfg: GlobalConfiguration, |
| | | ): (f1: QuartzPluginData, f2: QuartzPluginData) => number { |
| | | return (f1, f2) => { |
| | | if (f1.dates && f2.dates) { |
| | | // sort descending by last modified |
| | | return f2.dates.modified.getTime() - f1.dates.modified.getTime() |
| | | // sort descending |
| | | return getDate(cfg, f2)!.getTime() - getDate(cfg, f1)!.getTime() |
| | | } else if (f1.dates && !f2.dates) { |
| | | // prioritize files with dates |
| | | return -1 |
| | |
| | | const f2Title = f2.frontmatter?.title.toLowerCase() ?? "" |
| | | return f1Title.localeCompare(f2Title) |
| | | } |
| | | } |
| | | |
| | | type Props = { |
| | | limit?: number |
| | | } & QuartzComponentProps |
| | | |
| | | export function PageList({ fileData, allFiles, limit }: Props) { |
| | | let list = allFiles.sort(byDateAndAlphabetical) |
| | | export function PageList({ cfg, fileData, allFiles, limit }: Props) { |
| | | let list = allFiles.sort(byDateAndAlphabetical(cfg)) |
| | | if (limit) { |
| | | list = list.slice(0, limit) |
| | | } |
| | |
| | | <div class="section"> |
| | | {page.dates && ( |
| | | <p class="meta"> |
| | | <Date date={page.dates.modified} /> |
| | | <Date date={getDate(cfg, page)!} /> |
| | | </p> |
| | | )} |
| | | <div class="desc"> |
| | |
| | | import { QuartzPluginData } from "../plugins/vfile" |
| | | import { byDateAndAlphabetical } from "./PageList" |
| | | import style from "./styles/recentNotes.scss" |
| | | import { Date } from "./Date" |
| | | import { Date, getDate } from "./Date" |
| | | import { GlobalConfiguration } from "../cfg" |
| | | |
| | | interface Options { |
| | | title: string |
| | |
| | | sort: (f1: QuartzPluginData, f2: QuartzPluginData) => number |
| | | } |
| | | |
| | | const defaultOptions: Options = { |
| | | const defaultOptions = (cfg: GlobalConfiguration): Options => ({ |
| | | title: "Recent Notes", |
| | | limit: 3, |
| | | linkToMore: false, |
| | | filter: () => true, |
| | | sort: byDateAndAlphabetical, |
| | | } |
| | | sort: byDateAndAlphabetical(cfg), |
| | | }) |
| | | |
| | | export default ((userOpts?: Partial<Options>) => { |
| | | const opts = { ...defaultOptions, ...userOpts } |
| | | function RecentNotes(props: QuartzComponentProps) { |
| | | const { allFiles, fileData, displayClass } = props |
| | | const { allFiles, fileData, displayClass, cfg } = props |
| | | const opts = { ...defaultOptions(cfg), ...userOpts } |
| | | const pages = allFiles.filter(opts.filter).sort(opts.sort) |
| | | const remaining = Math.max(0, pages.length - opts.limit) |
| | | return ( |
| | |
| | | </div> |
| | | {page.dates && ( |
| | | <p class="meta"> |
| | | <Date date={page.dates.modified} /> |
| | | <Date date={getDate(cfg, fileData)!} /> |
| | | </p> |
| | | )} |
| | | <ul class="tags"> |
| | |
| | | import { GlobalConfiguration } from "../../cfg" |
| | | import { getDate } from "../../components/Date" |
| | | import { FilePath, FullSlug, SimpleSlug, simplifySlug } from "../../util/path" |
| | | import { QuartzEmitterPlugin } from "../types" |
| | | import path from "path" |
| | |
| | | const linkIndex: ContentIndex = new Map() |
| | | for (const [_tree, file] of content) { |
| | | const slug = file.data.slug! |
| | | const date = file.data.dates?.modified ?? new Date() |
| | | const date = getDate(ctx.cfg.configuration, file.data) ?? new Date() |
| | | if (opts?.includeEmptyFiles || (file.data.text && file.data.text !== "")) { |
| | | linkIndex.set(slug, { |
| | | title: file.data.frontmatter?.title!, |