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
package/mcp-server.ts
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { readFileSync, existsSync, readdirSync, statSync } from "fs";
|
|
5
|
-
import { join, dirname } from "path";
|
|
6
|
-
import { fileURLToPath } from "url";
|
|
7
|
-
|
|
8
|
-
const getBaseDir = () => {
|
|
9
|
-
if (import.meta.dir) {
|
|
10
|
-
return import.meta.dir;
|
|
11
|
-
}
|
|
12
|
-
const currentFile = import.meta.url
|
|
13
|
-
? fileURLToPath(import.meta.url)
|
|
14
|
-
: __filename;
|
|
15
|
-
return dirname(currentFile);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const BASE_DIR = getBaseDir();
|
|
19
|
-
const DOCS_DIR = join(BASE_DIR, "docs");
|
|
20
|
-
const EXAMPLES_DIR = join(BASE_DIR, "examples");
|
|
21
|
-
|
|
22
|
-
const getVersion = (): string => {
|
|
23
|
-
const pkgPath = join(BASE_DIR, "package.json");
|
|
24
|
-
if (existsSync(pkgPath)) {
|
|
25
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
26
|
-
return pkg.version || "0.0.0";
|
|
27
|
-
}
|
|
28
|
-
return "0.0.0";
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const DOCS = [
|
|
32
|
-
{
|
|
33
|
-
uri: "tkeron://overview",
|
|
34
|
-
name: "Tkeron Overview",
|
|
35
|
-
description: "What tkeron is, what it does, and what it's not",
|
|
36
|
-
file: "overview.md",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
uri: "tkeron://getting-started",
|
|
40
|
-
name: "Getting Started",
|
|
41
|
-
description: "Installation, first project, and basic workflow",
|
|
42
|
-
file: "getting-started.md",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
uri: "tkeron://components-html",
|
|
46
|
-
name: "HTML Components",
|
|
47
|
-
description: "Create reusable HTML components with .com.html files",
|
|
48
|
-
file: "components-html.md",
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
uri: "tkeron://components-typescript",
|
|
52
|
-
name: "TypeScript Components",
|
|
53
|
-
description: "Build dynamic components with .com.ts files",
|
|
54
|
-
file: "components-typescript.md",
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
uri: "tkeron://components-markdown",
|
|
58
|
-
name: "Markdown Components",
|
|
59
|
-
description: "Create components with Markdown using .com.md files",
|
|
60
|
-
file: "components-markdown.md",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
uri: "tkeron://pre-rendering",
|
|
64
|
-
name: "Pre-rendering",
|
|
65
|
-
description: "Transform HTML at build time with .pre.ts files",
|
|
66
|
-
file: "pre-rendering.md",
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
uri: "tkeron://cli-reference",
|
|
70
|
-
name: "CLI Reference",
|
|
71
|
-
description: "Complete command-line interface documentation",
|
|
72
|
-
file: "cli-reference.md",
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
uri: "tkeron://best-practices",
|
|
76
|
-
name: "Best Practices",
|
|
77
|
-
description: "Patterns, anti-patterns, and limitations",
|
|
78
|
-
file: "best-practices.md",
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
uri: "tkeron://common-issues",
|
|
82
|
-
name: "Common Issues and Solutions",
|
|
83
|
-
description:
|
|
84
|
-
"Troubleshooting guide: script references, component naming, dependencies, and common mistakes",
|
|
85
|
-
file: "common-issues.md",
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
uri: "tkeron://testing",
|
|
89
|
-
name: "Testing Tkeron Projects",
|
|
90
|
-
description:
|
|
91
|
-
"How to test tkeron projects using getBuildResult(), DOM assertions, and bounded content verification",
|
|
92
|
-
file: "testing.md",
|
|
93
|
-
},
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
const EXAMPLE_DESCRIPTIONS: { [key: string]: string } = {
|
|
97
|
-
init_sample:
|
|
98
|
-
"Complete starter template with all features (used by 'tk init')",
|
|
99
|
-
basic_build: "Simple HTML + TypeScript bundling",
|
|
100
|
-
with_assets: "HTML in multiple directories with asset references",
|
|
101
|
-
with_pre: "Pre-rendering HTML at build time with .pre.ts files",
|
|
102
|
-
with_com_html_priority:
|
|
103
|
-
"Static HTML components (.com.html) with local override priority",
|
|
104
|
-
with_com_ts: "TypeScript components (.com.ts) generating HTML at build time",
|
|
105
|
-
with_com_ts_priority:
|
|
106
|
-
"TypeScript components (.com.ts) with local override priority",
|
|
107
|
-
with_com_mixed_priority:
|
|
108
|
-
"Mixed .com.html and .com.ts showing processing order",
|
|
109
|
-
with_com_html_in_ts:
|
|
110
|
-
"HTML template (.com.html) injected into .com.ts as com.innerHTML before execution",
|
|
111
|
-
with_component_iteration:
|
|
112
|
-
"Component iteration: .com.ts with logic, .com.html for templates",
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const readDirRecursive = (
|
|
116
|
-
dir: string,
|
|
117
|
-
baseDir: string = dir,
|
|
118
|
-
): { [key: string]: string } => {
|
|
119
|
-
const files: { [key: string]: string } = {};
|
|
120
|
-
const items = readdirSync(dir);
|
|
121
|
-
|
|
122
|
-
for (const item of items) {
|
|
123
|
-
const fullPath = join(dir, item);
|
|
124
|
-
const relativePath = fullPath.substring(baseDir.length + 1);
|
|
125
|
-
|
|
126
|
-
if (statSync(fullPath).isDirectory()) {
|
|
127
|
-
Object.assign(files, readDirRecursive(fullPath, baseDir));
|
|
128
|
-
} else {
|
|
129
|
-
files[relativePath] = readFileSync(fullPath, "utf-8");
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return files;
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const server = new McpServer({
|
|
137
|
-
name: "tkeron-mcp",
|
|
138
|
-
version: getVersion(),
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
for (const doc of DOCS) {
|
|
142
|
-
server.registerResource(
|
|
143
|
-
doc.name,
|
|
144
|
-
doc.uri,
|
|
145
|
-
{ description: doc.description, mimeType: "text/markdown" },
|
|
146
|
-
() => {
|
|
147
|
-
const filePath = join(DOCS_DIR, doc.file);
|
|
148
|
-
|
|
149
|
-
if (!existsSync(filePath)) {
|
|
150
|
-
throw new Error(`Documentation file not found: ${doc.file}`);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const content = readFileSync(filePath, "utf-8");
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
contents: [
|
|
157
|
-
{
|
|
158
|
-
uri: doc.uri,
|
|
159
|
-
mimeType: "text/markdown",
|
|
160
|
-
text: content,
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
};
|
|
164
|
-
},
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
server.registerTool(
|
|
169
|
-
"list_examples",
|
|
170
|
-
{
|
|
171
|
-
description:
|
|
172
|
-
"List all available Tkeron example projects with their descriptions",
|
|
173
|
-
annotations: { readOnlyHint: true },
|
|
174
|
-
},
|
|
175
|
-
() => {
|
|
176
|
-
const examples = readdirSync(EXAMPLES_DIR).filter((name) => {
|
|
177
|
-
const examplePath = join(EXAMPLES_DIR, name);
|
|
178
|
-
return (
|
|
179
|
-
statSync(examplePath).isDirectory() &&
|
|
180
|
-
existsSync(join(examplePath, "websrc"))
|
|
181
|
-
);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const exampleList = examples.map((name) => ({
|
|
185
|
-
name,
|
|
186
|
-
description: EXAMPLE_DESCRIPTIONS[name] || "No description available",
|
|
187
|
-
path: `examples/${name}`,
|
|
188
|
-
}));
|
|
189
|
-
|
|
190
|
-
return {
|
|
191
|
-
content: [
|
|
192
|
-
{
|
|
193
|
-
type: "text" as const,
|
|
194
|
-
text: JSON.stringify(exampleList, null, 2),
|
|
195
|
-
},
|
|
196
|
-
],
|
|
197
|
-
};
|
|
198
|
-
},
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
server.registerTool(
|
|
202
|
-
"get_example",
|
|
203
|
-
{
|
|
204
|
-
description:
|
|
205
|
-
"Get the source code and structure of a specific Tkeron example project",
|
|
206
|
-
inputSchema: {
|
|
207
|
-
example: {
|
|
208
|
-
type: "string",
|
|
209
|
-
description:
|
|
210
|
-
"Example name (e.g., 'basic_build', 'with_component_iteration')",
|
|
211
|
-
},
|
|
212
|
-
} as any,
|
|
213
|
-
annotations: { readOnlyHint: true },
|
|
214
|
-
},
|
|
215
|
-
({ example: exampleName }: { example: string }) => {
|
|
216
|
-
const examplePath = join(EXAMPLES_DIR, exampleName);
|
|
217
|
-
|
|
218
|
-
if (!existsSync(examplePath)) {
|
|
219
|
-
return {
|
|
220
|
-
content: [
|
|
221
|
-
{
|
|
222
|
-
type: "text" as const,
|
|
223
|
-
text: `Example not found: ${exampleName}. Use the list_examples tool to see available examples.`,
|
|
224
|
-
},
|
|
225
|
-
],
|
|
226
|
-
isError: true,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const srcPath = join(examplePath, "websrc");
|
|
231
|
-
|
|
232
|
-
if (!existsSync(srcPath)) {
|
|
233
|
-
return {
|
|
234
|
-
content: [
|
|
235
|
-
{
|
|
236
|
-
type: "text" as const,
|
|
237
|
-
text: `Example ${exampleName} does not have a websrc directory`,
|
|
238
|
-
},
|
|
239
|
-
],
|
|
240
|
-
isError: true,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const sourceFiles = readDirRecursive(srcPath);
|
|
245
|
-
|
|
246
|
-
const result = {
|
|
247
|
-
example: exampleName,
|
|
248
|
-
path: `examples/${exampleName}`,
|
|
249
|
-
files: sourceFiles,
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
return {
|
|
253
|
-
content: [
|
|
254
|
-
{
|
|
255
|
-
type: "text" as const,
|
|
256
|
-
text: JSON.stringify(result, null, 2),
|
|
257
|
-
},
|
|
258
|
-
],
|
|
259
|
-
};
|
|
260
|
-
},
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
const main = async () => {
|
|
264
|
-
const transport = new StdioServerTransport();
|
|
265
|
-
await server.connect(transport);
|
|
266
|
-
console.error(`[tkeron-mcp] Server v${getVersion()} started`);
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
main().catch((error) => {
|
|
270
|
-
console.error(`[tkeron-mcp] Fatal error:`, error);
|
|
271
|
-
process.exit(1);
|
|
272
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { readdir, rm } from "fs/promises";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import type { Logger } from "@tkeron/tools";
|
|
4
|
-
|
|
5
|
-
export const TEMP_DIR_PREFIX = ".tktmp_build-";
|
|
6
|
-
|
|
7
|
-
export const cleanupOrphanedTempDirs = async (
|
|
8
|
-
parentDir: string,
|
|
9
|
-
log: Logger,
|
|
10
|
-
): Promise<void> => {
|
|
11
|
-
try {
|
|
12
|
-
const entries = await readdir(parentDir, { withFileTypes: true });
|
|
13
|
-
const orphanedDirs = entries.filter(
|
|
14
|
-
(entry) => entry.isDirectory() && entry.name.startsWith(TEMP_DIR_PREFIX),
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
await Promise.all(
|
|
18
|
-
orphanedDirs.map(async (dir) => {
|
|
19
|
-
const dirPath = join(parentDir, dir.name);
|
|
20
|
-
try {
|
|
21
|
-
await rm(dirPath, { recursive: true, force: true });
|
|
22
|
-
log.log(`🧹 Cleaned up orphaned temp directory: ${dir.name}`);
|
|
23
|
-
} catch (error) {
|
|
24
|
-
log.warn(
|
|
25
|
-
`Warning: Failed to cleanup orphaned temp directory ${dirPath}`,
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
}),
|
|
29
|
-
);
|
|
30
|
-
} catch (error) {}
|
|
31
|
-
};
|
package/src/promptUser.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export const promptUser = async (question: string): Promise<boolean> => {
|
|
2
|
-
const readline = await import("readline");
|
|
3
|
-
const rl = readline.createInterface({
|
|
4
|
-
input: process.stdin,
|
|
5
|
-
output: process.stdout,
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
return new Promise((resolve) => {
|
|
9
|
-
rl.question(question, (answer) => {
|
|
10
|
-
rl.close();
|
|
11
|
-
const response = answer.trim().toLowerCase();
|
|
12
|
-
resolve(response === "y" || response === "yes");
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
};
|
|
File without changes
|