跳到主要内容

teek配置rewrite模式

最后更新于:

Teek配置rewrite模式

目录

[[toc]]

[toc]

前言

那么,为什么要切换到rewrite呢?

  1. 左下角会有中文路径提示
  2. url打开会有中文提示

注意

使用原则

  1. 必须保证 一级目录下的 所有md都得有同一个一级前缀,例如 /一级前缀/随机uid
  2. 一级前缀决定了是否都在同一个侧边栏显示
  3. 你一级目录下,都是其子目录,默认都弄成同一个一级前缀就好了呗。如果不想让他出现在侧边栏,那就单独指定一个一级目录。
  4. 所以,一级前缀 就统一整成 /技术/xxx /专题/xxx /生活/xxx /兴趣/xxx /关于/xxx (这里的中文可以替换为对应的英文)

image-20250824213924835

环境

Teek@1.5.0-2025.9.23 版本上测试

自己的开源库《vitepress-theme-teek-one》 –(克隆自 作者Teeker的文档风开源库《vitepress-theme-teek-docs-template》)

2025年9月26日测试

1、从proxy模式切换到rewrite模式

默认安装的Teek是proxy模式,这里需要手动切换到rewrite模式。

1、导入

编辑docs\.vitepress\config.ts文件

1import { createRewrites } from "vitepress-theme-teek/config"; //配置rewrites

2、配置

编辑docs\.vitepress\config.ts文件

export default defineConfig({}) 区域配置。

1//配置rewrites  
2rewrites: createRewrites({
3    srcDir: 'docs',
4  }),

image-20250926210407809

编辑docs\.vitepress\teekConfig.ts文件:

 1  // 开启 permalink 插件
 2  vitePlugins: {
 3    permalink: true,
 4    sidebar: true,
 5
 6
 7    sidebarOption: {
 8      // initItems: false, //这条命令注释后,才会让文档和目录的样式保持一致
 9      collapsed: true, //打开侧边栏自动收缩功能
10      ignoreList: [/^_.*$/],
11      resolveRule: "rewrites",
12      checkRewritesPrefix: true,    
13      ignoreIndexMd: true,
14    },
15
16    autoFrontmatter: true, // 自动生成 frontmatter
17    // permalinkOption: {
18    //   notFoundDelayLoad: 1000, // 1秒后加载
19    // },
20
21    // 自动格式formatter插件 添加文章封面图
22    autoFrontmatterOption: {
23      // exclude: { title: true, date: true }, // 排除自动生成字段
24      transform: frontmatter => {
25       // 如果文件本身存在了 coverImg,则不生成
26       if (frontmatter.coverImg) return;
27        
28       const list = CoverImgList;
29        
30       const coverImg = list[Math.floor(Math.random() * list.length)];
31        
32       const transformResult = { ...frontmatter, coverImg };
33        
34       return Object.keys(transformResult).length ? transformResult : undefined;
35      },
36    }, 
37  }, 

image-20250827181141148

NOTE

以上配置就将我们的Teek从proxy模式切换到了rewrite模式。

但是,如何把自己之前的老库全部迁移过来呢?(老库有成千上万的md文档时,我们的头都要炸了……此时,就可以用到如下autoformatter插件了,让脚本替我们完成。😜)

2、配置autoformatter插件

这里利用autoformatter插件来自动注入 带对应一级前缀的permalink。

📌1.安装插件

1pnpm add vitepress-plugin-auto-frontmatter

📌2.配置代码

01.导入

编辑docs\.vitepress\config.ts文件

1import AutoFrontmatter, {FileInfo} from "vitepress-plugin-auto-frontmatter";
2import { useTransformByRules, type TransformRule } from "./theme/composables/useTransform";

image-20250827093206444

02.配置

