2023-06-29 18:11:15 +08:00

172 lines
5.5 KiB
TypeScript

import { createRequire } from 'node:module'
import path from 'node:path'
import type { App } from '@vuepress/core'
import { resolveLocalePath } from '@vuepress/shared'
import type {
AutoFrontmatterOptions,
FormatterArray,
FormatterObject,
} from '@vuepress-plume/vuepress-plugin-auto-frontmatter'
import type { NotesItem } from '@vuepress-plume/vuepress-plugin-notes-data'
import { format } from 'date-fns'
import { customAlphabet } from 'nanoid'
import type { PlumeThemeLocaleOptions } from '../shared/index.js'
const nanoid = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 8)
const require = createRequire(process.cwd())
const getPackage = () => {
let pkg = {} as any
try {
pkg = require('package.json') || {}
} catch {}
return pkg
}
const normalizePath = (dir: string) => {
return dir.replace(/\\+/g, '/')
}
export default function autoFrontmatter(
app: App,
localeOption: PlumeThemeLocaleOptions
): AutoFrontmatterOptions {
const sourceDir = app.dir.source()
const pkg = getPackage()
const articlePrefix = localeOption.article || '/article/'
const locales = (app.siteData.locales || {}) as PlumeThemeLocaleOptions
const localesNotesDirs = Object.keys(locales)
.map((locale) => {
const notes = localeOption.locales?.[locale].notes
if (!notes) return ''
const dir = notes.dir
return dir
? path.join(locale, dir).replace(/\\+/g, '/').replace(/^\//, '')
: ''
})
.filter(Boolean)
const baseFormatter: FormatterObject = {
author(author: string) {
if (author) return author
return localeOption.avatar?.name || pkg.author || ''
},
createTime(formatTime: string, { createTime }) {
if (formatTime) return formatTime
return format(new Date(createTime), 'yyyy/MM/dd hh:mm:ss')
},
}
const resolveLocale = (filepath: string) => {
const file = path.join('/', path.relative(sourceDir, filepath))
return resolveLocalePath(localeOption.locales!, file)
}
const notesByLocale = (locale: string) => {
const notes = localeOption.locales![locale].notes || localeOption.notes
if (notes === false) return undefined
return notes
}
const findNote = (filepath: string) => {
const file = path.join('/', path.relative(sourceDir, filepath))
const locale = resolveLocalePath(localeOption.locales!, file)
const notes = notesByLocale(locale)
if (!notes) return undefined
const notesList = notes?.notes || []
const notesDir = notes?.dir || ''
return notesList.find((note) =>
file.startsWith(path.join(locale, notesDir, note.dir))
)
}
const getCurrentDirname = (note: NotesItem | undefined, filepath: string) => {
const dirList = (note?.dir || path.dirname(filepath))
.replace(/^\/|\/$/g, '')
.split('/')
return dirList.length > 0 ? dirList[dirList.length - 1] : ''
}
return {
include: ['**/*.md'],
formatter: [
localesNotesDirs.length
? {
// note 首页链接
include: localesNotesDirs.map((dir) =>
path.join(dir, '**/{readme,README,index}.md')
),
formatter: {
title(title: string, { filepath }) {
if (title) return title
const note = findNote(filepath)
if (note?.text) return note.text
return getCurrentDirname(note, filepath) || ''
},
...baseFormatter,
permalink(permalink: string, { filepath }) {
if (permalink) return permalink
const locale = resolveLocale(filepath)
const notes = notesByLocale(locale)
const note = findNote(filepath)
return path.join(
locale,
notes?.link || '',
note?.link || getCurrentDirname(note, filepath),
'/'
)
},
},
}
: '',
localesNotesDirs.length
? {
include: localesNotesDirs.map((dir) => path.join(dir, '**/**.md')),
formatter: {
title(title: string, { filepath }) {
if (title) return title
const basename = path.basename(filepath, '.md')
return basename
},
...baseFormatter,
permalink(permalink: string, { filepath }) {
if (permalink) return permalink
const locale = resolveLocale(filepath)
const note = findNote(filepath)
const notes = notesByLocale(locale)
return normalizePath(
path.join(
locale,
notes?.link || '',
note?.link || getCurrentDirname(note, filepath),
nanoid(),
'/'
)
)
},
},
}
: '',
{
include: '**/{readme,README,index}.md',
formatter: {},
},
{
include: '*',
formatter: {
title(title: string, { filepath }) {
if (title) return title
const basename = path.basename(filepath, '.md')
return basename
},
...baseFormatter,
permalink(permalink: string, { filepath }) {
if (permalink) return permalink
const locale = resolveLocale(filepath)
return normalizePath(
path.join(locale, articlePrefix, nanoid(), '/')
)
},
},
},
].filter(Boolean) as FormatterArray,
}
}