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.
- package/README.md +17 -16
- package/bun.lock +13 -196
- package/changelog.md +55 -0
- package/examples/init_sample/websrc/about.html +19 -0
- package/examples/init_sample/websrc/components/content/about-intro.com.md +7 -0
- package/examples/init_sample/websrc/components/layout/hero-section.com.html +88 -0
- package/examples/init_sample/websrc/components/layout/site-footer.com.html +20 -0
- package/examples/init_sample/websrc/components/layout/site-header.com.html +44 -0
- package/examples/init_sample/websrc/components/ui/counter-button.com.html +48 -0
- package/examples/init_sample/websrc/components/ui/crypto-prices-card.com.html +52 -0
- package/examples/init_sample/websrc/components/ui/html-components-card.com.html +10 -0
- package/examples/init_sample/websrc/{info-card.com.html → components/ui/info-card.com.html} +10 -6
- package/examples/init_sample/websrc/components/ui/markdown-card.com.html +21 -0
- package/examples/init_sample/websrc/{pre-render-card.com.html → components/ui/pre-render-card.com.html} +6 -3
- package/examples/init_sample/websrc/components/ui/quote-card.com.html +32 -0
- package/examples/init_sample/websrc/components/ui/styles-injector.com.ts +5 -0
- package/examples/init_sample/websrc/components/ui/ts-components-card.com.html +11 -0
- package/examples/init_sample/websrc/components/ui/user-badge.com.ts +30 -0
- package/examples/init_sample/websrc/docs.html +33 -0
- package/examples/init_sample/websrc/index.html +10 -209
- package/examples/init_sample/websrc/index.post.ts +70 -0
- package/examples/init_sample/websrc/index.pre.ts +10 -61
- package/examples/init_sample/websrc/index.ts +9 -7
- package/examples/init_sample/websrc/styles/global-styles.com.ts +5 -0
- package/examples/init_sample/websrc/styles/main.css +112 -0
- package/examples/init_sample/websrc/utils/api-service.ts +93 -0
- package/examples/with_global_styles/websrc/bad.html +23 -0
- package/examples/with_global_styles/websrc/global-styles.com.ts +5 -0
- package/examples/with_global_styles/websrc/good.html +22 -0
- package/examples/with_global_styles/websrc/index.html +25 -0
- package/examples/with_global_styles/websrc/styles.css +24 -0
- package/examples/with_style_dedup/websrc/tag-chip.com.html +15 -0
- package/examples/with_style_dedup/websrc/tag-chip.com.ts +2 -18
- package/index.ts +15 -0
- package/package.json +9 -13
- package/skills/tkeron/SKILL.md +287 -0
- package/skills/tkeron-components/SKILL.md +785 -0
- package/skills/tkeron-organization/SKILL.md +231 -0
- package/skills/tkeron-patterns/SKILL.md +587 -0
- package/skills/tkeron-testing/SKILL.md +194 -0
- package/skills/tkeron-troubleshooting/SKILL.md +263 -0
- package/src/build.ts +4 -6
- package/src/develop.ts +1 -2
- package/src/init.ts +1 -2
- package/src/skills.ts +139 -0
- package/src/skillsWrapper.ts +79 -0
- package/docs/mcp-server.md +0 -240
- package/examples/init_sample/websrc/api-service.ts +0 -98
- package/examples/init_sample/websrc/counter-card.com.html +0 -9
- package/examples/init_sample/websrc/favicon.ico +0 -0
- package/examples/init_sample/websrc/hero-section.com.html +0 -23
- package/examples/init_sample/websrc/html-components-card.com.html +0 -6
- package/examples/init_sample/websrc/ts-components-card.com.html +0 -6
- package/examples/init_sample/websrc/user-badge.com.ts +0 -17
- package/mcp-server.ts +0 -272
- package/src/cleanupOrphanedTempDirs.ts +0 -31
- package/src/promptUser.ts +0 -15
- package/src/setupSigintHandler.ts +0 -6
- /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, "<")
|
|
11
|
+
.replace(/>/g, ">")
|
|
12
|
+
.replace(/"/g, """)
|
|
13
|
+
.replace(/'/g, "'");
|
|
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><link rel="stylesheet"></code></h1>
|
|
11
|
+
<p>
|
|
12
|
+
The CSS is referenced via a <code><link></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><link rel="stylesheet" href="./bad.css"></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,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><global-styles></code></h1>
|
|
11
|
+
<p>
|
|
12
|
+
The <code><global-styles></code> component reads
|
|
13
|
+
<code>styles.css</code> at build time and injects it as a
|
|
14
|
+
<code><style></code> block directly in <code><head></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><link rel="stylesheet"></code></a>:
|
|
17
|
+
CSS ends up in a separate file (extra HTTP request).
|
|
18
|
+
</li>
|
|
19
|
+
<li>
|
|
20
|
+
<a href="good.html">Good — <code><global-styles></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
|
-
|
|
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": "
|
|
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
|
-
"@
|
|
27
|
-
"@tkeron/
|
|
28
|
-
"@tkeron/
|
|
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.
|
|
33
|
-
"prettier": "^3.8.
|
|
34
|
-
"typescript": "^6.0.
|
|
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
|
-
"
|
|
45
|
-
"model-context-protocol",
|
|
46
|
-
"ai-integration"
|
|
42
|
+
"ai-agents"
|
|
47
43
|
],
|
|
48
44
|
"publishConfig": {
|
|
49
45
|
"access": "public"
|