编辑docs\.vitepress\config.ts文件

 1    plugins: [
 2      // 自动注入一级前缀(rewrite模式)
 3      AutoFrontmatter({
 4          pattern: "**/*.md",
 5          // exclude 指定的对象如果在 markdown frontmatter 存在,则忽略该文件。当 include 和 exclude 存在相同文件时,exclude 优先级高
 6          //exclude: { coverImg: true},
 7          recoverTransform: true, // false 只添加不存在的字段
 8          // 返回一个新的 frontmatter 或只返回 undefined,如果返回 {},则清空 MD 文件本身存在的 frontmatter
 9          transform: (frontMatter: Record<string, any>, fileInfo: FileInfo) => {
10
11              // 定义需要处理的所有规则(可扩展多个)
12              const rules: TransformRule[] = [
13                  // { folderName: "95.Teek", prefix: "/teek" }, // 添加前缀
14                  // { folderName: "10.Teek", prefix: "/teek" }, // 添加前缀
15                  // { folderName: "20.工具资源/01.SSL证书", prefix: "/tool", removeLevel: 1 }, // 移除一层前缀后再添加前缀
16                  // { folderName: "10.笔记专栏/99.博客搭建", prefix: "/note", clear: true }, // 清空 permalink,优先级最高
17                  // { folderName: "20.文档", prefix: "/note", clear: true }, // 清空 permalink,优先级最高
18                  // { folderName: "01.前端/01.vite/", prefix: "/testa/$uuid5/$uuid1/$uuid10/$uuid99", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
19                  { folderName: "10.运维", prefix: "/linux/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
20                  { folderName: "20.前端", prefix: "/qianduan/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
21                  { folderName: "30.编程", prefix: "/code/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
22                  { folderName: "35.黑客", prefix: "/hacker/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
23                  { folderName: "40.专题", prefix: "/zhuanti/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
24                  { folderName: "50.工具", prefix: "/tools/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
25                  { folderName: "60.生活", prefix: "/life/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
26                  { folderName: "70.精神小屋", prefix: "/love/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
27                  { folderName: "80.娱乐", prefix: "/yule/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
28                  { folderName: "85.兴趣", prefix: "/xingqu/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
29                  { folderName: "90.关于", prefix: "/about/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
30                  { folderName: "100.Teek", prefix: "/teek/$uuid5", removeLevel: 99}, // 清空前缀并且添加前缀使用随机数
31              ];
32              // 应用规则转换
33              return useTransformByRules(frontMatter, fileInfo, rules);
34
35  /*            // 如果文件本身存在了 coverImg,则不生成
36              if (frontMatter.coverImg) return; // 随机获取 coverImg
37              const list = [...Wallpaper, ...BlogCover];
38              const coverImg = list[Math.floor(Math.random() * list.length)];
39              const transformResult = { ...frontMatter, coverImg };
40              console.log("transformResult", transformResult)
41              return Object.keys(transformResult).length
42                  ? transformResult
43                  : undefined;*/
44          },
45      }),      
46
47    ],

image-20250827093318367

03.创建docs\.vitepress\theme\composables\useTransform.ts文件

  1import { FileInfo } from "vitepress-plugin-auto-frontmatter";
  2
  3// 定义规则类型
  4export interface TransformRule {
  5  folderName: string;        // 匹配文件或文件夹名称
  6  prefix: string;            // 要添加的前缀
  7  removeLevel?: number;      // 可选:要移除的前缀层级(以 / 分割),可以填写一个很大的数,那么就会全部清空然后添加前缀,适合移除前缀并添加的场景
  8  clear?: boolean;           // 可选,是否清空 permalink,适合只想要清空使用。true=清空(即使填了prefix也会清空,clear优先级高),默认false
  9}
 10
 11/**
 12 * 获取路径按 / 分割后的第一个有效分组(忽略空字符串)
 13 * @param path
 14 */
 15const getFirstPathSegment = (path: string): string => {
 16  // 按 / 分割并过滤空字符串(处理开头/结尾的斜杠或连续斜杠)
 17  const segments = path.split('/').filter(segment => segment.trim() !== '');
 18  return segments.length > 0 ? segments[0] : '';
 19};
 20
 21/**
 22 * 生成指定长度的随机字符串(数字 + 小写字母)
 23 * @param length 字符串长度(最大为10)
 24 * @returns 指定长度的随机字符串
 25 */
 26const generateRandomString = (length: number): string => {
 27  if (length <= 0) return '';
 28  const maxLen = 10;
 29  const actualLength = Math.min(length, maxLen); // 最大10位
 30
 31  const chars = '0123456789abcdefghijklmnopqrstuvwxyz';
 32  const charsLength = chars.length;
 33  let result = '';
 34
 35  for (let i = 0; i < actualLength; i++) {
 36    result += chars[Math.floor(Math.random() * charsLength)];
 37  }
 38
 39  return result;
 40};
 41
 42/**
 43 * 替换字符串中的 $UUID{n} 占位符
 44 * 支持 $UUID2, $UUID5, $UUID10 等格式
 45 * - n 超过 10 按 10 处理
 46 * - 不区分大小写(可选)
 47 * @param str 原始字符串
 48 * @returns 替换后的字符串
 49 * @example
 50 * replaceUuidPlaceholder('/test/$UUID10') → '/test/a3k9m2x8p1'
 51 * replaceUuidPlaceholder('/user/$UUID5/$UUID2') → '/user/abc12/de'
 52 */
 53const replaceUuidPlaceholder = (str: string): string => {
 54  return str.replace(/\$UUID(\d+)/gi, (match, numStr) => {
 55    const length = parseInt(numStr, 10);
 56    return generateRandomString(length);
 57  });
 58};
 59
 60export const useTransformByRules = (frontMatter: Record<string, any>, fileInfo: FileInfo, rules: TransformRule[]) => {
 61
 62  // 转换函数:支持移除指定层级前缀后再添加新前缀,新增clear清空逻辑 + UUID占位符替换
 63  for (const rule of rules) {
 64    const { folderName, prefix, removeLevel, clear = false } = rule; // 解构时给clear默认值false
 65
 66    // 1. 检查文件路径是否匹配文件夹规则(精确匹配单个文件时,需完全一致)
 67    if (!fileInfo.relativePath.startsWith(folderName)) {
 68      continue;
 69    }
 70
 71    // 处理日期:减去8小时抵消时区转换(原有逻辑不变)
 72    if (frontMatter.date) {
 73      const originalDate = new Date(frontMatter.date);
 74      originalDate.setHours(originalDate.getHours() - 8);
 75      frontMatter.date = originalDate;
 76    }
 77
 78    // 2. 如果clear为true,直接清空permalink并返回(优先级最高)
 79    if (clear) {
 80      const newFrontMatter = { ...frontMatter, permalink: '' };
 81      console.log(`匹配规则:${folderName}(clear=true)→ 清空permalink`);
 82      return newFrontMatter;
 83    }
 84
 85/*    // 3. 非clear模式:检查permalink是否存在(原有逻辑不变)
 86    if (!frontMatter.permalink) {
 87      continue;
 88    }*/
 89
 90    // 4. 新增!替换prefix中的$UUID/$UUID10占位符
 91    let normalizedPrefix = replaceUuidPlaceholder(prefix);
 92    // 原有:标准化前缀(确保以 / 开头)
 93    normalizedPrefix = normalizedPrefix.startsWith('/') ? normalizedPrefix : `/${normalizedPrefix}`;
 94    if (prefix === ""){
 95      normalizedPrefix = ""
 96    }
 97
 98    let originalPermalink = frontMatter.permalink;
 99    if (originalPermalink === null || originalPermalink === undefined) {
100      originalPermalink = "";
101    }
102
103    // 5. 核心调整:按 / 分组,比较第一个前缀是否一致(原有逻辑不变)
104    // 获取目标前缀的第一个分组(如 "/test/12345" → "test")
105    const targetFirstSegment = getFirstPathSegment(normalizedPrefix);
106    // 获取当前 permalink 的第一个分组(如 "/old/path" → "old")
107    const currentFirstSegment = getFirstPathSegment(originalPermalink);
108
109    // 若第一个分组相同,说明已包含目标前缀,无需处理(原有逻辑不变)
110    if (currentFirstSegment === targetFirstSegment) {
111      continue;
112    }
113
114    // 7. 处理 permalink:先移除指定层级,再添加新前缀(原有逻辑不变)
115    if (removeLevel !== undefined && removeLevel > 0) {
116      // 分割permalink(处理空字符串和开头的 /)
117      const parts = originalPermalink.split('/').filter(part => part);
118      // 确保移除的层级不超过实际存在的层级(removeLevel=99时,会移除所有层级,只剩根路径)
119      const actualRemoveLevel = Math.min(removeLevel, parts.length);
120      // 移除前N个层级,再重新拼接
121      const remainingParts = parts.slice(actualRemoveLevel);
122      originalPermalink = remainingParts.length > 0
123        ? `/${remainingParts.join('/')}`
124        : ''; // 移除所有层级后,originalPermalink为 ""
125    }
126
127    // 8. 拼接新 permalink 并返回结果(原有逻辑不变,此时prefix已替换占位符)
128    const newPermalink = `${normalizedPrefix}${originalPermalink}`;
129    const newFrontMatter = { ...frontMatter, permalink: newPermalink };
130
131    console.log(`原permalink:${frontMatter.permalink} → 新permalink:${newPermalink}`);
132    return newFrontMatter;
133  }
134  // 没有匹配的规则,返回undefined(不修改数据)
135  return undefined;
136}

📌3.配置一级前缀

警告

根据自己docs下的目录,填好上述代码,然后运行测试:

image-20250827093525618

📌4.修改nav

编辑D:\vitepress-theme-teek-one-private\docs\.vitepress\ConfigHyde\Nav.ts文件:

  1// nav导航栏配置
  2import { TeekIcon, VdoingIcon, SSLIcon, BlogIcon } from "./icon/NavIcon";
  3export const Nav = [
  4    { text: "🏡首页", link: "/" },
  5    {
  6      text: `
  7        <div style="display: flex; align-items: center; gap: 4px;">
  8          <img src="/img/nav/teek.svg" alt="" style="width: 16px; height: 16px;">
  9          <span>Teek</span>
 10        </div>
 11        `,
 12      link: '/teek/teek',
 13    },
 14
 15
 16
 17
 18    // 笔记
 19    {
 20      text: '📚知识库',
 21      items: [
 22        {
 23          text: `
 24            <div style="display: flex; align-items: center; gap: 4px;">
 25              <img src="/img/nav/linux.svg" alt="" style="width: 16px; height: 16px;">
 26              <span>运维</span>
 27            </div>
 28            `,
 29          link: '/linux/linux',
 30        },
 31        {
 32          text: `
 33            <div style="display: flex; align-items: center; gap: 4px;">
 34              <img src="/img/nav/前端.svg" alt="" style="width: 16px; height: 16px;">
 35              <span>前端</span>
 36            </div>
 37            `,
 38          link: '/qianduan/qianduan',
 39        },
 40                {
 41          text: `
 42            <div style="display: flex; align-items: center; gap: 4px;">
 43              <img src="/img/nav/编程.svg" alt="" style="width: 16px; height: 16px;">
 44              <span>编程</span>
 45            </div>
 46            `,
 47          link: '/code/code',
 48        },
 49        {
 50          text: `
 51            <div style="display: flex; align-items: center; gap: 4px;">
 52              <img src="/img/nav/黑客.svg" alt="" style="width: 16px; height: 16px;">
 53              <span>黑客</span>
 54            </div>
 55            `,
 56          link: '/hacker/hacker',
 57        },
 58      ],
 59    },  
 60
 61    // 专题
 62    {
 63      text: '🛠️专题',
 64      items: [
 65        {
 66          text: `
 67            <div style="display: flex; align-items: center; gap: 4px;">
 68              <img src="/img/nav/博客.svg" alt="" style="width: 16px; height: 16px;">
 69              <span>博客搭建</span>
 70            </div>
 71            `,
 72          link: '/zhuanti/blog',
 73        },
 74        {
 75          text: `
 76            <div style="display: flex; align-items: center; gap: 4px;">
 77              <img src="/img/nav/前端demo.svg" alt="" style="width: 16px; height: 16px;">
 78              <span>前端demo</span>
 79            </div>
 80            `,
 81          link: '/zhuanti/qianduan-demo',
 82        },
 83        {
 84          text: `
 85            <div style="display: flex; align-items: center; gap: 4px;">
 86              <img src="/img/nav/Git.svg" alt="" style="width: 16px; height: 16px;">
 87              <span>Git</span>
 88            </div>
 89            `,
 90          link: '/zhuanti/git',
 91        },
 92        {
 93          text: `
 94            <div style="display: flex; align-items: center; gap: 4px;">
 95              <img src="/img/nav/面试.svg" alt="" style="width: 16px; height: 16px;">
 96              <span>面试</span>
 97            </div>
 98            `,
 99          link: '/zhuanti/mianshi',
100        },
101        {
102          text: `
103            <div style="display: flex; align-items: center; gap: 4px;">
104              <img src="/img/nav/NAS.svg" alt="" style="width: 16px; height: 16px;">
105              <span>NAS</span>
106            </div>
107            `,
108          link: '/zhuanti/NAS',
109        },
110        {
111          text: `
112            <div style="display: flex; align-items: center; gap: 4px;">
113              <img src="/img/nav/脚本.svg" alt="" style="width: 16px; height: 16px;">
114              <span>脚本</span>
115            </div>
116            `,
117          link: '/zhuanti/jiaoben',
118        },
119        {
120          text: `
121            <div style="display: flex; align-items: center; gap: 4px;">
122              <img src="/img/nav/工具.svg" alt="" style="width: 16px; height: 16px;">
123              <span>工具</span>
124            </div>
125            `,
126          link: '/tools/tools',
127        },
128        {
129          text: `
130            <div style="display: flex; align-items: center; gap: 4px;">
131              <img src="/img/nav/开源项目.svg" alt="" style="width: 16px; height: 16px;">
132              <span>开源项目</span>
133            </div>
134            `,
135          link: '/zhuanti/opensource',
136        },        
137      ],
138    },  
139
140
141
142
143
144
145
146    // 生活
147    {
148      text: '🏓生活',
149      items: [
150        {
151          // 分组标题1
152          text: '娱乐',
153          items: [
154            {
155              text: `
156                <div style="display: flex; align-items: center; gap: 4px;">
157                  <img src="/img/nav/相册.svg" alt="" style="width: 16px; height: 16px;">
158                  <span>相册</span>
159                </div>
160                `,
161              link: '/yule/photo',
162            },
163            {
164              text: `
165                <div style="display: flex; align-items: center; gap: 4px;">
166                  <img src="/img/nav/电影.svg" alt="" style="width: 16px; height: 16px;">
167                  <span>电影</span>
168                </div>
169                `,
170              link: '/yule/movie',
171            },
172            {
173              text: `
174                <div style="display: flex; align-items: center; gap: 4px;">
175                  <img src="/img/nav/音乐.svg" alt="" style="width: 16px; height: 16px;">
176                  <span>音乐</span>
177                </div>
178                `,
179              link: '/yule/music',
180            },
181          ],
182        },
183        {
184          // 分组标题2
185          text: '小屋',
186          items: [
187            {
188              text: `
189                <div style="display: flex; align-items: center; gap: 4px;">
190                  <img src="/img/nav/精神小屋.svg" alt="" style="width: 16px; height: 16px;">
191                  <span>精神小屋</span>
192                </div>
193                `,
194              link: '/love/love',
195            },
196            {
197              text: `
198                <div style="display: flex; align-items: center; gap: 4px;">
199                  <img src="/img/nav/时间管理.svg" alt="" style="width: 16px; height: 16px;">
200                  <span>时间管理</span>
201                </div>
202                `,
203              link: '/love/time-plan',
204            },
205            {
206              text: `
207                <div style="display: flex; align-items: center; gap: 4px;">
208                  <img src="/img/nav/文案.svg" alt="" style="width: 16px; height: 16px;">
209                  <span>情感文案</span>
210                </div>
211                `,
212              link: '/love/wenan',
213            },
214            // { text: "💖情侣空间", link: "https://fxj.onedayxyy.cn/" },
215          ],
216        },
217      ],
218    },  
219
220
221    // 兴趣
222    {
223      text: '🎨兴趣',
224      items: [
225        {
226          text: `
227            <div style="display: flex; align-items: center; gap: 4px;">
228              <img src="/img/nav/旅行.svg" alt="" style="width: 16px; height: 16px;">
229              <span>旅行</span>
230            </div>
231            `,
232          link: '/xingqu/travel',
233        },
234        {
235          text: `
236            <div style="display: flex; align-items: center; gap: 4px;">
237              <img src="/img/nav/读书.svg" alt="" style="width: 16px; height: 16px;">
238              <span>读书</span>
239            </div>
240            `,
241          link: '/xingqu/reading',
242        },
243      ],
244    },  
245    
246    
247    // 索引
248    {
249      text: '👏索引',
250      items: [
251        { text: '📃分类页', link: '/categories' },
252        { text: '🔖标签页', link: '/tags' },
253        {
254          text: `
255            <div style="display: flex; align-items: center; gap: 4px;">
256              <img src="/img/nav/归档.svg" alt="" style="width: 16px; height: 16px;">
257              <span>归档页</span>
258            </div>
259            `,
260          link: '/archives',
261        },
262        {
263          text: `
264            <div style="display: flex; align-items: center; gap: 4px;">
265              <img src="/img/nav/清单.svg" alt="" style="width: 16px; height: 16px;">
266              <span>清单页</span>
267            </div>
268            `,
269          link: '/articleOverview',
270        },
271        {
272          text: `
273            <div style="display: flex; align-items: center; gap: 4px;">
274              <img src="/img/nav/登录.svg" alt="" style="width: 16px; height: 16px;">
275              <span>登录页</span>
276            </div>
277            `,
278          link: '/login',
279        },
280        {
281          text: `
282            <div style="display: flex; align-items: center; gap: 4px;">
283              <img src="/img/nav/风险提示.svg" alt="" style="width: 16px; height: 16px;">
284              <span>风险链接提示页</span>
285            </div>
286            `,
287          link: '/risk-link?target=https://onedayxyy.cn/',
288        },
289      ],
290    },  
291
292    // 关于
293    {
294      text: '🍷关于',
295      items: [
296        { text: '👋关于我', link: '/about/me' },
297        { text: '🎉关于本站', link: '/about/website' },
298        { text: '🌐网站导航', link: '/about/websites' },          
299        { text: "👂留言区", link: "/about/liuyanqu" },
300        { text: "💡思考", link: "/about/thinking" },
301        {
302          text: `
303            <div style="display: flex; align-items: center; gap: 4px;">
304              <img src="/img/nav/时间轴.svg" alt="" style="width: 16px; height: 16px;">
305              <span>时间轴</span>
306            </div>
307            `,
308          link: 'https://one.onedayxyy.cn/',
309        },
310        {
311          text: `
312            <div style="display: flex; align-items: center; gap: 4px;">
313              <img src="/img/nav/网站统计.svg" alt="" style="width: 16px; height: 16px;">
314              <span>网站统计</span>
315            </div>
316            `,
317          link: 'https://umami.onedayxyy.cn/share/DzS4g85V8JkxsNRk/onedayxyy.cn',
318        },
319        {
320          text: `
321            <div style="display: flex; align-items: center; gap: 4px;">
322              <img src="/img/nav/站点监控.svg" alt="" style="width: 16px; height: 16px;">
323              <span>站点监控</span>
324            </div>
325            `,
326          link: 'https://status.onedayxyy.cn/status/monitor',
327        },
328
329      ],
330    },       
331  ]

以上配置完成后,验证。

3、验证

2025年8月27日测试。

结束。

最新文章

文档导航