tkeron 5.3.0 → 6.0.1

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 (59) hide show
  1. package/README.md +17 -16
  2. package/bun.lock +13 -196
  3. package/changelog.md +55 -0
  4. package/examples/init_sample/websrc/about.html +19 -0
  5. package/examples/init_sample/websrc/components/content/about-intro.com.md +7 -0
  6. package/examples/init_sample/websrc/components/layout/hero-section.com.html +88 -0
  7. package/examples/init_sample/websrc/components/layout/site-footer.com.html +20 -0
  8. package/examples/init_sample/websrc/components/layout/site-header.com.html +44 -0
  9. package/examples/init_sample/websrc/components/ui/counter-button.com.html +48 -0
  10. package/examples/init_sample/websrc/components/ui/crypto-prices-card.com.html +52 -0
  11. package/examples/init_sample/websrc/components/ui/html-components-card.com.html +10 -0
  12. package/examples/init_sample/websrc/{info-card.com.html → components/ui/info-card.com.html} +10 -6
  13. package/examples/init_sample/websrc/components/ui/markdown-card.com.html +21 -0
  14. package/examples/init_sample/websrc/{pre-render-card.com.html → components/ui/pre-render-card.com.html} +6 -3
  15. package/examples/init_sample/websrc/components/ui/quote-card.com.html +32 -0
  16. package/examples/init_sample/websrc/components/ui/styles-injector.com.ts +5 -0
  17. package/examples/init_sample/websrc/components/ui/ts-components-card.com.html +11 -0
  18. package/examples/init_sample/websrc/components/ui/user-badge.com.ts +30 -0
  19. package/examples/init_sample/websrc/docs.html +33 -0
  20. package/examples/init_sample/websrc/index.html +10 -209
  21. package/examples/init_sample/websrc/index.post.ts +70 -0
  22. package/examples/init_sample/websrc/index.pre.ts +10 -61
  23. package/examples/init_sample/websrc/index.ts +9 -7
  24. package/examples/init_sample/websrc/styles/global-styles.com.ts +5 -0
  25. package/examples/init_sample/websrc/styles/main.css +112 -0
  26. package/examples/init_sample/websrc/utils/api-service.ts +93 -0
  27. package/examples/with_global_styles/websrc/bad.html +23 -0
  28. package/examples/with_global_styles/websrc/global-styles.com.ts +5 -0
  29. package/examples/with_global_styles/websrc/good.html +22 -0
  30. package/examples/with_global_styles/websrc/index.html +25 -0
  31. package/examples/with_global_styles/websrc/styles.css +24 -0
  32. package/examples/with_style_dedup/websrc/tag-chip.com.html +15 -0
  33. package/examples/with_style_dedup/websrc/tag-chip.com.ts +2 -18
  34. package/index.ts +15 -0
  35. package/package.json +9 -13
  36. package/skills/tkeron/SKILL.md +287 -0
  37. package/skills/tkeron-components/SKILL.md +785 -0
  38. package/skills/tkeron-organization/SKILL.md +231 -0
  39. package/skills/tkeron-patterns/SKILL.md +587 -0
  40. package/skills/tkeron-testing/SKILL.md +194 -0
  41. package/skills/tkeron-troubleshooting/SKILL.md +263 -0
  42. package/src/build.ts +4 -6
  43. package/src/develop.ts +1 -2
  44. package/src/init.ts +1 -2
  45. package/src/skills.ts +139 -0
  46. package/src/skillsWrapper.ts +79 -0
  47. package/docs/mcp-server.md +0 -240
  48. package/examples/init_sample/websrc/api-service.ts +0 -98
  49. package/examples/init_sample/websrc/counter-card.com.html +0 -9
  50. package/examples/init_sample/websrc/favicon.ico +0 -0
  51. package/examples/init_sample/websrc/hero-section.com.html +0 -23
  52. package/examples/init_sample/websrc/html-components-card.com.html +0 -6
  53. package/examples/init_sample/websrc/ts-components-card.com.html +0 -6
  54. package/examples/init_sample/websrc/user-badge.com.ts +0 -17
  55. package/mcp-server.ts +0 -272
  56. package/src/cleanupOrphanedTempDirs.ts +0 -31
  57. package/src/promptUser.ts +0 -15
  58. package/src/setupSigintHandler.ts +0 -6
  59. /package/examples/init_sample/websrc/{profile.png → assets/profile.png} +0 -0
