@icebreakers/monorepo-templates 1.0.2 → 1.0.4

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 (57) hide show
  1. package/assets/.github/workflows/release.yml +42 -2
  2. package/assets/commitlint.config.ts +1 -3
  3. package/assets/eslint.config.js +2 -14
  4. package/assets/lint-staged.config.js +1 -3
  5. package/assets/package.json +8 -6
  6. package/assets/stylelint.config.js +1 -3
  7. package/assets/tsconfig.json +2 -1
  8. package/assets/vitest.config.ts +1 -3
  9. package/assets-data.mjs +0 -1
  10. package/dist/cli.d.mts +1 -0
  11. package/dist/cli.mjs +12 -0
  12. package/dist/index.mjs +1 -260
  13. package/dist/prepare-CtCifHGT.mjs +306 -0
  14. package/package.json +2 -2
  15. package/templates/client/package.json +2 -2
  16. package/templates/client/vite.config.ts +27 -21
  17. package/templates/vitepress/.vitepress/config.ts +152 -69
  18. package/templates/vitepress/en/index.md +63 -0
  19. package/templates/vitepress/en/knowledge/monorepo.md +37 -0
  20. package/templates/vitepress/en/repoctl/adopt-existing.md +131 -0
  21. package/templates/vitepress/en/repoctl/aliases.md +71 -0
  22. package/templates/vitepress/en/repoctl/commands.md +120 -0
  23. package/templates/vitepress/en/repoctl/config.md +69 -0
  24. package/templates/vitepress/en/repoctl/getting-started.md +116 -0
  25. package/templates/vitepress/en/repoctl/index.md +74 -0
  26. package/templates/vitepress/en/repoctl/scenarios.md +117 -0
  27. package/templates/vitepress/en/repoctl/templates.md +128 -0
  28. package/templates/vitepress/en/repoctl/troubleshooting.md +96 -0
  29. package/templates/vitepress/en/repoctl/workflows.md +89 -0
  30. package/templates/vitepress/getting-started.md +21 -224
  31. package/templates/vitepress/index.md +47 -176
  32. package/templates/vitepress/monorepo/commands.md +13 -283
  33. package/templates/vitepress/monorepo/manage.md +16 -3
  34. package/templates/vitepress/monorepo/publish.md +52 -6
  35. package/templates/vitepress/monorepo/templates.md +14 -60
  36. package/templates/vitepress/monorepo/troubleshooting.md +14 -220
  37. package/templates/vitepress/package.json +3 -2
  38. package/templates/vitepress/repoctl/adopt-existing.md +135 -0
  39. package/templates/vitepress/repoctl/aliases.md +71 -0
  40. package/templates/vitepress/repoctl/commands.md +154 -0
  41. package/templates/vitepress/repoctl/config.md +81 -0
  42. package/templates/vitepress/repoctl/getting-started.md +122 -0
  43. package/templates/vitepress/repoctl/index.md +74 -0
  44. package/templates/vitepress/repoctl/scenarios.md +119 -0
  45. package/templates/vitepress/repoctl/templates.md +156 -0
  46. package/templates/vitepress/repoctl/troubleshooting.md +98 -0
  47. package/templates/vitepress/repoctl/workflows.md +105 -0
  48. package/templates/vitepress/tools/changeset.md +11 -0
  49. package/templates/vitepress/tools/husky.md +17 -0
  50. package/templates/vitepress/tools/lint-staged.md +10 -0
  51. package/templates/vitepress/tools/llms-txt.md +29 -0
  52. package/templates/vitepress/tools/pnpm.md +26 -0
  53. package/templates/vitepress/tools/turborepo.md +17 -0
  54. package/templates/vitepress/why/examples/2.npm-basic-package/README.md +1 -1
  55. package/templates/vitepress/why/examples/3.npm-basic-package/README.md +1 -1
  56. package/templates/vitepress/wrangler.jsonc +5 -0
  57. package/templates/vue-lib/package.json +1 -1
