feat(theme): add auto frontmatter config

This commit is contained in:
pengzhanbo 2023-02-13 23:07:35 +08:00
parent 016d092ee0
commit c1587fd3cd
10 changed files with 374 additions and 408 deletions

View File

@ -11,7 +11,7 @@ import type {
MarkdownFile,
} from '../shared/index.js'
import { readMarkdown, readMarkdownList } from './readFiles.js'
import { ensureArray } from './utils.js'
import { ensureArray, isEmptyObject } from './utils.js'
export const autoFrontmatterPlugin = ({
include = ['**/*.{md,MD}'],
@ -35,7 +35,7 @@ export const autoFrontmatterPlugin = ({
.map(({ include, formatter }) => {
return {
include,
filter: createFilter(ensureArray(include)),
filter: createFilter(ensureArray(include), [], { resolve: false }),
formatter,
}
})
@ -43,22 +43,28 @@ export const autoFrontmatterPlugin = ({
function formatMarkdown(file: MarkdownFile): void {
const { filepath, relativePath } = file
const formatter =
otherFormatters.find(({ filter }) => filter(relativePath))?.formatter ||
globFormatter
const current = otherFormatters.find(({ filter }) => filter(relativePath))
const formatter = current?.formatter || globFormatter
const { data, content } = grayMatter(file.content)
Object.keys(formatter).forEach((key) => {
const value = formatter[key](data[key], data, file)
data[key] = value ?? data[key]
})
const yaml = jsonToYaml
.stringify(data)
.replace(/\n\s{2}/g, '\n')
.replace(/"/g, '')
const newContent = `${yaml}---\n${content}`
fs.writeFileSync(filepath, newContent, 'utf-8')
try {
const yaml = isEmptyObject(data)
? '---\n'
: jsonToYaml
.stringify(data)
.replace(/\n\s{2}/g, '\n')
.replace(/"/g, '')
const newContent = `${yaml}---\n${content}`
fs.writeFileSync(filepath, newContent, 'utf-8')
} catch (e) {
console.log(e)
}
}
return {

View File

@ -3,3 +3,7 @@ export function ensureArray<T>(thing: T | T[] | null | undefined): T[] {
if (thing === null || thing === undefined) return []
return [thing]
}
export function isEmptyObject(obj: object) {
return Object.keys(obj).length === 0
}

View File

@ -69,6 +69,7 @@
"@vueuse/core": "^9.10.0",
"body-scroll-lock": "4.0.0-beta.0",
"date-fns": "^2.29.3",
"lodash.merge": "^4.6.2",
"nanoid": "^4.0.0",
"ts-debounce": "^4.0.0",
"vue": "^3.2.47",

View File

@ -119,9 +119,9 @@ const actions = computed(() => {
font-weight: 500;
margin-top: 1.5rem;
color: var(--vp-c-text-hero-text);
padding: 6px 20px;
/* padding: 6px 20px; */
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.25);
/* background-color: rgba(0, 0, 0, 0.25); */
}
.actions {

View File

@ -1,20 +1,93 @@
import { createRequire } from 'node:module'
import path from 'node:path'
import type { AutoFrontmatterOptions } from '@vuepress-plume/vuepress-plugin-auto-frontmatter'
import type {
NotesDataOptions,
NotesItem,
} from '@vuepress-plume/vuepress-plugin-notes-data'
import type { App } from '@vuepress/core'
import { format } from 'date-fns'
import { customAlphabet } from 'nanoid'
import type { PlumeThemeLocaleOptions } from '../shared/index.js'
const nanoid = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 8)
export default function (
app: App,
localeOption: PlumeThemeLocaleOptions
): AutoFrontmatterOptions {
// const sourceDir = app.dir.source()
const sourceDir = app.dir.source()
const require = createRequire(process.cwd())
const pkg = require('./package.json') || {}
const articlePrefix = localeOption.article || '/article/'
const {
dir,
link: notesLink,
notes: notesList,
} = localeOption.notes as NotesDataOptions
const notesDir = dir.replace(/^\//, '')
const baseFormatter = {
author(author: string) {
if (author) return author
return localeOption.avatar?.name || pkg.author || ''
},
createTime(formatTime: string, _: any, { createTime }) {
if (formatTime) return formatTime
return format(new Date(createTime), 'yyyy/MM/dd hh:mm:ss')
},
}
const findNote = (filepath: string) => {
const file = path.relative(sourceDir, filepath)
return notesList.find((note) =>
file.startsWith(path.join(notesDir.replace(/^\//, ''), 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: [],
include: ['**/*.md'],
formatter: [
{
// note 首页链接
include: path.join(notesDir, `**/{readme,README,index}.md`),
formatter: {
...baseFormatter,
title(title: string, _, { filepath }) {
if (title) return title
const note = findNote(filepath)
if (note?.text) return note.text
return getCurrentDirname(note, filepath) || ''
},
permalink(permalink: string, _, { filepath }) {
if (permalink) return permalink
const note = findNote(filepath)
const dirname = getCurrentDirname(note, filepath)
return path.join(notesLink, note?.link || dirname, '/')
},
},
},
{
include: path.join(notesDir, '**/*.md'),
formatter: {
title(title: string, _, { filepath }) {
if (title) return title
const basename = path.basename(filepath, '.md')
return basename
},
permalink(permalink: string, _, { filepath }) {
if (permalink) return permalink
const note = findNote(filepath)
const dirname = getCurrentDirname(note, filepath)
return path.join(notesLink, note?.link || dirname, nanoid())
},
},
},
{
include: '**/{readme,README,index}.md',
formatter: {},
@ -22,21 +95,14 @@ export default function (
{
include: '*',
formatter: {
...baseFormatter,
title(title: string) {
if (title) return title
return title
},
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')
},
permalink(permalink: string, _, { filepath }) {
permalink(permalink: string) {
if (permalink) return permalink
return permalink
return path.join(articlePrefix, nanoid())
},
},
},

View File

@ -0,0 +1,11 @@
import merge from 'lodash.merge'
import type { PlumeThemeLocaleOptions } from '../shared/index.js'
export const defaultLocaleOption: Partial<PlumeThemeLocaleOptions> = {
article: '/article',
notes: { link: '/note', dir: 'notes', notes: [] },
}
export const mergeLocaleOptions = (options: PlumeThemeLocaleOptions) => {
return merge(defaultLocaleOption, options)
}

View File

@ -33,6 +33,11 @@ export const setupPlugins = (
): PluginConfig => {
const isProd = !app.env.isDev
let notesDir: string | undefined
if (localeOptions.notes !== false) {
notesDir = localeOptions.notes?.dir
}
return [
palettePlugin({ preset: 'sass' }),
themeDataPlugin({
@ -46,7 +51,10 @@ export const setupPlugins = (
autoFrontmatterPlugin(autoFrontmatter(app, localeOptions)),
blogDataPlugin({
include: ['**/*.md'],
exclude: ['**/{README,index}.md', 'notes/**'],
exclude: [
'**/{README,index}.md',
notesDir ? `${notesDir}/**` : '',
].filter(Boolean),
sortBy: 'createTime',
excerpt: true,
extendBlogData(page: any) {

View File

@ -1,6 +1,7 @@
import type { App, Page, Theme } from '@vuepress/core'
import { fs, getDirname, path } from '@vuepress/utils'
import type { PlumeThemeOptions, PlumeThemePageData } from '../shared/index.js'
import { mergeLocaleOptions } from './defaultOptions.js'
import { setupPlugins } from './plugins.js'
import { autoCategory, pageContentRendered, setupPage } from './setupPages.js'
@ -10,6 +11,7 @@ export const plumeTheme = ({
themePlugins = {},
...localeOptions
}: PlumeThemeOptions = {}): Theme => {
localeOptions = mergeLocaleOptions(localeOptions)
return (app: App) => {
return {
name: '@vuepress-plume/theme-plume',

View File

@ -1,6 +1,6 @@
import type { NotesDataOptions } from '@vuepress-plume/vuepress-plugin-notes-data'
import type { LocaleData } from '@vuepress/core'
import type { NavItem, NavItemWithLink } from './navbar.js'
import type { NavItem } from './navbar.js'
// import type { NavbarConfig, NavLink } from '../layout/index.js'
// import type { PlumeThemeNotesOptions } from './notes.js'
@ -85,14 +85,14 @@ export interface PlumeThemeLocaleData extends LocaleData {
*
* @def{ text: '标签', link: '/tag/' }
*/
tag?: false | NavItemWithLink
// tag?: false | NavItemWithLink
/**
* navbar配置
*
* @default { text: '分类', link: '/category/ }
*/
category?: false | NavItemWithLink
// category?: false | NavItemWithLink
/**
* navbar
@ -101,7 +101,7 @@ export interface PlumeThemeLocaleData extends LocaleData {
*
* @default { text: '归档', link: '/timeline/' }
*/
archive?: false | NavItemWithLink
// archive?: false | NavItemWithLink
/**
*
@ -113,23 +113,23 @@ export interface PlumeThemeLocaleData extends LocaleData {
/**
* language text
*/
selectLanguageText?: string
// selectLanguageText?: string
/**
* language aria label
*/
selectLanguageAriaLabel?: string
// selectLanguageAriaLabel?: string
/**
* language name
*/
selectLanguageName?: string
// selectLanguageName?: string
/**
* repository of navbar
*/
repo?: null | string
// repo?: null | string
/**
* repository text of navbar
*/
repoLabel?: string
// repoLabel?: string
/**
* Navbar config
@ -142,9 +142,9 @@ export interface PlumeThemeLocaleData extends LocaleData {
*/
openInNewWindow?: string | boolean
notFound?: string[]
// notFound?: string[]
backToHome?: string
// backToHome?: string
footer?:
| false

610
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff