cf-yoyo 1.0.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 (141) hide show
  1. package/.eslintrc.json +28 -0
  2. package/.github/workflows/ci.yml +96 -0
  3. package/.prettierrc.json +10 -0
  4. package/CHANGELOG.md +55 -0
  5. package/README.md +138 -0
  6. package/__tests__/cli-e2e.test.ts +145 -0
  7. package/__tests__/config.test.ts +268 -0
  8. package/__tests__/filesystem.test.ts +453 -0
  9. package/__tests__/logger.test.ts +274 -0
  10. package/__tests__/template-engine.test.ts +450 -0
  11. package/__tests__/types.test.ts +25 -0
  12. package/deep_todos.md +766 -0
  13. package/dist/cli/commands/create.d.ts +26 -0
  14. package/dist/cli/commands/create.d.ts.map +1 -0
  15. package/dist/cli/commands/create.js +308 -0
  16. package/dist/cli/commands/create.js.map +1 -0
  17. package/dist/cli/commands/git.d.ts +10 -0
  18. package/dist/cli/commands/git.d.ts.map +1 -0
  19. package/dist/cli/commands/git.js +887 -0
  20. package/dist/cli/commands/git.js.map +1 -0
  21. package/dist/cli/commands/list.d.ts +10 -0
  22. package/dist/cli/commands/list.d.ts.map +1 -0
  23. package/dist/cli/commands/list.js +90 -0
  24. package/dist/cli/commands/list.js.map +1 -0
  25. package/dist/cli/index.d.ts +15 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +62 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/core/config.d.ts +35 -0
  30. package/dist/core/config.d.ts.map +1 -0
  31. package/dist/core/config.js +260 -0
  32. package/dist/core/config.js.map +1 -0
  33. package/dist/core/filesystem.d.ts +84 -0
  34. package/dist/core/filesystem.d.ts.map +1 -0
  35. package/dist/core/filesystem.js +417 -0
  36. package/dist/core/filesystem.js.map +1 -0
  37. package/dist/core/git-token.d.ts +81 -0
  38. package/dist/core/git-token.d.ts.map +1 -0
  39. package/dist/core/git-token.js +244 -0
  40. package/dist/core/git-token.js.map +1 -0
  41. package/dist/core/git.d.ts +70 -0
  42. package/dist/core/git.d.ts.map +1 -0
  43. package/dist/core/git.js +367 -0
  44. package/dist/core/git.js.map +1 -0
  45. package/dist/core/prompt.d.ts +28 -0
  46. package/dist/core/prompt.d.ts.map +1 -0
  47. package/dist/core/prompt.js +253 -0
  48. package/dist/core/prompt.js.map +1 -0
  49. package/dist/core/template-engine.d.ts +52 -0
  50. package/dist/core/template-engine.d.ts.map +1 -0
  51. package/dist/core/template-engine.js +308 -0
  52. package/dist/core/template-engine.js.map +1 -0
  53. package/dist/core/template-manager.d.ts +54 -0
  54. package/dist/core/template-manager.d.ts.map +1 -0
  55. package/dist/core/template-manager.js +330 -0
  56. package/dist/core/template-manager.js.map +1 -0
  57. package/dist/index.d.ts +12 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +19 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/types/index.d.ts +244 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +51 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/dist/utils/logger.d.ts +68 -0
  66. package/dist/utils/logger.d.ts.map +1 -0
  67. package/dist/utils/logger.js +140 -0
  68. package/dist/utils/logger.js.map +1 -0
  69. package/memory.md +241 -0
  70. package/need-debug.md +395 -0
  71. package/package.json +42 -0
  72. package/src/cli/commands/create.ts +326 -0
  73. package/src/cli/commands/git.ts +1001 -0
  74. package/src/cli/commands/list.ts +97 -0
  75. package/src/cli/index.ts +71 -0
  76. package/src/core/config.ts +262 -0
  77. package/src/core/filesystem.ts +408 -0
  78. package/src/core/git-token.ts +248 -0
  79. package/src/core/git.ts +384 -0
  80. package/src/core/prompt.ts +345 -0
  81. package/src/core/template-engine.ts +324 -0
  82. package/src/core/template-manager.ts +338 -0
  83. package/src/index.ts +19 -0
  84. package/src/types/index.ts +259 -0
  85. package/src/utils/logger.ts +150 -0
  86. package/templates/pages/basic/README.md.mustache +63 -0
  87. package/templates/pages/basic/package.json.mustache +23 -0
  88. package/templates/pages/basic/public/css/style.css +199 -0
  89. package/templates/pages/basic/public/index.html.mustache +72 -0
  90. package/templates/pages/basic/public/js/main.js +103 -0
  91. package/templates/pages/basic/template.json +38 -0
  92. package/templates/pages/basic/tsconfig.json +21 -0
  93. package/templates/pages/basic/wrangler.toml.mustache +14 -0
  94. package/templates/pages/basic-js/README.md.mustache +62 -0
  95. package/templates/pages/basic-js/package.json.mustache +25 -0
  96. package/templates/pages/basic-js/public/css/style.css +212 -0
  97. package/templates/pages/basic-js/public/index.html.mustache +53 -0
  98. package/templates/pages/basic-js/public/js/main.js +134 -0
  99. package/templates/pages/basic-js/template.json +35 -0
  100. package/templates/pages/basic-js/wrangler.toml.mustache +14 -0
  101. package/templates/pages/react/README.md.mustache +97 -0
  102. package/templates/pages/react/index.html.mustache +14 -0
  103. package/templates/pages/react/package.json.mustache +34 -0
  104. package/templates/pages/react/src/App.css +168 -0
  105. package/templates/pages/react/src/App.tsx.mustache +62 -0
  106. package/templates/pages/react/src/index.css +53 -0
  107. package/templates/pages/react/src/main.tsx.mustache +10 -0
  108. package/templates/pages/react/src/vite-env.d.ts +1 -0
  109. package/templates/pages/react/template.json +54 -0
  110. package/templates/pages/react/tsconfig.json +21 -0
  111. package/templates/pages/react/tsconfig.node.json +10 -0
  112. package/templates/pages/react/vite.config.ts +16 -0
  113. package/templates/worker/basic/README.md.mustache +56 -0
  114. package/templates/worker/basic/package.json.mustache +29 -0
  115. package/templates/worker/basic/src/index.ts.mustache +125 -0
  116. package/templates/worker/basic/template.json +30 -0
  117. package/templates/worker/basic/tsconfig.json +24 -0
  118. package/templates/worker/basic/wrangler.toml.mustache +33 -0
  119. package/templates/worker/basic-js/README.md.mustache +55 -0
  120. package/templates/worker/basic-js/package.json.mustache +25 -0
  121. package/templates/worker/basic-js/src/index.js.mustache +146 -0
  122. package/templates/worker/basic-js/template.json +27 -0
  123. package/templates/worker/basic-js/wrangler.toml.mustache +33 -0
  124. package/templates/worker/hono/README.md.mustache +79 -0
  125. package/templates/worker/hono/package.json.mustache +33 -0
  126. package/templates/worker/hono/src/index.ts.mustache +64 -0
  127. package/templates/worker/hono/src/routes/index.ts.mustache +165 -0
  128. package/templates/worker/hono/template.json +34 -0
  129. package/templates/worker/hono/tsconfig.json +24 -0
  130. package/templates/worker/hono/wrangler.toml.mustache +36 -0
  131. package/templates/worker/hono-js/README.md.mustache +67 -0
  132. package/templates/worker/hono-js/package.json.mustache +29 -0
  133. package/templates/worker/hono-js/src/index.js.mustache +55 -0
  134. package/templates/worker/hono-js/src/routes/index.js.mustache +127 -0
  135. package/templates/worker/hono-js/template.json +31 -0
  136. package/templates/worker/hono-js/wrangler.toml.mustache +36 -0
  137. package/thoughts/ledgers/CONTINUITY_ses_287e.md +74 -0
  138. package/thoughts/ledgers/CONTINUITY_ses_28b5.md +85 -0
  139. package/tsconfig.json +30 -0
  140. package/vitest.config.ts +20 -0
  141. package//351/240/205/347/233/256/350/241/250.md +140 -0
