2023-05-30 15:02:20 +00:00
import fs from "fs"
2023-07-23 00:27:41 +00:00
import path from "path"
2023-05-30 15:02:20 +00:00
import { Repository } from "@napi-rs/simple-git"
import { QuartzTransformerPlugin } from "../types"
2023-09-22 17:04:37 +00:00
import chalk from "chalk"
2023-05-30 15:02:20 +00:00
export interface Options {
2023-07-23 00:27:41 +00:00
priority : ( "frontmatter" | "git" | "filesystem" ) [ ]
2023-05-30 15:02:20 +00:00
}
const defaultOptions : Options = {
2023-07-23 00:27:41 +00:00
priority : [ "frontmatter" , "git" , "filesystem" ] ,
2023-05-30 15:02:20 +00:00
}
2024-01-29 05:27:16 +00:00
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
2023-07-23 00:27:41 +00:00
export const CreatedModifiedDate : QuartzTransformerPlugin < Partial < Options > | undefined > = (
userOpts ,
) = > {
2023-06-12 06:26:43 +00:00
const opts = { . . . defaultOptions , . . . userOpts }
return {
name : "CreatedModifiedDate" ,
markdownPlugins() {
return [
( ) = > {
let repo : Repository | undefined = undefined
return async ( _tree , file ) = > {
2024-01-29 05:27:16 +00:00
let created : MaybeDate = undefined
let modified : MaybeDate = undefined
let published : MaybeDate = undefined
2023-05-30 15:02:20 +00:00
2023-09-22 17:04:37 +00:00
const fp = file . data . filePath !
2024-02-02 17:51:34 +00:00
const fullFp = path . isAbsolute ( fp ) ? fp : path.posix.join ( file . cwd , fp )
2023-06-12 06:26:43 +00:00
for ( const source of opts . priority ) {
if ( source === "filesystem" ) {
2023-09-22 17:04:37 +00:00
const st = await fs . promises . stat ( fullFp )
2024-01-29 05:27:16 +00:00
created || = st . birthtimeMs
modified || = st . mtimeMs
2023-06-12 06:26:43 +00:00
} else if ( source === "frontmatter" && file . data . frontmatter ) {
2024-01-29 05:27:16 +00:00
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
2023-06-12 06:26:43 +00:00
} else if ( source === "git" ) {
if ( ! repo ) {
2024-01-02 17:23:28 +00:00
// 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 )
2023-06-12 06:26:43 +00:00
}
2023-05-30 15:02:20 +00:00
2024-01-02 17:23:28 +00:00
try {
2024-01-29 05:27:16 +00:00
modified || = await repo . getFileLatestModifiedDateAsync ( file . data . filePath ! )
2024-01-02 17:23:28 +00:00
} catch {
console . log (
chalk . yellow (
` \ nWarning: ${ file . data
. filePath ! } isn ' t yet tracked by git , last modification date is not available for this file ` ,
) ,
)
}
2023-05-30 15:02:20 +00:00
}
}
2023-06-12 06:26:43 +00:00
file . data . dates = {
2024-01-29 05:27:16 +00:00
created : coerceDate ( fp , created ) ,
modified : coerceDate ( fp , modified ) ,
published : coerceDate ( fp , published ) ,
2023-06-12 06:26:43 +00:00
}
2023-05-30 15:02:20 +00:00
}
2023-07-23 00:27:41 +00:00
} ,
2023-06-12 06:26:43 +00:00
]
} ,
2023-05-30 15:02:20 +00:00
}
}
2023-07-23 00:27:41 +00:00
declare module "vfile" {
2023-05-30 15:02:20 +00:00
interface DataMap {
dates : {
created : Date
modified : Date
published : Date
}
}
}