bece8fcab6
When providing an absolute path to the content directory (e.g. when using an Obsidian Vault in another directory), the build step would fail with Failed to process `/absolute/path/to/file.md`: ENOENT: no such file or directory, stat '/current/working/directory/absolute/path/' This problem originated in the `CreatedModifiedDate` transformer which tries to construct a native filesystem path to the file to call `fs.stat` on. It did not however, account for the original file path contained in the received `VFile` being an absolute path and so, just concatenated the current working directory with the absolute path producing a nonexistent one. This patch adds a simple fix for this issue by checking if the original file path is already absolute before concatenating with the current working directory.
100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
import fs from "fs"
|
|
import path from "path"
|
|
import { Repository } from "@napi-rs/simple-git"
|
|
import { QuartzTransformerPlugin } from "../types"
|
|
import chalk from "chalk"
|
|
|
|
export interface Options {
|
|
priority: ("frontmatter" | "git" | "filesystem")[]
|
|
}
|
|
|
|
const defaultOptions: Options = {
|
|
priority: ["frontmatter", "git", "filesystem"],
|
|
}
|
|
|
|
function coerceDate(fp: string, d: any): Date {
|
|
const dt = new Date(d)
|
|
const invalidDate = isNaN(dt.getTime()) || dt.getTime() === 0
|
|
if (invalidDate && d !== undefined) {
|
|
console.log(
|
|
chalk.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> | undefined> = (
|
|
userOpts,
|
|
) => {
|
|
const opts = { ...defaultOptions, ...userOpts }
|
|
return {
|
|
name: "CreatedModifiedDate",
|
|
markdownPlugins() {
|
|
return [
|
|
() => {
|
|
let repo: Repository | undefined = undefined
|
|
return async (_tree, file) => {
|
|
let created: MaybeDate = undefined
|
|
let modified: MaybeDate = undefined
|
|
let published: MaybeDate = undefined
|
|
|
|
const fp = file.data.filePath!
|
|
const fullFp = path.isAbsolute(fp) ? fp : path.posix.join(file.cwd, fp)
|
|
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.date as MaybeDate
|
|
modified ||= file.data.frontmatter.lastmod as MaybeDate
|
|
modified ||= file.data.frontmatter.updated as MaybeDate
|
|
modified ||= file.data.frontmatter["last-modified"] as MaybeDate
|
|
published ||= file.data.frontmatter.publishDate as MaybeDate
|
|
} else if (source === "git") {
|
|
if (!repo) {
|
|
// Get a reference to the main git repo.
|
|
// It's either the same as the workdir,
|
|
// or 1+ level higher in case of a submodule/subtree setup
|
|
repo = Repository.discover(file.cwd)
|
|
}
|
|
|
|
try {
|
|
modified ||= await repo.getFileLatestModifiedDateAsync(file.data.filePath!)
|
|
} catch {
|
|
console.log(
|
|
chalk.yellow(
|
|
`\nWarning: ${file.data
|
|
.filePath!} isn't yet tracked by git, last modification date is not available for this file`,
|
|
),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|