diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11862493..b22fcbab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,12 +11,7 @@ 在 `plugins` 目录中: -- `plugin-auto-frontmatter` : 为 md 文件自动添加 frontmatter。 -- `plugin-blog-data`: 生成 blog 文章列表数据 -- `plugin-notes-data`: 生成 notes 数据,管理不同 note 的 `sidebar` 的数据 -- ~~`plugin-caniuse`: 添加 `caniuse` 内容容器,已弃用,不再维护~~ - `plugin-content-update`: 重写 `Content` 组件,提供 `onContentUpdated` 钩子 -- ~~`plugin-copy-code`: 为 代码块添加 复制 按钮,并适配 `shikiji`,已弃用,不再维护~~ - `plugin-search`: 为主题提供 全文模糊搜索 功能 - `plugin-shikiji`: 代码高亮插件,支持 highlight、diff、focus、error level - `plugin-iconify`: 添加全局组件 `Iconify` diff --git a/plugins/plugin-auto-frontmatter/LICENSE b/plugins/plugin-auto-frontmatter/LICENSE deleted file mode 100644 index 9f677c90..00000000 --- a/plugins/plugin-auto-frontmatter/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (C) 2021 - PRESENT by pengzhanbo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/plugins/plugin-auto-frontmatter/README.md b/plugins/plugin-auto-frontmatter/README.md deleted file mode 100644 index 78877dc5..00000000 --- a/plugins/plugin-auto-frontmatter/README.md +++ /dev/null @@ -1,126 +0,0 @@ -# `@vuepress-plume/plugin-auto-frontmatter` - -自动生成 `*.md` 文件的 `frontmatter` 配置。 - -## Install - -```sh -npm install @vuepress-plume/plugin-auto-frontmatter -# or -pnpm add @vuepress-plume/plugin-auto-frontmatter -# or -yarn add @vuepress-plume/plugin-auto-frontmatter -``` - -## Usage - -``` js -// .vuepress/config.[jt]s -import { autoFrontmatterPlugin } from '@vuepress-plume/plugin-auto-frontmatter' - -export default { - // ... - plugins: [ - autoFrontmatterPlugin({ - formatter: { - createTime(formatTime, file, matter) { - if (formatTime) - return formatTime - return file.createTime - } - } - }) - ] - // ... -} -``` - -## `autoFrontmatterPlugin([options])` - -### options - -`{ include?: string | string[]; exclude?: string | string[]; formatter: Formatter }` - -- `include` - include 匹配字符串或数组,匹配需要自动生成 `frontmatter` 的 md文件。 - 默认预设为 `['**/*.md']`。 - -- `exclude` - exclude 排除不需要的文件 - 默认预设为: `['!.vuepress/', '!node_modules/']` - -- `formatter` - 配置`frontmatter`每个字段的生成规则。 - - ```ts - interface MarkdownFile { - filepath: string - relativePath: string - content: string - createTime: Date - stats: fs.Stats - } - - interface FormatterFn { - (value: T, file: MarkdownFile, data: K): T - } - - type FormatterObject = Record< - string, - FormatterFn - > - - type FormatterArray = { - include: string | string[] - formatter: FormatterObject - }[] - - type Formatter = FormatterObject | FormatterArray - - /** - * formatterObj 对象中的 key 即为 frontmatter 配置中的key - * 其方法返回的值将作为 frontmatter[key] 的值 - * .md - * --- - * createTime: 2022-03-26T11:46:50.000Z - * --- - */ - const formatterObj: Formatter = { - createTime(formatTime, file, matter) { - if (formatTime) - return formatTime - return file.createTime - } - } - - const formatterArr: Formatter = [ - { - // 更精细化的匹配某个 md文件,支持glob 匹配字符串 - include: '**/{README,index}.md', - // formatter 仅对 glob命中的文件有效 - formatter: { - home(value, file, matter) { - return value - } - }, - }, - { - // 通配,如果文件没有被其他精细glob命中, - // 则使用 通配 formatter - // 如果是数组,必须有且用一个 include 为 * 的 项 - include: '*', - formatter: { - title(title) { - return title || '默认标题' - } - } - } - ] - ``` - -## Why ? - -- **为什么需要这个插件?** - - 有时候在开发一些主题时,期望使用户更专注于内容的编写,尽可能减少配置性的工作,可以将一些重复性的必要的配置 - 直接通过本插件自动生成。 diff --git a/plugins/plugin-auto-frontmatter/package.json b/plugins/plugin-auto-frontmatter/package.json deleted file mode 100644 index c89628ed..00000000 --- a/plugins/plugin-auto-frontmatter/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "@vuepress-plume/plugin-auto-frontmatter", - "type": "module", - "version": "1.0.0-rc.75", - "private": true, - "description": "The Plugin for VuePress 2 - auto frontmatter", - "author": "pengzhanbo ", - "license": "MIT", - "homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git", - "directory": "plugins/plugin-auto-frontmatter" - }, - "bugs": { - "url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues" - }, - "exports": { - ".": { - "types": "./lib/node/index.d.ts", - "import": "./lib/node/index.js" - }, - "./package.json": "./package.json" - }, - "main": "lib/node/index.js", - "types": "./lib/node/index.d.ts", - "files": [ - "lib" - ], - "scripts": { - "build": "pnpm run copy && pnpm run ts", - "clean": "rimraf --glob ./lib ./*.tsbuildinfo", - "copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib", - "ts": "tsc -b tsconfig.build.json" - }, - "peerDependencies": { - "vuepress": "2.0.0-rc.14" - }, - "dependencies": { - "@pengzhanbo/utils": "^1.1.2", - "chokidar": "^3.6.0", - "create-filter": "^1.1.0", - "fast-glob": "^3.3.2", - "gray-matter": "^4.0.3", - "json2yaml": "^1.1.0" - }, - "publishConfig": { - "access": "public" - }, - "keyword": [ - "VuePress", - "vuepress plugin", - "autoFrontmatter", - "vuepress-plugin-plugin-auto-frontmatter" - ] -} diff --git a/plugins/plugin-auto-frontmatter/src/node/env.d.ts b/plugins/plugin-auto-frontmatter/src/node/env.d.ts deleted file mode 100644 index 5591cb30..00000000 --- a/plugins/plugin-auto-frontmatter/src/node/env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'json2yaml' { - const result: any - - export default result -} diff --git a/plugins/plugin-auto-frontmatter/src/node/index.ts b/plugins/plugin-auto-frontmatter/src/node/index.ts deleted file mode 100644 index 6d08b744..00000000 --- a/plugins/plugin-auto-frontmatter/src/node/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { - AutoFrontmatterOptions, - FrontmatterArray, - FrontmatterObject, -} from '../shared/index.js' -import { autoFrontmatterPlugin } from './plugin.js' - -export * from './plugin.js' - -export type { AutoFrontmatterOptions, FrontmatterArray, FrontmatterObject } - -export default autoFrontmatterPlugin diff --git a/plugins/plugin-auto-frontmatter/src/node/plugin.ts b/plugins/plugin-auto-frontmatter/src/node/plugin.ts deleted file mode 100644 index 2785709a..00000000 --- a/plugins/plugin-auto-frontmatter/src/node/plugin.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { colors, fs, logger } from 'vuepress/utils' -import type { Plugin } from 'vuepress/core' -import chokidar from 'chokidar' -import { createFilter } from 'create-filter' -import grayMatter from 'gray-matter' -import jsonToYaml from 'json2yaml' -import { promiseParallel } from '@pengzhanbo/utils' -import type { - AutoFrontmatterOptions, - FrontmatterArray, - FrontmatterObject, - MarkdownFile, -} from '../shared/index.js' -import { readMarkdown, readMarkdownList } from './readFiles.js' -import { ensureArray, isEmptyObject } from './utils.js' - -const PLUGIN_NAME = '@vuepress-plume/plugin-auto-frontmatter' - -export function autoFrontmatterPlugin({ - include = ['**/*.md'], - exclude = ['.vuepress/**/*', 'node_modules'], - frontmatter = {}, -}: AutoFrontmatterOptions = {}): Plugin { - include = ensureArray(include) - exclude = ensureArray(exclude) - - const globFilter = createFilter(include, exclude, { resolve: false }) - - const matterFrontmatter: FrontmatterArray = Array.isArray(frontmatter) - ? frontmatter - : [{ include: '*', frontmatter }] - - const globFormatter: FrontmatterObject - = matterFrontmatter.find(({ include }) => include === '*')?.frontmatter || {} - - const otherFormatters = matterFrontmatter - .filter(({ include }) => include !== '*') - .map(({ include, frontmatter }) => { - return { - include, - filter: createFilter(ensureArray(include), [], { resolve: false }), - frontmatter, - } - }) - - async function formatMarkdown(file: MarkdownFile): Promise { - const { filepath, relativePath } = file - - const current = otherFormatters.find(({ filter }) => filter(relativePath)) - const formatter = current?.frontmatter || globFormatter - const { data, content } = grayMatter(file.content) - - for (const key in formatter) { - const value = await formatter[key](data[key], file, data) - data[key] = value ?? data[key] - } - - try { - const yaml = isEmptyObject(data) - ? '' - : jsonToYaml - .stringify(data) - .replace(/\n\s{2}/g, '\n') - .replace(/"/g, '') - .replace(/\s+\n/g, '\n') - const newContent = yaml ? `${yaml}---\n${content}` : content - - fs.writeFileSync(filepath, newContent, 'utf-8') - } - catch (e) { - console.error(e) - } - } - - return { - name: PLUGIN_NAME, - onInitialized: async (app) => { - const start = performance.now() - const markdownList = await readMarkdownList(app.dir.source(), globFilter) - await promiseParallel( - markdownList.map(file => () => formatMarkdown(file)), - 64, - ) - if (app.env.isDebug) - logger.info(`\n[${colors.green(PLUGIN_NAME)}] Init time spent: ${(performance.now() - start).toFixed(2)}ms`) - }, - onWatched: async (app, watchers) => { - const watcher = chokidar.watch('**/*.md', { - cwd: app.dir.source(), - ignoreInitial: true, - ignored: /(node_modules|\.vuepress)\//, - }) - - watcher.on('add', async (relativePath) => { - if (!globFilter(relativePath)) - return - await formatMarkdown(readMarkdown(app.dir.source(), relativePath)) - }) - - watchers.push(watcher) - }, - } -} diff --git a/plugins/plugin-auto-frontmatter/src/node/readFiles.ts b/plugins/plugin-auto-frontmatter/src/node/readFiles.ts deleted file mode 100644 index ed4b2e07..00000000 --- a/plugins/plugin-auto-frontmatter/src/node/readFiles.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { fs, path } from 'vuepress/utils' -import fg from 'fast-glob' -import type { MarkdownFile } from '../shared/index.js' - -type MarkdownFileList = MarkdownFile[] - -export async function readMarkdownList(sourceDir: string, filter: (id: string) => boolean): Promise { - const files: string[] = await fg(['**/*.md'], { - cwd: sourceDir, - ignore: ['node_modules', '.vuepress'], - }) - - return files - .filter(file => filter(file)) - .map(file => readMarkdown(sourceDir, file)) -} - -export function readMarkdown(sourceDir: string, relativePath: string): MarkdownFile { - const filepath = path.join(sourceDir, relativePath) - const stats = fs.statSync(filepath) - return { - filepath, - relativePath, - content: fs.readFileSync(filepath, 'utf-8'), - createTime: getFileCreateTime(stats), - stats, - } -} - -export function getFileCreateTime(stats: fs.Stats): Date { - return stats.birthtime.getFullYear() !== 1970 ? stats.birthtime : stats.atime -} diff --git a/plugins/plugin-auto-frontmatter/src/node/utils.ts b/plugins/plugin-auto-frontmatter/src/node/utils.ts deleted file mode 100644 index 4ba1705d..00000000 --- a/plugins/plugin-auto-frontmatter/src/node/utils.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function ensureArray(thing: T | T[] | null | undefined): T[] { - if (Array.isArray(thing)) - return thing - if (thing === null || thing === undefined) - return [] - return [thing] -} - -export function isEmptyObject(obj: object) { - return Object.keys(obj).length === 0 -} diff --git a/plugins/plugin-auto-frontmatter/src/shared/index.ts b/plugins/plugin-auto-frontmatter/src/shared/index.ts deleted file mode 100644 index cd1f8cf7..00000000 --- a/plugins/plugin-auto-frontmatter/src/shared/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type fs from 'node:fs' - -export interface MarkdownFile { - filepath: string - relativePath: string - content: string - createTime: Date - stats: fs.Stats -} - -export type FrontmatterFn = ( - value: T, - file: MarkdownFile, - data: K -) => T | PromiseLike - -export type FrontmatterObject = Record> - -export type FrontmatterArray = { - include: string | string[] - frontmatter: FrontmatterObject -}[] - -export interface AutoFrontmatterOptions { - /** - * FilterPattern - */ - include?: string | string[] - - exclude?: string | string[] - - /** - * { - * key(value, file, data) { - * return value - * } - * } - */ - frontmatter?: FrontmatterArray | FrontmatterObject -} diff --git a/plugins/plugin-auto-frontmatter/tsconfig.build.json b/plugins/plugin-auto-frontmatter/tsconfig.build.json deleted file mode 100644 index 809551b3..00000000 --- a/plugins/plugin-auto-frontmatter/tsconfig.build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "outDir": "./lib" - }, - "files": [], - "include": ["./src"] -} diff --git a/plugins/plugin-blog-data/LICENSE b/plugins/plugin-blog-data/LICENSE deleted file mode 100644 index 9f677c90..00000000 --- a/plugins/plugin-blog-data/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (C) 2021 - PRESENT by pengzhanbo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/plugins/plugin-blog-data/README.md b/plugins/plugin-blog-data/README.md deleted file mode 100644 index fdb0e6d7..00000000 --- a/plugins/plugin-blog-data/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# `@vuepress-plume/plugin-blog-data` - -## Install - -```sh -npm install @vuepress-plume/plugin-blog-data -# or -pnpm add @vuepress-plume/plugin-blog-data -# or -yarn add @vuepress-plume/plugin-blog-data -``` - -## Usage - -``` js -// .vuepress/config.[jt]s -import { blogDataPlugin } from '@vuepress-plume/plugin-blog-data' - -export default { - // ... - plugins: [ - blogDataPlugin() - ] - // ... -} -``` - -## Options - -```ts -interface BlogDataPluginOptions { - include?: string | string[] - exclude?: string | string[] - sortBy?: 'createTime' | false | ((prev: T, next: T) => boolean) - excerpt?: boolean - extendBlogData?: (page: T) => Record -} -``` diff --git a/plugins/plugin-blog-data/package.json b/plugins/plugin-blog-data/package.json deleted file mode 100644 index d7eb5986..00000000 --- a/plugins/plugin-blog-data/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@vuepress-plume/plugin-blog-data", - "type": "module", - "version": "1.0.0-rc.75", - "private": "true", - "description": "The Plugin for VuePress 2 - blog data", - "author": "pengzhanbo ", - "license": "MIT", - "homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git", - "directory": "plugins/plugin-blog-data" - }, - "bugs": { - "url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues" - }, - "exports": { - ".": { - "types": "./lib/node/index.d.ts", - "import": "./lib/node/index.js" - }, - "./client": { - "types": "./lib/client/index.d.ts", - "import": "./lib/client/index.js" - }, - "./package.json": "./package.json" - }, - "main": "lib/node/index.js", - "types": "./lib/node/index.d.ts", - "files": [ - "lib" - ], - "scripts": { - "build": "pnpm run copy && pnpm run ts", - "clean": "rimraf --glob ./lib ./*.tsbuildinfo", - "copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib", - "ts": "tsc -b tsconfig.build.json" - }, - "peerDependencies": { - "vuepress": "2.0.0-rc.14" - }, - "dependencies": { - "@vue/devtools-api": "6.6.3", - "chokidar": "^3.6.0", - "create-filter": "^1.1.0", - "vue": "^3.4.31" - }, - "publishConfig": { - "access": "public" - }, - "keyword": [ - "VuePress", - "vuepress plugin", - "blogData", - "vuepress-plugin-plugin-blog-data" - ] -} diff --git a/plugins/plugin-blog-data/src/client/blogPostData.d.ts b/plugins/plugin-blog-data/src/client/blogPostData.d.ts deleted file mode 100644 index 52fa5598..00000000 --- a/plugins/plugin-blog-data/src/client/blogPostData.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { BlogPostData } from '../shared/index.js' - -declare module '@internal/blogData' { - const blogPostData: BlogPostData - - export { blogPostData } -} diff --git a/plugins/plugin-blog-data/src/client/composables/index.ts b/plugins/plugin-blog-data/src/client/composables/index.ts deleted file mode 100644 index 43aec1ef..00000000 --- a/plugins/plugin-blog-data/src/client/composables/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './useBlogPostData.js' diff --git a/plugins/plugin-blog-data/src/client/composables/useBlogPostData.ts b/plugins/plugin-blog-data/src/client/composables/useBlogPostData.ts deleted file mode 100644 index fc2f2eae..00000000 --- a/plugins/plugin-blog-data/src/client/composables/useBlogPostData.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { - blogPostData as blogPostDataRaw, -} from '@internal/blogData' -import { ref } from 'vue' -import type { Ref } from 'vue' -import type { BlogPostData } from '../../shared/index.js' - -declare const __VUE_HMR_RUNTIME__: Record - -export type BlogDataRef = Ref - -export const blogPostData: BlogDataRef = ref(blogPostDataRaw) - -export function useBlogPostData< - T extends BlogPostData = BlogPostData, ->(): BlogDataRef { - return blogPostData as BlogDataRef -} - -if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) { - __VUE_HMR_RUNTIME__.updateBlogData = (data: BlogPostData) => { - blogPostData.value = data - } -} diff --git a/plugins/plugin-blog-data/src/client/config.ts b/plugins/plugin-blog-data/src/client/config.ts deleted file mode 100644 index 09d2f231..00000000 --- a/plugins/plugin-blog-data/src/client/config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { setupDevtoolsPlugin } from '@vue/devtools-api' -import { defineClientConfig } from 'vuepress/client' -import type { ClientConfig } from 'vuepress/client' -import { useBlogPostData } from './composables/index.js' - -declare const __VUE_PROD_DEVTOOLS__: boolean - -export default defineClientConfig({ - enhance({ app }) { - const blogPostData = useBlogPostData() - - Object.defineProperties(app.config.globalProperties, { - $blogPostData: { - get() { - return blogPostData.value - }, - }, - }) - - // setup devtools in dev mode - if (__VUEPRESS_DEV__ || __VUE_PROD_DEVTOOLS__) { - const PLUGIN_ID = 'org.vuejs.vuepress' - const PLUGIN_LABEL = 'VuePress' - const INSPECTOR_ID = PLUGIN_ID - - setupDevtoolsPlugin( - { - // fix recursive reference - app: app as any, - id: PLUGIN_ID, - label: PLUGIN_LABEL, - packageName: '@vuepress-plume/plugin-blog-data', - homepage: 'https://pengzhanbo.cn', - logo: 'https://v2.vuepress.vuejs.org/images/hero.png', - componentStateTypes: ['VuePress'], - }, - (api) => { - api.on.inspectComponent((payload) => { - payload.instanceData.state.push({ - type: 'VuePress', - key: 'blogPostData', - editable: false, - value: blogPostData.value, - }) - }) - api.on.getInspectorTree((payload) => { - if (payload.inspectorId !== INSPECTOR_ID) - return - payload.rootNodes.push({ - id: 'blog_post_data', - label: 'Blog Post Data', - }) - }) - api.on.getInspectorState((payload) => { - if (payload.inspectorId !== INSPECTOR_ID) - return - if (payload.nodeId === 'blog_post_data') { - payload.state = { - BlogPostData: [{ - key: 'blogPostData', - value: blogPostData.value, - }], - } - } - }) - }, - ) - } - }, -}) as ClientConfig diff --git a/plugins/plugin-blog-data/src/client/index.ts b/plugins/plugin-blog-data/src/client/index.ts deleted file mode 100644 index f07e6cc1..00000000 --- a/plugins/plugin-blog-data/src/client/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { BlogPostData, BlogPostDataItem } from '../shared/index.js' - -export * from './composables/index.js' - -export type { BlogPostData, BlogPostDataItem } diff --git a/plugins/plugin-blog-data/src/node/index.ts b/plugins/plugin-blog-data/src/node/index.ts deleted file mode 100644 index 289ed329..00000000 --- a/plugins/plugin-blog-data/src/node/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { blogDataPlugin } from './plugin.js' - -export * from '../shared/index.js' -export { blogDataPlugin } - -export default blogDataPlugin diff --git a/plugins/plugin-blog-data/src/node/plugin.ts b/plugins/plugin-blog-data/src/node/plugin.ts deleted file mode 100644 index 5d6ac8bd..00000000 --- a/plugins/plugin-blog-data/src/node/plugin.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { Plugin } from 'vuepress/core' -import { getDirname, path } from 'vuepress/utils' -import chokidar from 'chokidar' -import { createFilter } from 'create-filter' -import { preparedBlogData } from './prepareBlogData.js' -import type { BlogDataPluginOptions } from './index.js' - -const __dirname = getDirname(import.meta.url) - -export type PluginOption = Omit - -export function blogDataPlugin({ - include, - exclude, - ...pluginOptions -}: BlogDataPluginOptions = {}): Plugin { - const pageFilter = createFilter(toArray(include), toArray(exclude), { - resolve: false, - }) - - return { - name: '@vuepress-plume/plugin-blog-data', - clientConfigFile: path.resolve(__dirname, '../client/config.js'), - extendsPage(page) { - if (page.filePathRelative && pageFilter(page.filePathRelative)) { - ;(page.data as any).isBlogPost = true - } - }, - onPrepared: async app => - await preparedBlogData(app, pageFilter, pluginOptions), - onWatched(app, watchers) { - const watcher = chokidar.watch('pages/**/*', { - cwd: app.dir.temp(), - ignoreInitial: true, - }) - - const handler = () => preparedBlogData(app, pageFilter, pluginOptions) - - watcher.on('add', handler) - watcher.on('change', handler) - watcher.on('unlink', handler) - - watchers.push(watcher) - }, - } -} - -function toArray(likeArr: string | string[] | undefined): string[] { - if (Array.isArray(likeArr)) - return likeArr - return likeArr ? [likeArr] : [] -} diff --git a/plugins/plugin-blog-data/src/node/prepareBlogData.ts b/plugins/plugin-blog-data/src/node/prepareBlogData.ts deleted file mode 100644 index c8edc603..00000000 --- a/plugins/plugin-blog-data/src/node/prepareBlogData.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { createHash } from 'node:crypto' -import type { App, Page } from 'vuepress/core' -import { colors, logger } from 'vuepress/utils' -import type { BlogPostData, BlogPostDataItem } from '../shared/index.js' -import type { PluginOption } from './plugin.js' - -const HMR_CODE = ` -if (import.meta.webpackHot) { - import.meta.webpackHot.accept() - if (__VUE_HMR_RUNTIME__.updateBlogData) { - __VUE_HMR_RUNTIME__.updateBlogData(blogPostData) - } -} - -if (import.meta.hot) { - import.meta.hot.accept(({ blogPostData }) => { - __VUE_HMR_RUNTIME__.updateBlogData(blogPostData) - }) -} -` - -const headingRe = /]*>.*?<\/h\1>/gi - -const EXCERPT_SPLIT = '' -let contentHash: string | undefined - -export async function preparedBlogData(app: App, pageFilter: (id: string) => boolean, options: PluginOption): Promise { - const start = performance.now() - - let pages = app.pages.filter((page) => { - return page.filePathRelative && pageFilter(page.filePathRelative) - }) - if (options.pageFilter) - pages = pages.filter(options.pageFilter) - - if (options.sortBy) { - pages = pages.sort((prev, next) => { - if (options.sortBy === 'createTime') { - return getTimestamp(prev.frontmatter.createTime as Date) - < getTimestamp(next.frontmatter.createTime as Date) - ? 1 - : -1 - } - else { - return typeof options.sortBy === 'function' - && options.sortBy(prev, next) - ? 1 - : -1 - } - }) - } - - const blogData: BlogPostData = pages.map((page: Page) => { - let extended: Partial = {} - if (typeof options.extendBlogData === 'function') - extended = options.extendBlogData(page) - - const data = { - path: page.path, - title: page.title, - ...extended, - } - - if (options.excerpt && page.contentRendered.includes(EXCERPT_SPLIT)) { - const contents = page.contentRendered.split(EXCERPT_SPLIT) - let excerpt = contents[0] - // 删除摘要中的标题 - excerpt = excerpt.replace(headingRe, '') - data.excerpt = excerpt - } - - return data as BlogPostDataItem - }) - - let content = `\ -export const blogPostData = ${JSON.stringify(blogData)}; -` - - // inject HMR code - if (app.env.isDev) - content += HMR_CODE - - const currentHash = hash(content) - if (!contentHash || contentHash !== currentHash) { - contentHash = currentHash - await app.writeTemp('internal/blogData.js', content) - } - - if (app.env.isDebug) - logger.info(`\n[${colors.green('@vuepress-plume/plugin-blog-data')}] prepare blog data time spent: ${(performance.now() - start).toFixed(2)}ms`) -} - -function getTimestamp(time: Date): number { - return new Date(time).getTime() -} - -function hash(content: string): string { - return createHash('md5').update(content).digest('hex') -} diff --git a/plugins/plugin-blog-data/src/shared/index.ts b/plugins/plugin-blog-data/src/shared/index.ts deleted file mode 100644 index 86af918c..00000000 --- a/plugins/plugin-blog-data/src/shared/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { Page } from 'vuepress/core' - -export interface BlogDataPluginOptions { - include?: string | string[] - exclude?: string | string[] - sortBy?: 'createTime' | false | ((prev: T, next: T) => boolean) - excerpt?: boolean - extendBlogData?: (page: T) => Record - pageFilter?: (page: Page) => boolean -} - -export type BlogPostData = BlogPostDataItem[] - -export type BlogPostDataItem = { - path: string - title: string - excerpt: string - [x: string]: any -} & T diff --git a/plugins/plugin-blog-data/tsconfig.build.json b/plugins/plugin-blog-data/tsconfig.build.json deleted file mode 100644 index 3f0244f8..00000000 --- a/plugins/plugin-blog-data/tsconfig.build.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../tsconfig.build.json", - "compilerOptions": { - "baseUrl": ".", - "rootDir": "./src", - "paths": { - "@internal/blogData": ["./src/client/blogPostData.d.ts"] - }, - "types": ["vuepress/client-types", "vite/client", "webpack-env"], - "outDir": "./lib" - }, - "include": ["./src"] -} diff --git a/plugins/plugin-caniuse/LICENSE b/plugins/plugin-caniuse/LICENSE deleted file mode 100644 index 9f677c90..00000000 --- a/plugins/plugin-caniuse/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (C) 2021 - PRESENT by pengzhanbo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/plugins/plugin-caniuse/README.md b/plugins/plugin-caniuse/README.md deleted file mode 100644 index 4015b7ce..00000000 --- a/plugins/plugin-caniuse/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# vuepress-plugin-caniuse - -VuePress 2 Plugin - -VuePress 2 插件 - -在Markdown中添加 [can-i-use](https://caniuse.com/) 支持,这对于你在写前端技术博客时,说明某个feature的兼容性时特别有用。 - -## Install - -``` sh -npm install @vuepress-plume/plugin-caniuse -# or -pnpm add @vuepress-plume/plugin-caniuse -# or -yarn add @vuepress-plume/plugin-caniuse -``` - -## Usage - -### 在VuePress 配置文件中添加插件 - -``` js -// .vuepress/config.[jt]s -import { caniusePlugin } from '@vuepress-plume/plugin-caniuse' - -export default { - // ... - plugins: [ - caniusePlugin({ mode: 'image' }), - ] - // ... -} -``` - -### 在markdown中编写 - -``` md -::: caniuse {{browser_versions}} -::: -``` - -### Options - -- `options.mode`: can-i-use插入文档的模式, 支持 `embed` 和`image`, 默认值是 `image`。 - - `image`: 插入图片 - - `embed`: 使用iframe嵌入 can-i-use - -### \ - -正确取值请参考 [https://caniuse.bitsofco.de/](https://caniuse.bitsofco.de/) - -### \{browser_versions\}` - -可选。当前特性在多个版本中的支持情况。 - -格式: `{number,number,...}` 取值范围为 `-5 ~ 3` - -- 小于`0` 表示低于当前浏览器版本的支持情况 -- `0` 表示当前浏览器版本的支持情况 -- 大于`0` 表示高于当前浏览器版本的支持情况 - -## Example - -``` md -::: caniuse css-matches-pseudo {-2,-1,1} -::: -``` - -效果: -![can-i-use css-matches-pseudo](https://caniuse.bitsofco.de/image/css-dir-pseudo.webp) diff --git a/plugins/plugin-caniuse/package.json b/plugins/plugin-caniuse/package.json deleted file mode 100644 index f509a4d3..00000000 --- a/plugins/plugin-caniuse/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@vuepress-plume/plugin-caniuse", - "type": "module", - "version": "1.0.0-rc.75", - "private": "true", - "description": "The Plugin for VuePress 2, Support Can-I-Use feature", - "author": "pengzhanbo ", - "license": "MIT", - "homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git", - "directory": "plugins/plugin-caniuse" - }, - "bugs": { - "url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues" - }, - "keywords": [ - "VuePress", - "plugin", - "vuepress-plugin", - "can-i-use", - "caniuse" - ], - "exports": { - ".": { - "types": "./lib/node/index.d.ts", - "import": "./lib/node/index.js" - }, - "./client": { - "types": "./lib/client/index.d.ts", - "import": "./lib/client/index.js" - }, - "./package.json": "./package.json" - }, - "main": "lib/node/index.js", - "types": "./lib/node/index.d.ts", - "files": [ - "lib" - ], - "scripts": { - "build": "pnpm run ts", - "clean": "rimraf --glob ./lib ./*.tsbuildinfo", - "ts": "tsc -b tsconfig.build.json" - }, - "peerDependencies": { - "vuepress": "2.0.0-rc.14" - }, - "dependencies": { - "markdown-it-container": "^4.0.0" - }, - "devDependencies": { - "@types/markdown-it": "^14.1.1" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/plugins/plugin-caniuse/src/client/clientConfig.ts b/plugins/plugin-caniuse/src/client/clientConfig.ts deleted file mode 100644 index cf788296..00000000 --- a/plugins/plugin-caniuse/src/client/clientConfig.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { defineClientConfig } from 'vuepress/client' -import type { ClientConfig } from 'vuepress/client' -import type { CanIUseMode } from '../shared/index.js' -import { resolveCanIUse } from './resolveCanIUse.js' - -declare const __CAN_I_USE_INJECT_MODE__: CanIUseMode -declare const __VUEPRESS_SSR__: boolean - -const mode = __CAN_I_USE_INJECT_MODE__ - -export default defineClientConfig({ - enhance({ router }) { - if (__VUEPRESS_SSR__) - return - - router.afterEach(() => { - if (mode === 'embed') - resolveCanIUse() - }) - }, -}) as ClientConfig diff --git a/plugins/plugin-caniuse/src/client/index.ts b/plugins/plugin-caniuse/src/client/index.ts deleted file mode 100644 index 72593733..00000000 --- a/plugins/plugin-caniuse/src/client/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '../shared/index.js' diff --git a/plugins/plugin-caniuse/src/client/resolveCanIUse.ts b/plugins/plugin-caniuse/src/client/resolveCanIUse.ts deleted file mode 100644 index 6c60b7ac..00000000 --- a/plugins/plugin-caniuse/src/client/resolveCanIUse.ts +++ /dev/null @@ -1,20 +0,0 @@ -let isBind = false -export function resolveCanIUse(): void { - if (isBind) - return - isBind = true - - window.addEventListener('message', (message) => { - const data = message.data - - if (typeof data === 'string' && data.includes('ciu_embed')) { - const [, feature, height] = data.split(':') - const el = document.querySelector(`.ciu_embed[data-feature="${feature}"]:not([data-skip])`) - if (el) { - const h = Number.parseInt(height) + 30 - ;(el.childNodes[0] as any).height = `${h}px` - el.setAttribute('data-skip', 'true') - } - } - }) -} diff --git a/plugins/plugin-caniuse/src/node/index.ts b/plugins/plugin-caniuse/src/node/index.ts deleted file mode 100644 index d83b030d..00000000 --- a/plugins/plugin-caniuse/src/node/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { caniusePlugin } from './plugin.js' - -export * from './plugin.js' -export * from '../shared/index.js' - -export default caniusePlugin diff --git a/plugins/plugin-caniuse/src/node/markdown-it-container.d.ts b/plugins/plugin-caniuse/src/node/markdown-it-container.d.ts deleted file mode 100644 index 44347be7..00000000 --- a/plugins/plugin-caniuse/src/node/markdown-it-container.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'markdown-it-container' { - import type { PluginWithParams } from 'markdown-it' - - const container: PluginWithParams - export = container -} diff --git a/plugins/plugin-caniuse/src/node/plugin.ts b/plugins/plugin-caniuse/src/node/plugin.ts deleted file mode 100644 index 4941687c..00000000 --- a/plugins/plugin-caniuse/src/node/plugin.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { Plugin, PluginObject } from 'vuepress/core' -import { getDirname, path } from 'vuepress/utils' -import type Token from 'markdown-it/lib/token.mjs' -import container from 'markdown-it-container' -import type { CanIUseMode, CanIUsePluginOptions } from '../shared/index.js' -import { resolveCanIUse } from './resolveCanIUse.js' - -const __dirname = getDirname(import.meta.url) -const modeMap: CanIUseMode[] = ['image', 'embed'] -const isMode = (mode: CanIUseMode): boolean => modeMap.includes(mode) - -export function caniusePlugin({ - mode = modeMap[0], -}: CanIUsePluginOptions): Plugin { - mode = isMode(mode) ? mode : modeMap[0] - const type = 'caniuse' - const validateReg = new RegExp(`^${type}(?:$|\s)`) - const pluginObj: PluginObject = { - name: '@vuepress-plume/plugin-caniuse', - clientConfigFile: path.resolve(__dirname, '../client/clientConfig.js'), - define: { - __CAN_I_USE_INJECT_MODE__: mode, - }, - } - - const validate = (info: string): boolean => { - return validateReg.test(info.trim()) - } - - const render = (tokens: Token[], index: number): string => { - const token = tokens[index] - if (token.nesting === 1) { - const info = token.info.trim().slice(type.length).trim() || '' - const feature = info.split(/\s+/)[0] - const versions = info.match(/\{(.*)\}/)?.[1] || '' - return feature ? resolveCanIUse(feature, mode, versions) : '' - } - else { - return '' - } - } - - pluginObj.extendsMarkdown = (md) => { - md.use(container as any, type, { validate, render }) - } - - return pluginObj -} diff --git a/plugins/plugin-caniuse/src/node/resolveCanIUse.ts b/plugins/plugin-caniuse/src/node/resolveCanIUse.ts deleted file mode 100644 index 9c4a9994..00000000 --- a/plugins/plugin-caniuse/src/node/resolveCanIUse.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { CanIUseMode } from '../shared/index.js' - -export function resolveCanIUse(feature: string, mode: CanIUseMode, versions: string): string { - if (!feature) - return '' - - if (mode === 'image') { - return ` - - - Data on support for the ${feature} feature across the major browsers from caniuse.com - ` - } - - const periods = resolveVersions(versions) - const accessible = 'false' - const image = 'none' - const url = 'https://caniuse.bitsofco.de/embed/index.html' - const src = `${url}?feat=${feature}&periods=${periods}&accessible-colours=${accessible}&image-base=${image}` - - return `
` -} - -function resolveVersions(versions: string): string { - if (!versions) - return 'future_1,current,past_1,past_2' - - const list = versions - .split(',') - .map(v => Number(v.trim())) - .filter(v => !Number.isNaN(v) && v >= -5 && v <= 3) - - list.push(0) - - const uniq = [...new Set(list)].sort((a, b) => b - a) - const result: string[] = [] - uniq.forEach((v) => { - if (v < 0) - result.push(`past_${Math.abs(v)}`) - if (v === 0) - result.push('current') - if (v > 0) - result.push(`future_${v}`) - }) - return result.join(',') -} diff --git a/plugins/plugin-caniuse/src/shared/caniuse.ts b/plugins/plugin-caniuse/src/shared/caniuse.ts deleted file mode 100644 index 65d37638..00000000 --- a/plugins/plugin-caniuse/src/shared/caniuse.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type CanIUseMode = 'embed' | 'image' - -/** - * can-i-use plugin options - */ -export interface CanIUsePluginOptions { - /** - * 嵌入模式 - * - * embed 通过iframe嵌入,提供可交互视图 - * - * image 通过图片嵌入,静态 - */ - mode: CanIUseMode -} diff --git a/plugins/plugin-caniuse/src/shared/index.ts b/plugins/plugin-caniuse/src/shared/index.ts deleted file mode 100644 index 3a1fb664..00000000 --- a/plugins/plugin-caniuse/src/shared/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './caniuse.js' diff --git a/plugins/plugin-caniuse/tsconfig.build.json b/plugins/plugin-caniuse/tsconfig.build.json deleted file mode 100644 index 6bf67375..00000000 --- a/plugins/plugin-caniuse/tsconfig.build.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "outDir": "./lib" - }, - "include": ["./src"] -} diff --git a/plugins/plugin-copy-code/LICENSE b/plugins/plugin-copy-code/LICENSE deleted file mode 100644 index 9f677c90..00000000 --- a/plugins/plugin-copy-code/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (C) 2021 - PRESENT by pengzhanbo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/plugins/plugin-copy-code/README.md b/plugins/plugin-copy-code/README.md deleted file mode 100644 index 99c57123..00000000 --- a/plugins/plugin-copy-code/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# `@vuepress-plume/plugin-copy-code` - -## Install - -```sh -npm install @vuepress-plume/plugin-copy-code -# or -pnpm add @vuepress-plume/plugin-copy-code -# or -yarn add @vuepress-plume/plugin-copy-code -``` - -## Usage - -``` js -// .vuepress/config.js -import { copyCodePlugin } from '@vuepress-plume/plugin-copy-code' - -export default { - // ... - plugins: [ - copyCodePlugin() - ] - // ... -} -``` diff --git a/plugins/plugin-copy-code/package.json b/plugins/plugin-copy-code/package.json deleted file mode 100644 index 07c7af74..00000000 --- a/plugins/plugin-copy-code/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "@vuepress-plume/plugin-copy-code", - "type": "module", - "version": "1.0.0-rc.75", - "private": "true", - "description": "The Plugin for VuePress 2 - copy code", - "author": "pengzhanbo ", - "license": "MIT", - "homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git", - "directory": "plugins/plugin-copy-code" - }, - "bugs": { - "url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues" - }, - "exports": { - ".": { - "types": "./lib/node/index.d.ts", - "import": "./lib/node/index.js" - }, - "./client": { - "types": "./lib/client/index.d.ts", - "import": "./lib/client/index.js" - }, - "./package.json": "./package.json" - }, - "main": "lib/node/index.js", - "types": "./lib/node/index.d.ts", - "files": [ - "lib" - ], - "scripts": { - "build": "pnpm run copy && pnpm run ts", - "clean": "rimraf --glob ./lib ./*.tsbuildinfo", - "copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib", - "ts": "tsc -b tsconfig.build.json" - }, - "peerDependencies": { - "vuepress": "2.0.0-rc.14" - }, - "dependencies": { - "@vuepress-plume/plugin-content-update": "workspace:~", - "vue": "^3.4.31" - }, - "publishConfig": { - "access": "public" - }, - "keyword": [ - "VuePress", - "vuepress plugin", - "copyCode", - "vuepress-plugin-plugin-copy-code" - ] -} diff --git a/plugins/plugin-copy-code/src/client/clientConfig.ts b/plugins/plugin-copy-code/src/client/clientConfig.ts deleted file mode 100644 index 3a44ee3f..00000000 --- a/plugins/plugin-copy-code/src/client/clientConfig.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineClientConfig } from 'vuepress/client' -import type { ClientConfig } from 'vuepress/client' -import { setupCopyCode } from './setupCopyCode.js' - -import './styles/button.css' - -export default defineClientConfig({ - setup() { - setupCopyCode() - }, -}) as ClientConfig diff --git a/plugins/plugin-copy-code/src/client/index.ts b/plugins/plugin-copy-code/src/client/index.ts deleted file mode 100644 index 72593733..00000000 --- a/plugins/plugin-copy-code/src/client/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '../shared/index.js' diff --git a/plugins/plugin-copy-code/src/client/setupCopyCode.ts b/plugins/plugin-copy-code/src/client/setupCopyCode.ts deleted file mode 100644 index a7cbadeb..00000000 --- a/plugins/plugin-copy-code/src/client/setupCopyCode.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { nextTick, onMounted } from 'vue' -import { onContentUpdated } from '@vuepress-plume/plugin-content-update/client' -import type { CopyCodeOptions } from '../shared/index.js' - -declare const __COPY_CODE_OPTIONS__: CopyCodeOptions - -const options = __COPY_CODE_OPTIONS__ -const RE_LANGUAGE = /language-(\w+)/ -const RE_START_CODE = /^ *(\$|>)/gm -const shells = ['shellscript', 'shell', 'bash', 'sh', 'zsh'] -const ignoredNodes = ['.diff.remove', '.vp-copy-ignore'] - -function isMobile(): boolean { - return navigator - ? /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/iu.test( - navigator.userAgent, - ) - : false -} - -function sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)) -} - -export function setupCopyCode(): void { - const insertBtn = (codeBlockEl: HTMLElement): void => { - if (codeBlockEl.hasAttribute('has-copy-code')) - return - const button = document.createElement('button') - button.className = 'copy-code-button' - const parent = codeBlockEl.parentElement - - if (parent) { - parent.insertBefore(button, codeBlockEl) - const classes = parent.className - const match = classes.match(RE_LANGUAGE) || [] - if (match[1]) - button.setAttribute('data-lang', match[1]) - } - - codeBlockEl.setAttribute('has-copy-code', '') - } - - const generateButton = async () => { - const { selector, delay } = options - await nextTick() - await sleep(delay || 0) - const selectors = Array.isArray(selector) ? selector : [selector!] - selectors.forEach((item) => { - document.querySelectorAll(item).forEach(insertBtn) - }) - } - - onMounted(async () => { - if (!isMobile() || options.showInMobile) { - await generateButton() - - const timeoutIdMap: WeakMap = new WeakMap() - window.addEventListener('click', (e) => { - const el = e.target as HTMLElement - if (el.matches('div[class*="language-"] > button.copy-code-button')) { - const parent = el.parentElement - const sibling = el.nextElementSibling - if (!parent || !sibling) - return - - // Clone the node and remove the ignored nodes - const clone = sibling.cloneNode(true) as HTMLElement - clone - .querySelectorAll(ignoredNodes.join(',')) - .forEach(node => node.remove()) - - let text = clone.textContent || '' - const lang = el.getAttribute('data-lang') || '' - if (lang && shells.includes(lang)) - text = text.replace(RE_START_CODE, '').trim() - - copyToClipboard(text).then(() => { - el.classList.add('copied') - clearTimeout(timeoutIdMap.get(el)) - const timeoutId = setTimeout(() => { - el.classList.remove('copied') - el.blur() - timeoutIdMap.delete(el) - }, options.duration) - timeoutIdMap.set(el, timeoutId) - }) - } - }) - } - }) - - onContentUpdated(() => { - if (!isMobile() || options.showInMobile) - generateButton() - }) -} - -async function copyToClipboard(text: string) { - try { - return navigator.clipboard.writeText(text) - } - catch { - const element = document.createElement('textarea') - const previouslyFocusedElement = document.activeElement - - element.value = text - - // Prevent keyboard from showing on mobile - element.setAttribute('readonly', '') - - element.style.contain = 'strict' - element.style.position = 'absolute' - element.style.left = '-9999px' - element.style.fontSize = '12pt' // Prevent zooming on iOS - - const selection = document.getSelection() - const originalRange = selection - ? selection.rangeCount > 0 && selection.getRangeAt(0) - : null - - document.body.appendChild(element) - element.select() - - // Explicit selection workaround for iOS - element.selectionStart = 0 - element.selectionEnd = text.length - - document.execCommand('copy') - document.body.removeChild(element) - - if (originalRange) { - selection!.removeAllRanges() // originalRange can't be truthy when selection is falsy - selection!.addRange(originalRange) - } - - // Get the focus back on the previously focused element, if any - if (previouslyFocusedElement) { - ; (previouslyFocusedElement as HTMLElement).focus() - } - } -} diff --git a/plugins/plugin-copy-code/src/client/styles/button.css b/plugins/plugin-copy-code/src/client/styles/button.css deleted file mode 100644 index bf2f8fab..00000000 --- a/plugins/plugin-copy-code/src/client/styles/button.css +++ /dev/null @@ -1,100 +0,0 @@ -:root { - --vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E"); - --vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E"); -} - -:root { - --vp-code-copy-code-border-color: #e2e2e3; - --vp-code-copy-code-bg: #f6f6f7; - --vp-code-copy-code-hover-border-color: #e2e2e3; - --vp-code-copy-code-hover-bg: #fff; - --vp-code-copy-code-active-text: rgba(60, 60, 67, 0.78); - --vp-code-copy-copied-text-content: "Copied"; -} - -html[lang="zh-CN"] { - --vp-code-copy-copied-text-content: "已复制"; -} - -.dark { - --vp-code-copy-code-border-color: #2e2e32; - --vp-code-copy-code-bg: #202127; - --vp-code-copy-code-hover-bg: #1b1b1f; - --vp-code-copy-code-hover-border-color: #2e2e32; - --vp-code-copy-code-active-text: rgba(235, 235, 245, 0.6); -} - -.copy-code-button { - position: absolute; - top: 12px; - - /* rtl:ignore */ - right: 12px; - z-index: 3; - width: 40px; - height: 40px; - cursor: pointer; - background-color: var(--vp-code-copy-code-bg); - background-image: var(--vp-icon-copy); - background-repeat: no-repeat; - background-position: 50%; - background-size: 20px; - border: 1px solid var(--vp-code-copy-code-border-color); - border-radius: 4px; - opacity: 0; - transition: - border-color 0.25s, - background-color 0.25s, - opacity 0.25s; - - /* rtl:ignore */ - direction: ltr; -} - -[class*="language-"]:hover > .copy-code-button, -[class*="language-"] > .copy-code-button:focus, -[class*="language-"] > .copy-code-button.copied { - opacity: 1; -} - -[class*="language-"] > .copy-code-button:hover, -[class*="language-"] > .copy-code-button.copied { - background-color: var(--vp-code-copy-code-hover-bg); - border-color: var(--vp-code-copy-code-hover-border-color); -} - -[class*="language-"] > .copy-code-button.copied, -[class*="language-"] > .copy-code-button:hover.copied { - background-color: var(--vp-code-copy-code-hover-bg); - background-image: var(--vp-icon-copied); - - /* rtl:ignore */ - border-radius: 0 4px 4px 0; -} - -[class*="language-"] > .copy-code-button.copied::before, -[class*="language-"] > .copy-code-button:hover.copied::before { - position: relative; - top: -1px; - display: flex; - align-items: center; - justify-content: center; - width: fit-content; - height: 40px; - padding: 0 10px; - font-size: 12px; - font-weight: 500; - color: var(--vp-code-copy-code-active-text); - text-align: center; - white-space: nowrap; - content: var(--vp-code-copy-copied-text-content); - background-color: var(--vp-code-copy-code-hover-bg); - border: 1px solid var(--vp-code-copy-code-hover-border-color); - - /* rtl:ignore */ - border-right: 0; - border-radius: 4px 0 0 4px; - - /* rtl:ignore */ - transform: translateX(calc(-100% - 1px)); -} diff --git a/plugins/plugin-copy-code/src/node/index.ts b/plugins/plugin-copy-code/src/node/index.ts deleted file mode 100644 index 6b3df8a9..00000000 --- a/plugins/plugin-copy-code/src/node/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { copyCodePlugin } from './plugin.js' - -export * from './plugin.js' -export * from '../shared/index.js' - -export default copyCodePlugin diff --git a/plugins/plugin-copy-code/src/node/plugin.ts b/plugins/plugin-copy-code/src/node/plugin.ts deleted file mode 100644 index 1f8bd3fd..00000000 --- a/plugins/plugin-copy-code/src/node/plugin.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Plugin } from 'vuepress/core' -import { getDirname, path } from 'vuepress/utils' -import type { CopyCodeOptions } from '../shared/index.js' - -const __dirname = getDirname(import.meta.url) - -const defaultOptions: CopyCodeOptions = { - selector: '.theme-default-content div[class*="language-"] pre', - duration: 1500, - delay: 500, - showInMobile: false, -} - -export function copyCodePlugin(options: CopyCodeOptions): Plugin { - options = Object.assign({}, defaultOptions, options) - - return { - name: '@vuepress-plume/plugin-copy-code', - - define: (): Record => ({ - __COPY_CODE_OPTIONS__: options, - }), - - clientConfigFile: path.resolve(__dirname, '../client/clientConfig.js'), - } -} diff --git a/plugins/plugin-copy-code/src/shared/index.ts b/plugins/plugin-copy-code/src/shared/index.ts deleted file mode 100644 index 1af4b158..00000000 --- a/plugins/plugin-copy-code/src/shared/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -export interface CopyCodeOptions { - /** - * 代码块选择器 - * - * @default '.theme-default-content dev[class*="language-"] pre' - */ - selector?: string | string[] - - /** - * 提示消息显示时间 - * - * @description 设置为 `0` 将会禁用提示 - * - * @default 1500 - */ - duration?: number - - /** - * 是否展示在移动端 - */ - showInMobile?: boolean - - /** - * 注册复制按钮的延时,单位 ms - * - * @default 500 - */ - delay?: number -} diff --git a/plugins/plugin-copy-code/tsconfig.build.json b/plugins/plugin-copy-code/tsconfig.build.json deleted file mode 100644 index 6bf67375..00000000 --- a/plugins/plugin-copy-code/tsconfig.build.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "outDir": "./lib" - }, - "include": ["./src"] -} diff --git a/plugins/plugin-notes-data/LICENSE b/plugins/plugin-notes-data/LICENSE deleted file mode 100644 index 9f677c90..00000000 --- a/plugins/plugin-notes-data/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (C) 2021 - PRESENT by pengzhanbo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/plugins/plugin-notes-data/README.md b/plugins/plugin-notes-data/README.md deleted file mode 100644 index ef52022f..00000000 --- a/plugins/plugin-notes-data/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# `@vuepress-plume/plugin-notes-data` - -## Install - -```sh -npm install @vuepress-plume/plugin-notes-data -# or -pnpm add @vuepress-plume/plugin-notes-data -# or -yarn add @vuepress-plume/plugin-notes-data -``` - -## Usage - -``` js -// .vuepress/config.[jt]s -import { notesDataPlugin } from '@vuepress-plume/plugin-notes-data' - -export default { - // ... - plugins: [ - notesDataPlugin() - ] - // ... -} -``` - -## Options - -``` ts -interface NotesDataOptions { - dir: string - link: string - include?: string | string[] - exclude?: string | string[] - notes: NotesItem[] -} - -interface NotesItem { - dir: string - link: string - text: string - sidebar?: NotesSidebar | 'auto' -} - -type NotesSidebar = (NotesSidebarItem | string)[] - -interface NotesSidebarItem { - text?: string - link?: string - dir?: string - collapsed?: boolean - items?: NotesSidebar -} -``` diff --git a/plugins/plugin-notes-data/package.json b/plugins/plugin-notes-data/package.json deleted file mode 100644 index 9a650afe..00000000 --- a/plugins/plugin-notes-data/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@vuepress-plume/plugin-notes-data", - "type": "module", - "version": "1.0.0-rc.75", - "private": "true", - "description": "The Plugin for VuePress 2 - notes data", - "author": "pengzhanbo ", - "license": "MIT", - "homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git", - "directory": "plugins/plugin-notes-data" - }, - "bugs": { - "url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues" - }, - "exports": { - ".": { - "types": "./lib/node/index.d.ts", - "import": "./lib/node/index.js" - }, - "./client": { - "types": "./lib/client/index.d.ts", - "import": "./lib/client/index.js" - }, - "./package.json": "./package.json" - }, - "main": "lib/node/index.js", - "types": "./lib/node/index.d.ts", - "files": [ - "lib" - ], - "scripts": { - "build": "pnpm run copy && pnpm run ts", - "clean": "rimraf --glob ./lib ./*.tsbuildinfo", - "copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib", - "ts": "tsc -b tsconfig.build.json" - }, - "peerDependencies": { - "vuepress": "2.0.0-rc.14" - }, - "dependencies": { - "@vue/devtools-api": "6.6.3", - "chokidar": "^3.6.0", - "create-filter": "^1.1.0", - "vue": "^3.4.31" - }, - "publishConfig": { - "access": "public" - }, - "keyword": [ - "VuePress", - "vuepress plugin", - "notesData", - "vuepress-plugin-plugin-notes-data" - ] -} diff --git a/plugins/plugin-notes-data/src/client/clientConfig.ts b/plugins/plugin-notes-data/src/client/clientConfig.ts deleted file mode 100644 index 4cd6b0e1..00000000 --- a/plugins/plugin-notes-data/src/client/clientConfig.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { setupDevtoolsPlugin } from '@vue/devtools-api' -import { defineClientConfig } from 'vuepress/client' -import type { ClientConfig } from 'vuepress/client' -import { useNotesData } from './composables/index.js' - -declare const __VUE_PROD_DEVTOOLS__: boolean - -export default defineClientConfig({ - enhance({ app }) { - const notesData = useNotesData() - - Object.defineProperties(app.config.globalProperties, { - $notesData: { - get() { - return notesData.value - }, - }, - }) - - // setup devtools in dev mode - if (__VUEPRESS_DEV__ || __VUE_PROD_DEVTOOLS__) { - const PLUGIN_ID = 'org.vuejs.vuepress' - const PLUGIN_LABEL = 'VuePress' - const INSPECTOR_ID = PLUGIN_ID - - setupDevtoolsPlugin( - { - // fix recursive reference - app: app as any, - id: PLUGIN_ID, - label: PLUGIN_LABEL, - packageName: '@vuepress-plume/plugin-notes-data', - homepage: 'https://theme-plume.vuejs.press/', - logo: 'https://v2.vuepress.vuejs.org/images/hero.png', - componentStateTypes: ['VuePress'], - }, - (api) => { - api.on.inspectComponent((payload) => { - payload.instanceData.state.push({ - type: 'VuePress', - key: 'notesData', - editable: false, - value: notesData.value, - }) - }) - api.on.getInspectorTree((payload) => { - if (payload.inspectorId !== INSPECTOR_ID) - return - payload.rootNodes.push({ - id: 'notes_data', - label: 'Notes Data', - }) - }) - api.on.getInspectorState((payload) => { - if (payload.inspectorId !== INSPECTOR_ID) - return - if (payload.nodeId === 'notes_data') { - payload.state = { - NotesData: [{ - key: 'notesData', - value: notesData.value, - }], - } - } - }) - }, - ) - } - }, -}) as ClientConfig diff --git a/plugins/plugin-notes-data/src/client/composables/index.ts b/plugins/plugin-notes-data/src/client/composables/index.ts deleted file mode 100644 index 6434f5b2..00000000 --- a/plugins/plugin-notes-data/src/client/composables/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './notesDate.js' diff --git a/plugins/plugin-notes-data/src/client/composables/notesDate.ts b/plugins/plugin-notes-data/src/client/composables/notesDate.ts deleted file mode 100644 index bf357409..00000000 --- a/plugins/plugin-notes-data/src/client/composables/notesDate.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { notesData as notesDataRaw } from '@internal/notesData' -import { ref } from 'vue' -import type { Ref } from 'vue' -import type { NotesData } from '../../shared/index.js' - -declare const __VUE_HMR_RUNTIME__: Record - -export type NotesDataRef = Ref - -export const notesData: NotesDataRef = ref(notesDataRaw) - -export function useNotesData< - T extends NotesData = NotesData, ->(): NotesDataRef { - return notesData as NotesDataRef -} - -if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) { - __VUE_HMR_RUNTIME__.updateNotesData = (data: NotesData) => { - notesData.value = data - } -} diff --git a/plugins/plugin-notes-data/src/client/index.ts b/plugins/plugin-notes-data/src/client/index.ts deleted file mode 100644 index 16748f83..00000000 --- a/plugins/plugin-notes-data/src/client/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { NotesData, NotesSidebarItem } from '../shared/index.js' -export * from './composables/index.js' diff --git a/plugins/plugin-notes-data/src/client/notesData.d.ts b/plugins/plugin-notes-data/src/client/notesData.d.ts deleted file mode 100644 index f5258ec2..00000000 --- a/plugins/plugin-notes-data/src/client/notesData.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { NotesData } from '../shared/index.js' - -declare module '@internal/notesData' { - const notesData: NotesData - - export { notesData } -} diff --git a/plugins/plugin-notes-data/src/node/index.ts b/plugins/plugin-notes-data/src/node/index.ts deleted file mode 100644 index 69e663e0..00000000 --- a/plugins/plugin-notes-data/src/node/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { notesDataPlugin } from './plugin.js' - -export * from './plugin.js' -export * from '../shared/index.js' - -export default notesDataPlugin diff --git a/plugins/plugin-notes-data/src/node/plugin.ts b/plugins/plugin-notes-data/src/node/plugin.ts deleted file mode 100644 index 62b1f47f..00000000 --- a/plugins/plugin-notes-data/src/node/plugin.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { Plugin } from 'vuepress/core' -import { getDirname, path } from 'vuepress/utils' -import type { NotesDataOptions } from '../shared/index.js' -import { prepareNotesData, watchNotesData } from './prepareNotesData.js' -import { wait } from './utils.js' - -export function notesDataPlugin(options: NotesDataOptions | NotesDataOptions[]): Plugin { - return { - name: '@vuepress-plume/plugin-notes-data', - - clientConfigFile: path.join( - getDirname(import.meta.url), - '../client/clientConfig.js', - ), - - onPrepared: async (app) => { - await wait(50) - await prepareNotesData(app, options) - }, - onWatched: (app, watchers) => watchNotesData(app, watchers, options), - } -} diff --git a/plugins/plugin-notes-data/src/node/prepareNotesData.ts b/plugins/plugin-notes-data/src/node/prepareNotesData.ts deleted file mode 100644 index 557c623e..00000000 --- a/plugins/plugin-notes-data/src/node/prepareNotesData.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { colors, logger, path } from 'vuepress/utils' -import type { App } from 'vuepress/core' -import * as chokidar from 'chokidar' -import { createFilter } from 'create-filter' -import type { - NotesData, - NotesDataOptions, - NotesItemOptions, - NotesSidebar, - NotesSidebarItem, -} from '../shared/index.js' -import { ensureArray, hash, normalizePath } from './utils.js' - -const HMR_CODE = ` -if (import.meta.webpackHot) { - import.meta.webpackHot.accept() - if (__VUE_HMR_RUNTIME__.updateNotesData) { - __VUE_HMR_RUNTIME__.updateNotesData(notesData) - } -} - -if (import.meta.hot) { - import.meta.hot.accept(({ notesData }) => { - __VUE_HMR_RUNTIME__.updateNotesData(notesData) - }) -} -` - -interface NotePage { - relativePath: string - title: string - link: string - frontmatter: Record -} - -function resolvedNotesData(app: App, options: NotesDataOptions, result: NotesData) { - const { include, exclude, notes, dir: _dir, link } = options - if (!notes || notes.length === 0) - return - const dir = normalizePath(_dir).replace(/^\//, '') - const filter = createFilter(ensureArray(include), ensureArray(exclude), { - resolve: false, - }) - const DIR_PATTERN = new RegExp(`^${normalizePath(path.join(dir, '/'))}`) - const notesPageList: NotePage[] = app.pages - .filter( - page => - page.filePathRelative - && page.filePathRelative.startsWith(dir) - && filter(page.filePathRelative), - ) - .map(page => ({ - relativePath: page.filePathRelative?.replace(DIR_PATTERN, '') || '', - title: page.title, - link: page.path, - frontmatter: page.frontmatter, - })) - notes.forEach((note) => { - result[normalizePath(path.join('/', link, note.link))] = initSidebar( - note, - notesPageList.filter(page => - page.relativePath.startsWith(note.dir.trim().replace(/^\/|\/$/g, '')), - ), - ) - }) -} - -let contentHash: string | undefined -export async function prepareNotesData(app: App, options: NotesDataOptions | NotesDataOptions[]) { - const start = performance.now() - const notesData: NotesData = {} - const allOptions = ensureArray(options) - - allOptions.forEach(option => resolvedNotesData(app, option, notesData)) - - let content = ` -export const notesData = ${JSON.stringify(notesData, null, 2)} -` - if (app.env.isDev) - content += HMR_CODE - - const currentHash = hash(content) - if (!contentHash || contentHash !== currentHash) { - contentHash = currentHash - await app.writeTemp('internal/notesData.js', content) - } - - if (app.env.isDebug) { - logger.info( - `\n[${colors.green('@vuepress-plume/plugin-notes-data')}] prepare notes data time spent: ${(performance.now() - start).toFixed(2)}ms`, - ) - } -} - -export function watchNotesData(app: App, watchers: any[], options: NotesDataOptions | NotesDataOptions[]): void { - const allOptions = ensureArray(options) - if (!allOptions.length) - return - - const [firstLink, ...links] = allOptions.map(option => option.link).filter(Boolean) - - if (!firstLink) - return - - const dir = path.join('pages', firstLink, '**/*') - const watcher = chokidar.watch(dir, { - cwd: app.dir.temp(), - ignoreInitial: true, - }) - - links.length && watcher.add(links.map(link => path.join('pages', link, '**/*'))) - - watcher.on('add', () => prepareNotesData(app, options)) - watcher.on('change', () => prepareNotesData(app, options)) - watcher.on('unlink', () => prepareNotesData(app, options)) - watchers.push(watcher) -} - -function initSidebar(note: NotesItemOptions, pages: NotePage[]): NotesSidebarItem[] { - if (!note.sidebar) - return [] - if (note.sidebar === 'auto') - return initSidebarByAuto(note, pages) - return initSidebarByConfig(note, pages) -} - -function initSidebarByAuto( - note: NotesItemOptions, - pages: NotePage[], -): NotesSidebarItem[] { - let tempPages = pages.map((page) => { - return { ...page, splitPath: page.relativePath.split('/') } - }) - - const maxIndex = Math.max(...tempPages.map(page => page.splitPath.length)) - let nowIndex = 0 - - while (nowIndex < maxIndex) { - tempPages = tempPages.sort((prev, next) => { - const pi = prev.splitPath?.[nowIndex]?.match(/(\d+)\.(?=[^/]+$)/)?.[1] - const ni = next.splitPath?.[nowIndex]?.match(/(\d+)\.(?=[^/]+$)/)?.[1] - if (!pi || !ni) - return 0 - return Number.parseFloat(pi) < Number.parseFloat(ni) ? -1 : 1 - }) - - nowIndex++ - } - - pages = tempPages.map((page) => { - delete (page as any).splitPath - return page - }) - - const RE_INDEX = ['index.md', 'README.md', 'readme.md'] - const result: NotesSidebarItem[] = [] - for (const page of pages) { - const { relativePath, title, link, frontmatter } = page - const paths = relativePath - .slice(note.dir.replace(/^\/|\/$/g, '').length + 1) - .split('/') - let index = 0 - let dir: string - let items = result - // eslint-disable-next-line no-cond-assign - while ((dir = paths[index])) { - const text = dir.replace(/\.md$/, '').replace(/^\d+\./, '') - let current = items.find(item => item.text === text) - if (!current) { - current = { text, link: undefined, items: [] } - !RE_INDEX.includes(dir) ? items.push(current) : items.unshift(current) - } - if (dir.endsWith('.md')) { - current.link = link - current.text = title - } - if (frontmatter.icon) - current.icon = frontmatter.icon - - items = current.items as NotesSidebarItem[] - index++ - } - } - return result -} - -function initSidebarByConfig( - { text, dir, sidebar }: NotesItemOptions, - pages: NotePage[], -): NotesSidebarItem[] { - return (sidebar as NotesSidebar).map((item) => { - if (typeof item === 'string') { - const current = findNotePage(item, dir, pages) - return { - text: current?.title || text, - link: current?.link, - icon: current?.frontmatter.icon, - // items: [], - } - } - else { - const current = findNotePage(item.link || '', dir, pages) - return { - text: item.text || item.dir || current?.title, - collapsed: item.collapsed, - icon: item.icon || current?.frontmatter.icon, - link: item.link, - items: initSidebarByConfig( - { - link: item.link || '', - text: item.text || '', - sidebar: item.items, - dir: normalizePath(path.join(dir, item.dir || '')), - }, - pages, - ), - } - } - }) -} - -function findNotePage( - sidebar: string, - dir: string, - notePageList: NotePage[], -): NotePage | undefined { - if (sidebar === '' || sidebar === 'README.md' || sidebar === 'index.md') { - return notePageList.find((page) => { - const relative = page.relativePath - return ( - relative === normalizePath(path.join(dir, 'README.md')) - || relative === normalizePath(path.join(dir, 'index.md')) - ) - }) - } - else { - return notePageList.find((page) => { - const relative = page.relativePath - return ( - relative === normalizePath(path.join(dir, sidebar)) - || relative === normalizePath(path.join(dir, `${sidebar}.md`)) - || page.link === sidebar - ) - }) - } -} diff --git a/plugins/plugin-notes-data/src/node/utils.ts b/plugins/plugin-notes-data/src/node/utils.ts deleted file mode 100644 index 8e3da042..00000000 --- a/plugins/plugin-notes-data/src/node/utils.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createHash } from 'node:crypto' - -export function ensureArray(thing: T | T[] | null | undefined): T[] { - if (Array.isArray(thing)) - return thing - if (thing === null || thing === undefined) - return [] - return [thing] -} - -export function normalizePath(str: string) { - return str.replace(/\\+/g, '/') -} - -export function wait(time: number) { - return new Promise(resolve => setTimeout(resolve, time)) -} - -export function hash(content: string): string { - return createHash('md5').update(content).digest('hex') -} diff --git a/plugins/plugin-notes-data/src/shared/index.ts b/plugins/plugin-notes-data/src/shared/index.ts deleted file mode 100644 index 0253d665..00000000 --- a/plugins/plugin-notes-data/src/shared/index.ts +++ /dev/null @@ -1,77 +0,0 @@ -export interface NotesDataOptions { - /** - * 保存所有笔记的目录 - * @default '/notes/' - */ - dir: string - /** - * 所有笔记的默认链接前缀 - * @default '/' - */ - link: string - /** - * global include,只加载需要加载到笔记中的文件 - */ - include?: string | string[] - /** - * global exclude,排除不需要加载到笔记中的文件 - */ - exclude?: string | string[] - /** - * 笔记配置 - */ - notes: NotesItemOptions[] -} - -export type NotesItemOptions = (Omit & { text?: string }) - -export interface NotesItem { - /** - * 保存笔记的目录 - */ - dir: string - /** - * 当前笔记的链接前缀,将会与 `notes.link` 合并 - */ - link: string - /** - * 当前笔记名称 - */ - text: string - /** - * 当前笔记的侧边栏配置 - */ - sidebar?: NotesSidebar | 'auto' -} - -export type NotesSidebar = (NotesSidebarItem | string)[] - -export interface NotesSidebarItem { - /** - * 侧边栏文本,如果为空,则使用 `dir` - */ - text?: string - /** - * 侧边栏链接 - */ - link?: string - /** - * 次级侧边栏所在目录 - */ - dir?: string - /** - * 是否折叠, 未定义时不可折叠 - * @default undefined - */ - collapsed?: boolean - /** - * 次级侧边栏 - */ - items?: NotesSidebar - /** - * 侧边栏图标 - */ - icon?: string | { svg: string } -} - -export type NotesData = Record diff --git a/plugins/plugin-notes-data/tsconfig.build.json b/plugins/plugin-notes-data/tsconfig.build.json deleted file mode 100644 index e2bd7e8d..00000000 --- a/plugins/plugin-notes-data/tsconfig.build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../tsconfig.build.json", - "compilerOptions": { - "rootDir": "./src", - "paths": { - "@internal/notesData": ["./src/client/notesData.d.ts"] - }, - "types": ["vuepress/client-types", "vite/client", "webpack-env"], - "outDir": "./lib" - }, - "include": ["./src"] -} diff --git a/plugins/tsconfig.build.json b/plugins/tsconfig.build.json index 7f254e32..79fcf8d6 100644 --- a/plugins/tsconfig.build.json +++ b/plugins/tsconfig.build.json @@ -4,13 +4,9 @@ "composite": true }, "references": [ - { "path": "./plugin-auto-frontmatter/tsconfig.build.json" }, { "path": "./plugin-baidu-tongji/tsconfig.build.json" }, - { "path": "./plugin-blog-data/tsconfig.build.json" }, - { "path": "./plugin-caniuse/tsconfig.build.json" }, - { "path": "./plugin-copy-code/tsconfig.build.json" }, { "path": "./plugin-iconify/tsconfig.build.json" }, - { "path": "./plugin-notes-data/tsconfig.build.json" }, + { "path": "./plugin-fonts/tsconfig.build.json" }, { "path": "./plugin-shikiji/tsconfig.build.json" }, { "path": "./plugin-content-update/tsconfig.build.json" }, { "path": "./plugin-search/tsconfig.build.json" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2632c5a4..40ada0cf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,67 +106,12 @@ importers: specifier: ^4.17.21 version: 4.17.21 - plugins/plugin-auto-frontmatter: - dependencies: - '@pengzhanbo/utils': - specifier: ^1.1.2 - version: 1.1.2 - chokidar: - specifier: ^3.6.0 - version: 3.6.0 - create-filter: - specifier: ^1.1.0 - version: 1.1.0 - fast-glob: - specifier: ^3.3.2 - version: 3.3.2 - gray-matter: - specifier: ^4.0.3 - version: 4.0.3 - json2yaml: - specifier: ^1.1.0 - version: 1.1.0 - vuepress: - specifier: 2.0.0-rc.14 - version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - plugins/plugin-baidu-tongji: dependencies: vuepress: specifier: 2.0.0-rc.14 version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - plugins/plugin-blog-data: - dependencies: - '@vue/devtools-api': - specifier: 6.6.3 - version: 6.6.3 - chokidar: - specifier: ^3.6.0 - version: 3.6.0 - create-filter: - specifier: ^1.1.0 - version: 1.1.0 - vue: - specifier: ^3.4.31 - version: 3.4.31(typescript@5.5.3) - vuepress: - specifier: 2.0.0-rc.14 - version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - - plugins/plugin-caniuse: - dependencies: - markdown-it-container: - specifier: ^4.0.0 - version: 4.0.0 - vuepress: - specifier: 2.0.0-rc.14 - version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - devDependencies: - '@types/markdown-it': - specifier: ^14.1.1 - version: 14.1.1 - plugins/plugin-content-update: dependencies: vue: @@ -176,18 +121,6 @@ importers: specifier: 2.0.0-rc.14 version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - plugins/plugin-copy-code: - dependencies: - '@vuepress-plume/plugin-content-update': - specifier: workspace:~ - version: link:../plugin-content-update - vue: - specifier: ^3.4.31 - version: 3.4.31(typescript@5.5.3) - vuepress: - specifier: 2.0.0-rc.14 - version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - plugins/plugin-fonts: dependencies: vuepress: @@ -249,24 +182,6 @@ importers: specifier: ^14.1.1 version: 14.1.1 - plugins/plugin-notes-data: - dependencies: - '@vue/devtools-api': - specifier: 6.6.3 - version: 6.6.3 - chokidar: - specifier: ^3.6.0 - version: 3.6.0 - create-filter: - specifier: ^1.1.0 - version: 1.1.0 - vue: - specifier: ^3.4.31 - version: 3.4.31(typescript@5.5.3) - vuepress: - specifier: 2.0.0-rc.14 - version: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(typescript@5.5.3))(typescript@5.5.3)(vue@3.4.31(typescript@5.5.3)) - plugins/plugin-search: dependencies: '@vuepress/helper': diff --git a/tsconfig.json b/tsconfig.json index 7b9356ef..c267a5ab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,12 +4,6 @@ "jsx": "preserve", "baseUrl": ".", "paths": { - "@internal/blogData": [ - "./plugins/plugin-blog-data/src/client/blogPostData.d.ts" - ], - "@internal/notesData": [ - "./plugins/plugin-notes-data/src/client/notesData.d.ts" - ], "@internal/md-power/replEditorData": [ "./plugins/plugin-md-power/src/client/shim.d.ts" ], @@ -22,9 +16,7 @@ "vuepress-plugin-md-power": [ "./plugins/plugin-md-power/src/node/index.ts" ], - "@theme/*": [ - "./theme/src/client/components/*" - ] + "@theme/*": ["./theme/src/client/components/*"] }, "types": ["webpack-env", "vite/client", "vuepress/client-types"] },