feat: 重构部分插件

This commit is contained in:
pengzhanbo 2022-11-04 21:07:32 +08:00
parent 5de60d4d6e
commit 9737e9810c
24 changed files with 329 additions and 57 deletions

View File

@ -76,6 +76,7 @@
"sort-package-json": "^2.0.0",
"taze": "^0.8.2",
"ts-node": "^10.9.1",
"tsconfig-vuepress": "^4.0.0",
"typescript": "^4.8.4",
"vite": "^3.1.8"
},

View File

@ -2,7 +2,8 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib"
"outDir": "./lib",
"composite": true
},
"include": ["./src"],
"files": []

View File

@ -4,7 +4,6 @@ import { useBlogPostData } from './composables/index.js'
export default defineClientConfig({
enhance({ app }) {
// provide theme data & theme locale data
const blogPostData = useBlogPostData()
// setup devtools in dev mode

View File

@ -1,6 +1,6 @@
import { blogDataPlugin } from './plugin.js'
export * from '../shared/index.js'
export * from './plugin.js'
export { blogDataPlugin }
export default blogDataPlugin

View File

@ -41,6 +41,15 @@ export const blogDataPlugin = ({
return {
name: '@vuepress-plume/vuepress-plugin-blog-data',
clientConfigFile: path.resolve(__dirname, '../client/config.js'),
extendsPage(page) {
if (
page.filePathRelative &&
options.exclude.every((filter) => filter(page.filePathRelative!)) &&
options.include.some((filter) => filter(page.filePathRelative!))
) {
;(page.data as any).isBlogPost = true
}
},
onPrepared: async (app) => await preparedBlogData(app, options),
onWatched(app, watchers) {
const watcher = chokidar.watch('pages/**/*', {

View File

@ -1,5 +1,6 @@
import { defineClientConfig } from '@vuepress/client'
// import 'virtual:windi-devtools'
import 'virtual:windi.css'
export default defineClientConfig({})

View File

@ -14,7 +14,10 @@ export const windiCSSPlugin = (options?: WindiCSSOptions | string): Plugin => {
let userOptions: UserOptions | undefined
let utilsOptions: WindiPluginUtilsOptions | undefined
if (typeof options === 'string') {
userOptions = { config: options }
userOptions = {
config: options,
include: ['**/.vuepress/**/*.{vue,jsx,tsx}', '**/*.md'],
}
} else {
options = options || {}
userOptions = options.userOptions

View File

@ -1,17 +1,17 @@
declare module 'windicss-webpack-plugin' {
const result: any
// declare module 'windicss-webpack-plugin' {
// const result: any
export default result
}
// export default result
// }
declare module 'vite-plugin-windicss' {
const result: any
// declare module 'vite-plugin-windicss' {
// const result: any
type UserOptions = any
// type UserOptions = any
type WindiPluginUtilsOptions = any
// type WindiPluginUtilsOptions = any
export default result
// export default result
export { UserOptions, WindiPluginUtilsOptions }
}
// export { UserOptions, WindiPluginUtilsOptions }
// }

View File

@ -39,6 +39,7 @@
"@vuepress-plume/vuepress-plugin-blog-data": "workspace:*",
"@vuepress-plume/vuepress-plugin-caniuse": "workspace:*",
"@vuepress-plume/vuepress-plugin-copy-code": "workspace:*",
"@vuepress-plume/vuepress-plugin-windicss": "workspace:*",
"@vuepress/client": "2.0.0-beta.51",
"@vuepress/core": "2.0.0-beta.51",
"@vuepress/plugin-active-header-links": "2.0.0-beta.51",
@ -55,6 +56,7 @@
"@vuepress/plugin-toc": "2.0.0-beta.51",
"@vuepress/shared": "2.0.0-beta.51",
"@vuepress/utils": "2.0.0-beta.51",
"@vueuse/core": "^9.3.0",
"date-fns": "^2.29.3",
"nanoid": "^4.0.0",
"ts-debounce": "^4.0.0",
@ -63,6 +65,7 @@
"vuepress-plugin-comment2": "2.0.0-beta.110",
"vuepress-plugin-md-enhance": "2.0.0-beta.110",
"vuepress-plugin-seo2": "2.0.0-beta.110",
"vuepress-plugin-sitemap2": "2.0.0-beta.110"
"vuepress-plugin-sitemap2": "2.0.0-beta.110",
"windicss": "^3.5.6"
}
}

View File

@ -0,0 +1,4 @@
<script lang="ts" setup></script>
<template>
<div class="navbar-wrapper"></div>
</template>

View File

@ -0,0 +1,4 @@
export * from './useDarkMode.js'
export * from './useScrollPromise.js'
export * from './useThemeData.js'
export * from './useResolveRouteWithRedirect.js'

View File

@ -0,0 +1,72 @@
import { usePreferredDark, useStorage } from '@vueuse/core'
import { computed, inject, onMounted, onUnmounted, provide, watch } from 'vue'
import type { InjectionKey, WritableComputedRef } from 'vue'
import { useThemeLocaleData } from './useThemeData.js'
export type DarkModeRef = WritableComputedRef<boolean>
export const darkModeSymbol: InjectionKey<DarkModeRef> = Symbol(
__VUEPRESS_DEV__ ? 'darkMode' : ''
)
/**
* Inject dark mode global computed
*/
export const useDarkMode = (): DarkModeRef => {
const isDarkMode = inject(darkModeSymbol)
if (!isDarkMode) {
throw new Error('useDarkMode() is called without provider.')
}
return isDarkMode
}
/**
* Create dark mode ref and provide as global computed in setup
*/
export const setupDarkMode = (): void => {
const themeLocale = useThemeLocaleData()
const isDarkPreferred = usePreferredDark()
const darkStorage = useStorage(
'vuepress-color-scheme',
themeLocale.value.colorMode
)
const isDarkMode = computed<boolean>({
get() {
// disable color mode switching
if (!themeLocale.value.colorModeSwitch) {
return themeLocale.value.colorMode === 'dark'
}
// auto detected from prefers-color-scheme
if (darkStorage.value === 'auto') {
return isDarkPreferred.value
}
// storage value
return darkStorage.value === 'dark'
},
set(val) {
if (val === isDarkPreferred.value) {
darkStorage.value = 'auto'
} else {
darkStorage.value = val ? 'dark' : 'light'
}
},
})
provide(darkModeSymbol, isDarkMode)
updateHtmlDarkClass(isDarkMode)
}
export const updateHtmlDarkClass = (isDarkMode: DarkModeRef): void => {
const update = (value = isDarkMode.value): void => {
// set `class="dark"` on `<html>` element
const htmlEl = window?.document.querySelector('html')
htmlEl?.classList.toggle('dark', value)
}
onMounted(() => {
watch(isDarkMode, update, { immediate: true })
})
onUnmounted(() => update())
}

View File

@ -0,0 +1,28 @@
import { isFunction, isString } from '@vuepress/shared'
import { useRouter } from 'vue-router'
import type { Router } from 'vue-router'
/**
* Resolve a route with redirection
*/
export const useResolveRouteWithRedirect = (
...args: Parameters<Router['resolve']>
): ReturnType<Router['resolve']> => {
const router = useRouter()
const route = router.resolve(...args)
const lastMatched = route.matched[route.matched.length - 1]
if (!lastMatched?.redirect) {
return route
}
const { redirect } = lastMatched
const resolvedRedirect = isFunction(redirect) ? redirect(route) : redirect
const resolvedRedirectObj = isString(resolvedRedirect)
? { path: resolvedRedirect }
: resolvedRedirect
return useResolveRouteWithRedirect({
hash: route.hash,
query: route.query,
params: route.params,
...resolvedRedirectObj,
})
}

View File

@ -0,0 +1,22 @@
export interface ScrollPromise {
wait(): Promise<void> | null
pending: () => void
resolve: () => void
}
let promise: Promise<void> | null = null
let promiseResolve: (() => void) | null = null
const scrollPromise: ScrollPromise = {
wait: () => promise,
pending: () => {
promise = new Promise((resolve) => (promiseResolve = resolve))
},
resolve: () => {
promiseResolve?.()
promise = null
promiseResolve = null
},
}
export const useScrollPromise = (): ScrollPromise => scrollPromise

View File

@ -0,0 +1,14 @@
import {
useThemeData as _useThemeData,
useThemeLocaleData as _useThemeLocaleData,
} from '@vuepress/plugin-theme-data/client'
import type {
ThemeDataRef,
ThemeLocaleDataRef,
} from '@vuepress/plugin-theme-data/client'
import type { PlumeThemeData } from '../../shared/index.js'
export const useThemeData = (): ThemeDataRef<PlumeThemeData> =>
_useThemeData<PlumeThemeData>()
export const useThemeLocaleData = (): ThemeLocaleDataRef<PlumeThemeData> =>
_useThemeLocaleData<PlumeThemeData>()

View File

@ -1,8 +1,14 @@
import { defineClientConfig } from '@vuepress/client'
import { setupDarkMode } from './composables/index.js'
import Layout from './layouts/Layout.vue'
import NotFound from './layouts/NotFound.vue'
import './styles/index.scss'
export default defineClientConfig({
setup() {
setupDarkMode()
},
layouts: {
Layout,
NotFound,

View File

@ -1,3 +1,14 @@
<script setup lang="ts">
import Navbar from '../components/Navbar/index.vue'
import { useScrollPromise, useThemeLocaleData } from '../composables/index.js'
// handle scrollBehavior with transition
const scrollPromise = useScrollPromise()
const onBeforeEnter = scrollPromise.resolve
const onBeforeLeave = scrollPromise.pending
</script>
<template>
<div>layout</div>
<div class="theme-plume relative min-h-100vh">
<Navbar />
</div>
</template>

View File

@ -0,0 +1,73 @@
import { getDirname, path } from '@vuepress/utils'
import { defineConfig } from 'windicss/helpers'
import typography from 'windicss/plugin/typography'
const __dirname = getDirname(import.meta.url)
export default defineConfig({
darkMode: 'class',
// attributify: true,
plugins: [(typography as any)()],
theme: {
extend: {
textColor: '#2c3e50',
fontFamily: {
sans: [
'ui-sans-serif',
'-apple-system',
'BlinkMackSystemFont',
'"Segoe UI"',
'Roboto',
'Oxygen',
'Ubuntu',
'Cantarell',
'"Fira Sans"',
'"Droid Sans"',
'"Helvetica Neue"',
'sans-serif',
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
'"Noto Color Emoji"',
],
mono: [
'Consolas',
'Monaco',
'ui-monospace',
'SFMono-Regular',
'Menlo',
'"Andale Mono"',
'"Ubuntu Mono"',
'monospace',
],
},
typography: {
DEFAULT: {
css: {
color: '#2c3e50',
a: {
color: 'red',
},
h1: { color: 'inherit' },
h2: { color: 'inherit' },
h3: { color: 'inherit' },
h4: { color: 'inherit' },
h5: { color: 'inherit' },
h6: { color: 'inherit' },
b: { color: 'inherit' },
em: { color: 'inherit' },
strong: { color: 'inherit' },
blockquote: { color: 'inherit' },
},
},
},
},
},
extract: {
include: [
path.resolve(__dirname, '{components,layouts}/**/*'),
path.resolve(process.cwd(), '**/.vuepress/{components,layouts}/*'),
path.resolve(process.cwd(), '**/*.md'),
],
},
})

View File

@ -3,6 +3,7 @@ import { baiduTongjiPlugin } from '@vuepress-plume/vuepress-plugin-baidu-tongji'
import { blogDataPlugin } from '@vuepress-plume/vuepress-plugin-blog-data'
import { caniusePlugin } from '@vuepress-plume/vuepress-plugin-caniuse'
import { copyCodePlugin } from '@vuepress-plume/vuepress-plugin-copy-code'
import { windiCSSPlugin } from '@vuepress-plume/vuepress-plugin-windicss'
import type { App, PluginConfig } from '@vuepress/core'
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
@ -14,6 +15,7 @@ import { palettePlugin } from '@vuepress/plugin-palette'
import { prismjsPlugin } from '@vuepress/plugin-prismjs'
import { searchPlugin } from '@vuepress/plugin-search'
import { themeDataPlugin } from '@vuepress/plugin-theme-data'
import { getDirname, path } from '@vuepress/utils'
import { commentPlugin } from 'vuepress-plugin-comment2'
import { mdEnhancePlugin } from 'vuepress-plugin-md-enhance'
import { seoPlugin } from 'vuepress-plugin-seo2'
@ -24,6 +26,8 @@ import type {
} from '../shared/index.js'
import autoFrontmatter from './autoFrontmatter.js'
const __dirname = getDirname(import.meta.url)
export const setupPlugins = (
app: App,
options: PlumeThemePluginOptions,
@ -33,6 +37,7 @@ export const setupPlugins = (
return [
palettePlugin({ preset: 'sass' }),
windiCSSPlugin(path.resolve(__dirname, '../client/windi.config.js')),
themeDataPlugin({ themeData: localeOptions }),
autoFrontmatterPlugin(autoFrontmatter(app, localeOptions)),
blogDataPlugin({

View File

@ -7,6 +7,42 @@ export interface PlumeThemeOptions extends PlumeThemeLocaleOptions {
* 使
*/
themePlugins?: PlumeThemePluginOptions
/**
* 使
*
* @default false
*/
onlyBlog?: boolean
blog?: {
/**
* blog
*
* @default './' vuepress source
*/
dir?: string
/**
* `blog.dir` glob string
*
* @default - ['**\*.md']
*/
include?: string[]
/**
* `blog.dir` glob string
*
* _README.md blog文章_
*
* @default - ['.vuepress/', 'node_modules/', '{README,index}.md']
*/
exclude?: string[]
}
notes?: {
dir?: string
}
}
export type PlumeThemeLocaleOptions = PlumeThemeData

View File

@ -71,9 +71,11 @@ export interface PlumeThemeLocaleData extends LocaleData {
*/
logoDark?: string
/**
*
*
*/
darkMode?: boolean
colorModeSwitch?: boolean
colorMode?: 'auto' | 'light' | 'dark'
toggleDarkMode?: string

12
pnpm-lock.yaml generated
View File

@ -33,6 +33,7 @@ importers:
sort-package-json: ^2.0.0
taze: ^0.8.2
ts-node: ^10.9.1
tsconfig-vuepress: ^4.0.0
typescript: ^4.8.4
vite: ^3.1.8
devDependencies:
@ -65,6 +66,7 @@ importers:
sort-package-json: 2.0.0
taze: 0.8.2
ts-node: 10.9.1_5ra3kupzwcghzakkfdrtyjk72u
tsconfig-vuepress: 4.0.0
typescript: 4.8.4
vite: 3.1.8
@ -255,6 +257,7 @@ importers:
'@vuepress-plume/vuepress-plugin-blog-data': workspace:*
'@vuepress-plume/vuepress-plugin-caniuse': workspace:*
'@vuepress-plume/vuepress-plugin-copy-code': workspace:*
'@vuepress-plume/vuepress-plugin-windicss': workspace:*
'@vuepress/client': 2.0.0-beta.51
'@vuepress/core': 2.0.0-beta.51
'@vuepress/plugin-active-header-links': 2.0.0-beta.51
@ -271,6 +274,7 @@ importers:
'@vuepress/plugin-toc': 2.0.0-beta.51
'@vuepress/shared': 2.0.0-beta.51
'@vuepress/utils': 2.0.0-beta.51
'@vueuse/core': ^9.3.0
date-fns: ^2.29.3
nanoid: ^4.0.0
ts-debounce: ^4.0.0
@ -280,6 +284,7 @@ importers:
vuepress-plugin-md-enhance: 2.0.0-beta.110
vuepress-plugin-seo2: 2.0.0-beta.110
vuepress-plugin-sitemap2: 2.0.0-beta.110
windicss: ^3.5.6
dependencies:
'@types/lodash.merge': 4.6.7
'@vuepress-plume/vuepress-plugin-auto-frontmatter': link:../plugin-auto-frontmatter
@ -287,6 +292,7 @@ importers:
'@vuepress-plume/vuepress-plugin-blog-data': link:../plugin-blog-data
'@vuepress-plume/vuepress-plugin-caniuse': link:../plugin-caniuse
'@vuepress-plume/vuepress-plugin-copy-code': link:../plugin-copy-code
'@vuepress-plume/vuepress-plugin-windicss': link:../plugin-windicss
'@vuepress/client': 2.0.0-beta.51
'@vuepress/core': 2.0.0-beta.51
'@vuepress/plugin-active-header-links': 2.0.0-beta.51
@ -303,6 +309,7 @@ importers:
'@vuepress/plugin-toc': 2.0.0-beta.51
'@vuepress/shared': 2.0.0-beta.51
'@vuepress/utils': 2.0.0-beta.51
'@vueuse/core': 9.3.0_vue@3.2.41
date-fns: 2.29.3
nanoid: 4.0.0
ts-debounce: 4.0.0
@ -312,6 +319,7 @@ importers:
vuepress-plugin-md-enhance: 2.0.0-beta.110
vuepress-plugin-seo2: 2.0.0-beta.110
vuepress-plugin-sitemap2: 2.0.0-beta.110
windicss: 3.5.6
packages/theme-back:
specifiers:
@ -14322,6 +14330,10 @@ packages:
strip-bom: 3.0.0
dev: true
/tsconfig-vuepress/4.0.0:
resolution: {integrity: sha512-bhujOtmpGdclg92bBrc+Y4L+emxN7jldlmogfT0ks9TmBzcEmzCAiphYRZ+J4idyDyLL+O7Kd9w4nOkUFtOoZA==}
dev: true
/tslib/1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}

View File

@ -1,47 +1,13 @@
{
"extends": "tsconfig-vuepress/base.json",
"compilerOptions": {
"composite": true,
"allowSyntheticDefaultImports": true,
"lib": ["DOM", "ES2020"],
"module": "esnext",
"module": "ESNext",
"moduleResolution": "NodeNext",
"noEmitOnError": true,
"esModuleInterop": true,
"noImplicitAny": false,
"skipLibCheck": true,
"target": "ES2020",
"allowJs": false,
"allowUmdGlobalAccess": false,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"alwaysStrict": true,
"checkJs": false,
"declaration": true,
"declarationMap": false,
"exactOptionalPropertyTypes": false,
"forceConsistentCasingInFileNames": true,
"importsNotUsedAsValues": "error",
"newLine": "lf",
"noFallthroughCasesInSwitch": false,
"noImplicitAny": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitUseStrict": false,
"noPropertyAccessFromIndexSignature": false,
"noStrictGenericChecks": false,
"noUncheckedIndexedAccess": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"preserveValueImports": false,
"removeComments": false,
"resolveJsonModule": true,
"sourceMap": false,
"strict": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"stripInternal": true,
"useUnknownInCatchVariables": true
"target": "ES2020"
}
}