@@ -0,0 +1,259 @@
1
+ /**
2
+ * 類型定義模組
3
+ * 定義 CLI 工具使用的所有 TypeScript 類型
4
+ */
5
+
6
+ /**
7
+ * 程式語言列舉
8
+ * 支援 TypeScript 和 JavaScript
9
+ */
10
+ export enum Language {
11
+ TYPESCRIPT = 'typescript',
12
+ JAVASCRIPT = 'javascript',
13
+ }
14
+
15
+ /**
16
+ * 專案類型列舉
17
+ */
18
+ export enum ProjectType {
19
+ WORKER = 'worker',
20
+ PAGES = 'pages',
21
+ D1 = 'd1',
22
+ KV = 'kv',
23
+ R2 = 'r2',
24
+ }
25
+
26
+ /**
27
+ * 模板類型列舉
28
+ */
29
+ export enum TemplateType {
30
+ BASIC = 'basic',
31
+ HONO = 'hono',
32
+ ITTY_ROUTER = 'itty-router',
33
+ STATIC = 'static',
34
+ REACT = 'react',
35
+ VUE = 'vue',
36
+ NEXTJS = 'nextjs',
37
+ }
38
+
39
+ /**
40
+ * 專案配置接口
41
+ */
42
+ export interface ProjectConfig {
43
+ /** 專案名稱 */
44
+ projectName: string;
45
+ /** 程式語言 */
46
+ language: Language;
47
+ /** 專案類型 */
48
+ projectType: ProjectType;
49
+ /** 模板類型 */
50
+ template: TemplateType;
51
+ /** 是否初始化 Git 倉庫 */
52
+ initGit: boolean;
53
+ /** 是否安裝依賴 */
54
+ installDeps: boolean;
55
+ /** 目標目錄路徑 */
56
+ targetDir: string;
57
+ /** Node.js 版本 */
58
+ nodeVersion: string;
59
+ /** TypeScript 版本(僅適用於 TypeScript) */
60
+ tsVersion: string;
61
+ }
62
+
63
+ /**
64
+ * 用戶輸入接口
65
+ */
66
+ export interface UserInput {
67
+ projectName?: string;
68
+ language?: Language;
69
+ projectType?: ProjectType;
70
+ template?: TemplateType;
71
+ initGit?: boolean;
72
+ installDeps?: boolean;
73
+ }
74
+
75
+ /**
76
+ * 命令選項接口
77
+ */
78
+ export interface CommandOptions {
79
+ template?: string;
80
+ git?: boolean;
81
+ install?: boolean;
82
+ }
83
+
84
+ /**
85
+ * 模板信息接口
86
+ */
87
+ export interface TemplateInfo {
88
+ /** 模板 ID */
89
+ id: string;
90
+ /** 模板名稱 */
91
+ name: string;
92
+ /** 模板描述 */
93
+ description: string;
94
+ /** 適用專案類型 */
95
+ projectType: ProjectType;
96
+ /** 模板語言 */
97
+ language: Language;
98
+ /** 模板路徑 */
99
+ path: string;
100
+ }
101
+
102
+ /**
103
+ * 檔案系統操作結果
104
+ */
105
+ export interface FileSystemResult {
106
+ /** 是否成功 */
107
+ success: boolean;
108
+ /** 錯誤訊息(如有) */
109
+ error?: string;
110
+ /** 創建的檔案列表 */
111
+ files?: string[];
112
+ /** 創建的目錄列表 */
113
+ directories?: string[];
114
+ }
115
+
116
+ /**
117
+ * 衝突處理選項
118
+ */
119
+ export interface ConflictResolution {
120
+ /** 覆蓋所有 */
121
+ overwriteAll?: boolean;
122
+ /** 跳過所有 */
123
+ skipAll?: boolean;
124
+ /** 當前操作 */
125
+ action: 'overwrite' | 'skip' | 'abort';
126
+ }
127
+
128
+ /**
129
+ * 日誌級別
130
+ */
131
+ export enum LogLevel {
132
+ DEBUG = 'debug',
133
+ INFO = 'info',
134
+ WARN = 'warn',
135
+ ERROR = 'error',
136
+ }
137
+
138
+ /**
139
+ * 日誌選項
140
+ */
141
+ export interface LoggerOptions {
142
+ /** 日誌級別 */
143
+ level?: LogLevel;
144
+ /** 是否顯示時間戳 */
145
+ timestamp?: boolean;
146
+ /** 是否使用彩色輸出 */
147
+ color?: boolean;
148
+ /** 是否靜默模式(不輸出任何日誌) */
149
+ silent?: boolean;
150
+ }
151
+
152
+ /**
153
+ * 模板上下文介面
154
+ * 用於模板渲染的變數對象
155
+ */
156
+ export interface TemplateContext {
157
+ [key: string]: unknown;
158
+ projectName: string;
159
+ projectType: string;
160
+ template: string;
161
+ author?: string;
162
+ email?: string;
163
+ description?: string;
164
+ version?: string;
165
+ license?: string;
166
+ year?: number;
167
+ date?: string;
168
+ timestamp?: string;
169
+ isWorker?: boolean;
170
+ isPages?: boolean;
171
+ isD1?: boolean;
172
+ isKV?: boolean;
173
+ isR2?: boolean;
174
+ isHono?: boolean;
175
+ isReact?: boolean;
176
+ isVue?: boolean;
177
+ isNextjs?: boolean;
178
+ }
179
+
180
+ /**
181
+ * 模板檔案定義
182
+ */
183
+ export interface TemplateFile {
184
+ /** 目標檔案路徑(可包含變數,例如:__projectName__.ts) */
185
+ targetPath: string;
186
+ /** 來源模板檔案路徑(可選,與 content 二選一) */
187
+ sourcePath?: string | undefined;
188
+ /** 內嵌模板內容(可選,與 sourcePath 二選一) */
189
+ content?: string | undefined;
190
+ }
191
+
192
+ /**
193
+ * 模板配置介面
194
+ */
195
+ export interface TemplateConfig {
196
+ /** 模板名稱 */
197
+ name: string;
198
+ /** 模板描述 */
199
+ description: string;
200
+ /** 專案類型 */
201
+ projectType: ProjectType;
202
+ /** 模板類型 */
203
+ templateType: TemplateType;
204
+ /** 模板檔案列表 */
205
+ files: TemplateFile[];
206
+ /** 需要的變數 */
207
+ requiredVars?: string[];
208
+ /** 可選變數 */
209
+ optionalVars?: string[];
210
+ }
211
+
212
+ /**
213
+ * 模板渲染結果
214
+ */
215
+ export interface TemplateRenderResult {
216
+ /** 是否成功 */
217
+ success: boolean;
218
+ /** 生成的檔案列表 */
219
+ files: string[];
220
+ /** 錯誤列表 */
221
+ errors: Array<{ file: string; error: string }>;
222
+ }
223
+
224
+ /**
225
+ * 渲染選項
226
+ */
227
+ export interface RenderOptions {
228
+ /** 是否轉義 HTML 實體 */
229
+ escapeHtml?: boolean;
230
+ }
231
+
232
+ /**
233
+ * Git 操作結果
234
+ */
235
+ export interface GitResult {
236
+ /** 是否成功 */
237
+ success: boolean;
238
+ /** 結果訊息 */
239
+ message: string;
240
+ /** 輸出內容(可選) */
241
+ output?: string | undefined;
242
+ }
243
+
244
+ /**
245
+ * Git Token 資料結構
246
+ */
247
+ export interface GitToken {
248
+ id: string;
249
+ name: string;
250
+ token: string;
251
+ createdAt: string;
252
+ }
253
+
254
+ /**
255
+ * Git Token 配置結構
256
+ */
257
+ export interface GitTokenConfig {
258
+ tokens: GitToken[];
259
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * 日誌輸出工具模組
3
+ * 提供統一的日誌輸出接口,支援分級、彩色輸出
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { LogLevel, LoggerOptions } from '../types';
8
+
9
+ /**
10
+ * 日誌類
11
+ * 負責終端輸出的格式化與美化
12
+ */
13
+ class LoggerClass {
14
+ private level: LogLevel;
15
+ private showTimestamp: boolean;
16
+ private useColor: boolean;
17
+ private silent: boolean;
18
+
19
+ constructor(options: LoggerOptions = {}) {
20
+ this.level = options.level ?? LogLevel.INFO;
21
+ this.showTimestamp = options.timestamp ?? false;
22
+ this.useColor = options.color ?? true;
23
+ this.silent = options.silent ?? false;
24
+ }
25
+
26
+ /**
27
+ * 設定日誌級別
28
+ */
29
+ setLevel(level: LogLevel): void {
30
+ this.level = level;
31
+ }
32
+
33
+ /**
34
+ * 獲取當前日誌級別
35
+ */
36
+ getLevel(): LogLevel {
37
+ return this.level;
38
+ }
39
+
40
+ /**
41
+ * 檢查是否應該輸出指定級別的日誌
42
+ */
43
+ private shouldLog(level: LogLevel): boolean {
44
+ if (this.silent) return false;
45
+ const levels: LogLevel[] = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR];
46
+ const currentIndex = levels.indexOf(level);
47
+ const thresholdIndex = levels.indexOf(this.level);
48
+ return currentIndex >= thresholdIndex;
49
+ }
50
+
51
+ /**
52
+ * 格式化時間戳
53
+ */
54
+ private getTimestamp(): string {
55
+ if (!this.showTimestamp) {
56
+ return '';
57
+ }
58
+ const now = new Date();
59
+ const timestamp = now.toISOString().replace('T', ' ').substring(0, 19);
60
+ return chalk.dim(`[${timestamp}] `);
61
+ }
62
+
63
+ /**
64
+ * 輸出調試訊息
65
+ */
66
+ debug(message: string): void {
67
+ if (this.shouldLog(LogLevel.DEBUG)) {
68
+ const timestamp = this.getTimestamp();
69
+ console.log(`${timestamp}${chalk.gray('DEBUG')} ${message}`);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * 輸出普通訊息
75
+ */
76
+ info(message: string): void {
77
+ if (this.shouldLog(LogLevel.INFO)) {
78
+ const timestamp = this.getTimestamp();
79
+ console.log(`${timestamp}${chalk.blue('INFO')} ${message}`);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * 輸出警告訊息
85
+ */
86
+ warn(message: string): void {
87
+ if (this.shouldLog(LogLevel.WARN)) {
88
+ const timestamp = this.getTimestamp();
89
+ console.log(`${timestamp}${chalk.yellow('WARN')} ${message}`);
90
+ }
91
+ }
92
+
93
+ /**
94
+ * 輸出錯誤訊息
95
+ */
96
+ error(message: string): void {
97
+ if (this.shouldLog(LogLevel.ERROR)) {
98
+ const timestamp = this.getTimestamp();
99
+ console.log(`${timestamp}${chalk.red('ERROR')} ${message}`);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * 輸出成功訊息
105
+ */
106
+ success(message: string): void {
107
+ if (this.shouldLog(LogLevel.INFO)) {
108
+ const timestamp = this.getTimestamp();
109
+ console.log(`${timestamp}${chalk.green('SUCCESS')} ${message}`);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * 輸出帶圖標的訊息
115
+ */
116
+ icon(icon: string, message: string): void {
117
+ if (this.shouldLog(LogLevel.INFO)) {
118
+ const timestamp = this.getTimestamp();
119
+ const coloredIcon = this.useColor ? icon : `[${icon}]`;
120
+ console.log(`${timestamp}${coloredIcon} ${message}`);
121
+ }
122
+ }
123
+
124
+ /**
125
+ * 輸出空行
126
+ */
127
+ empty(): void {
128
+ console.log('');
129
+ }
130
+
131
+ /**
132
+ * 輸出分隔線
133
+ */
134
+ divider(char: string = '─', length: number = 40): void {
135
+ if (this.useColor) {
136
+ console.log(chalk.dim(char.repeat(length)));
137
+ } else {
138
+ console.log(char.repeat(length));
139
+ }
140
+ }
141
+ }
142
+
143
+ // 匯出單例
144
+ export const logger = new LoggerClass();
145
+
146
+ // 預設匯出
147
+ export default logger;
148
+
149
+ // 型別匯出
150
+ export { LoggerClass };
@@ -0,0 +1,63 @@
1
+ # {{projectName}}
2
+
3
+ {{description}}
4
+
5
+ 這是一個基於 Cloudflare Pages 的靜態網站專案,使用 create-cf-project 腳手架工具建立。
6
+
7
+ ## 快速開始
8
+
9
+ ### 安裝依賴
10
+
11
+ \`\`\`bash
12
+ npm install
13
+ \`\`\`
14
+
15
+ ### 開發模式
16
+
17
+ \`\`\`bash
18
+ npm run dev
19
+ \`\`\`
20
+
21
+ 這會啟動本地開發伺服器,你可以在 http://localhost:8788 預覽網站。
22
+
23
+ ### 部署
24
+
25
+ \`\`\`bash
26
+ npm run deploy
27
+ \`\`\`
28
+
29
+ ## 專案結構
30
+
31
+ \`\`\`
32
+ {{projectName}}/
33
+ ├── public/ # 靜態資源目錄
34
+ │ ├── index.html # 首頁
35
+ │ ├── css/ # 樣式表
36
+ │ │ └── style.css
37
+ │ └── js/ # JavaScript
38
+ │ └── main.js
39
+ ├── package.json # 專案配置
40
+ ├── tsconfig.json # TypeScript 配置
41
+ ├── wrangler.toml # Cloudflare 配置
42
+ └── README.md # 本文件
43
+ \`\`\`
44
+
45
+ ## 技術細節
46
+
47
+ - **平台**: Cloudflare Pages
48
+ - **類型**: 靜態網站
49
+ - **語言**: HTML5, CSS3, JavaScript (ES2022)
50
+
51
+ ## 自定義
52
+
53
+ 你可以隨意修改 `public/` 目錄下的檔案來自定義你的網站:
54
+
55
+ - 編輯 `index.html` 修改內容
56
+ - 編輯 `css/style.css` 修改樣式
57
+ - 編輯 `js/main.js` 添加交互功能
58
+
59
+ ## 授權
60
+
61
+ {{#license}}{{license}}{{/license}}{{^license}}MIT{{/license}}
62
+
63
+ 建立於 {{date}} | {{year}}
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "wrangler pages dev public",
8
+ "deploy": "wrangler pages deploy public",
9
+ "build": "echo '靜態網站無需建置'",
10
+ "preview": "wrangler pages dev public --port 8788"
11
+ },
12
+ "keywords": [
13
+ "cloudflare",
14
+ "pages",
15
+ "static",
16
+ "edge"
17
+ ],
18
+ "author": "{{#author}}{{author}}{{/author}}{{^author}}Anonymous{{/author}}",
19
+ "license": "{{#license}}{{license}}{{/license}}{{^license}}MIT{{/license}}",
20
+ "devDependencies": {
21
+ "wrangler": "^3.39.0"
22
+ }
23
+ }
@@ -0,0 +1,199 @@
1
+ /**
2
+ * 主樣式表
3
+ * {{projectName}}
4
+ */
5
+
6
+ /* CSS 變數 */
7
+ :root {
8
+ --primary-color: #667eea;
9
+ --secondary-color: #764ba2;
10
+ --text-color: #333;
11
+ --text-light: #666;
12
+ --bg-color: #f8f9fa;
13
+ --card-bg: #fff;
14
+ --border-radius: 12px;
15
+ --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
16
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
17
+ }
18
+
19
+ /* 重置 */
20
+ * {
21
+ margin: 0;
22
+ padding: 0;
23
+ box-sizing: border-box;
24
+ }
25
+
26
+ body {
27
+ font-family:
28
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
29
+ line-height: 1.6;
30
+ color: var(--text-color);
31
+ background: var(--bg-color);
32
+ }
33
+
34
+ .container {
35
+ max-width: 1200px;
36
+ margin: 0 auto;
37
+ padding: 0 1.5rem;
38
+ }
39
+
40
+ /* Hero 區塊 */
41
+ .hero {
42
+ background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
43
+ color: white;
44
+ padding: 6rem 0;
45
+ text-align: center;
46
+ }
47
+
48
+ .hero h1 {
49
+ font-size: 3.5rem;
50
+ font-weight: 700;
51
+ margin-bottom: 1rem;
52
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
53
+ }
54
+
55
+ .hero .description {
56
+ font-size: 1.25rem;
57
+ opacity: 0.9;
58
+ max-width: 600px;
59
+ margin: 0 auto 2rem;
60
+ line-height: 1.7;
61
+ }
62
+
63
+ .badges {
64
+ display: flex;
65
+ gap: 1rem;
66
+ justify-content: center;
67
+ flex-wrap: wrap;
68
+ }
69
+
70
+ .badge {
71
+ background: rgba(255, 255, 255, 0.2);
72
+ backdrop-filter: blur(10px);
73
+ padding: 0.5rem 1rem;
74
+ border-radius: 20px;
75
+ font-size: 0.875rem;
76
+ font-weight: 500;
77
+ }
78
+
79
+ /* 功能區塊 */
80
+ .features {
81
+ padding: 4rem 0;
82
+ }
83
+
84
+ .features h2 {
85
+ text-align: center;
86
+ font-size: 2rem;
87
+ margin-bottom: 3rem;
88
+ color: var(--text-color);
89
+ }
90
+
91
+ .feature-grid {
92
+ display: grid;
93
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
94
+ gap: 2rem;
95
+ }
96
+
97
+ .feature-card {
98
+ background: var(--card-bg);
99
+ padding: 2rem;
100
+ border-radius: var(--border-radius);
101
+ box-shadow: var(--shadow);
102
+ transition:
103
+ transform 0.3s,
104
+ box-shadow 0.3s;
105
+ }
106
+
107
+ .feature-card:hover {
108
+ transform: translateY(-5px);
109
+ box-shadow: var(--shadow-lg);
110
+ }
111
+
112
+ .feature-icon {
113
+ font-size: 2.5rem;
114
+ margin-bottom: 1rem;
115
+ }
116
+
117
+ .feature-card h3 {
118
+ font-size: 1.25rem;
119
+ margin-bottom: 0.5rem;
120
+ color: var(--text-color);
121
+ }
122
+
123
+ .feature-card p {
124
+ color: var(--text-light);
125
+ line-height: 1.6;
126
+ }
127
+
128
+ /* CTA 區塊 */
129
+ .cta {
130
+ padding: 4rem 0;
131
+ text-align: center;
132
+ }
133
+
134
+ .cta h2 {
135
+ font-size: 2rem;
136
+ margin-bottom: 1rem;
137
+ }
138
+
139
+ .cta p {
140
+ color: var(--text-light);
141
+ margin-bottom: 2rem;
142
+ }
143
+
144
+ .code-block {
145
+ background: #1e1e1e;
146
+ border-radius: var(--border-radius);
147
+ padding: 1.5rem;
148
+ max-width: 500px;
149
+ margin: 0 auto;
150
+ text-align: left;
151
+ overflow-x: auto;
152
+ }
153
+
154
+ .code-block code {
155
+ font-family: 'Fira Code', 'Consolas', monospace;
156
+ font-size: 0.9rem;
157
+ color: #d4d4d4;
158
+ line-height: 1.5;
159
+ }
160
+
161
+ .code-block .comment {
162
+ color: #6a9955;
163
+ }
164
+
165
+ /* Footer */
166
+ footer {
167
+ background: var(--text-color);
168
+ color: white;
169
+ padding: 2rem 0;
170
+ text-align: center;
171
+ }
172
+
173
+ footer p {
174
+ opacity: 0.8;
175
+ margin: 0.5rem 0;
176
+ }
177
+
178
+ /* 響應式 */
179
+ @media (max-width: 768px) {
180
+ .hero {
181
+ padding: 4rem 0;
182
+ }
183
+
184
+ .hero h1 {
185
+ font-size: 2.5rem;
186
+ }
187
+
188
+ .hero .description {
189
+ font-size: 1rem;
190
+ }
191
+
192
+ .feature-grid {
193
+ grid-template-columns: 1fr;
194
+ }
195
+
196
+ .feature-card {
197
+ padding: 1.5rem;
198
+ }
199
+ }