@byh3071/vhk 0.7.1 โ 0.8.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.
- package/README.md +35 -2
- package/dist/{chunk-3HHU7V77.js โ chunk-NQ4V3VN4.js} +11 -0
- package/dist/index.js +400 -12
- package/dist/mcp/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: vhk-readme
|
|
3
3
|
date: 2026-05-24
|
|
4
|
-
tags: [vhk, cli, readme, v0.
|
|
4
|
+
tags: [vhk, cli, readme, v0.8.0]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# ๐ง VHK โ Vibe Harness Kit
|
|
8
8
|
|
|
9
|
-
> AI ์ฝ๋ฉ ์์ด์ ํธ๋ฅผ ๋ถ๋ฆฌ๋ ์ฌ๋์ ์ํ **ํ๊ตญ์ด ํ์ฌ์ดํด CLI** (v0.
|
|
9
|
+
> AI ์ฝ๋ฉ ์์ด์ ํธ๋ฅผ ๋ถ๋ฆฌ๋ ์ฌ๋์ ์ํ **ํ๊ตญ์ด ํ์ฌ์ดํด CLI** (v0.8.0)
|
|
10
10
|
>
|
|
11
11
|
> ๐ฝ๏ธ **VHK๋ VHK๋ก ๋ถํธ์คํธ๋ฉ๋จ** โ ์ด ๋ ํฌ์ `docs/`, `CLAUDE.md`, `.cursorrules`๋ `vhk init`์ด ๋ง๋ค์์ต๋๋ค.
|
|
12
12
|
|
|
@@ -95,6 +95,10 @@ vhk ๊ธฐํ ๋๋ฌ๊ณ ๋ฐ๋ก ์์
|
|
|
95
95
|
| `vhk env` | `ํ๊ฒฝ๋ณ์` | `.env` โ `.env.example` ๋๊ธฐํ + `.gitignore`์ `.env` ์๋ ์ถ๊ฐ |
|
|
96
96
|
| `vhk env-check` | `ํ๊ฒฝ๋ณ์์ ๊ฒ` | `.env.example` ๊ธฐ์ค ๋๋ฝ ํ๊ฒฝ๋ณ์ ๊ฒ์ฌ |
|
|
97
97
|
| `vhk publish` | `์ถ์` | npm ๋ฐฐํฌ ์๋ํ (๋ฒ์ ๋ฒํ โ ๋น๋ โ ํ
์คํธ โ publish โ git tag) |
|
|
98
|
+
| `vhk design` | `๋์์ธ` | ๋์์ธ ํ ํฐ ์์ฑ (Tailwind config ๋๋ CSS ๋ณ์) |
|
|
99
|
+
| `vhk design-palette` | `ํ๋ ํธ` | ์ปฌ๋ฌ ํ๋ ํธ ํ๋ฆฌ์
์ ํ + ์ ์ฉ |
|
|
100
|
+
| `vhk theme` | `ํ
๋ง` | ๋คํฌ/๋ผ์ดํธ ๋ชจ๋ CSS + ํ ๊ธ ์ ํธ๋ฆฌํฐ ์์ฑ |
|
|
101
|
+
| `vhk ref` | `๋ ํผ๋ฐ์ค` | ๋ ํผ๋ฐ์ค URL ๊ด๋ฆฌ (`add` / `list` / `open`) |
|
|
98
102
|
|
|
99
103
|
### init ์ต์
|
|
100
104
|
|
|
@@ -129,6 +133,31 @@ MCP ์๋ฒ๋ฅผ ์๋์ผ๋ก ๋์ฐ๋ ค๋ฉด:
|
|
|
129
133
|
vhk mcp # stdio ์๋ฒ ์์ (Cursor๊ฐ ์๋์ผ๋ก ํธ์ถ)
|
|
130
134
|
```
|
|
131
135
|
|
|
136
|
+
## v0.8.0 ํ์ด๋ผ์ดํธ
|
|
137
|
+
|
|
138
|
+
| ๊ธฐ๋ฅ | ์ค๋ช
|
|
|
139
|
+
|------|------|
|
|
140
|
+
| **design** | ํ๋ ํธ ํ๋ฆฌ์
4์ข
(Minimal/Vibrant/Corporate/Pastel) ์ ํ โ `src/styles/tokens.css` ๋๋ `src/styles/vhk-colors.ts` (Tailwind config๊ฐ ์์ผ๋ฉด TS) ์์ฑ |
|
|
141
|
+
| **theme** | `src/styles/theme.css` (๋คํฌ/๋ผ์ดํธ + `prefers-color-scheme` + `data-theme` ์
๋ ํฐ) + `src/lib/theme-toggle.ts` (`getTheme`/`setTheme`/`toggleTheme`/`initTheme`) ์์ฑ |
|
|
142
|
+
| **ref** | `.vhk/refs.json` ๊ธฐ๋ฐ ๋ ํผ๋ฐ์ค URL ๊ด๋ฆฌ. `ref add <url> --memo "..."` / `ref list` / `ref open <๋ฒํธ>` (Windows/macOS/Linux ๋ธ๋ผ์ฐ์ ์๋ ์คํ) |
|
|
143
|
+
| **์์ฐ์ด ํ์ฅ** | `"๋์์ธ ํ ํฐ ๋ง๋ค์ด์ค"` / `"ํ๋ ํธ ๊ณจ๋ผ์ค"` / `"๋คํฌ ๋ชจ๋ ์ ์ฉ"` / `"๋ ํผ๋ฐ์ค ๋ณด์ฌ์ค"` ์ธ์. `ref add`/`open`์ ์ธ์ ์ถ์ถ ์ธํ๋ผ๊ฐ ์์ด ์๋์ ์ผ๋ก NL ๋ฐฐ์ โ commander ์๋ธ์ปค๋งจ๋๋ง ์ฌ์ฉ |
|
|
144
|
+
|
|
145
|
+
```powershell
|
|
146
|
+
vhk design # ํ๋ ํธ ์ ํ โ src/styles/tokens.css ๋๋ vhk-colors.ts
|
|
147
|
+
vhk theme # src/styles/theme.css + src/lib/theme-toggle.ts
|
|
148
|
+
vhk ref add https://example.com --memo "์ฐธ๊ณ ์ฌ์ดํธ"
|
|
149
|
+
vhk ref list # ์ ์ฅ๋ ๋ ํผ๋ฐ์ค ๋ชฉ๋ก
|
|
150
|
+
vhk ref open 1 # 1๋ฒ ๋ ํผ๋ฐ์ค๋ฅผ ๋ธ๋ผ์ฐ์ ๋ก ์ด๊ธฐ
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## v0.7.0 ํ์ด๋ผ์ดํธ
|
|
154
|
+
|
|
155
|
+
| ๊ธฐ๋ฅ | ์ค๋ช
|
|
|
156
|
+
|------|------|
|
|
157
|
+
| **deploy** | Vercel / Netlify / Cloudflare Workers ์๋ ๊ฐ์ง + ํ๋ก๋์
๋ฐฐํฌ |
|
|
158
|
+
| **env / env-check** | `.env` โ `.env.example` ๋๊ธฐํ + ๋๋ฝ ํ๊ฒฝ๋ณ์ ๊ฒ์ฌ. MCP ๋๊ตฌ๋ก๋ ๋
ธ์ถ (v0.7.1) |
|
|
159
|
+
| **publish** | semver ๋ฒํ + ๋น๋ + ํ
์คํธ + `npm publish` + git tag ์๋ํ |
|
|
160
|
+
|
|
132
161
|
## v0.6.0 ํ์ด๋ผ์ดํธ
|
|
133
162
|
|
|
134
163
|
| ๊ธฐ๋ฅ | ์ค๋ช
|
|
|
@@ -191,6 +220,10 @@ vhk mcp # stdio ์๋ฒ ์์ (Cursor๊ฐ ์๋์ผ๋ก ํธ์ถ)
|
|
|
191
220
|
| ๋ณด์ ์ค์บ ๋๋ ค | `vhk ๋ณด์` |
|
|
192
221
|
| ๋ฐฐํฌํ๊ณ ์ถ์ด | `vhk ๋ฐฐํฌ` |
|
|
193
222
|
| ๋ญ๊ฐ ์ ๋ผ | `vhk doctor` |
|
|
223
|
+
| ๋์์ธ ํ ํฐ ๋ง๋ค์ด์ค | `vhk design` |
|
|
224
|
+
| ํ๋ ํธ ๊ณจ๋ผ์ค | `vhk design-palette` |
|
|
225
|
+
| ๋คํฌ ๋ชจ๋ ์ ์ฉ | `vhk theme` |
|
|
226
|
+
| ๋ ํผ๋ฐ์ค ๋ณด์ฌ์ค | `vhk ref` (list) |
|
|
194
227
|
|
|
195
228
|
## ํน์ง
|
|
196
229
|
|
|
@@ -272,6 +272,17 @@ var ko = {
|
|
|
272
272
|
changelogNoUnreleased: "CHANGELOG.md\uC5D0 [Unreleased] \uC139\uC158\uC774 \uC5C6\uC5B4 \uC790\uB3D9 \uAC31\uC2E0\uC744 \uC2A4\uD0B5\uD588\uC5B4\uC694",
|
|
273
273
|
changelogMissing: "CHANGELOG.md\uAC00 \uC5C6\uC5B4\uC694. \uB9CC\uB4E4\uBA74 ship\uC774 \uC790\uB3D9\uC73C\uB85C [Unreleased] \u2192 \uBC84\uC804 \uC139\uC158\uC73C\uB85C \uC62E\uACA8\uC90D\uB2C8\uB2E4."
|
|
274
274
|
},
|
|
275
|
+
design: {
|
|
276
|
+
title: "\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131",
|
|
277
|
+
selectPalette: "\uCEEC\uB7EC \uD314\uB808\uD2B8\uB97C \uC120\uD0DD\uD558\uC138\uC694:"
|
|
278
|
+
},
|
|
279
|
+
theme: {
|
|
280
|
+
title: "\uD14C\uB9C8 \uC124\uC815 (\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC)"
|
|
281
|
+
},
|
|
282
|
+
ref: {
|
|
283
|
+
addTitle: "\uB808\uD37C\uB7F0\uC2A4 \uCD94\uAC00",
|
|
284
|
+
listTitle: "\uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D"
|
|
285
|
+
},
|
|
275
286
|
mcp: {
|
|
276
287
|
initTitle: "Cursor MCP \uC5F0\uB3D9 \uC124\uC815",
|
|
277
288
|
serverStarted: "VHK MCP \uC11C\uBC84 \uC2DC\uC791\uB428"
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
safeExecFileStream,
|
|
11
11
|
startMcpServer,
|
|
12
12
|
t
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-NQ4V3VN4.js";
|
|
14
14
|
|
|
15
15
|
// node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
|
|
16
16
|
var require_ignore = __commonJS({
|
|
@@ -472,7 +472,7 @@ var require_ignore = __commonJS({
|
|
|
472
472
|
|
|
473
473
|
// src/index.ts
|
|
474
474
|
import { Command, Help } from "commander";
|
|
475
|
-
import
|
|
475
|
+
import inquirer12 from "inquirer";
|
|
476
476
|
|
|
477
477
|
// src/lib/nlp-router.ts
|
|
478
478
|
function normalize(input) {
|
|
@@ -516,6 +516,30 @@ var RULES = [
|
|
|
516
516
|
confidence: "high",
|
|
517
517
|
test: (t2) => /mcp.*(์ค์ |์ฐ๋|์ด๊ธฐ|init)|์ปค์.*(์ฐ๋|์ค์ |mcp)|cursor.*mcp/.test(t2)
|
|
518
518
|
},
|
|
519
|
+
{
|
|
520
|
+
command: "design-palette",
|
|
521
|
+
explanation: "\uCEEC\uB7EC \uD314\uB808\uD2B8 \uC120\uD0DD (vhk design-palette)",
|
|
522
|
+
confidence: "high",
|
|
523
|
+
test: (t2) => /ํ๋ ํธ|palette|์ปฌ๋ฌ\s*(๊ณ |์ ํ|๋ฐ๊ฟ|๋ณ๊ฒฝ)|์์\s*(๊ณ |์ ํ|๋ณ๊ฒฝ)|์๊น\s*์ ํ/.test(t2)
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
command: "design",
|
|
527
|
+
explanation: "\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131 (vhk design)",
|
|
528
|
+
confidence: "high",
|
|
529
|
+
test: (t2) => /๋์์ธ\s*(ํ ํฐ|์์คํ
|๋ง๋ค|์์ฑ|์
์
|์ค์ )|design\s*(token|system|setup)|ํ ํฐ\s*๋ง๋ค|css\s*๋ณ์.*๋ง๋ค|tailwind\s*(์ปฌ๋ฌ|์ค์ )/.test(t2)
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
command: "theme",
|
|
533
|
+
explanation: "\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uD14C\uB9C8 \uC801\uC6A9 (vhk theme)",
|
|
534
|
+
confidence: "high",
|
|
535
|
+
test: (t2) => /ํ
๋ง(?!\s*(ํ์ผ|์ด๋ฆ))|theme|๋คํฌ\s*๋ชจ๋|๋ผ์ดํธ\s*๋ชจ๋|dark\s*mode|light\s*mode|์์\s*๋ชจ๋|๋ชจ๋\s*์ ํ/.test(t2)
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
command: "ref",
|
|
539
|
+
explanation: "\uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D (vhk ref list)",
|
|
540
|
+
confidence: "high",
|
|
541
|
+
test: (t2) => /^๋ ํผ๋ฐ์ค$|^ref$|๋ ํผ๋ฐ์ค.*(๋ณด|๋ชฉ๋ก|ํ์ธ|์|๋ญ)|์ฐธ๊ณ \s*(์ฌ์ดํธ|๋ชฉ๋ก|๋งํฌ)|reference.*list/.test(t2) && !/(add|์ถ๊ฐ|open|์ด|https?:\/\/)/.test(t2)
|
|
542
|
+
},
|
|
519
543
|
{
|
|
520
544
|
command: "secure",
|
|
521
545
|
explanation: "\uBCF4\uC548 \uC2A4\uCE94 (vhk \uBCF4\uC548)",
|
|
@@ -674,6 +698,14 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
|
|
|
674
698
|
"publish",
|
|
675
699
|
"\uCD9C\uC2DC",
|
|
676
700
|
"\uCD9C\uD558",
|
|
701
|
+
"design",
|
|
702
|
+
"\uB514\uC790\uC778",
|
|
703
|
+
"design-palette",
|
|
704
|
+
"\uD314\uB808\uD2B8",
|
|
705
|
+
"theme",
|
|
706
|
+
"\uD14C\uB9C8",
|
|
707
|
+
"ref",
|
|
708
|
+
"\uB808\uD37C\uB7F0\uC2A4",
|
|
677
709
|
"help"
|
|
678
710
|
]);
|
|
679
711
|
function isOptionToken(token) {
|
|
@@ -697,8 +729,8 @@ function detectNaturalLanguageInput(argv) {
|
|
|
697
729
|
}
|
|
698
730
|
|
|
699
731
|
// src/lib/nlp-run.ts
|
|
700
|
-
import
|
|
701
|
-
import
|
|
732
|
+
import chalk21 from "chalk";
|
|
733
|
+
import inquirer11 from "inquirer";
|
|
702
734
|
|
|
703
735
|
// src/commands/gate.ts
|
|
704
736
|
import inquirer from "inquirer";
|
|
@@ -3571,6 +3603,329 @@ async function publish() {
|
|
|
3571
3603
|
});
|
|
3572
3604
|
}
|
|
3573
3605
|
|
|
3606
|
+
// src/commands/design.ts
|
|
3607
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
3608
|
+
import chalk18 from "chalk";
|
|
3609
|
+
import inquirer9 from "inquirer";
|
|
3610
|
+
var PALETTES = [
|
|
3611
|
+
{
|
|
3612
|
+
name: "Minimal",
|
|
3613
|
+
colors: {
|
|
3614
|
+
primary: "#1a1a1a",
|
|
3615
|
+
secondary: "#6b7280",
|
|
3616
|
+
accent: "#3b82f6",
|
|
3617
|
+
background: "#ffffff",
|
|
3618
|
+
surface: "#f9fafb",
|
|
3619
|
+
text: "#111827",
|
|
3620
|
+
muted: "#9ca3af"
|
|
3621
|
+
}
|
|
3622
|
+
},
|
|
3623
|
+
{
|
|
3624
|
+
name: "Vibrant",
|
|
3625
|
+
colors: {
|
|
3626
|
+
primary: "#7c3aed",
|
|
3627
|
+
secondary: "#ec4899",
|
|
3628
|
+
accent: "#f59e0b",
|
|
3629
|
+
background: "#ffffff",
|
|
3630
|
+
surface: "#faf5ff",
|
|
3631
|
+
text: "#1e1b4b",
|
|
3632
|
+
muted: "#8b5cf6"
|
|
3633
|
+
}
|
|
3634
|
+
},
|
|
3635
|
+
{
|
|
3636
|
+
name: "Corporate",
|
|
3637
|
+
colors: {
|
|
3638
|
+
primary: "#1e40af",
|
|
3639
|
+
secondary: "#0f766e",
|
|
3640
|
+
accent: "#ca8a04",
|
|
3641
|
+
background: "#ffffff",
|
|
3642
|
+
surface: "#f0f9ff",
|
|
3643
|
+
text: "#0f172a",
|
|
3644
|
+
muted: "#64748b"
|
|
3645
|
+
}
|
|
3646
|
+
},
|
|
3647
|
+
{
|
|
3648
|
+
name: "Pastel",
|
|
3649
|
+
colors: {
|
|
3650
|
+
primary: "#a78bfa",
|
|
3651
|
+
secondary: "#f9a8d4",
|
|
3652
|
+
accent: "#fcd34d",
|
|
3653
|
+
background: "#fffbeb",
|
|
3654
|
+
surface: "#fef3c7",
|
|
3655
|
+
text: "#44403c",
|
|
3656
|
+
muted: "#a8a29e"
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3659
|
+
];
|
|
3660
|
+
function hasTailwind() {
|
|
3661
|
+
return existsSync4("tailwind.config.js") || existsSync4("tailwind.config.ts") || existsSync4("tailwind.config.mjs") || existsSync4("tailwind.config.cjs");
|
|
3662
|
+
}
|
|
3663
|
+
function generateCSSTokens(palette) {
|
|
3664
|
+
const lines = Object.entries(palette.colors).map(([key, value]) => ` --color-${key}: ${value};`).join("\n");
|
|
3665
|
+
return `:root {
|
|
3666
|
+
${lines}
|
|
3667
|
+
}
|
|
3668
|
+
`;
|
|
3669
|
+
}
|
|
3670
|
+
function generateTailwindExtend(palette) {
|
|
3671
|
+
const entries = Object.entries(palette.colors).map(([key, value]) => ` '${key}': '${value}',`).join("\n");
|
|
3672
|
+
return `// vhk design \u2014 Tailwind config \uD655\uC7A5\uC6A9 \uCEEC\uB7EC \uD1A0\uD070
|
|
3673
|
+
// tailwind.config\uC758 theme.extend.colors\uC5D0 spread \uD558\uC138\uC694.
|
|
3674
|
+
const vhkColors = {
|
|
3675
|
+
${entries}
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
export default vhkColors
|
|
3679
|
+
`;
|
|
3680
|
+
}
|
|
3681
|
+
async function design() {
|
|
3682
|
+
console.log(chalk18.bold("\n\u{1F3A8} " + t("design.title")));
|
|
3683
|
+
console.log(chalk18.gray("\u2500".repeat(40)));
|
|
3684
|
+
const { paletteIndex } = await inquirer9.prompt([
|
|
3685
|
+
{
|
|
3686
|
+
type: "list",
|
|
3687
|
+
name: "paletteIndex",
|
|
3688
|
+
message: t("design.selectPalette"),
|
|
3689
|
+
choices: PALETTES.map((p, i) => ({
|
|
3690
|
+
name: `${p.name} \u2014 primary ${p.colors.primary}`,
|
|
3691
|
+
value: i
|
|
3692
|
+
}))
|
|
3693
|
+
}
|
|
3694
|
+
]);
|
|
3695
|
+
const palette = PALETTES[paletteIndex];
|
|
3696
|
+
console.log(chalk18.cyan(`
|
|
3697
|
+
\u{1F3A8} \uC120\uD0DD\uB41C \uD314\uB808\uD2B8: ${palette.name}`));
|
|
3698
|
+
const targetPath = hasTailwind() ? "src/styles/vhk-colors.ts" : "src/styles/tokens.css";
|
|
3699
|
+
const content = hasTailwind() ? generateTailwindExtend(palette) : generateCSSTokens(palette);
|
|
3700
|
+
if (existsSync4(targetPath)) {
|
|
3701
|
+
const { overwrite } = await inquirer9.prompt([{
|
|
3702
|
+
type: "confirm",
|
|
3703
|
+
name: "overwrite",
|
|
3704
|
+
message: `${targetPath} \uC774\uBBF8 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?`,
|
|
3705
|
+
default: false
|
|
3706
|
+
}]);
|
|
3707
|
+
if (!overwrite) {
|
|
3708
|
+
console.log(chalk18.yellow("\n\u23ED\uFE0F \uC0DD\uC131 \uCDE8\uC18C \u2014 \uAE30\uC874 \uD30C\uC77C \uC720\uC9C0."));
|
|
3709
|
+
return;
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
mkdirSync2("src/styles", { recursive: true });
|
|
3713
|
+
writeFileSync3(targetPath, content, "utf-8");
|
|
3714
|
+
if (hasTailwind()) {
|
|
3715
|
+
console.log(chalk18.green("\n\u2705 src/styles/vhk-colors.ts \uC0DD\uC131"));
|
|
3716
|
+
console.log(chalk18.gray(" tailwind.config\uC758 extend.colors\uC5D0 import \uD574\uC11C \uC0AC\uC6A9\uD558\uC138\uC694."));
|
|
3717
|
+
} else {
|
|
3718
|
+
console.log(chalk18.green("\n\u2705 src/styles/tokens.css \uC0DD\uC131"));
|
|
3719
|
+
console.log(chalk18.gray(" HTML\uC5D0 <link>\uB85C \uCD94\uAC00\uD558\uAC70\uB098 CSS\uC5D0\uC11C @import \uD558\uC138\uC694."));
|
|
3720
|
+
}
|
|
3721
|
+
console.log(chalk18.bold("\n\u{1F308} \uCEEC\uB7EC \uBBF8\uB9AC\uBCF4\uAE30:"));
|
|
3722
|
+
for (const [key, value] of Object.entries(palette.colors)) {
|
|
3723
|
+
console.log(` ${key.padEnd(12)} ${value}`);
|
|
3724
|
+
}
|
|
3725
|
+
printNextStep({
|
|
3726
|
+
message: "\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131 \uC644\uB8CC!",
|
|
3727
|
+
command: "vhk theme",
|
|
3728
|
+
cursorHint: "\uD14C\uB9C8 \uC124\uC815\uD574\uC918"
|
|
3729
|
+
});
|
|
3730
|
+
}
|
|
3731
|
+
async function designPalette() {
|
|
3732
|
+
await design();
|
|
3733
|
+
}
|
|
3734
|
+
|
|
3735
|
+
// src/commands/theme.ts
|
|
3736
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3737
|
+
import chalk19 from "chalk";
|
|
3738
|
+
import inquirer10 from "inquirer";
|
|
3739
|
+
function generateDarkCSS() {
|
|
3740
|
+
return `/* vhk theme \u2014 \uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC CSS \uBCC0\uC218 */
|
|
3741
|
+
|
|
3742
|
+
@media (prefers-color-scheme: dark) {
|
|
3743
|
+
:root {
|
|
3744
|
+
--color-background: #0f172a;
|
|
3745
|
+
--color-surface: #1e293b;
|
|
3746
|
+
--color-text: #f1f5f9;
|
|
3747
|
+
--color-muted: #64748b;
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
|
|
3751
|
+
[data-theme="dark"] {
|
|
3752
|
+
--color-background: #0f172a;
|
|
3753
|
+
--color-surface: #1e293b;
|
|
3754
|
+
--color-text: #f1f5f9;
|
|
3755
|
+
--color-muted: #64748b;
|
|
3756
|
+
}
|
|
3757
|
+
|
|
3758
|
+
[data-theme="light"] {
|
|
3759
|
+
--color-background: #ffffff;
|
|
3760
|
+
--color-surface: #f9fafb;
|
|
3761
|
+
--color-text: #111827;
|
|
3762
|
+
--color-muted: #9ca3af;
|
|
3763
|
+
}
|
|
3764
|
+
`;
|
|
3765
|
+
}
|
|
3766
|
+
function generateToggleUtil() {
|
|
3767
|
+
return `// vhk theme \u2014 \uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC \uD1A0\uAE00 \uC720\uD2F8\uB9AC\uD2F0
|
|
3768
|
+
|
|
3769
|
+
export function getTheme(): 'light' | 'dark' {
|
|
3770
|
+
if (typeof window === 'undefined') return 'light'
|
|
3771
|
+
const stored = localStorage.getItem('vhk-theme') as 'light' | 'dark' | null
|
|
3772
|
+
if (stored === 'light' || stored === 'dark') return stored
|
|
3773
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
export function setTheme(theme: 'light' | 'dark'): void {
|
|
3777
|
+
if (typeof document === 'undefined') return
|
|
3778
|
+
document.documentElement.setAttribute('data-theme', theme)
|
|
3779
|
+
localStorage.setItem('vhk-theme', theme)
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
export function toggleTheme(): 'light' | 'dark' {
|
|
3783
|
+
const next = getTheme() === 'light' ? 'dark' : 'light'
|
|
3784
|
+
setTheme(next)
|
|
3785
|
+
return next
|
|
3786
|
+
}
|
|
3787
|
+
|
|
3788
|
+
export function initTheme(): void {
|
|
3789
|
+
setTheme(getTheme())
|
|
3790
|
+
}
|
|
3791
|
+
`;
|
|
3792
|
+
}
|
|
3793
|
+
async function theme() {
|
|
3794
|
+
console.log(chalk19.bold("\n\u{1F319} " + t("theme.title")));
|
|
3795
|
+
console.log(chalk19.gray("\u2500".repeat(40)));
|
|
3796
|
+
const cssPath = "src/styles/theme.css";
|
|
3797
|
+
const togglePath = "src/lib/theme-toggle.ts";
|
|
3798
|
+
const conflicts = [cssPath, togglePath].filter((p) => existsSync5(p));
|
|
3799
|
+
if (conflicts.length > 0) {
|
|
3800
|
+
const { overwrite } = await inquirer10.prompt([{
|
|
3801
|
+
type: "confirm",
|
|
3802
|
+
name: "overwrite",
|
|
3803
|
+
message: `\uB2E4\uC74C \uD30C\uC77C\uC774 \uC774\uBBF8 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?
|
|
3804
|
+
${conflicts.join("\n ")}`,
|
|
3805
|
+
default: false
|
|
3806
|
+
}]);
|
|
3807
|
+
if (!overwrite) {
|
|
3808
|
+
console.log(chalk19.yellow("\n\u23ED\uFE0F \uC0DD\uC131 \uCDE8\uC18C \u2014 \uAE30\uC874 \uD30C\uC77C \uC720\uC9C0."));
|
|
3809
|
+
return;
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
mkdirSync3("src/styles", { recursive: true });
|
|
3813
|
+
mkdirSync3("src/lib", { recursive: true });
|
|
3814
|
+
writeFileSync4(cssPath, generateDarkCSS(), "utf-8");
|
|
3815
|
+
console.log(chalk19.green("\n\u2705 src/styles/theme.css \uC0DD\uC131 (\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC)"));
|
|
3816
|
+
writeFileSync4(togglePath, generateToggleUtil(), "utf-8");
|
|
3817
|
+
console.log(chalk19.green("\u2705 src/lib/theme-toggle.ts \uC0DD\uC131 (\uD1A0\uAE00 \uC720\uD2F8\uB9AC\uD2F0)"));
|
|
3818
|
+
console.log(chalk19.bold("\n\u{1F4D6} \uC0AC\uC6A9\uBC95:"));
|
|
3819
|
+
console.log(chalk19.gray(" 1. theme.css\uB97C \uAE00\uB85C\uBC8C \uC2A4\uD0C0\uC77C\uC5D0 \uCD94\uAC00"));
|
|
3820
|
+
console.log(chalk19.gray(' 2. import { initTheme, toggleTheme } from "./lib/theme-toggle"'));
|
|
3821
|
+
console.log(chalk19.gray(" 3. \uC571 \uC9C4\uC785\uC810\uC5D0\uC11C initTheme() \uD638\uCD9C"));
|
|
3822
|
+
console.log(chalk19.gray(" 4. \uD1A0\uAE00 \uBC84\uD2BC\uC5D0\uC11C toggleTheme() \uD638\uCD9C"));
|
|
3823
|
+
printNextStep({
|
|
3824
|
+
message: "\uD14C\uB9C8 \uC124\uC815 \uC644\uB8CC!",
|
|
3825
|
+
command: "vhk ref list",
|
|
3826
|
+
cursorHint: "\uB808\uD37C\uB7F0\uC2A4 \uD655\uC778\uD574\uC918"
|
|
3827
|
+
});
|
|
3828
|
+
}
|
|
3829
|
+
|
|
3830
|
+
// src/commands/ref.ts
|
|
3831
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
3832
|
+
import chalk20 from "chalk";
|
|
3833
|
+
var REFS_PATH = ".vhk/refs.json";
|
|
3834
|
+
function loadRefs() {
|
|
3835
|
+
if (!existsSync6(REFS_PATH)) return [];
|
|
3836
|
+
try {
|
|
3837
|
+
const raw = readFileSync3(REFS_PATH, "utf-8");
|
|
3838
|
+
const parsed = JSON.parse(raw);
|
|
3839
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
3840
|
+
} catch {
|
|
3841
|
+
return [];
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
function saveRefs(refs) {
|
|
3845
|
+
mkdirSync4(".vhk", { recursive: true });
|
|
3846
|
+
writeFileSync5(REFS_PATH, JSON.stringify(refs, null, 2) + "\n", "utf-8");
|
|
3847
|
+
}
|
|
3848
|
+
async function refAdd(url, memo = "") {
|
|
3849
|
+
console.log(chalk20.bold("\n\u{1F517} " + t("ref.addTitle")));
|
|
3850
|
+
console.log(chalk20.gray("\u2500".repeat(40)));
|
|
3851
|
+
if (!url) {
|
|
3852
|
+
console.log(chalk20.red("\u274C URL\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694."));
|
|
3853
|
+
console.log(chalk20.gray(' \uC608: vhk ref add https://example.com --memo "\uCC38\uACE0 \uC0AC\uC774\uD2B8"'));
|
|
3854
|
+
return;
|
|
3855
|
+
}
|
|
3856
|
+
const refs = loadRefs();
|
|
3857
|
+
if (refs.some((r) => r.url === url)) {
|
|
3858
|
+
console.log(chalk20.yellow("\u26A0\uFE0F \uC774\uBBF8 \uC800\uC7A5\uB41C URL\uC785\uB2C8\uB2E4."));
|
|
3859
|
+
return;
|
|
3860
|
+
}
|
|
3861
|
+
refs.push({ url, memo, addedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
3862
|
+
saveRefs(refs);
|
|
3863
|
+
console.log(chalk20.green(`
|
|
3864
|
+
\u2705 \uB808\uD37C\uB7F0\uC2A4 \uCD94\uAC00\uB428 (#${refs.length})`));
|
|
3865
|
+
console.log(chalk20.cyan(` ${url}`));
|
|
3866
|
+
if (memo) console.log(chalk20.gray(` \u{1F4DD} ${memo}`));
|
|
3867
|
+
printNextStep({
|
|
3868
|
+
message: "\uB808\uD37C\uB7F0\uC2A4 \uC800\uC7A5 \uC644\uB8CC!",
|
|
3869
|
+
command: "vhk ref list",
|
|
3870
|
+
cursorHint: "\uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D \uBCF4\uC5EC\uC918"
|
|
3871
|
+
});
|
|
3872
|
+
}
|
|
3873
|
+
async function refList() {
|
|
3874
|
+
console.log(chalk20.bold("\n\u{1F4DA} " + t("ref.listTitle")));
|
|
3875
|
+
console.log(chalk20.gray("\u2500".repeat(40)));
|
|
3876
|
+
const refs = loadRefs();
|
|
3877
|
+
if (refs.length === 0) {
|
|
3878
|
+
console.log(chalk20.yellow("\n\u{1F4ED} \uC800\uC7A5\uB41C \uB808\uD37C\uB7F0\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
3879
|
+
console.log(chalk20.gray(' vhk ref add <url> --memo "\uBA54\uBAA8"\uB85C \uCD94\uAC00\uD558\uC138\uC694.'));
|
|
3880
|
+
return;
|
|
3881
|
+
}
|
|
3882
|
+
console.log(chalk20.cyan(`
|
|
3883
|
+
\uCD1D ${refs.length}\uAC1C\uC758 \uB808\uD37C\uB7F0\uC2A4:
|
|
3884
|
+
`));
|
|
3885
|
+
refs.forEach((ref, index) => {
|
|
3886
|
+
const date = new Date(ref.addedAt).toLocaleDateString("ko-KR");
|
|
3887
|
+
console.log(chalk20.white(` [${index + 1}] ${ref.url}`));
|
|
3888
|
+
if (ref.memo) console.log(chalk20.gray(` \u{1F4DD} ${ref.memo}`));
|
|
3889
|
+
console.log(chalk20.gray(` \u{1F4C5} ${date}`));
|
|
3890
|
+
console.log("");
|
|
3891
|
+
});
|
|
3892
|
+
}
|
|
3893
|
+
async function refOpen(indexStr) {
|
|
3894
|
+
const refs = loadRefs();
|
|
3895
|
+
const idx = parseInt(indexStr, 10) - 1;
|
|
3896
|
+
if (Number.isNaN(idx) || idx < 0 || idx >= refs.length) {
|
|
3897
|
+
console.log(chalk20.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uBC88\uD638\uC785\uB2C8\uB2E4. (1~${refs.length || 0})`));
|
|
3898
|
+
return;
|
|
3899
|
+
}
|
|
3900
|
+
const ref = refs[idx];
|
|
3901
|
+
let parsed;
|
|
3902
|
+
try {
|
|
3903
|
+
parsed = new URL(ref.url);
|
|
3904
|
+
} catch {
|
|
3905
|
+
console.log(chalk20.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 URL: ${ref.url}`));
|
|
3906
|
+
return;
|
|
3907
|
+
}
|
|
3908
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
3909
|
+
console.log(chalk20.red(`\u274C http(s) URL\uB9CC \uC5F4 \uC218 \uC788\uC2B5\uB2C8\uB2E4 (${parsed.protocol})`));
|
|
3910
|
+
return;
|
|
3911
|
+
}
|
|
3912
|
+
console.log(chalk20.cyan(`
|
|
3913
|
+
\u{1F310} \uC5F4\uAE30: ${ref.url}`));
|
|
3914
|
+
let result;
|
|
3915
|
+
if (process.platform === "darwin") {
|
|
3916
|
+
result = safeExecFile("open", [ref.url]);
|
|
3917
|
+
} else if (process.platform === "win32") {
|
|
3918
|
+
result = safeExecFile("cmd.exe", ["/c", "start", "", ref.url]);
|
|
3919
|
+
} else {
|
|
3920
|
+
result = safeExecFile("xdg-open", [ref.url]);
|
|
3921
|
+
}
|
|
3922
|
+
if (result.ok) {
|
|
3923
|
+
console.log(chalk20.green("\u2705 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
3924
|
+
} else {
|
|
3925
|
+
console.log(chalk20.yellow("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. URL\uC744 \uC9C1\uC811 \uBC29\uBB38\uD574\uC8FC\uC138\uC694."));
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
|
|
3574
3929
|
// src/lib/nlp-run.ts
|
|
3575
3930
|
async function dispatchNlpRoute(route, input) {
|
|
3576
3931
|
switch (route.command) {
|
|
@@ -3611,28 +3966,36 @@ async function dispatchNlpRoute(route, input) {
|
|
|
3611
3966
|
return envCheck();
|
|
3612
3967
|
case "publish":
|
|
3613
3968
|
return publish();
|
|
3969
|
+
case "design":
|
|
3970
|
+
return design();
|
|
3971
|
+
case "design-palette":
|
|
3972
|
+
return designPalette();
|
|
3973
|
+
case "theme":
|
|
3974
|
+
return theme();
|
|
3975
|
+
case "ref":
|
|
3976
|
+
return refList();
|
|
3614
3977
|
}
|
|
3615
3978
|
}
|
|
3616
3979
|
async function runNaturalLanguageRoute(input) {
|
|
3617
3980
|
const route = routeNaturalLanguage(input);
|
|
3618
3981
|
if (!route) {
|
|
3619
|
-
console.log(
|
|
3982
|
+
console.log(chalk21.yellow(`
|
|
3620
3983
|
\u2753 "${input}" \u2014 ${ko.nlp.notMatched}
|
|
3621
3984
|
`));
|
|
3622
3985
|
return;
|
|
3623
3986
|
}
|
|
3624
3987
|
console.log("");
|
|
3625
|
-
console.log(
|
|
3626
|
-
console.log(
|
|
3988
|
+
console.log(chalk21.cyan(` \u{1F4AC} "${input}"`));
|
|
3989
|
+
console.log(chalk21.cyan(` \u2192 ${route.explanation}`));
|
|
3627
3990
|
if (route.confidence === "low") {
|
|
3628
|
-
const { confirm } = await
|
|
3991
|
+
const { confirm } = await inquirer11.prompt([{
|
|
3629
3992
|
type: "confirm",
|
|
3630
3993
|
name: "confirm",
|
|
3631
3994
|
message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
|
|
3632
3995
|
default: true
|
|
3633
3996
|
}]);
|
|
3634
3997
|
if (!confirm) {
|
|
3635
|
-
console.log(
|
|
3998
|
+
console.log(chalk21.dim(` ${ko.nlp.menuHint}`));
|
|
3636
3999
|
return;
|
|
3637
4000
|
}
|
|
3638
4001
|
}
|
|
@@ -3659,9 +4022,13 @@ var KO_ALIASES = {
|
|
|
3659
4022
|
deploy: "\uBC30\uD3EC",
|
|
3660
4023
|
env: "\uD658\uACBD\uBCC0\uC218",
|
|
3661
4024
|
"env-check": "\uD658\uACBD\uBCC0\uC218\uC810\uAC80",
|
|
3662
|
-
publish: "\uCD9C\uC2DC"
|
|
4025
|
+
publish: "\uCD9C\uC2DC",
|
|
4026
|
+
design: "\uB514\uC790\uC778",
|
|
4027
|
+
"design-palette": "\uD314\uB808\uD2B8",
|
|
4028
|
+
theme: "\uD14C\uB9C8",
|
|
4029
|
+
ref: "\uB808\uD37C\uB7F0\uC2A4"
|
|
3663
4030
|
};
|
|
3664
|
-
program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.
|
|
4031
|
+
program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.8.0");
|
|
3665
4032
|
program.configureHelp({
|
|
3666
4033
|
formatHelp(cmd, helper) {
|
|
3667
4034
|
if (cmd.parent) {
|
|
@@ -3722,6 +4089,27 @@ program.command("env-check").alias("\uD658\uACBD\uBCC0\uC218\uC810\uAC80").descr
|
|
|
3722
4089
|
program.command("publish").alias("\uCD9C\uC2DC").description("npm \uBC30\uD3EC (\uBC84\uC804 \uBC94\uD504 \u2192 \uBE4C\uB4DC \u2192 \uD14C\uC2A4\uD2B8 \u2192 publish)").action(async () => {
|
|
3723
4090
|
await publish();
|
|
3724
4091
|
});
|
|
4092
|
+
program.command("design").alias("\uB514\uC790\uC778").description("\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131 (Tailwind config \uB610\uB294 CSS \uBCC0\uC218)").action(async () => {
|
|
4093
|
+
await design();
|
|
4094
|
+
});
|
|
4095
|
+
program.command("design-palette").alias("\uD314\uB808\uD2B8").description("\uCEEC\uB7EC \uD314\uB808\uD2B8 \uD504\uB9AC\uC14B \uC120\uD0DD + \uC801\uC6A9").action(async () => {
|
|
4096
|
+
await designPalette();
|
|
4097
|
+
});
|
|
4098
|
+
program.command("theme").alias("\uD14C\uB9C8").description("\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC CSS + \uD1A0\uAE00 \uC720\uD2F8\uB9AC\uD2F0 \uC0DD\uC131").action(async () => {
|
|
4099
|
+
await theme();
|
|
4100
|
+
});
|
|
4101
|
+
var refCmd = program.command("ref").alias("\uB808\uD37C\uB7F0\uC2A4").description("\uB808\uD37C\uB7F0\uC2A4 URL \uAD00\uB9AC (add / list / open)").action(async () => {
|
|
4102
|
+
await refList();
|
|
4103
|
+
});
|
|
4104
|
+
refCmd.command("add <url>").option("--memo <memo>", "\uBA54\uBAA8 \uCD94\uAC00").description("\uB808\uD37C\uB7F0\uC2A4 URL \uCD94\uAC00").action(async (url, opts) => {
|
|
4105
|
+
await refAdd(url, opts.memo);
|
|
4106
|
+
});
|
|
4107
|
+
refCmd.command("list").alias("\uBAA9\uB85D").description("\uC800\uC7A5\uB41C \uB808\uD37C\uB7F0\uC2A4 \uBAA9\uB85D").action(async () => {
|
|
4108
|
+
await refList();
|
|
4109
|
+
});
|
|
4110
|
+
refCmd.command("open <index>").alias("\uC5F4\uAE30").description("\uB808\uD37C\uB7F0\uC2A4\uB97C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uAE30").action(async (index) => {
|
|
4111
|
+
await refOpen(index);
|
|
4112
|
+
});
|
|
3725
4113
|
program.on("command:*", async (operands) => {
|
|
3726
4114
|
const unknown = operands[0] ?? "";
|
|
3727
4115
|
const rest = operands.slice(1);
|
|
@@ -3730,7 +4118,7 @@ program.on("command:*", async (operands) => {
|
|
|
3730
4118
|
});
|
|
3731
4119
|
program.action(async () => {
|
|
3732
4120
|
console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
|
|
3733
|
-
const { choice } = await
|
|
4121
|
+
const { choice } = await inquirer12.prompt([{
|
|
3734
4122
|
type: "list",
|
|
3735
4123
|
name: "choice",
|
|
3736
4124
|
message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
|
package/dist/mcp/index.js
CHANGED