@tnotesjs/core 0.1.28 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +2 -1
  2. package/package.json +3 -1
  3. package/templates/sub-repo/.gitattributes +30 -0
  4. package/templates/sub-repo/.github/workflows/deploy.yml +87 -0
  5. package/templates/sub-repo/.vitepress/config.mts +12 -0
  6. package/templates/sub-repo/.vitepress/env.d.ts +10 -0
  7. package/templates/sub-repo/.vitepress/theme/index.ts +12 -0
  8. package/templates/sub-repo/.vscode/settings.json +330 -0
  9. package/templates/sub-repo/.vscode/tnotes.code-snippets +110 -0
  10. package/templates/sub-repo/public/favicon.ico +0 -0
  11. package/templates/sub-repo/public/logo.png +0 -0
  12. package/templates/sub-repo/tsconfig.json +45 -0
  13. package/vitepress/assets/icons/icon__setting_dark.svg +4 -0
  14. package/vitepress/assets/icons/icon__setting_light.svg +4 -0
  15. package/vitepress/assets/icons/index.ts +2 -2
  16. package/vitepress/client/localSearchIndexBridge.ts +24 -0
  17. package/vitepress/components/Discussions/Discussions.vue +1 -1
  18. package/vitepress/components/Footprints/Footprints.vue +90 -25
  19. package/vitepress/components/Layout/CustomSidebar.vue +489 -117
  20. package/vitepress/components/Layout/Layout.vue +5 -0
  21. package/vitepress/components/Layout/NavBarSettingsTrigger.vue +10 -2
  22. package/vitepress/components/Layout/SidebarItems.vue +517 -342
  23. package/vitepress/components/Layout/SidebarNavBefore.vue +1 -50
  24. package/vitepress/components/Layout/SidebarResizeHandle.vue +6 -23
  25. package/vitepress/components/Layout/composables/docLayoutLogic.ts +59 -0
  26. package/vitepress/components/Layout/composables/useDocLayout.test.ts +69 -0
  27. package/vitepress/components/Layout/composables/useDocLayout.ts +128 -0
  28. package/vitepress/components/Layout/composables/useSidebarDrag.ts +514 -0
  29. package/vitepress/components/Layout/composables/useSidebarLayout.ts +25 -8
  30. package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +8 -3
  31. package/vitepress/components/Layout/sidebarCollapsedState.test.ts +183 -0
  32. package/vitepress/components/Layout/sidebarCollapsedState.ts +241 -0
  33. package/vitepress/components/Layout/sidebarDragLogic.test.ts +1146 -0
  34. package/vitepress/components/Layout/sidebarDragLogic.ts +1307 -0
  35. package/vitepress/components/Layout/sidebarHitTest.test.ts +572 -0
  36. package/vitepress/components/Layout/sidebarHitTest.ts +801 -0
  37. package/vitepress/components/Layout/sidebarItemRenderLogic.test.ts +53 -0
  38. package/vitepress/components/Layout/sidebarItemRenderLogic.ts +50 -0
  39. package/vitepress/components/MarkMap/MarkMap.vue +67 -10
  40. package/vitepress/components/Settings/Settings.vue +78 -74
  41. package/vitepress/components/SidebarCard/FolderTreeItems.vue +268 -0
  42. package/vitepress/components/SidebarCard/SidebarCard.vue +125 -274
  43. package/vitepress/components/constants.ts +18 -6
  44. package/vitepress/components/sidebar.data.ts +13 -11
  45. package/vitepress/components/sidebarTreeHelpers.test.ts +142 -0
  46. package/vitepress/components/sidebarTreeHelpers.ts +168 -0
  47. package/vitepress/components/utils/vscodePaths.test.ts +41 -0
  48. package/vitepress/components/utils/vscodePaths.ts +52 -0
  49. package/vitepress/config/index.ts +2 -0
  50. package/vitepress/plugins/localSearchIndexBuilder.ts +209 -0
  51. package/vitepress/plugins/localSearchReindex.test.ts +46 -0
  52. package/vitepress/plugins/localSearchReindexLogic.ts +50 -0
  53. package/vitepress/plugins/localSearchReindexPatch.test.ts +30 -0
  54. package/vitepress/plugins/localSearchReindexPatch.ts +37 -0
  55. package/vitepress/plugins/localSearchReindexPlugin.ts +318 -0
  56. package/vitepress/plugins/sidebarStructurePlugin.ts +209 -63
  57. package/vitepress/theme/index.ts +8 -0
  58. package/vitepress/theme/styles/base.scss +0 -8
  59. package/vitepress/theme/styles/components/markmap.scss +23 -2
  60. package/vitepress/theme/styles/components/swiper.scss +1 -1
  61. package/vitepress/theme/styles/doc-layout.scss +212 -0
  62. package/vitepress/theme/styles/index.scss +3 -0
  63. package/vitepress/theme/styles/layout.scss +60 -10
  64. package/dist/chunk-4KG6RXFS.js +0 -4637
  65. package/dist/chunk-AGSL3VZE.js +0 -193
  66. package/dist/cli/index.js +0 -683
  67. package/dist/index.js +0 -8
  68. package/dist/vitepress/config/index.js +0 -1178
  69. package/vitepress/assets/icons/icon__mindmap.svg +0 -1
  70. package/vitepress/assets/icons/icon__setting.svg +0 -1
  71. package/vitepress/components/SidebarCard/MindMapView.vue +0 -488