@@ -0,0 +1,112 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
9
+ line-height: 1.6;
10
+ color: #1a1a1a;
11
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
12
+ min-height: 100vh;
13
+ padding: 1rem;
14
+ display: flex;
15
+ flex-direction: column;
16
+ align-items: center;
17
+ }
18
+
19
+ .container {
20
+ max-width: 1200px;
21
+ margin: 0 auto;
22
+ width: 100%;
23
+ }
24
+
25
+ .grid {
26
+ display: grid;
27
+ grid-template-columns: repeat(3, 1fr);
28
+ grid-template-rows: repeat(2, 1fr);
29
+ gap: 1rem;
30
+ }
31
+
32
+ @media (max-width: 900px) {
33
+ .grid {
34
+ grid-template-columns: 1fr;
35
+ grid-template-rows: auto;
36
+ }
37
+ }
38
+
39
+ .page {
40
+ background: white;
41
+ border-radius: 12px;
42
+ padding: 2rem;
43
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
44
+ margin-top: 1rem;
45
+ }
46
+
47
+ .page h1 {
48
+ color: #4c51bf;
49
+ margin-bottom: 0.5rem;
50
+ font-size: 1.75rem;
51
+ }
52
+
53
+ .page p {
54
+ margin-bottom: 0.5rem;
55
+ }
56
+
57
+ h1 {
58
+ font-size: 2rem;
59
+ margin-bottom: 0.25rem;
60
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
61
+ }
62
+
63
+ h2 {
64
+ color: #667eea;
65
+ margin-bottom: 0.75rem;
66
+ font-size: 1.2rem;
67
+ display: flex;
68
+ align-items: center;
69
+ gap: 0.5rem;
70
+ }
71
+
72
+ p {
73
+ margin-bottom: 0.5rem;
74
+ }
75
+
76
+ section {
77
+ background: white;
78
+ padding: 1.25rem;
79
+ border-radius: 12px;
80
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
81
+ transition:
82
+ transform 0.2s,
83
+ box-shadow 0.2s;
84
+ }
85
+
86
+ section:hover {
87
+ transform: translateY(-4px);
88
+ box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
89
+ }
90
+
91
+ section p {
92
+ font-size: 0.9rem;
93
+ }
94
+
95
+ code {
96
+ background: #f0f0f0;
97
+ padding: 0.2rem 0.4rem;
98
+ border-radius: 4px;
99
+ font-family: "Courier New", monospace;
100
+ font-size: 0.9em;
101
+ }
102
+
103
+ a {
104
+ transition:
105
+ transform 0.2s,
106
+ box-shadow 0.2s;
107
+ }
108
+
109
+ a:hover {
110
+ transform: translateY(-2px);
111
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
112
+ }
@@ -0,0 +1,93 @@
1
+ export interface Quote {
2
+ id: number;
3
+ quote: string;
4
+ author: string;
5
+ }
6
+
7
+ export const escapeHtml = (str: string): string =>
8
+ str
9
+ .replace(/&/g, "&")
10
+ .replace(/</g, "&lt;")
11
+ .replace(/>/g, "&gt;")
12
+ .replace(/"/g, "&quot;")
13
+ .replace(/'/g, "&#39;");
14
+
15
+ export const getRandomQuote = async (): Promise<Quote> => {
16
+ const controller = new AbortController();
17
+ const timeout = setTimeout(() => controller.abort(), 5000);
18
+ try {
19
+ const response = await fetch("https://dummyjson.com/quotes/random", {
20
+ signal: controller.signal,
21
+ });
22
+ if (!response.ok) {
23
+ throw new Error(`HTTP error! status: ${response.status}`);
24
+ }
25
+ const data = await response.json();
26
+ return data as Quote;
27
+ } catch {
28
+ return {
29
+ id: 0,
30
+ quote: "The only way to do great work is to love what you do.",
31
+ author: "Steve Jobs",
32
+ };
33
+ } finally {
34
+ clearTimeout(timeout);
35
+ }
36
+ };
37
+
38
+ export const getBuildMetadata = () => ({
39
+ timestamp: new Date().toLocaleString(),
40
+ runtime: `Bun ${Bun.version}`,
41
+ tkeron: process.env.TKERON_VERSION || "unknown",
42
+ platform: process.platform,
43
+ });
44
+
45
+ export interface CryptoPrice {
46
+ id: string;
47
+ symbol: string;
48
+ name: string;
49
+ current_price: number;
50
+ price_change_percentage_24h: number;
51
+ }
52
+
53
+ export const getCryptoPrices = async (): Promise<CryptoPrice[]> => {
54
+ const controller = new AbortController();
55
+ const timeout = setTimeout(() => controller.abort(), 5000);
56
+ try {
57
+ const response = await fetch(
58
+ "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=bitcoin,ethereum,solana&order=market_cap_desc&sparkline=false",
59
+ { signal: controller.signal },
60
+ );
61
+ if (!response.ok) {
62
+ throw new Error(`HTTP error! status: ${response.status}`);
63
+ }
64
+ const data = await response.json();
65
+ return data as CryptoPrice[];
66
+ } catch {
67
+ return [
68
+ {
69
+ id: "bitcoin",
70
+ symbol: "btc",
71
+ name: "Bitcoin",
72
+ current_price: 95000,
73
+ price_change_percentage_24h: 2.5,
74
+ },
75
+ {
76
+ id: "ethereum",
77
+ symbol: "eth",
78
+ name: "Ethereum",
79
+ current_price: 3500,
80
+ price_change_percentage_24h: -1.2,
81
+ },
82
+ {
83
+ id: "solana",
84
+ symbol: "sol",
85
+ name: "Solana",
86
+ current_price: 180,
87
+ price_change_percentage_24h: 5.8,
88
+ },
89
+ ];
90
+ } finally {
91
+ clearTimeout(timeout);
92
+ }
93
+ };
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Bad — link rel stylesheet</title>
7
+ <link rel="stylesheet" href="./styles.css" />
8
+ </head>
9
+ <body>
10
+ <h1>Bad: <code>&lt;link rel="stylesheet"&gt;</code></h1>
11
+ <p>
12
+ The CSS is referenced via a <code>&lt;link&gt;</code> tag. tkeron bundles
13
+ it into a separate <code>.css</code> file — an extra HTTP request on every
14
+ page load.
15
+ </p>
16
+ <p>
17
+ Check <code>web/bad.html</code>: you will find a
18
+ <code>&lt;link rel="stylesheet" href="./bad.css"&gt;</code> and a
19
+ companion <code>bad.css</code> file next to it.
20
+ </p>
21
+ <a href="index.html">Back to index</a>
22
+ </body>
23
+ </html>
@@ -0,0 +1,5 @@
1
+ import { join } from "path";
2
+
3
+ const css = await Bun.file(join(__dirname, "styles.css")).text();
4
+
5
+ com.innerHTML = `<style>${css}</style>`;
@@ -0,0 +1,22 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Good — global-styles component</title>
7
+ <global-styles></global-styles>
8
+ </head>
9
+ <body>
10
+ <h1>Good: <code>&lt;global-styles&gt;</code></h1>
11
+ <p>
12
+ The <code>&lt;global-styles&gt;</code> component reads
13
+ <code>styles.css</code> at build time and injects it as a
14
+ <code>&lt;style&gt;</code> block directly in <code>&lt;head&gt;</code>.
15
+ </p>
16
+ <p>
17
+ Check <code>web/good.html</code>: no external CSS file, all styles are
18
+ inline. Zero extra HTTP requests.
19
+ </p>
20
+ <a href="index.html">Back to index</a>
21
+ </body>
22
+ </html>
@@ -0,0 +1,25 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Global Styles — Overview</title>
7
+ </head>
8
+ <body>
9
+ <h1>Global Styles Import</h1>
10
+ <p>
11
+ Two approaches for adding shared CSS to a tkeron page. Compare the
12
+ compiled output in <code>web/</code>.
13
+ </p>
14
+ <ul>
15
+ <li>
16
+ <a href="bad.html">Bad — <code>&lt;link rel="stylesheet"&gt;</code></a>:
17
+ CSS ends up in a separate file (extra HTTP request).
18
+ </li>
19
+ <li>
20
+ <a href="good.html">Good — <code>&lt;global-styles&gt;</code></a>:
21
+ CSS is inlined at build time (no extra request).
22
+ </li>
23
+ </ul>
24
+ </body>
25
+ </html>
@@ -0,0 +1,24 @@
1
+ body {
2
+ font-family: system-ui, sans-serif;
3
+ max-width: 640px;
4
+ margin: 2rem auto;
5
+ padding: 0 1rem;
6
+ color: #1a1a1a;
7
+ line-height: 1.6;
8
+ }
9
+
10
+ h1 {
11
+ font-size: 1.5rem;
12
+ margin-bottom: 0.5rem;
13
+ }
14
+
15
+ p {
16
+ margin: 0.75rem 0;
17
+ }
18
+
19
+ code {
20
+ background: #f0f0f0;
21
+ padding: 0.1em 0.35em;
22
+ border-radius: 3px;
23
+ font-size: 0.875em;
24
+ }
@@ -0,0 +1,15 @@
1
+ <style>
2
+ .tag-chip {
3
+ display: inline-block;
4
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
5
+ color: white;
6
+ padding: 0.2rem 0.65rem;
7
+ border-radius: 999px;
8
+ font-size: 0.75rem;
9
+ font-weight: 600;
10
+ margin: 0.2rem;
11
+ font-family: monospace;
12
+ letter-spacing: 0.02em;
13
+ }
14
+ </style>
15
+ <span class="tag-chip">label...</span>
@@ -1,19 +1,3 @@
1
1
  const label = com.getAttribute("label") || "tag";
2
-
3
- com.innerHTML = `
4
- <style>
5
- .tag-chip {
6
- display: inline-block;
7
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
8
- color: white;
9
- padding: 0.2rem 0.65rem;
10
- border-radius: 999px;
11
- font-size: 0.75rem;
12
- font-weight: 600;
13
- margin: 0.2rem;
14
- font-family: monospace;
15
- letter-spacing: 0.02em;
16
- }
17
- </style>
18
- <span class="tag-chip">${label}</span>
19
- `;
2
+ const span = com.querySelector(".tag-chip");
3
+ if (span) span.textContent = label;
package/index.ts CHANGED
@@ -3,6 +3,7 @@ import { getCommands } from "@tkeron/commands";
3
3
  import { buildWrapper } from "./src/buildWrapper";
4
4
  import { develop } from "./src/develop";
5
5
  import { initWrapper } from "./src/initWrapper";
6
+ import { skillsWrapper } from "./src/skillsWrapper";
6
7
  import { showBanner } from "./src/banner";
7
8
  import packageJson from "./package.json";
8
9
 
@@ -36,5 +37,19 @@ getCommands("tkeron", packageJson.version)
36
37
  .addOption("force")
37
38
  .setCallback(initWrapper)
38
39
 
40
+ .commands()
41
+
42
+ .addCommand("skills")
43
+ .addDescription("Install AI agent skills into the current project")
44
+ .addPositionedArgument("target")
45
+ .addOption("force")
46
+ .addOption({
47
+ name: "dryRun",
48
+ aliases: ["dry-run"],
49
+ type: "boolean",
50
+ description: "Preview what would be installed without making changes",
51
+ })
52
+ .setCallback(skillsWrapper)
53
+
39
54
  .commands()
40
55
  .start();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tkeron",
3
- "version": "5.3.0",
3
+ "version": "6.0.1",
4
4
  "description": "CLI build tool for vanilla web development with TypeScript.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -12,8 +12,7 @@
12
12
  },
13
13
  "bin": {
14
14
  "tkeron": "./index.ts",
15
- "tk": "./index.ts",
16
- "tkeron-mcp": "./mcp-server.ts"
15
+ "tk": "./index.ts"
17
16
  },
18
17
  "scripts": {
19
18
  "tk": "bun index.ts ",
@@ -23,15 +22,14 @@
23
22
  "author": "tkeron",
24
23
  "license": "MIT",
25
24
  "dependencies": {
26
- "@modelcontextprotocol/sdk": "^1.29.0",
27
- "@tkeron/commands": "0.4.7",
28
- "@tkeron/html-parser": "1.5.6",
29
- "@tkeron/tools": "^0.4.1"
25
+ "@tkeron/commands": "0.4.8",
26
+ "@tkeron/html-parser": "1.5.7",
27
+ "@tkeron/tools": "^0.5.0"
30
28
  },
31
29
  "devDependencies": {
32
- "@types/bun": "^1.3.11",
33
- "prettier": "^3.8.1",
34
- "typescript": "^6.0.2"
30
+ "@types/bun": "^1.3.14",
31
+ "prettier": "^3.8.3",
32
+ "typescript": "^6.0.3"
35
33
  },
36
34
  "keywords": [
37
35
  "cli",
@@ -41,9 +39,7 @@
41
39
  "pre-rendering",
42
40
  "static-site-generator",
43
41
  "backend-driven",
44
- "mcp",
45
- "model-context-protocol",
46
- "ai-integration"
42
+ "ai-agents"
47
43
  ],
48
44
  "publishConfig": {
49
45
  "access": "public"