@@ -0,0 +1,306 @@
1
+ import * as path$1 from "node:path";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import fs from "node:fs/promises";
5
+ //#region assets-data.mjs
6
+ const coreAssetTargets = [
7
+ ".changeset",
8
+ ".husky",
9
+ ".vscode",
10
+ ".editorconfig",
11
+ ".gitattributes",
12
+ ".gitignore",
13
+ ".npmrc",
14
+ "commitlint.config.ts",
15
+ "eslint.config.js",
16
+ "lint-staged.config.js",
17
+ "stylelint.config.js",
18
+ "repoctl.config.ts",
19
+ "package.json",
20
+ "AGENTS.md",
21
+ "pnpm-workspace.yaml",
22
+ "tsconfig.json",
23
+ "turbo.json",
24
+ "vitest.config.ts",
25
+ "Dockerfile",
26
+ ".dockerignore"
27
+ ];
28
+ const extraAssetTargets = [
29
+ ".github",
30
+ "LICENSE",
31
+ "renovate.json",
32
+ "SECURITY.md",
33
+ "CODE_OF_CONDUCT.md",
34
+ "CONTRIBUTING.md",
35
+ "netlify.toml"
36
+ ];
37
+ const assetTargets = [...coreAssetTargets, ...extraAssetTargets];
38
+ function getAssetTargets(core = false) {
39
+ return core ? [...coreAssetTargets] : [...assetTargets];
40
+ }
41
+ //#endregion
42
+ //#region src/paths.ts
43
+ const packageDir = path$1.resolve(fileURLToPath(new URL("../", import.meta.url)));
44
+ const templatesDir = path$1.join(packageDir, "templates");
45
+ const assetsDir = path$1.join(packageDir, "assets");
46
+ const skeletonDir = assetsDir;
47
+ //#endregion
48
+ //#region template-data.mjs
49
+ const templateChoices = [
50
+ {
51
+ key: "tsdown",
52
+ label: "tsdown 打包",
53
+ source: "tsdown",
54
+ target: "packages/tsdown",
55
+ category: "library",
56
+ description: "使用 tsdown 构建的 TypeScript 库包"
57
+ },
58
+ {
59
+ key: "vue-lib",
60
+ label: "vue 组件",
61
+ source: "vue-lib",
62
+ target: "packages/vue-lib",
63
+ category: "library",
64
+ description: "Vue 3 组件库模板,适合沉淀可复用 UI"
65
+ },
66
+ {
67
+ key: "vue-hono",
68
+ label: "vue hono 全栈",
69
+ source: "client",
70
+ target: "apps/client",
71
+ category: "app",
72
+ description: "Vue 3 + Hono 的前后端一体应用模板"
73
+ },
74
+ {
75
+ key: "hono-server",
76
+ label: "hono 模板",
77
+ source: "server",
78
+ target: "apps/server",
79
+ category: "service",
80
+ description: "Hono API 服务模板"
81
+ },
82
+ {
83
+ key: "vitepress",
84
+ label: "vitepress 文档",
85
+ source: "vitepress",
86
+ target: "apps/website",
87
+ category: "docs",
88
+ description: "VitePress 文档站模板"
89
+ },
90
+ {
91
+ key: "cli",
92
+ label: "cli 模板",
93
+ source: "cli",
94
+ target: "apps/cli",
95
+ category: "tool",
96
+ description: "TypeScript 命令行工具模板"
97
+ }
98
+ ];
99
+ //#endregion
100
+ //#region src/utils/gitignore.ts
101
+ const publishBasename = "gitignore";
102
+ const workspaceBasename = ".gitignore";
103
+ const normalizedPathPattern = /[\\/]/;
104
+ function detectSeparator(input) {
105
+ if (input.includes("\\") && !input.includes("/")) return "\\";
106
+ return "/";
107
+ }
108
+ function replaceBasename(input, from, to) {
109
+ if (!input) return input;
110
+ const separator = detectSeparator(input);
111
+ const normalized = input.replace(normalizedPathPattern, separator);
112
+ const hasTrailingSeparator = normalized.endsWith(separator);
113
+ const segments = normalized.split(separator);
114
+ if (hasTrailingSeparator && segments.at(-1) === "") segments.pop();
115
+ const lastIndex = segments.length - 1;
116
+ if (lastIndex >= 0 && segments[lastIndex] === from) {
117
+ segments[lastIndex] = to;
118
+ const rebuilt = segments.join(separator);
119
+ return hasTrailingSeparator ? `${rebuilt}${separator}` : rebuilt;
120
+ }
121
+ return input;
122
+ }
123
+ function toPublishGitignorePath(input) {
124
+ return replaceBasename(input, workspaceBasename, publishBasename);
125
+ }
126
+ function toWorkspaceGitignorePath(input) {
127
+ return replaceBasename(input, publishBasename, workspaceBasename);
128
+ }
129
+ function isGitignoreFile(name) {
130
+ return toPublishGitignorePath(name) !== name || toWorkspaceGitignorePath(name) !== name;
131
+ }
132
+ //#endregion
133
+ //#region src/utils/template-filter.ts
134
+ const skipDirs = new Set([
135
+ "node_modules",
136
+ "dist",
137
+ ".turbo",
138
+ ".cache",
139
+ ".vite",
140
+ ".tmp",
141
+ ".vue-global-types",
142
+ ".wrangler"
143
+ ]);
144
+ const skipFiles = new Set([
145
+ ".DS_Store",
146
+ "CHANGELOG.md",
147
+ "route-map.d.ts"
148
+ ]);
149
+ function shouldSkipTemplatePath(rootDir, targetPath) {
150
+ const basename = path.basename(targetPath);
151
+ if (skipFiles.has(basename)) return true;
152
+ if (basename.endsWith(".tsbuildinfo")) return true;
153
+ if (/\.timestamp-\d+-[a-z0-9]+\.mjs$/i.test(basename)) return true;
154
+ const relative = path.relative(rootDir, targetPath);
155
+ if (!relative || relative.startsWith("..")) return false;
156
+ const segments = relative.split(path.sep);
157
+ if (segments.some((segment) => skipDirs.has(segment))) return true;
158
+ for (let i = 0; i < segments.length - 1; i += 1) if (segments[i] === ".vitepress" && segments[i + 1] === "cache") return true;
159
+ return false;
160
+ }
161
+ function createTemplateCopyFilter(rootDir) {
162
+ return (src) => !shouldSkipTemplatePath(rootDir, src);
163
+ }
164
+ //#endregion
165
+ //#region src/prepare.ts
166
+ const huskySkippedEntryPattern = /[\\/]_$/;
167
+ const publishedToolingConfigs = {
168
+ "commitlint.config.ts": [
169
+ `import { defineCommitlintConfig } from 'repoctl/tooling'`,
170
+ "",
171
+ "export default await defineCommitlintConfig()",
172
+ ""
173
+ ].join("\n"),
174
+ "eslint.config.js": [
175
+ `import { defineEslintConfig } from 'repoctl/tooling'`,
176
+ "",
177
+ "export default await defineEslintConfig()",
178
+ ""
179
+ ].join("\n"),
180
+ "lint-staged.config.js": [
181
+ `import { defineLintStagedConfig } from 'repoctl/tooling'`,
182
+ "",
183
+ "export default await defineLintStagedConfig()",
184
+ ""
185
+ ].join("\n"),
186
+ "stylelint.config.js": [
187
+ `import { defineStylelintConfig } from 'repoctl/tooling'`,
188
+ "",
189
+ "export default await defineStylelintConfig()",
190
+ ""
191
+ ].join("\n"),
192
+ "vitest.config.ts": [
193
+ `import { defineConfig } from 'vitest/config'`,
194
+ `import { defineVitestConfig } from 'repoctl/tooling'`,
195
+ "",
196
+ "export default defineConfig(async () => await defineVitestConfig())",
197
+ ""
198
+ ].join("\n")
199
+ };
200
+ async function pathExists(targetPath) {
201
+ try {
202
+ await fs.access(targetPath);
203
+ return true;
204
+ } catch {
205
+ return false;
206
+ }
207
+ }
208
+ async function renameGitignoreFiles(targetDir) {
209
+ let entries;
210
+ try {
211
+ entries = await fs.readdir(targetDir, { withFileTypes: true });
212
+ } catch (error) {
213
+ if (error.code === "ENOENT") return;
214
+ throw error;
215
+ }
216
+ await Promise.all(entries.map(async (entry) => {
217
+ const current = path$1.join(targetDir, entry.name);
218
+ if (entry.isDirectory()) {
219
+ await renameGitignoreFiles(current);
220
+ return;
221
+ }
222
+ const renamed = toPublishGitignorePath(entry.name);
223
+ if (renamed !== entry.name) await fs.rename(current, path$1.join(targetDir, renamed));
224
+ }));
225
+ }
226
+ async function resetDir(targetDir, overwriteExisting) {
227
+ if (!overwriteExisting && await pathExists(targetDir)) return;
228
+ try {
229
+ await fs.rm(targetDir, {
230
+ recursive: true,
231
+ force: true
232
+ });
233
+ } catch (error) {
234
+ const err = error;
235
+ if (err?.code !== "ENOTEMPTY" && err?.code !== "EBUSY" && err?.code !== "EPERM") throw error;
236
+ }
237
+ await fs.mkdir(targetDir, { recursive: true });
238
+ }
239
+ async function copyEntry(from, to, overwriteExisting, filter) {
240
+ if (!overwriteExisting && await pathExists(to)) {
241
+ const [fromStats, toStats] = await Promise.all([fs.stat(from), fs.stat(to)]);
242
+ if (fromStats.isDirectory() && toStats.isDirectory()) await fs.cp(from, to, {
243
+ recursive: true,
244
+ force: false,
245
+ errorOnExist: false,
246
+ filter
247
+ });
248
+ return;
249
+ }
250
+ try {
251
+ await fs.cp(from, to, {
252
+ recursive: true,
253
+ force: overwriteExisting,
254
+ filter
255
+ });
256
+ } catch (error) {
257
+ const err = error;
258
+ if (!overwriteExisting && (err?.code === "EEXIST" || err?.code === "ENOTEMPTY")) return;
259
+ throw error;
260
+ }
261
+ }
262
+ async function copyAssets(repoRoot, overwriteExisting) {
263
+ const monorepoAssetRoot = path$1.resolve(repoRoot, "packages/monorepo/assets");
264
+ for (const target of assetTargets) {
265
+ const packageAsset = path$1.join(monorepoAssetRoot, toPublishGitignorePath(target));
266
+ const repoAsset = path$1.join(repoRoot, target);
267
+ const from = await pathExists(repoAsset) ? repoAsset : packageAsset;
268
+ if (!await pathExists(from)) continue;
269
+ const to = path$1.join(assetsDir, toPublishGitignorePath(target));
270
+ const stats = await fs.stat(from);
271
+ await copyEntry(from, to, overwriteExisting, target === ".husky" ? (src) => !huskySkippedEntryPattern.test(src) : void 0);
272
+ if (target === "tsconfig.json") await fs.writeFile(to, `${JSON.stringify({
273
+ extends: "repoctl/tsconfig.json",
274
+ files: []
275
+ }, null, 2)}\n`);
276
+ if (stats.isDirectory()) await renameGitignoreFiles(to);
277
+ }
278
+ }
279
+ async function writePublishedToolingConfigs() {
280
+ await Promise.all(Object.entries(publishedToolingConfigs).map(async ([filename, content]) => {
281
+ const targetPath = path$1.join(assetsDir, filename);
282
+ if (await pathExists(targetPath)) await fs.writeFile(targetPath, content);
283
+ }));
284
+ }
285
+ async function copyTemplates(repoRoot, overwriteExisting) {
286
+ for (const template of templateChoices) {
287
+ const from = path$1.join(repoRoot, "templates", template.source);
288
+ if (!await pathExists(from)) continue;
289
+ const to = path$1.join(templatesDir, template.source);
290
+ const filter = (src) => !shouldSkipTemplatePath(from, src);
291
+ await copyEntry(from, to, overwriteExisting, filter);
292
+ await renameGitignoreFiles(to);
293
+ }
294
+ }
295
+ async function prepareAssets(options = {}) {
296
+ const overwriteExisting = options.overwriteExisting ?? true;
297
+ const repoRoot = path$1.resolve(packageDir, "..", "..");
298
+ if (!await pathExists(path$1.join(repoRoot, "templates"))) return;
299
+ await resetDir(assetsDir, overwriteExisting);
300
+ await resetDir(templatesDir, overwriteExisting);
301
+ await copyAssets(repoRoot, overwriteExisting);
302
+ await writePublishedToolingConfigs();
303
+ await copyTemplates(repoRoot, overwriteExisting);
304
+ }
305
+ //#endregion
306
+ export { toPublishGitignorePath as a, assetsDir as c, templatesDir as d, assetTargets as f, isGitignoreFile as i, packageDir as l, createTemplateCopyFilter as n, toWorkspaceGitignorePath as o, getAssetTargets as p, shouldSkipTemplatePath as r, templateChoices as s, prepareAssets as t, skeletonDir as u };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icebreakers/monorepo-templates",
3
3
  "type": "module",