@@ -1,1178 +0,0 @@
1
- import {
2
- FileWatcherService,
3
- NoteIndexCache,
4
- NoteService,
5
- ReadmeService,
6
- RenameNoteCommand,
7
- UpdateNoteConfigCommand,
8
- generateAnchor,
9
- logger
10
- } from "../../chunk-4KG6RXFS.js";
11
- import {
12
- ConfigManager
13
- } from "../../chunk-AGSL3VZE.js";
14
-
15
- // vitepress/config/index.ts
16
- import fs2 from "fs";
17
- import path2 from "path";
18
- import { defineConfig } from "vitepress";
19
-
20
- // vitepress/configs/constants.ts
21
- function getIgnoreList(config) {
22
- return [...config.ignore_dirs.map((dir) => `**/${dir}/**`)];
23
- }
24
- function getGithubPageUrl(config) {
25
- return "https://" + config.author.toLowerCase() + ".github.io/" + config.repoName + "/";
26
- }
27
-
28
- // vitepress/configs/head.config.ts
29
- function getHeadConfig(config, githubPageUrl) {
30
- const head = [
31
- [
32
- "meta",
33
- {
34
- name: "keywords",
35
- content: config.keywords.join(", ")
36
- }
37
- ],
38
- ["meta", { name: "author", content: config.author }],
39
- ["link", { rel: "canonical", href: githubPageUrl }],
40
- ["link", { rel: "icon", href: githubPageUrl + "favicon.ico" }],
41
- ["link", { rel: "preconnect", href: "https://fonts.googleapis.com" }]
42
- ];
43
- return head;
44
- }
45
-
46
- // vitepress/configs/markdown.config.ts
47
- import fs from "fs";
48
- import markdownItContainer from "markdown-it-container";
49
- import mila from "markdown-it-link-attributes";
50
- import markdownItTaskLists from "markdown-it-task-lists";
51
- import path from "path";
52
- function esc(s = "") {
53
- return s.replace(
54
- /[&<>"']/g,
55
- (ch) => ({
56
- "&": "&amp;",
57
- "<": "&lt;",
58
- ">": "&gt;",
59
- '"': "&quot;",
60
- "'": "&#39;"
61
- })[ch]
62
- );
63
- }
64
- var simpleMermaidMarkdown = (md) => {
65
- const fence = md.renderer.rules.fence ? md.renderer.rules.fence.bind(md.renderer.rules) : () => "";
66
- md.renderer.rules.fence = (tokens, index, options, env, slf) => {
67
- const token = tokens[index];
68
- if (token.info.trim() === "mermaid") {
69
- try {
70
- const key = `mermaid-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
71
- const content = token.content;
72
- return `<Mermaid id="${key}" graph="${encodeURIComponent(content)}" />`;
73
- } catch (err) {
74
- return `<pre>${err}</pre>`;
75
- }
76
- }
77
- if (token.info.trim() === "mmd") {
78
- tokens[index].info = "mermaid";
79
- }
80
- return fence(tokens, index, options, env, slf);
81
- };
82
- };
83
- function configureMarkMapContainer(md) {
84
- md.use(markdownItContainer, "markmap", {
85
- marker: "`",
86
- validate(params) {
87
- const p = (params || "").trim();
88
- return p.startsWith("markmap");
89
- },
90
- render() {
91
- return "";
92
- }
93
- });
94
- md.core.ruler.after("block", "tn_replace_markmap_container", (state) => {
95
- const src = state.env.source || "";
96
- const lines = src.split("\n");
97
- const tokens = state.tokens;
98
- for (let i = 0; i < tokens.length; i++) {
99
- const t = tokens[i];
100
- if (t.type === "container_markmap_open") {
101
- let j = i + 1;
102
- while (j < tokens.length && tokens[j].type !== "container_markmap_close")
103
- j++;
104
- if (j >= tokens.length) continue;
105
- const open = t;
106
- const startLine = open.map ? open.map[0] + 1 : null;
107
- const endLine = open.map ? open.map[1] - 1 : null;
108
- const params = {};
109
- if (open.map && typeof open.map[0] === "number") {
110
- const openLine = (lines[open.map[0]] || "").trim();
111
- let paramPart = "";
112
- const braceMatch = openLine.match(/\{([^}]*)\}/);
113
- if (braceMatch) {
114
- paramPart = braceMatch[1].trim();
115
- } else {
116
- const after = openLine.replace(/^`+\s*/, "");
117
- if (after.startsWith("markmap")) {
118
- paramPart = after.slice("markmap".length).trim();
119
- }
120
- }
121
- if (paramPart) {
122
- const tokenArr = paramPart.match(/"[^"]*"|'[^']*'|\S+/g) || [];
123
- let startIdx = 0;
124
- if (tokenArr.length > 0 && /^\d+$/.test(tokenArr[0])) {
125
- params.initialExpandLevel = Number(tokenArr[0]);
126
- startIdx = 1;
127
- }
128
- for (let k = startIdx; k < tokenArr.length; k++) {
129
- const pair = tokenArr[k];
130
- if (!pair) continue;
131
- const m = pair.match(/^([^=:\s]+)\s*(=|:)\s*(.+)$/);
132
- if (m) {
133
- const key = m[1];
134
- let val = m[3];
135
- if (/^".*"$/.test(val) && val.length >= 2 || /^'.*'$/.test(val) && val.length >= 2) {
136
- val = val.slice(1, -1);
137
- } else if (/^\d+$/.test(val)) {
138
- val = String(Number(val));
139
- }
140
- params[key] = val;
141
- }
142
- }
143
- }
144
- }
145
- let content = "";
146
- if (startLine !== null && endLine !== null) {
147
- for (let k = startLine; k <= endLine && k < lines.length; k++) {
148
- content += lines[k] + "\n";
149
- }
150
- } else {
151
- for (let k = i + 1; k < j; k++) {
152
- content += tokens[k].content || "";
153
- }
154
- }
155
- const firstNonEmptyLine = (content || "").split("\n").find((ln) => ln.trim() !== "") || "";
156
- const refMatch = firstNonEmptyLine.trim().match(/^<<<\s*(.+)$/);
157
- if (refMatch) {
158
- const refRaw = refMatch[1].trim().replace(/^['"]|['"]$/g, "");
159
- try {
160
- const env = state.env || {};
161
- const possibleRel = env.relativePath || env.path || env.filePath || env.file || "";
162
- let refFullPath = refRaw;
163
- if (!path.isAbsolute(refRaw)) {
164
- if (possibleRel) {
165
- const currentDir = path.dirname(possibleRel);
166
- refFullPath = path.resolve(process.cwd(), currentDir, refRaw);
167
- } else {
168
- refFullPath = path.resolve(process.cwd(), refRaw);
169
- }
170
- } else {
171
- refFullPath = refRaw;
172
- }
173
- const fileContent = fs.readFileSync(refFullPath, "utf-8");
174
- content = fileContent;
175
- } catch (err) {
176
- const errorMsg = err instanceof Error ? err.message : String(err);
177
- content = `Failed to load referenced file: ${esc(
178
- String(refRaw)
179
- )}
180
-
181
- Error: ${esc(errorMsg)}`;
182
- }
183
- }
184
- const encodedContent = encodeURIComponent(content.trim());
185
- let propsStr = `content="${encodedContent}"`;
186
- for (const [k, v] of Object.entries(params)) {
187
- if (typeof v === "number" || /^\d+$/.test(String(v))) {
188
- propsStr += ` :${k}="${v}"`;
189
- } else {
190
- const safe = String(v).replace(/"/g, "&quot;");
191
- propsStr += ` ${k}="${safe}"`;
192
- }
193
- }
194
- const html = `<MarkMap ${propsStr}></MarkMap>
195
- `;
196
- const htmlToken = new state.Token("html_block", "", 0);
197
- htmlToken.content = html;
198
- tokens.splice(i, j - i + 1, htmlToken);
199
- }
200
- }
201
- return true;
202
- });
203
- }
204
- function configureSwiperContainer(md) {
205
- let __tn_swiper_uid = 0;
206
- let __tn_rules_stack = [];
207
- md.core.ruler.before("block", "tn_swiper_reset_uid", () => {
208
- __tn_swiper_uid = 0;
209
- __tn_rules_stack = [];
210
- return true;
211
- });
212
- md.use(markdownItContainer, "swiper", {
213
- render: (tokens, idx) => {
214
- if (tokens[idx].nesting === 1) {
215
- __tn_rules_stack.push({
216
- image: md.renderer.rules.image,
217
- pOpen: md.renderer.rules.paragraph_open,
218
- pClose: md.renderer.rules.paragraph_close
219
- });
220
- md.renderer.rules.paragraph_open = () => "";
221
- md.renderer.rules.paragraph_close = () => "";
222
- md.renderer.rules.image = (tokens2, i) => {
223
- const token = tokens2[i];
224
- const src = token.attrGet("src") || "";
225
- const alt = token.content || "";
226
- const title = alt && alt.trim() ? alt : "img";
227
- return `<div class="swiper-slide" data-title="${esc(
228
- title
229
- )}"><img src="${esc(src)}" alt="${esc(alt)}"></div>`;
230
- };
231
- const id = `tn-swiper-${++__tn_swiper_uid}`;
232
- return `
233
- <div class="tn-swiper" data-swiper-id="${id}">
234
- <div class="tn-swiper-tabs"></div>
235
- <div class="swiper-container">
236
- <div class="swiper-wrapper">
237
- `;
238
- } else {
239
- const prev = __tn_rules_stack.pop() || {
240
- image: null,
241
- pOpen: null,
242
- pClose: null
243
- };
244
- md.renderer.rules.image = prev.image;
245
- md.renderer.rules.paragraph_open = prev.pOpen;
246
- md.renderer.rules.paragraph_close = prev.pClose;
247
- return `
248
- </div>
249
- <!-- \u4E0B\u4E00\u9875\u6309\u94AE -->
250
- <!-- <div class="swiper-button-next"></div> -->
251
- <!-- \u4E0A\u4E00\u9875\u6309\u94AE -->
252
- <!-- <div class="swiper-button-prev"></div> -->
253
- <!-- \u5206\u9875\u5BFC\u822A -->
254
- <!-- <div class="swiper-pagination"></div> -->
255
- </div>
256
- </div>
257
- `;
258
- }
259
- }
260
- });
261
- }
262
- function getMarkdownConfig() {
263
- const markdown = {
264
- lineNumbers: true,
265
- math: true,
266
- config(md) {
267
- md.core.ruler.before("normalize", "save-source", (state) => {
268
- state.env.source = state.src;
269
- return true;
270
- });
271
- simpleMermaidMarkdown(md);
272
- configureMarkMapContainer(md);
273
- md.use(markdownItTaskLists);
274
- md.use(mila, {
275
- attrs: {
276
- target: "_self",
277
- rel: "noopener"
278
- }
279
- });
280
- configureSwiperContainer(md);
281
- },
282
- anchor: {
283
- slugify: generateAnchor
284
- },
285
- image: {
286
- lazyLoading: true
287
- }
288
- };
289
- return markdown;
290
- }
291
-
292
- // vitepress/configs/theme.config.ts
293
- function getThemeConfig(config) {
294
- const themeConfig = {
295
- docFooter: {
296
- prev: "\u4E0A\u4E00\u7BC7",
297
- next: "\u4E0B\u4E00\u7BC7"
298
- },
299
- externalLinkIcon: true,
300
- outline: {
301
- level: [2, 3],
302
- label: "\u76EE\u5F55"
303
- },
304
- nav: [
305
- {
306
- text: "\u{1F440} README",
307
- link: "/README"
308
- },
309
- {
310
- text: "Menus",
311
- items: config.menuItems
312
- }
313
- ],
314
- search: {
315
- // 使用本地搜索(不依赖远程服务器)
316
- provider: "local",
317
- options: {
318
- miniSearch: {
319
- /**
320
- * 控制如何对文档进行分词、字段提取等预处理
321
- * @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
322
- */
323
- options: {
324
- // 自定义分词逻辑
325
- tokenize: (text, language) => {
326
- if (language === "zh") {
327
- return text.match(/[\u4e00-\u9fa5]+|\S+/g) || [];
328
- }
329
- return text.split(/\s+/);
330
- },
331
- // 将所有词转为小写,确保大小写不敏感匹配
332
- processTerm: (term) => term.toLowerCase()
333
- },
334
- /**
335
- * 控制搜索时的行为(如模糊匹配、权重)
336
- * @type {import('minisearch').SearchOptions}
337
- * @default
338
- * { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
339
- */
340
- searchOptions: {
341
- fuzzy: 0.2,
342
- // 模糊匹配阈值(0-1),允许拼写错误的阈值(数值越低越严格)
343
- prefix: true,
344
- // 是否启用前缀匹配(输入"jav"可匹配"javascript")
345
- boost: {
346
- title: 10,
347
- // 文件名作为 h1 标题,权重最高
348
- headings: 5,
349
- // h2 - h6
350
- text: 3,
351
- // 正文内容索引
352
- code: 1
353
- // 代码块索引权重
354
- }
355
- }
356
- },
357
- /**
358
- * 控制哪些 Markdown 内容参与本地搜索引擎索引
359
- * @param {string} src 当前 Markdown 文件的原始内容(即 .md 文件中的文本)
360
- * @param {import('vitepress').MarkdownEnv} env 包含当前页面环境信息的对象,比如 frontmatter、路径等
361
- * @param {import('markdown-it-async')} md 一个 Markdown 渲染器实例,用来将 Markdown 转换为 HTML
362
- */
363
- async _render(src, env, md) {
364
- const filePath = env.relativePath;
365
- if (filePath.includes("TOC.md")) return "";
366
- const notesIndex = filePath.indexOf("notes/");
367
- let folderName = "";
368
- if (notesIndex !== -1) {
369
- const pathAfterNotes = filePath.slice(notesIndex + "notes/".length);
370
- folderName = pathAfterNotes.split("/")[0];
371
- }
372
- const titleField = `# ${folderName}
373
- `;
374
- const html = md.render(titleField + "\n\n" + src, env);
375
- return html;
376
- }
377
- }
378
- },
379
- // VitePress 只有 sidebar 非空才会渲染 sidebar 插槽,自定义侧边栏依赖这个外壳。
380
- sidebar: [
381
- {
382
- text: "",
383
- items: []
384
- }
385
- ],
386
- socialLinks: config.socialLinks
387
- };
388
- return themeConfig;
389
- }
390
-
391
- // vitepress/plugins/buildProgressPlugin.ts
392
- import {
393
- existsSync,
394
- readFileSync,
395
- writeFileSync,
396
- mkdirSync
397
- } from "fs";
398
- import { join } from "path";
399
- var CACHE_DIR = join(process.cwd(), "node_modules", ".tnotes-progress");
400
- var CACHE_FILE = join(CACHE_DIR, "build-cache.json");
401
- function getCacheData() {
402
- try {
403
- if (existsSync(CACHE_FILE)) {
404
- return JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
405
- }
406
- } catch {
407
- }
408
- return { transformCount: 0, chunkCount: 0 };
409
- }
410
- function setCacheData(data) {
411
- try {
412
- if (!existsSync(CACHE_DIR)) {
413
- mkdirSync(CACHE_DIR, { recursive: true });
414
- }
415
- writeFileSync(CACHE_FILE, JSON.stringify(data), "utf-8");
416
- } catch {
417
- }
418
- }
419
- var globalStartTime = 0;
420
- var globalTransformCount = 0;
421
- var globalChunkCount = 0;
422
- var globalHasError = false;
423
- var globalIsBuilding = false;
424
- var globalOutDir = "";
425
- var globalLastPercent = 0;
426
- var globalLastLoggedPercent = -1;
427
- var globalLastOutputTime = 0;
428
- var globalTransformEndTime = 0;
429
- var globalLastHookTime = 0;
430
- var globalStallTimer = null;
431
- var isTTY = !!(process.stdout.isTTY && process.stderr.isTTY);
432
- var isCI = !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.CIRCLECI || process.env.TRAVIS || process.env.JENKINS_URL);
433
- var useSingleLineMode = isTTY && !isCI;
434
- var originalStdoutWrite = null;
435
- var originalStderrWrite = null;
436
- function interceptOutput() {
437
- if (originalStdoutWrite) return;
438
- originalStdoutWrite = process.stdout.write.bind(process.stdout);
439
- originalStderrWrite = process.stderr.write.bind(process.stderr);
440
- const filter = (chunk) => {
441
- const str = chunk.toString();
442
- return str.includes("\u{1F528}") || str.includes("\u2705 \u6784\u5EFA\u6210\u529F") || str.includes("\u274C \u6784\u5EFA\u5931\u8D25") || str.includes("\u{1F4C1}") || str.includes("\u{1F4CA}") || str.includes("\u{1F4E6}") || str.includes("\u23F1\uFE0F") || str.includes("\x1B[2K");
443
- };
444
- process.stdout.write = ((chunk, encodingOrCallback, callback) => {
445
- if (filter(chunk)) {
446
- return originalStdoutWrite(chunk, encodingOrCallback, callback);
447
- }
448
- if (typeof encodingOrCallback === "function") encodingOrCallback();
449
- else if (callback) callback();
450
- return true;
451
- });
452
- process.stderr.write = ((chunk, encodingOrCallback, callback) => {
453
- const str = chunk.toString();
454
- if (filter(chunk) || str.toLowerCase().includes("error")) {
455
- return originalStderrWrite(chunk, encodingOrCallback, callback);
456
- }
457
- if (typeof encodingOrCallback === "function") encodingOrCallback();
458
- else if (callback) callback();
459
- return true;
460
- });
461
- }
462
- function restoreOutput() {
463
- if (originalStdoutWrite) {
464
- process.stdout.write = originalStdoutWrite;
465
- originalStdoutWrite = null;
466
- }
467
- if (originalStderrWrite) {
468
- process.stderr.write = originalStderrWrite;
469
- originalStderrWrite = null;
470
- }
471
- }
472
- function renderProgress(percent, transforms, chunks, width, complete, incomplete, isFinal = false) {
473
- if (!originalStderrWrite) return;
474
- if (!useSingleLineMode && !isFinal) {
475
- const currentPercent = Math.floor(percent * 100);
476
- const currentBucket = Math.floor(currentPercent / 10) * 10;
477
- const now = Date.now();
478
- if (currentBucket <= globalLastLoggedPercent || now - globalLastOutputTime < 500) {
479
- return;
480
- }
481
- globalLastLoggedPercent = currentBucket;
482
- globalLastOutputTime = now;
483
- }
484
- const filled = Math.floor(percent * width);
485
- const empty = width - filled;
486
- const bar = complete.repeat(filled) + incomplete.repeat(empty);
487
- const percentStr = (percent * 100).toFixed(0).padStart(3, " ");
488
- const elapsed = ((Date.now() - globalStartTime) / 1e3).toFixed(1);
489
- const prefix = useSingleLineMode ? "\r\x1B[2K" : "";
490
- const ending = isFinal || !useSingleLineMode ? "\n" : "";
491
- const line = `${prefix}Building [${bar}] ${percentStr}% | Transforms: ${transforms} | Chunks: ${chunks} | Time: ${elapsed}s${ending}`;
492
- originalStderrWrite(line);
493
- }
494
- function buildProgressPlugin(options = {}) {
495
- const { width = 40, complete = "\u2588", incomplete = "\u2591" } = options;
496
- const cache = getCacheData();
497
- const hasCache = cache.transformCount > 0;
498
- return {
499
- name: "tnotes-build-progress",
500
- enforce: "pre",
501
- apply: "build",
502
- config(config, { command }) {
503
- if (command === "build") {
504
- config.logLevel = "silent";
505
- if (!globalIsBuilding) {
506
- globalIsBuilding = true;
507
- globalStartTime = Date.now();
508
- globalTransformCount = 0;
509
- globalChunkCount = 0;
510
- globalHasError = false;
511
- globalLastPercent = 0;
512
- globalLastLoggedPercent = -1;
513
- globalLastOutputTime = 0;
514
- globalTransformEndTime = 0;
515
- globalLastHookTime = Date.now();
516
- globalOutDir = config.build?.outDir || "dist";
517
- interceptOutput();
518
- globalStallTimer = setInterval(() => {
519
- if (!globalIsBuilding || globalLastPercent <= 0 || globalLastPercent >= 0.98)
520
- return;
521
- const now = Date.now();
522
- if (now - globalLastHookTime < 2e3) return;
523
- const remaining = 0.98 - globalLastPercent;
524
- globalLastPercent += remaining * 0.02;
525
- const transformsStr = hasCache ? `${globalTransformCount}/${cache.transformCount * 2}` : `${globalTransformCount}`;
526
- const chunksStr = hasCache ? `${globalChunkCount}/${cache.chunkCount * 2}` : `${globalChunkCount}`;
527
- renderProgress(
528
- globalLastPercent,
529
- transformsStr,
530
- chunksStr,
531
- width,
532
- complete,
533
- incomplete
534
- );
535
- }, 1e3);
536
- }
537
- }
538
- },
539
- transform(_code, _id) {
540
- globalTransformCount++;
541
- globalLastHookTime = Date.now();
542
- const transformWeight = hasCache && cache.transformEndRatio != null ? Math.max(0.1, Math.min(0.85, cache.transformEndRatio * 0.98)) : 0.85;
543
- if (hasCache) {
544
- const totalTransforms = cache.transformCount * 2;
545
- globalLastPercent = Math.min(
546
- transformWeight,
547
- globalTransformCount / totalTransforms * transformWeight
548
- );
549
- } else {
550
- const k = 500;
551
- globalLastPercent = Math.min(
552
- transformWeight,
553
- transformWeight * globalTransformCount / (globalTransformCount + k)
554
- );
555
- }
556
- const transformsStr = hasCache ? `${globalTransformCount}/${cache.transformCount * 2}` : `${globalTransformCount}`;
557
- const chunksStr = hasCache ? `${globalChunkCount}/${cache.chunkCount * 2}` : `${globalChunkCount}`;
558
- renderProgress(
559
- globalLastPercent,
560
- transformsStr,
561
- chunksStr,
562
- width,
563
- complete,
564
- incomplete
565
- );
566
- return null;
567
- },
568
- renderChunk() {
569
- globalChunkCount++;
570
- globalLastHookTime = Date.now();
571
- if (!globalTransformEndTime) {
572
- globalTransformEndTime = Date.now();
573
- }
574
- const transformWeight = hasCache && cache.transformEndRatio != null ? Math.max(0.1, Math.min(0.85, cache.transformEndRatio * 0.98)) : 0.85;
575
- const chunkWeight = 0.98 - transformWeight;
576
- if (hasCache) {
577
- const totalChunks = cache.chunkCount * 2;
578
- globalLastPercent = Math.min(
579
- 0.98,
580
- transformWeight + globalChunkCount / totalChunks * chunkWeight
581
- );
582
- } else {
583
- globalLastPercent = Math.max(globalLastPercent, transformWeight);
584
- globalLastPercent = Math.min(0.98, globalLastPercent + 5e-5);
585
- }
586
- const transformsStr = hasCache ? `${globalTransformCount}/${cache.transformCount * 2}` : `${globalTransformCount}`;
587
- const chunksStr = hasCache ? `${globalChunkCount}/${cache.chunkCount * 2}` : `${globalChunkCount}`;
588
- renderProgress(
589
- globalLastPercent,
590
- transformsStr,
591
- chunksStr,
592
- width,
593
- complete,
594
- incomplete
595
- );
596
- return null;
597
- },
598
- buildEnd(err) {
599
- if (err) {
600
- globalHasError = true;
601
- }
602
- },
603
- closeBundle() {
604
- setTimeout(() => {
605
- if (!globalIsBuilding) return;
606
- if (globalStallTimer) {
607
- clearInterval(globalStallTimer);
608
- globalStallTimer = null;
609
- }
610
- const elapsed = ((Date.now() - globalStartTime) / 1e3).toFixed(1);
611
- const totalTransforms = hasCache ? cache.transformCount * 2 : globalTransformCount;
612
- const totalChunks = hasCache ? cache.chunkCount * 2 : globalChunkCount;
613
- const transformsStr = `${totalTransforms}/${totalTransforms}`;
614
- const chunksStr = `${totalChunks}/${totalChunks}`;
615
- renderProgress(
616
- 1,
617
- transformsStr,
618
- chunksStr,
619
- width,
620
- complete,
621
- incomplete,
622
- true
623
- );
624
- restoreOutput();
625
- if (!globalHasError) {
626
- const totalTime = Date.now() - globalStartTime;
627
- const transformTime = globalTransformEndTime ? globalTransformEndTime - globalStartTime : totalTime;
628
- setCacheData({
629
- transformCount: Math.floor(globalTransformCount / 2),
630
- chunkCount: Math.floor(globalChunkCount / 2),
631
- transformEndRatio: transformTime / totalTime
632
- });
633
- console.log(`\u{1F528} Rollup \u6253\u5305\u5B8C\u6210`);
634
- console.log(` \u{1F4C1} \u8F93\u51FA\u76EE\u5F55: ${globalOutDir}`);
635
- console.log(` \u23F1\uFE0F \u8017\u65F6: ${elapsed}s`);
636
- console.log(` \u23F3 VitePress \u6B63\u5728\u6E32\u67D3\u9875\u9762...`);
637
- } else {
638
- console.log(`
639
- \u274C \u6784\u5EFA\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u9519\u8BEF\u4FE1\u606F`);
640
- }
641
- globalIsBuilding = false;
642
- }, 500);
643
- }
644
- };
645
- }
646
-
647
- // vitepress/plugins/fileWatcherBridgePlugin.ts
648
- var RENAME_EVENT = "tnotes:note-renamed";
649
- var BROADCAST_PATH = "/__tnotes_broadcast_rename";
650
- function fileWatcherBridgePlugin() {
651
- return {
652
- name: "tnotes-file-watcher-bridge",
653
- apply: "serve",
654
- configureServer(server) {
655
- server.middlewares.use((req, res, next) => {
656
- const url = req.url ?? "";
657
- const isBroadcast = url === BROADCAST_PATH || url.endsWith(BROADCAST_PATH);
658
- if (!isBroadcast || req.method !== "POST") {
659
- return next();
660
- }
661
- let body = "";
662
- req.on("data", (chunk) => {
663
- body += chunk.toString();
664
- });
665
- req.on("end", () => {
666
- try {
667
- const data = JSON.parse(body || "{}");
668
- server.ws.send({ type: "custom", event: RENAME_EVENT, data });
669
- res.statusCode = 204;
670
- res.end();
671
- } catch (error) {
672
- res.statusCode = 400;
673
- res.end(
674
- error instanceof Error ? error.message : "Bad rename payload"
675
- );
676
- }
677
- });
678
- });
679
- }
680
- };
681
- }
682
-
683
- // vitepress/plugins/getNoteByConfigIdPlugin.ts
684
- function getNoteByConfigIdPlugin() {
685
- return {
686
- name: "tnotes-get-note-by-config-id",
687
- configureServer(server) {
688
- server.middlewares.use(async (req, res, next) => {
689
- if (req.url?.startsWith("/__tnotes_get_note?") && req.method === "GET") {
690
- try {
691
- const url = new URL(req.url, `http://${req.headers.host}`);
692
- const configId = url.searchParams.get("configId");
693
- if (!configId) {
694
- res.statusCode = 400;
695
- res.setHeader("Content-Type", "application/json");
696
- res.end(
697
- JSON.stringify({
698
- success: false,
699
- error: "Missing configId parameter"
700
- })
701
- );
702
- return;
703
- }
704
- const noteIndexCache = NoteIndexCache.getInstance();
705
- if (!noteIndexCache.isInitialized()) {
706
- res.statusCode = 503;
707
- res.setHeader("Content-Type", "application/json");
708
- res.end(
709
- JSON.stringify({
710
- success: false,
711
- error: "Service not initialized"
712
- })
713
- );
714
- return;
715
- }
716
- const noteItem = noteIndexCache.getByConfigId(configId);
717
- if (!noteItem) {
718
- res.statusCode = 200;
719
- res.setHeader("Content-Type", "application/json");
720
- res.end(
721
- JSON.stringify({
722
- success: true,
723
- found: false,
724
- data: null
725
- })
726
- );
727
- return;
728
- }
729
- res.statusCode = 200;
730
- res.setHeader("Content-Type", "application/json");
731
- res.end(
732
- JSON.stringify({
733
- success: true,
734
- found: true,
735
- data: {
736
- noteIndex: noteItem.noteIndex,
737
- folderName: noteItem.folderName,
738
- // 构建笔记的完整 URL(包含 README)
739
- url: `/notes/${encodeURIComponent(
740
- noteItem.folderName
741
- )}/README`
742
- }
743
- })
744
- );
745
- logger.debug(
746
- `\u67E5\u8BE2\u7B14\u8BB0: configId=${configId}, noteIndex=${noteItem.noteIndex}`
747
- );
748
- } catch (error) {
749
- logger.error("\u67E5\u8BE2\u7B14\u8BB0\u5931\u8D25:", error);
750
- res.statusCode = 500;
751
- res.setHeader("Content-Type", "application/json");
752
- res.end(
753
- JSON.stringify({
754
- success: false,
755
- error: error instanceof Error ? error.message : String(error)
756
- })
757
- );
758
- }
759
- } else {
760
- next();
761
- }
762
- });
763
- }
764
- };
765
- }
766
-
767
- // vitepress/plugins/renameNotePlugin.ts
768
- function renameNotePlugin() {
769
- const renameCommand = new RenameNoteCommand();
770
- return {
771
- name: "tnotes-rename-note",
772
- configureServer(server) {
773
- server.middlewares.use(async (req, res, next) => {
774
- if (req.url === "/__tnotes_rename_note" && req.method === "POST") {
775
- let body = "";
776
- req.on("data", (chunk) => {
777
- body += chunk.toString();
778
- });
779
- req.on("end", async () => {
780
- try {
781
- const { noteIndex, newTitle } = JSON.parse(body);
782
- if (!noteIndex || !newTitle) {
783
- res.statusCode = 400;
784
- res.end("Missing noteIndex or newTitle");
785
- return;
786
- }
787
- const startTime = Date.now();
788
- await renameCommand.renameNote({ noteIndex, newTitle });
789
- const duration = Date.now() - startTime;
790
- const newFolderName = `${noteIndex}. ${newTitle.trim()}`;
791
- const newUrl = `/notes/${encodeURIComponent(
792
- newFolderName
793
- )}/README`;
794
- res.statusCode = 200;
795
- res.setHeader("Content-Type", "application/json");
796
- res.end(
797
- JSON.stringify({
798
- success: true,
799
- duration,
800
- newTitle,
801
- newFolderName,
802
- newUrl,
803
- message: "\u91CD\u547D\u540D\u5B8C\u6210"
804
- })
805
- );
806
- } catch (error) {
807
- res.statusCode = 500;
808
- res.end(error instanceof Error ? error.message : "Rename failed");
809
- }
810
- });
811
- } else {
812
- next();
813
- }
814
- });
815
- }
816
- };
817
- }
818
-
819
- // vitepress/plugins/sidebarStructurePlugin.ts
820
- async function readJsonBody(req) {
821
- let body = "";
822
- await new Promise((resolve, reject) => {
823
- req.on("data", (chunk) => {
824
- body += chunk.toString();
825
- });
826
- req.on("end", resolve);
827
- req.on("error", reject);
828
- });
829
- return body ? JSON.parse(body) : {};
830
- }
831
- function sendJson(res, statusCode, payload) {
832
- res.statusCode = statusCode;
833
- res.setHeader("Content-Type", "application/json");
834
- res.end(JSON.stringify(payload));
835
- }
836
- function normalizePathname(url) {
837
- return (url || "").split("?")[0];
838
- }
839
- function normalizeGroupPath(value) {
840
- if (!Array.isArray(value) || value.length === 0) {
841
- throw new Error("Missing groupPath");
842
- }
843
- return value.map((item) => String(item));
844
- }
845
- function normalizeCount(value) {
846
- const count = Number(value ?? 1);
847
- if (!Number.isInteger(count) || count < 1 || count > 100) {
848
- throw new Error("count must be an integer between 1 and 100");
849
- }
850
- return count;
851
- }
852
- function getCreatedNotePayload(notes) {
853
- return notes.map((note) => ({
854
- index: note.index,
855
- dirName: note.dirName,
856
- link: `/notes/${encodeURIComponent(note.dirName)}/README`
857
- }));
858
- }
859
- async function withSuspendedWatcher(task) {
860
- const watcher = FileWatcherService.getInstance();
861
- try {
862
- watcher?.suspend();
863
- return await task();
864
- } finally {
865
- watcher?.unsuspend();
866
- }
867
- }
868
- function sidebarStructurePlugin() {
869
- const noteService = NoteService.getInstance();
870
- const readmeService = ReadmeService.getInstance();
871
- async function createNotes(count) {
872
- const notes = [];
873
- const usedIndexes = /* @__PURE__ */ new Set();
874
- for (const note of noteService.getAllNotes()) {
875
- const index = parseInt(note.index, 10);
876
- if (!isNaN(index)) {
877
- usedIndexes.add(index);
878
- }
879
- }
880
- for (let i = 0; i < count; i++) {
881
- const note = await noteService.createNote({
882
- title: "new",
883
- usedIndexes
884
- });
885
- const index = parseInt(note.index, 10);
886
- if (!isNaN(index)) {
887
- usedIndexes.add(index);
888
- }
889
- notes.push(note);
890
- }
891
- return notes;
892
- }
893
- return {
894
- name: "tnotes-sidebar-structure",
895
- configureServer(server) {
896
- server.middlewares.use(async (req, res, next) => {
897
- const pathname = normalizePathname(req.url);
898
- const handledPaths = /* @__PURE__ */ new Set([
899
- "/__tnotes_sidebar_rename_group",
900
- "/__tnotes_sidebar_delete_group",
901
- "/__tnotes_sidebar_create_note",
902
- "/__tnotes_sidebar_create_notes",
903
- "/__tnotes_sidebar_delete_note",
904
- "/__tnotes_sidebar_reorder"
905
- ]);
906
- if (!handledPaths.has(pathname)) {
907
- next();
908
- return;
909
- }
910
- if (req.method !== "POST") {
911
- sendJson(res, 405, { success: false, message: "Method Not Allowed" });
912
- return;
913
- }
914
- try {
915
- const data = await readJsonBody(req);
916
- const result = await withSuspendedWatcher(async () => {
917
- if (pathname === "/__tnotes_sidebar_rename_group") {
918
- const groupPath = normalizeGroupPath(data.groupPath);
919
- const newTitle = String(data.newTitle || "");
920
- await readmeService.renameGroupInReadme(groupPath, newTitle);
921
- await readmeService.refreshHomeReadmeAndSidebar();
922
- return {
923
- success: true,
924
- sidebarChanged: true,
925
- message: "\u76EE\u5F55\u5DF2\u91CD\u547D\u540D"
926
- };
927
- }
928
- if (pathname === "/__tnotes_sidebar_delete_group") {
929
- const groupPath = normalizeGroupPath(data.groupPath);
930
- const noteIndexes = await readmeService.deleteGroupFromReadme(
931
- groupPath
932
- );
933
- for (const noteIndex of noteIndexes) {
934
- await noteService.deleteNote(noteIndex);
935
- }
936
- await readmeService.refreshHomeReadmeAndSidebar();
937
- return {
938
- success: true,
939
- sidebarChanged: true,
940
- redirectUrl: "/",
941
- deletedNoteIndexes: noteIndexes,
942
- message: "\u76EE\u5F55\u5DF2\u5220\u9664"
943
- };
944
- }
945
- if (pathname === "/__tnotes_sidebar_delete_note") {
946
- const noteIndex = String(data.noteIndex || "");
947
- if (!noteIndex) throw new Error("Missing noteIndex");
948
- await readmeService.deleteNoteFromReadme(noteIndex);
949
- await noteService.deleteNote(noteIndex);
950
- await readmeService.refreshHomeReadmeAndSidebar();
951
- return {
952
- success: true,
953
- sidebarChanged: true,
954
- redirectUrl: "/",
955
- deletedNoteIndexes: [noteIndex],
956
- message: "\u7B14\u8BB0\u5DF2\u5220\u9664"
957
- };
958
- }
959
- if (pathname === "/__tnotes_sidebar_reorder") {
960
- if (data.dragType === "note") {
961
- const noteIndex = String(data.noteIndex || "");
962
- if (!noteIndex) throw new Error("Missing noteIndex");
963
- if (data.targetType === "group") {
964
- await readmeService.moveNoteInReadme(noteIndex, {
965
- targetGroupPath: normalizeGroupPath(data.targetGroupPath)
966
- });
967
- } else {
968
- await readmeService.moveNoteInReadme(noteIndex, {
969
- targetNoteIndex: String(data.targetNoteIndex || ""),
970
- placement: data.placement === "after" ? "after" : "before"
971
- });
972
- }
973
- } else if (data.dragType === "group") {
974
- await readmeService.moveGroupInReadme(
975
- normalizeGroupPath(data.groupPath),
976
- normalizeGroupPath(data.targetGroupPath),
977
- data.placement === "after" ? "after" : "before"
978
- );
979
- } else {
980
- throw new Error("Missing dragType");
981
- }
982
- await readmeService.refreshHomeReadmeAndSidebar();
983
- return {
984
- success: true,
985
- sidebarChanged: true,
986
- message: "\u6392\u5E8F\u5DF2\u66F4\u65B0"
987
- };
988
- }
989
- const count = normalizeCount(data.count);
990
- const notes = await createNotes(count);
991
- if (data.targetNoteIndex) {
992
- const placement = data.placement === "after" ? "after" : "before";
993
- await readmeService.insertNotesAroundNote(
994
- String(data.targetNoteIndex),
995
- notes,
996
- placement
997
- );
998
- } else {
999
- const groupPath = normalizeGroupPath(data.groupPath);
1000
- await readmeService.insertNotesAtGroupStart(groupPath, notes);
1001
- }
1002
- await readmeService.refreshHomeReadmeAndSidebar();
1003
- return {
1004
- success: true,
1005
- sidebarChanged: true,
1006
- createdNotes: getCreatedNotePayload(notes),
1007
- message: "\u7B14\u8BB0\u5DF2\u521B\u5EFA"
1008
- };
1009
- });
1010
- sendJson(res, 200, result);
1011
- } catch (error) {
1012
- console.error("\u4FA7\u8FB9\u680F\u7ED3\u6784\u64CD\u4F5C\u5931\u8D25:", error);
1013
- sendJson(res, 500, {
1014
- success: false,
1015
- message: error instanceof Error ? error.message : String(error)
1016
- });
1017
- }
1018
- });
1019
- }
1020
- };
1021
- }
1022
-
1023
- // vitepress/plugins/updateConfigPlugin.ts
1024
- function updateConfigPlugin() {
1025
- let updateCommand;
1026
- return {
1027
- name: "tnotes-update-config",
1028
- configureServer(server) {
1029
- updateCommand = new UpdateNoteConfigCommand();
1030
- server.middlewares.use(async (req, res, next) => {
1031
- if (req.url === "/__tnotes_update_config" && req.method === "POST") {
1032
- let body = "";
1033
- req.on("data", (chunk) => {
1034
- body += chunk.toString();
1035
- });
1036
- req.on("end", async () => {
1037
- try {
1038
- const data = JSON.parse(body);
1039
- const { noteIndex, config } = data;
1040
- if (!noteIndex || !config) {
1041
- res.statusCode = 400;
1042
- res.end("Missing noteIndex or config");
1043
- return;
1044
- }
1045
- await updateCommand.updateConfig({
1046
- noteIndex,
1047
- config: {
1048
- done: config.done,
1049
- enableDiscussions: config.enableDiscussions,
1050
- description: config.description
1051
- }
1052
- });
1053
- res.statusCode = 200;
1054
- res.setHeader("Content-Type", "application/json");
1055
- res.end(JSON.stringify({ success: true }));
1056
- } catch (error) {
1057
- console.error("\u66F4\u65B0\u914D\u7F6E\u5931\u8D25:", error);
1058
- res.statusCode = 500;
1059
- res.end(error instanceof Error ? error.message : String(error));
1060
- }
1061
- });
1062
- } else {
1063
- next();
1064
- }
1065
- });
1066
- }
1067
- };
1068
- }
1069
-
1070
- // vitepress/config/index.ts
1071
- function defineNotesConfig(overrides = {}) {
1072
- const rootPath = process.cwd();
1073
- ConfigManager.init({ rootPath });
1074
- const config = ConfigManager.getInstance().getAll();
1075
- const { repoName } = config;
1076
- const IGNORE_LIST = getIgnoreList(config);
1077
- const GITHUB_PAGE_URL = getGithubPageUrl(config);
1078
- const {
1079
- transformPageData: overrideTransformPageData,
1080
- vite: overrideVite,
1081
- ...restOverrides
1082
- } = overrides;
1083
- return defineConfig({
1084
- appearance: "dark",
1085
- base: "/" + repoName + "/",
1086
- cleanUrls: true,
1087
- description: repoName,
1088
- head: getHeadConfig(config, GITHUB_PAGE_URL),
1089
- ignoreDeadLinks: true,
1090
- lang: "zh-Hans",
1091
- lastUpdated: false,
1092
- markdown: getMarkdownConfig(),
1093
- sitemap: {
1094
- hostname: GITHUB_PAGE_URL,
1095
- lastmodDateOnly: false
1096
- },
1097
- themeConfig: getThemeConfig(config),
1098
- title: repoName,
1099
- srcExclude: IGNORE_LIST,
1100
- vite: {
1101
- plugins: [
1102
- buildProgressPlugin(),
1103
- updateConfigPlugin(),
1104
- renameNotePlugin(),
1105
- sidebarStructurePlugin(),
1106
- getNoteByConfigIdPlugin(),
1107
- fileWatcherBridgePlugin(),
1108
- ...overrideVite?.plugins || []
1109
- ],
1110
- server: {
1111
- // 显式同时监听 IPv4 / IPv6,避免 Node 18+ 在 Windows 下偶发只绑定 ::1
1112
- // 导致 Chrome 解析 localhost → 127.0.0.1 时连接被拒、页面一直 pending。
1113
- // host: true,
1114
- watch: {
1115
- ignored: IGNORE_LIST
1116
- },
1117
- ...overrideVite?.server
1118
- },
1119
- css: {
1120
- preprocessorOptions: {
1121
- scss: {
1122
- silenceDeprecations: ["legacy-js-api"]
1123
- }
1124
- },
1125
- ...overrideVite?.css
1126
- },
1127
- build: {
1128
- chunkSizeWarningLimit: 1e3,
1129
- ...overrideVite?.build
1130
- },
1131
- define: {
1132
- __TNOTES_REPO_NAME__: JSON.stringify(config.repoName),
1133
- __TNOTES_AUTHOR__: JSON.stringify(config.author),
1134
- __TNOTES_IGNORE_DIRS__: JSON.stringify(config.ignore_dirs),
1135
- __TNOTES_ROOT_ITEM__: JSON.stringify(config.root_item),
1136
- ...overrideVite?.define
1137
- },
1138
- resolve: {
1139
- dedupe: ["vue", "vitepress"],
1140
- ...overrideVite?.resolve
1141
- },
1142
- optimizeDeps: {
1143
- include: [
1144
- // VitePress 内部 CJS 依赖 —— 需要 Vite 预构建为 ESM
1145
- "vitepress > @vscode/markdown-it-katex",
1146
- "vitepress > @braintree/sanitize-url",
1147
- "vitepress > dayjs",
1148
- "vitepress > dayjs/plugin/utc",
1149
- "vitepress > dayjs/plugin/localizedFormat"
1150
- ],
1151
- ...overrideVite?.optimizeDeps
1152
- }
1153
- },
1154
- transformPageData(pageData, ctx) {
1155
- if (/^notes\/\d{4}/.test(pageData.relativePath)) {
1156
- const fullPath = path2.resolve(rootPath, pageData.relativePath);
1157
- try {
1158
- const raw = fs2.readFileSync(fullPath, "utf-8");
1159
- pageData.frontmatter.rawContent = Buffer.from(raw, "utf-8").toString(
1160
- "base64"
1161
- );
1162
- } catch {
1163
- pageData.frontmatter.rawContent = null;
1164
- }
1165
- }
1166
- if (typeof overrideTransformPageData === "function") {
1167
- return overrideTransformPageData(pageData, ctx);
1168
- }
1169
- },
1170
- router: {
1171
- prefetchLinks: false
1172
- },
1173
- ...restOverrides
1174
- });
1175
- }
1176
- export {
1177
- defineNotesConfig
1178
- };