1
0
mirror of https://gitlab.com/MisterBiggs/brain-quartz.git synced 2025-06-16 17:56:39 +00:00

116 lines
3.6 KiB
TypeScript

import fs from "fs"
import { Repository } from "@napi-rs/simple-git"
import { QuartzTransformerPlugin } from "../types"
import path from "path"
import { styleText } from "util"
export interface Options {
priority: ("frontmatter" | "git" | "filesystem")[]
}
const defaultOptions: Options = {
priority: ["frontmatter", "git", "filesystem"],
}
// YYYY-MM-DD
const iso8601DateOnlyRegex = /^\d{4}-\d{2}-\d{2}$/
function coerceDate(fp: string, d: any): Date {
// check ISO8601 date-only format
// we treat this one as local midnight as the normal
// js date ctor treats YYYY-MM-DD as UTC midnight
if (typeof d === "string" && iso8601DateOnlyRegex.test(d)) {
d = `${d}T00:00:00`
}
const dt = new Date(d)
const invalidDate = isNaN(dt.getTime()) || dt.getTime() === 0
if (invalidDate && d !== undefined) {
console.log(
styleText(
"yellow",
`\nWarning: found invalid date "${d}" in \`${fp}\`. Supported formats: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format`,
),
)
}
return invalidDate ? new Date() : dt
}
type MaybeDate = undefined | string | number
export const CreatedModifiedDate: QuartzTransformerPlugin<Partial<Options>> = (userOpts) => {
const opts = { ...defaultOptions, ...userOpts }
return {
name: "CreatedModifiedDate",
markdownPlugins(ctx) {
return [
() => {
let repo: Repository | undefined = undefined
let repositoryWorkdir: string
if (opts.priority.includes("git")) {
try {
repo = Repository.discover(ctx.argv.directory)
repositoryWorkdir = repo.workdir() ?? ctx.argv.directory
} catch (e) {
console.log(
styleText(
"yellow",
`\nWarning: couldn't find git repository for ${ctx.argv.directory}`,
),
)
}
}
return async (_tree, file) => {
let created: MaybeDate = undefined
let modified: MaybeDate = undefined
let published: MaybeDate = undefined
const fp = file.data.relativePath!
const fullFp = file.data.filePath!
for (const source of opts.priority) {
if (source === "filesystem") {
const st = await fs.promises.stat(fullFp)
created ||= st.birthtimeMs
modified ||= st.mtimeMs
} else if (source === "frontmatter" && file.data.frontmatter) {
created ||= file.data.frontmatter.created as MaybeDate
modified ||= file.data.frontmatter.modified as MaybeDate
published ||= file.data.frontmatter.published as MaybeDate
} else if (source === "git" && repo) {
try {
const relativePath = path.relative(repositoryWorkdir, fullFp)
modified ||= await repo.getFileLatestModifiedDateAsync(relativePath)
} catch {
console.log(
styleText(
"yellow",
`\nWarning: ${file.data.filePath!} isn't yet tracked by git, dates will be inaccurate`,
),
)
}
}
}
file.data.dates = {
created: coerceDate(fp, created),
modified: coerceDate(fp, modified),
published: coerceDate(fp, published),
}
}
},
]
},
}
}
declare module "vfile" {
interface DataMap {
dates: {
created: Date
modified: Date
published: Date
}
}
}