diff --git a/docs/docs/guide/folder-specification.md b/docs/docs/guide/folder-specification.md index 74ea22ae..f9e864d9 100644 --- a/docs/docs/guide/folder-specification.md +++ b/docs/docs/guide/folder-specification.md @@ -4,5 +4,5 @@ date: 2022-08-18 23:24:45 --- :::warning -reco 主题实现了博客的功能,但是 vuepress 没有办法区分博客或是文档,导致文档也会出现在博客区域,所以主题对博客和文档的存放位置进行了约束,博客文章请放在 `/blogs` 文件夹中(强制),文档请放在 `/docs` 中(不强制)。 +reco 主题实现了博客的功能,但是 vuepress 没有办法区分博客或是文档,导致文档也会出现在博客区域,所以主题对博客和文档的存放位置进行了约束,博客文章请放在 `/blogs` 文件夹中(强制),文档系列请放在 `/series` 文件夹中(强制),普通文档请放在 `/docs` 中(不强制)。 ::: diff --git a/docs/docs/theme/auto-set-series.md b/docs/docs/theme/auto-set-series.md index 132809d5..54d89547 100644 --- a/docs/docs/theme/auto-set-series.md +++ b/docs/docs/theme/auto-set-series.md @@ -5,12 +5,12 @@ date: 2023-02-17 ## 介绍 -为了节约用户的时间成本,主题可以自动将 `docs` 文件夹下的文档,按照文件夹嵌套关系生成系列的配置。 +为了节约用户的时间成本,主题可以自动将 `series` 文件夹下的文档,按照文件夹嵌套关系生成系列的配置。 ``` / └─ .vuepress -└─ docs +└─ series └─ 系列1 └─ 文档1.md └─ 文档2.md diff --git a/docs/en/docs/guide/folder-specification.md b/docs/en/docs/guide/folder-specification.md index b82e69a1..e2fb9433 100644 --- a/docs/en/docs/guide/folder-specification.md +++ b/docs/en/docs/guide/folder-specification.md @@ -4,5 +4,5 @@ date: 2022-08-18 23:24:45 --- :::warning -The reco theme implements the function of the blog, but vuepress has no way to distinguish blogs or documents, so the documents will also appear in the blog area, so the theme restricts the storage location of blogs and documents, blog articles should be placed in the `/blogs` file folder (mandatory), documents should be placed in `/docs` (not mandatory). +The reco theme implements the function of the blog, but vuepress has no way to distinguish blogs or documents, so the documents will also appear in the blog area, so the theme restricts the storage location of blogs and documents, blog articles should be placed in the `/blogs` file folder (mandatory), documents sery should be placed in the `/series` file folder (mandatory), ordinary documents should be placed in `/docs` (not mandatory). ::: diff --git a/docs/en/docs/theme/auto-set-series.md b/docs/en/docs/theme/auto-set-series.md index a7346e17..0beb0481 100644 --- a/docs/en/docs/theme/auto-set-series.md +++ b/docs/en/docs/theme/auto-set-series.md @@ -5,12 +5,12 @@ date: 2023-02-17 ## Introduction -In order to save users' time cost, the theme can automatically generate a series of configurations for the documents under the `docs` folder according to the folder nesting relationship. +In order to save users' time cost, the theme can automatically generate a series of configurations for the documents under the `series` folder according to the folder nesting relationship. ``` / └─ .vuepress -└─ docs +└─ series └─ sery 1 └─ doc1.md └─ doc2.md diff --git a/example/.vuepress/config.js b/example/.vuepress/config.js index c37ddc46..b4edb2b2 100644 --- a/example/.vuepress/config.js +++ b/example/.vuepress/config.js @@ -57,25 +57,25 @@ export default defineUserConfig({ gitBranch: 'main', sourceDir: 'example', lastUpdatedText: '', - series: { - '/group/': [ - { - text: 'group', - icon: 'Language', - children: ['/group/bar.md', '/group/foo.md'], - }, - ], - '/blogs/': [ - { - text: 'blogs1', - children: [ - '/blogs/category1/blog1.md', - '/blogs/category1/blog2.md', - '/blogs/category1/blog3.md', - ], - }, - ], - }, + // series: { + // '/group/': [ + // { + // text: 'group', + // icon: 'Language', + // children: ['/group/bar.md', '/group/foo.md'], + // }, + // ], + // '/blogs/': [ + // { + // text: 'blogs1', + // children: [ + // '/blogs/category1/blog1.md', + // '/blogs/category1/blog2.md', + // '/blogs/category1/blog3.md', + // ], + // }, + // ], + // }, navbar: [ { text: '博客', diff --git a/example/series/sery1/aaa2.md b/example/series/sery1/aaa2.md new file mode 100644 index 00000000..b1ae56ec --- /dev/null +++ b/example/series/sery1/aaa2.md @@ -0,0 +1,3 @@ +--- +title: aaa2 +--- \ No newline at end of file diff --git a/example/series/sery1/b/bbb1.md b/example/series/sery1/b/bbb1.md new file mode 100644 index 00000000..cf1627fb --- /dev/null +++ b/example/series/sery1/b/bbb1.md @@ -0,0 +1,3 @@ +--- +title: bbb1 +--- \ No newline at end of file diff --git a/example/series/sery1/b/bbb2.md b/example/series/sery1/b/bbb2.md new file mode 100644 index 00000000..661b8986 --- /dev/null +++ b/example/series/sery1/b/bbb2.md @@ -0,0 +1,3 @@ +--- +title: bbb2 +--- \ No newline at end of file diff --git "a/example/series/sery1/\346\265\213\350\257\225.md" "b/example/series/sery1/\346\265\213\350\257\225.md" new file mode 100644 index 00000000..fcebfb91 --- /dev/null +++ "b/example/series/sery1/\346\265\213\350\257\225.md" @@ -0,0 +1,3 @@ +--- +title: aaa +--- \ No newline at end of file diff --git a/example/series/sery2/ccc.md b/example/series/sery2/ccc.md new file mode 100644 index 00000000..fc2cb92c --- /dev/null +++ b/example/series/sery2/ccc.md @@ -0,0 +1,3 @@ +--- +title: ccc +--- \ No newline at end of file diff --git a/example/series/sery2/ccc2.md b/example/series/sery2/ccc2.md new file mode 100644 index 00000000..1b578e2a --- /dev/null +++ b/example/series/sery2/ccc2.md @@ -0,0 +1,3 @@ +--- +title: ccc2 +--- \ No newline at end of file diff --git a/packages/@vuepress-reco/plugin-page/src/node/PageCreater.ts b/packages/@vuepress-reco/plugin-page/src/node/PageCreater.ts index 08a7d487..280f26f3 100644 --- a/packages/@vuepress-reco/plugin-page/src/node/PageCreater.ts +++ b/packages/@vuepress-reco/plugin-page/src/node/PageCreater.ts @@ -95,12 +95,6 @@ export default class PageCreater { } parse() { - this._parsePageOptions() - - this._setBlogsToCategoryPageData() - - this._createExtendedPages() - /** * The name of the file is changed in the develop environment, * and bug of 404 appears during hot updates. @@ -109,6 +103,12 @@ export default class PageCreater { if (this.app.env.isBuild) { this._parseChineseInPagePathToPinyin() } + + this._parsePageOptions() + + this._setBlogsToCategoryPageData() + + this._createExtendedPages() } // 将 path 中的中文转换成拼音 @@ -211,7 +211,7 @@ export default class PageCreater { this.__blogs_to_be_released__ = blogsToBeReleased - blogsToBeReleased.forEach((page: ReleasedPage, index) => { + blogsToBeReleased.forEach((page: ReleasedPage) => { const categoryKeysOfFrontmatter = Object.keys(page.frontmatter) .filter((key: string) => { return this.__category_keys__.includes(key) @@ -320,45 +320,40 @@ export default class PageCreater { // 设置系列 private _setSeries(page) { - let docSeries = ((page.filePath || '') as string).match( - /.+\/docs\/(.+)\/(.+)\/(.+)\.md$/ + let matches = ((page.filePath || '') as string).match( + /\/series\/([^/]+)(\S*?)\/([^/.]+)\.md/ ) - if (docSeries) { - const group = docSeries[2] - const series = `/docs/${docSeries[1]}/` - const filePath = `${series}${group}/${docSeries[3]}.md` - - if (!this.__series__?.[series]) { - this.__series__[`/${series}/`] = [{ - text: group, - children: [filePath], - }] - } else if ( !this.__series__[series].some((groupItem) => groupItem?.text === group)) { - this.__series__[series].push({ - text: group, - children: [filePath], + if (!matches) return + + const [filePath, sery, dirStr] = matches + const seryKey = `/series/${sery}/` + + if (!this.__series__?.[seryKey]) { + this.__series__[seryKey] = [] + } + + const dirs = dirStr.split('/').splice(1) + const dirLen = dirs.length + if (dirLen === 0) { + this.__series__[seryKey].push(filePath) + return + } + dirs.reduce((total, current, index) => { + if (!total.some((groupItem) => groupItem?.text === current)) { + total.push({ + text: current, + children: index === dirLen - 1 ? [filePath] : [], }) } else { - this.__series__[series] - .find((groupItem) => groupItem?.text === group) - .children.push(filePath) + total.find((groupItem) => groupItem?.text === current).children.push(index === dirLen - 1 ? filePath : { + text: current, + children: index === dirLen - 1 ? [filePath] : [], + }) } - } else { - docSeries = ((page.filePath || '') as string).match( - /.+\/docs\/(.+)\/(.+)\.md$/ - ) - if (docSeries) { - const series = `/docs/${docSeries[1]}/` - const filePath = `${series}${docSeries[2]}.md` - if (!this.__series__?.[series]) { - this.__series__[series] = [filePath] - } else { - this.__series__[series].push(filePath) - } - } - } + return total + }, this.__series__[seryKey]) } } diff --git a/packages/vuepress-theme-reco/src/client/clientSetup.ts b/packages/vuepress-theme-reco/src/client/clientSetup.ts index 93692ac4..a7968127 100644 --- a/packages/vuepress-theme-reco/src/client/clientSetup.ts +++ b/packages/vuepress-theme-reco/src/client/clientSetup.ts @@ -4,12 +4,9 @@ import { usePageData, catalogSymbol, headersToCatalog, - seriesItemsSymbol, - resolveSeriesItems, useThemeLocaleData, usePageFrontmatter, } from '@composables/index.js' -import { useExtendPageData } from '@vuepress-reco/vuepress-plugin-page/composables' export function applyClientSetup() { // we need to access series items in multiple components @@ -17,11 +14,6 @@ export function applyClientSetup() { const themeLocal = useThemeLocaleData() const frontmatter = usePageFrontmatter() const route = useRoute() - const { series } = useExtendPageData() - const seriesItems = computed(() => - resolveSeriesItems(frontmatter.value, themeLocal.value, route, series) - ) - provide(seriesItemsSymbol, seriesItems) const page = usePageData() const catalog = computed(() => headersToCatalog(page.value.headers)) diff --git a/packages/vuepress-theme-reco/src/client/composables/useSeriesItems.ts b/packages/vuepress-theme-reco/src/client/composables/useSeriesItems.ts index 6b458478..437b614c 100644 --- a/packages/vuepress-theme-reco/src/client/composables/useSeriesItems.ts +++ b/packages/vuepress-theme-reco/src/client/composables/useSeriesItems.ts @@ -1,7 +1,11 @@ -import { inject } from 'vue' +import { computed } from 'vue' import type { ComputedRef, InjectionKey } from 'vue' -import type { RouteLocationNormalizedLoaded } from 'vuepress/client' +import { useRoute, usePageFrontmatter, type RouteLocationNormalizedLoaded } from 'vuepress/client' import { isPlainObject, isString, resolveLocalePath } from 'vuepress/shared' +import { useExtendPageData } from '@vuepress-reco/vuepress-plugin-page/composables' + + +import { useThemeLocaleData } from '@composables/index.js' import type { RecoThemeData, @@ -37,19 +41,22 @@ export interface ResolvedSeriesItem extends Partial { export type SeriesItemsRef = ComputedRef -export const seriesItemsSymbol: InjectionKey = Symbol( - 'seriesItems' -) - export const useSeriesItems = (): SeriesItemsRef => { - const seriesItems = inject(seriesItemsSymbol) + const route = useRoute() + const { series } = useExtendPageData() + const themeLocal = useThemeLocaleData() + const frontmatter = usePageFrontmatter() + const seriesItems = computed(() => + resolveSeriesItems(frontmatter.value, themeLocal.value, route, series) + ) + if (!seriesItems) { throw new Error('useSeriesItems() is called without provider.') } return seriesItems } -export const resolveSeriesItems = ( +const resolveSeriesItems = ( frontmatter: RecoThemeNormalPageFrontmatter, themeLocal: RecoThemeData, route: RouteLocationNormalizedLoaded, @@ -80,7 +87,7 @@ export const resolveSeriesItems = ( /** * Resolve series items if the config is an array */ -export const resolveArraySeriesItems = (seriesPath: string, seriesConfig: SeriesConfigArray): ResolvedSeriesItem[] => { +const resolveArraySeriesItems = (seriesPath: string, seriesConfig: SeriesConfigArray): ResolvedSeriesItem[] => { const handleChildItem = ( item: ResolvedSeriesItem | SeriesGroup | SeriesItem | string, ): ResolvedSeriesItem => { @@ -114,7 +121,7 @@ export const resolveArraySeriesItems = (seriesPath: string, seriesConfig: Series /** * Resolve series items if the config is a key -> value (path-prefix -> array) object */ -export const resolveMultiSeriesItems = ( +const resolveMultiSeriesItems = ( seriesConfig: SeriesConfigObject, route: RouteLocationNormalizedLoaded ): ResolvedSeriesItem[] => {