4
- "version": "1.0.2",
4
+ "version": "1.0.4",
5
5
  "description": "Template assets for icebreaker monorepo scaffolding",
6
6
  "author": "ice breaker <hi@sonofmagic.top>",
7
7
  "license": "MIT",
@@ -57,7 +57,7 @@
57
57
  "build": "tsdown",
58
58
  "typecheck": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json",
59
59
  "tsd": "pnpm build && tsd --files test-d/**/*.test-d.ts",
60
- "sync:assets": "pnpm run build && node scripts/sync-assets.mjs",
60
+ "sync:assets": "pnpm run build && node dist/cli.mjs",
61
61
  "lint": "eslint ."
62
62
  }
63
63
  }
@@ -26,7 +26,7 @@
26
26
  "tailwind-merge": "^3.5.0",
27
27
  "tailwind-variants": "^3.2.2",
28
28
  "vue": "^3.5.34",
29
- "vue-i18n": "^11.4.0",
29
+ "vue-i18n": "^11.4.2",
30
30
  "vue-router": "^5.0.6"
31
31
  },
32
32
  "devDependencies": {
@@ -42,7 +42,7 @@
42
42
  "hono": "^4.12.18",
43
43
  "tailwindcss": "^4.2.4",
44
44
  "typescript": "~6.0.3",
45
- "vite": "^8.0.10",
45
+ "vite": "^8.0.11",
46
46
  "vite-plugin-vue-devtools": "^8.1.1",
47
47
  "vite-tsconfig-paths": "^6.1.1",
48
48
  "vue-tsc": "3.2.8",
@@ -1,3 +1,4 @@
1
+ import type { PluginOption, UserConfig } from 'vite'
1
2
  import path from 'node:path'
2
3
  import { cloudflare } from '@cloudflare/vite-plugin'
3
4
  import Tailwindcss from '@tailwindcss/vite'
@@ -8,27 +9,32 @@ import VueDevTools from 'vite-plugin-vue-devtools'
8
9
  import VueRouter from 'vue-router/vite'
9
10
 
10
11
  // https://vite.dev/config/
11
- export default defineConfig(({ command }) => ({
12
- build: {
13
- target: 'baseline-widely-available',
14
- },
15
- resolve: {
16
- alias: {
17
- '@': path.resolve(import.meta.dirname, 'src'),
18
- '~': import.meta.dirname,
19
- },
20
- },
21
- plugins: [
22
- VueRouter(
23
- {
24
- dts: path.resolve(import.meta.dirname, 'src/route-map.d.ts'),
25
- watch: command === 'serve',
26
- },
27
- ),
12
+ export default defineConfig(({ command }): UserConfig => {
13
+ const plugins: PluginOption[] = [
14
+ VueRouter({
15
+ dts: path.resolve(import.meta.dirname, 'src/route-map.d.ts'),
16
+ watch: command === 'serve',
17
+ }) as PluginOption,
28
18
  Vue(),
29
19
  VueJsx(),
30
20
  Tailwindcss(),
31
- cloudflare(),
32
- command === 'serve' ? VueDevTools() : null,
33
- ],
34
- }))
21
+ cloudflare() as unknown as PluginOption,
22
+ ]
23
+
24
+ if (command === 'serve') {
25
+ plugins.push(VueDevTools() as unknown as PluginOption)
26
+ }
27
+
28
+ return {
29
+ build: {
30
+ target: 'baseline-widely-available',
31
+ },
32
+ resolve: {
33
+ alias: {
34
+ '@': path.resolve(import.meta.dirname, 'src'),
35
+ '~': import.meta.dirname,
36
+ },
37
+ },
38
+ plugins,
39
+ }
40
+ })
@@ -1,91 +1,174 @@
1
1
  import Tailwindcss from '@tailwindcss/vite'
2
2
  import { defineConfig } from 'vitepress'
3
+ import llmstxt from 'vitepress-plugin-llms'
3
4
  import { withMermaid } from 'vitepress-plugin-mermaid'
4
- // https://vitepress.dev/reference/site-config
5
+
6
+ const repoctlSidebar = [
7
+ {
8
+ text: 'repoctl',
9
+ items: [
10
+ { text: '概览', link: '/repoctl/' },
11
+ { text: '快速开始', link: '/repoctl/getting-started' },
12
+ { text: '接入已有仓库', link: '/repoctl/adopt-existing' },
13
+ { text: '按场景选命令', link: '/repoctl/scenarios' },
14
+ { text: '命令速查', link: '/repoctl/commands' },
15
+ { text: '配置文件', link: '/repoctl/config' },
16
+ { text: '模板与创建', link: '/repoctl/templates' },
17
+ { text: '工作流与 CI', link: '/repoctl/workflows' },
18
+ { text: '排障与报告', link: '/repoctl/troubleshooting' },
19
+ { text: '命令别名', link: '/repoctl/aliases' },
20
+ ],
21
+ },
22
+ {
23
+ text: '知识库',
24
+ items: [
25
+ { text: '为什么往 monorepo 方向演进', link: '/monorepo/' },
26
+ { text: '如何管理 monorepo', link: '/monorepo/manage' },
27
+ { text: '发包与变更日志', link: '/monorepo/publish' },
28
+ { text: '如何复用 js 代码', link: '/why/how-to-reuse-js-code' },
29
+ { text: 'JS 文件的各种后缀', link: '/why/js-cjs-mjs' },
30
+ { text: 'CJS 和 ESM 关键字/全局变量对比', link: '/why/js-keywords' },
31
+ { text: '什么是 npm 包', link: '/why/what-is-npm-package' },
32
+ { text: '如何发布 npm 包', link: '/why/publish-basic-npm-package' },
33
+ { text: '改进并发布现代 npm 包', link: '/why/index' },
34
+ ],
35
+ },
36
+ {
37
+ text: 'AI',
38
+ items: [
39
+ { text: 'AI 文档入口', link: '/tools/llms-txt' },
40
+ ],
41
+ },
42
+ {
43
+ text: '工具专题',
44
+ items: [
45
+ { text: 'pnpm', link: '/tools/pnpm' },
46
+ { text: 'turborepo', link: '/tools/turborepo' },
47
+ { text: 'changeset', link: '/tools/changeset' },
48
+ { text: 'husky', link: '/tools/husky' },
49
+ { text: 'lint-staged', link: '/tools/lint-staged' },
50
+ { text: 'renovate', link: '/tools/renovate' },
51
+ ],
52
+ },
53
+ ]
54
+
55
+ const enSidebar = [
56
+ {
57
+ text: 'repoctl',
58
+ items: [
59
+ { text: 'Overview', link: '/en/repoctl/' },
60
+ { text: 'Getting Started', link: '/en/repoctl/getting-started' },
61
+ { text: 'Adopt Existing Repos', link: '/en/repoctl/adopt-existing' },
62
+ { text: 'Choose By Scenario', link: '/en/repoctl/scenarios' },
63
+ { text: 'Command Reference', link: '/en/repoctl/commands' },
64
+ { text: 'Configuration', link: '/en/repoctl/config' },
65
+ { text: 'Templates', link: '/en/repoctl/templates' },
66
+ { text: 'Workflows and CI', link: '/en/repoctl/workflows' },
67
+ { text: 'Troubleshooting', link: '/en/repoctl/troubleshooting' },
68
+ { text: 'Command Aliases', link: '/en/repoctl/aliases' },
69
+ ],
70
+ },
71
+ {
72
+ text: 'Knowledge Base',
73
+ items: [
74
+ { text: 'Why Monorepo', link: '/en/knowledge/monorepo' },
75
+ ],
76
+ },
77
+ ]
78
+
5
79
  export default withMermaid(defineConfig({
6
80
  outDir: '.vitepress/dist',
7
- title: 'icebreaker\'s monorepo',
8
- description: 'A practical pnpm + turbo monorepo template with short onboarding commands and repo tooling.',
81
+ title: 'repoctl',
82
+ description: 'repoctl documentation for practical pnpm and Turborepo monorepos.',
83
+ lastUpdated: true,
84
+ cleanUrls: true,
85
+ head: [
86
+ ['link', { rel: 'icon', href: '/logo.jpg' }],
87
+ ],
9
88
  themeConfig: {
10
- // https://vitepress.dev/reference/default-theme-config
11
- nav: [
12
- { text: '开始使用', link: '/' },
13
- { text: '新手指南', link: '/getting-started' },
14
- { text: 'Monorepo', link: '/monorepo/' },
15
- { text: '工具专题', link: '/tools/turborepo' },
16
- { text: '一些思考', link: '/thinking' },
17
- ],
89
+ logo: '/logo.jpg',
90
+ search: {
91
+ provider: 'local',
92
+ },
18
93
  socialLinks: [
19
94
  { icon: 'github', link: 'https://github.com/sonofmagic/monorepo-template' },
20
95
  ],
21
- outline: {
22
- label: '目录',
23
- level: [2, 3],
24
- },
25
- logo: '/logo.jpg',
26
- sidebar: {
27
- '/': [
28
- {
29
- text: '开始使用',
30
- items: [
31
- { text: '首页', link: '/' },
32
- { text: '新手使用指南', link: '/getting-started' },
33
- { text: '一些思考', link: '/thinking' },
34
- ],
96
+ },
97
+ locales: {
98
+ root: {
99
+ label: '简体中文',
100
+ lang: 'zh-CN',
101
+ title: 'repoctl',
102
+ description: '围绕 repoctl 的 pnpm + Turborepo monorepo 使用文档。',
103
+ themeConfig: {
104
+ nav: [
105
+ { text: 'repoctl', link: '/repoctl/' },
106
+ { text: '快速开始', link: '/repoctl/getting-started' },
107
+ { text: '命令', link: '/repoctl/commands' },
108
+ { text: '知识库', link: '/monorepo/' },
109
+ { text: 'AI 文档', link: '/tools/llms-txt' },
110
+ { text: '工具专题', link: '/tools/turborepo' },
111
+ ],
112
+ outline: {
113
+ label: '目录',
114
+ level: [2, 3],
115
+ },
116
+ sidebar: {
117
+ '/': repoctlSidebar,
35
118
  },
36
- {
37
- text: 'Monorepo',
38
- items: [
39
- { text: '为什么往 monorepo 方向演进', link: '/monorepo/' },
40
- { text: '如何管理 monorepo', link: '/monorepo/manage' },
41
- { text: '模板速查', link: '/monorepo/templates' },
42
- { text: '命令速查', link: '/monorepo/commands' },
43
- { text: '常见问题排障', link: '/monorepo/troubleshooting' },
44
- { text: '发包与变更日志', link: '/monorepo/publish' },
45
- ],
119
+ editLink: {
120
+ pattern: 'https://github.com/sonofmagic/monorepo-template/edit/main/templates/vitepress/:path',
121
+ text: '为此页提供修改建议',
46
122
  },
47
- {
48
- text: 'npm 与包',
49
- items: [
50
- { text: '如何复用 js 代码', link: '/why/how-to-reuse-js-code' },
51
- { text: 'JS 文件的各种后缀', link: '/why/js-cjs-mjs' },
52
- { text: 'CJS 和 ESM 关键字/全局变量对比', link: '/why/js-keywords' },
53
- { text: '什么是 npm 包', link: '/why/what-is-npm-package' },
54
- { text: '如何发布 npm 包', link: '/why/publish-basic-npm-package' },
55
- { text: '改进并发布现代 npm 包', link: '/why/index' },
56
- ],
123
+ docFooter: {
124
+ prev: '上一页',
125
+ next: '下一页',
57
126
  },
58
- {
59
- text: '相关的工具',
60
- items: [
61
- { text: 'pnpm', link: '/tools/pnpm' },
62
- { text: 'turborepo', link: '/tools/turborepo' },
63
- { text: 'changeset', link: '/tools/changeset' },
64
- { text: 'husky', link: '/tools/husky' },
65
- { text: 'lint-staged', link: '/tools/lint-staged' },
66
- { text: 'renovate', link: '/tools/renovate' },
67
- ],
127
+ lastUpdated: {
128
+ text: '最后更新',
68
129
  },
69
- ],
130
+ },
70
131
  },
71
- editLink: {
72
- pattern: 'https://github.com/sonofmagic/monorepo-template/edit/main/templates/vitepress/:path',
73
- text: '为此页提供修改建议',
132
+ en: {
133
+ label: 'English',
134
+ lang: 'en-US',
135
+ title: 'repoctl',
136
+ description: 'Documentation for using repoctl in practical pnpm and Turborepo monorepos.',
137
+ themeConfig: {
138
+ nav: [
139
+ { text: 'repoctl', link: '/en/repoctl/' },
140
+ { text: 'Getting Started', link: '/en/repoctl/getting-started' },
141
+ { text: 'Commands', link: '/en/repoctl/commands' },
142
+ { text: 'Knowledge Base', link: '/en/knowledge/monorepo' },
143
+ { text: 'AI Docs', link: '/tools/llms-txt' },
144
+ ],
145
+ outline: {
146
+ label: 'On This Page',
147
+ level: [2, 3],
148
+ },
149
+ sidebar: {
150
+ '/en/': enSidebar,
151
+ },
152
+ editLink: {
153
+ pattern: 'https://github.com/sonofmagic/monorepo-template/edit/main/templates/vitepress/:path',
154
+ text: 'Edit this page',
155
+ },
156
+ docFooter: {
157
+ prev: 'Previous page',
158
+ next: 'Next page',
159
+ },
160
+ lastUpdated: {
161
+ text: 'Last updated',
162
+ },
163
+ },
74
164
  },
75
165
  },
76
166
  vite: {
77
167
  plugins: [
78
168
  // @ts-ignore
79
169
  Tailwindcss(),
170
+ llmstxt(),
80
171
  ],
81
- // server: {
82
- // hmr: {
83
- // overlay: false,
84
- // },
85
- // },
86
- },
87
- mermaid: {
88
-
89
172
  },
90
- }),
91
- )
173
+ mermaid: {},
174
+ }))