tkeron 5.0.2 → 5.1.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/bun.lock +13 -13
- package/changelog.md +12 -0
- package/docs/components-markdown.md +2 -0
- package/docs/components-typescript.md +59 -0
- package/docs/testing.md +1 -1
- package/examples/with_com_html_in_ts/websrc/index.html +19 -0
- package/examples/with_com_html_in_ts/websrc/info-panel.com.html +12 -0
- package/examples/with_com_html_in_ts/websrc/info-panel.com.ts +14 -0
- package/examples/with_com_html_in_ts/websrc/user-card.com.html +12 -0
- package/examples/with_com_html_in_ts/websrc/user-card.com.ts +8 -0
- package/mcp-server.ts +5 -7
- package/package.json +10 -8
- package/src/develop.ts +28 -13
- package/src/processComTs.ts +40 -0
- /package/examples/basic_build/{src → websrc}/index.html +0 -0
- /package/examples/basic_build/{src → websrc}/index.ts +0 -0
- /package/examples/with_assets/{src → websrc}/index.html +0 -0
- /package/examples/with_assets/{src → websrc}/index.ts +0 -0
- /package/examples/with_assets/{src → websrc}/profile.png +0 -0
- /package/examples/with_assets/{src → websrc}/section/index.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/admin/admin-panel.com.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/admin/dashboard.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/admin/dashboard.ts +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/admin/nested-stat.com.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/admin/site-header.com.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/blog/comment-item.com.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/blog/comment-section.com.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/blog/post.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/blog/post.ts +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/index.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/index.ts +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/info-box.com.html +0 -0
- /package/examples/with_com_html_priority/{src → websrc}/site-header.com.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/dashboard/main.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/dashboard/main.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/dashboard/page-header.com.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/dashboard/stats-widget.com.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/feature-card.com.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/footer-info.com.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/index.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/index.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/page-header.com.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/settings/config.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/settings/config.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/settings/priority-test.com.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/settings/priority-test.com.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/activity-feed.com.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/page-header.com.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/profile-actions.com.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/user-profile.com.ts +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/view.html +0 -0
- /package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/view.ts +0 -0
- /package/examples/with_com_ts/{src → websrc}/dynamic-list.com.ts +0 -0
- /package/examples/with_com_ts/{src → websrc}/greeting-message.com.ts +0 -0
- /package/examples/with_com_ts/{src → websrc}/index.html +0 -0
- /package/examples/with_com_ts/{src → websrc}/user-card.com.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/analytics/chart-widget.com.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/analytics/report.html +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/analytics/report.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/analytics/user-stats.com.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/data-table.com.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/index.html +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/index.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/sales/regional/data-table.com.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/sales/regional/overview.html +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/sales/regional/overview.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/sales/regional/sales-summary.com.ts +0 -0
- /package/examples/with_com_ts_priority/{src → websrc}/user-stats.com.ts +0 -0
- /package/examples/with_component_iteration/{src → websrc}/card-list.com.ts +0 -0
- /package/examples/with_component_iteration/{src → websrc}/engagement-meter.com.ts +0 -0
- /package/examples/with_component_iteration/{src → websrc}/index.html +0 -0
- /package/examples/with_component_iteration/{src → websrc}/index.ts +0 -0
- /package/examples/with_component_iteration/{src → websrc}/note-box.com.html +0 -0
- /package/examples/with_component_iteration/{src → websrc}/status-badge.com.ts +0 -0
- /package/examples/with_component_iteration/{src → websrc}/user-card.com.ts +0 -0
- /package/examples/with_pre/{src → websrc}/contact.pre.ts +0 -0
- /package/examples/with_pre/{src → websrc}/index.html +0 -0
- /package/examples/with_pre/{src → websrc}/index.ts +0 -0
- /package/examples/with_pre/{src → websrc}/profile.png +0 -0
- /package/examples/with_pre/{src → websrc}/section/index.html +0 -0
- /package/examples/with_pre/{src → websrc}/section/index.pre.ts +0 -0
- /package/examples/with_pre/{src → websrc}/section/no-linked-profile.png +0 -0
package/bun.lock
CHANGED
|
@@ -5,30 +5,30 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "tkeron",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
9
|
-
"@tkeron/commands": "0.4.
|
|
10
|
-
"@tkeron/html-parser": "1.5.
|
|
11
|
-
"@tkeron/tools": "^0.4.
|
|
8
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
9
|
+
"@tkeron/commands": "0.4.7",
|
|
10
|
+
"@tkeron/html-parser": "1.5.6",
|
|
11
|
+
"@tkeron/tools": "^0.4.1",
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@types/bun": "^1.3.
|
|
14
|
+
"@types/bun": "^1.3.11",
|
|
15
15
|
"prettier": "^3.8.1",
|
|
16
|
-
"typescript": "^
|
|
16
|
+
"typescript": "^6.0.2",
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
"packages": {
|
|
21
21
|
"@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="],
|
|
22
22
|
|
|
23
|
-
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.
|
|
23
|
+
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
|
|
24
24
|
|
|
25
|
-
"@tkeron/commands": ["@tkeron/commands@0.4.
|
|
25
|
+
"@tkeron/commands": ["@tkeron/commands@0.4.7", "", { "peerDependencies": { "typescript": "^5.9.3" } }, "sha512-QGYLnPcOFir5cMJpeUuLMZdW5IrcDyY/jjbML3o23yATI8Y3XzwYhRDW2l8kex0waLV7KsAwnGsb2zl8sRn1PQ=="],
|
|
26
26
|
|
|
27
|
-
"@tkeron/html-parser": ["@tkeron/html-parser@1.5.
|
|
27
|
+
"@tkeron/html-parser": ["@tkeron/html-parser@1.5.6", "", { "peerDependencies": { "typescript": "^5.9.3" } }, "sha512-dATXoSjxOuUjyjde5ocrZdd5xKfpKf7R9dwRklXHVCAvGwPR2UlJfISWmfmYIwlwFuidg+jmujXmLlLwA7hQgA=="],
|
|
28
28
|
|
|
29
|
-
"@tkeron/tools": ["@tkeron/tools@0.4.
|
|
29
|
+
"@tkeron/tools": ["@tkeron/tools@0.4.1", "", { "peerDependencies": { "typescript": "^5.9.3" } }, "sha512-nsmguSq/Ukx930ChwO11V433R786aJ/tniugzDdlfT/rzLrFxPJoHZerA71XGOIuD8/FRlvS7kJR9YI0CcxmqQ=="],
|
|
30
30
|
|
|
31
|
-
"@types/bun": ["@types/bun@1.3.
|
|
31
|
+
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
|
32
32
|
|
|
33
33
|
"@types/node": ["@types/node@25.3.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A=="],
|
|
34
34
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
"body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
|
42
42
|
|
|
43
|
-
"bun-types": ["bun-types@1.3.
|
|
43
|
+
"bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="],
|
|
44
44
|
|
|
45
45
|
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
|
46
46
|
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
|
|
203
203
|
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
|
204
204
|
|
|
205
|
-
"typescript": ["typescript@
|
|
205
|
+
"typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
|
206
206
|
|
|
207
207
|
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
|
208
208
|
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# v5.1.0
|
|
2
|
+
|
|
3
|
+
## Feature: .com.html template injection into .com.ts components
|
|
4
|
+
|
|
5
|
+
- When both `name.com.html` and `name.com.ts` exist for the same component, the `.com.html` content is loaded as `com.innerHTML` before executing the `.com.ts` code
|
|
6
|
+
- The `.com.html` acts as a static template that `.com.ts` can read, modify, or override
|
|
7
|
+
- Template resolution uses the same priority system: adjacent to `.com.ts` first, then fallback to root
|
|
8
|
+
- Fully backwards compatible: `.com.ts`-only components work exactly as before
|
|
9
|
+
- Added example `with_com_html_in_ts` demonstrating the feature
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# v5.0.2
|
|
2
14
|
|
|
3
15
|
## Performance: component processing optimization
|
|
@@ -76,6 +76,8 @@ When multiple component types exist for the same name, Tkeron uses this priority
|
|
|
76
76
|
2. **`.com.html`** (HTML components)
|
|
77
77
|
3. **`.com.md`** (Markdown components — lowest priority)
|
|
78
78
|
|
|
79
|
+
**Special case:** When both `.com.ts` and `.com.html` exist for the same name, the `.com.html` is loaded as the template (`com.innerHTML`) before the `.com.ts` executes. See [TypeScript Components — HTML Template + TypeScript Logic](./components-typescript.md#html-template--typescript-logic).
|
|
80
|
+
|
|
79
81
|
If both `hero-text.com.html` and `hero-text.com.md` exist, the `.com.html` version is used and `.com.md` is ignored.
|
|
80
82
|
|
|
81
83
|
### 4. Build Process
|
|
@@ -540,6 +540,65 @@ If a component doesn't need attributes or logic, use [HTML components](./compone
|
|
|
540
540
|
</footer>
|
|
541
541
|
```
|
|
542
542
|
|
|
543
|
+
## HTML Template + TypeScript Logic
|
|
544
|
+
|
|
545
|
+
When both `name.com.html` and `name.com.ts` exist for the same component, the `.com.html` content is loaded as `com.innerHTML` **before** the `.com.ts` code executes. This lets you separate structure from logic.
|
|
546
|
+
|
|
547
|
+
### How It Works
|
|
548
|
+
|
|
549
|
+
```
|
|
550
|
+
1. Tkeron finds <user-card name="Alice">
|
|
551
|
+
2. Loads user-card.com.html content into com.innerHTML
|
|
552
|
+
3. Executes user-card.com.ts (com already has the template)
|
|
553
|
+
4. Replaces <user-card> with the final com.innerHTML
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Example
|
|
557
|
+
|
|
558
|
+
**Template** (`user-card.com.html`):
|
|
559
|
+
|
|
560
|
+
```html
|
|
561
|
+
<div class="card">
|
|
562
|
+
<h3 class="name"></h3>
|
|
563
|
+
<p class="role"></p>
|
|
564
|
+
</div>
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
**Logic** (`user-card.com.ts`):
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
const name = com.getAttribute("data-name") || "Unknown";
|
|
571
|
+
const role = com.getAttribute("data-role") || "N/A";
|
|
572
|
+
|
|
573
|
+
const nameEl = com.querySelector(".name");
|
|
574
|
+
const roleEl = com.querySelector(".role");
|
|
575
|
+
|
|
576
|
+
if (nameEl) nameEl.textContent = name;
|
|
577
|
+
if (roleEl) roleEl.textContent = `Role: ${role}`;
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Usage:**
|
|
581
|
+
|
|
582
|
+
```html
|
|
583
|
+
<user-card data-name="Alice" data-role="Developer"></user-card>
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Output:**
|
|
587
|
+
|
|
588
|
+
```html
|
|
589
|
+
<div class="card">
|
|
590
|
+
<h3 class="name">Alice</h3>
|
|
591
|
+
<p class="role">Role: Developer</p>
|
|
592
|
+
</div>
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### Key Points
|
|
596
|
+
|
|
597
|
+
- The `.com.ts` can read, modify, or completely override the template
|
|
598
|
+
- If only `.com.ts` exists (no `.com.html`), it works exactly as before
|
|
599
|
+
- Template resolution follows the same directory priority as components (adjacent first, then root)
|
|
600
|
+
- Great for separating HTML structure from dynamic logic
|
|
601
|
+
|
|
543
602
|
## Debugging
|
|
544
603
|
|
|
545
604
|
### Log at Build Time
|
package/docs/testing.md
CHANGED
|
@@ -61,7 +61,7 @@ import { getBuildResult, type BuildResult } from "tkeron";
|
|
|
61
61
|
import { join } from "path";
|
|
62
62
|
|
|
63
63
|
describe("my project", () => {
|
|
64
|
-
const sourcePath = join(import.meta.dir, "
|
|
64
|
+
const sourcePath = join(import.meta.dir, "websrc");
|
|
65
65
|
let result: BuildResult;
|
|
66
66
|
|
|
67
67
|
beforeAll(async () => {
|
|
@@ -0,0 +1,19 @@
|
|
|
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>HTML Template in TS Component Example</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>.com.html Template + .com.ts Logic</h1>
|
|
10
|
+
|
|
11
|
+
<user-card data-name="Alice" data-role="Developer"></user-card>
|
|
12
|
+
<user-card data-name="Bob" data-role="Designer"></user-card>
|
|
13
|
+
|
|
14
|
+
<info-panel
|
|
15
|
+
data-title="Features"
|
|
16
|
+
data-items="HTML templates for structure,TypeScript for logic,Clean separation of concerns"
|
|
17
|
+
></info-panel>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const title = com.getAttribute("data-title") || "Info";
|
|
2
|
+
const rawItems = com.getAttribute("data-items") || "";
|
|
3
|
+
const items = rawItems
|
|
4
|
+
.split(",")
|
|
5
|
+
.map((s: string) => s.trim())
|
|
6
|
+
.filter((s: string) => s.length > 0);
|
|
7
|
+
|
|
8
|
+
const titleEl = com.querySelector(".title");
|
|
9
|
+
if (titleEl) titleEl.textContent = title;
|
|
10
|
+
|
|
11
|
+
const itemsEl = com.querySelector(".items");
|
|
12
|
+
if (itemsEl) {
|
|
13
|
+
itemsEl.innerHTML = items.map((item: string) => `<li>${item}</li>`).join("");
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const name = com.getAttribute("data-name") || "Unknown";
|
|
2
|
+
const role = com.getAttribute("data-role") || "N/A";
|
|
3
|
+
|
|
4
|
+
const nameEl = com.querySelector(".name");
|
|
5
|
+
const roleEl = com.querySelector(".role");
|
|
6
|
+
|
|
7
|
+
if (nameEl) nameEl.textContent = name;
|
|
8
|
+
if (roleEl) roleEl.textContent = `Role: ${role}`;
|
package/mcp-server.ts
CHANGED
|
@@ -106,6 +106,8 @@ const EXAMPLE_DESCRIPTIONS: { [key: string]: string } = {
|
|
|
106
106
|
"TypeScript components (.com.ts) with local override priority",
|
|
107
107
|
with_com_mixed_priority:
|
|
108
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",
|
|
109
111
|
with_component_iteration:
|
|
110
112
|
"Component iteration: .com.ts with logic, .com.html for templates",
|
|
111
113
|
};
|
|
@@ -175,8 +177,7 @@ server.registerTool(
|
|
|
175
177
|
const examplePath = join(EXAMPLES_DIR, name);
|
|
176
178
|
return (
|
|
177
179
|
statSync(examplePath).isDirectory() &&
|
|
178
|
-
|
|
179
|
-
existsSync(join(examplePath, "websrc")))
|
|
180
|
+
existsSync(join(examplePath, "websrc"))
|
|
180
181
|
);
|
|
181
182
|
});
|
|
182
183
|
|
|
@@ -226,17 +227,14 @@ server.registerTool(
|
|
|
226
227
|
};
|
|
227
228
|
}
|
|
228
229
|
|
|
229
|
-
|
|
230
|
-
if (!existsSync(srcPath)) {
|
|
231
|
-
srcPath = join(examplePath, "websrc");
|
|
232
|
-
}
|
|
230
|
+
const srcPath = join(examplePath, "websrc");
|
|
233
231
|
|
|
234
232
|
if (!existsSync(srcPath)) {
|
|
235
233
|
return {
|
|
236
234
|
content: [
|
|
237
235
|
{
|
|
238
236
|
type: "text" as const,
|
|
239
|
-
text: `Example ${exampleName} does not have a
|
|
237
|
+
text: `Example ${exampleName} does not have a websrc directory`,
|
|
240
238
|
},
|
|
241
239
|
],
|
|
242
240
|
isError: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tkeron",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "CLI build tool for vanilla web development with TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -26,20 +26,21 @@
|
|
|
26
26
|
"sample5": "bun . build examples/with_com_ts/src",
|
|
27
27
|
"sample6": "bun . build examples/with_com_ts_priority/src",
|
|
28
28
|
"sample7": "bun . build examples/with_com_mixed_priority/src",
|
|
29
|
-
"
|
|
29
|
+
"sample8": "bun . build examples/with_com_html_in_ts/src",
|
|
30
|
+
"build_examples": "bun run sample1 && bun run sample2 && bun run sample3 && bun run sample4 && bun run sample5 && bun run sample6 && bun run sample7 && bun run sample8"
|
|
30
31
|
},
|
|
31
32
|
"author": "tkeron",
|
|
32
33
|
"license": "MIT",
|
|
33
34
|
"dependencies": {
|
|
34
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
35
|
-
"@tkeron/commands": "0.4.
|
|
36
|
-
"@tkeron/html-parser": "1.5.
|
|
37
|
-
"@tkeron/tools": "^0.4.
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
36
|
+
"@tkeron/commands": "0.4.7",
|
|
37
|
+
"@tkeron/html-parser": "1.5.6",
|
|
38
|
+
"@tkeron/tools": "^0.4.1"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@types/bun": "^1.3.
|
|
41
|
+
"@types/bun": "^1.3.11",
|
|
41
42
|
"prettier": "^3.8.1",
|
|
42
|
-
"typescript": "^
|
|
43
|
+
"typescript": "^6.0.2"
|
|
43
44
|
},
|
|
44
45
|
"keywords": [
|
|
45
46
|
"cli",
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
"publishConfig": {
|
|
57
58
|
"access": "public"
|
|
58
59
|
},
|
|
60
|
+
"homepage": "https://tkeron.com",
|
|
59
61
|
"repository": {
|
|
60
62
|
"type": "git",
|
|
61
63
|
"url": "git+https://github.com/tkeron/tkeron.git"
|
package/src/develop.ts
CHANGED
|
@@ -130,30 +130,45 @@ export const develop = async (
|
|
|
130
130
|
|
|
131
131
|
log.log(`🚀 Development server running at http://${host}:${port}`);
|
|
132
132
|
|
|
133
|
+
let currentBuild: Promise<void> | null = null;
|
|
134
|
+
let isStopped = false;
|
|
135
|
+
|
|
133
136
|
const watcher = watch(
|
|
134
137
|
source,
|
|
135
138
|
{ recursive: true },
|
|
136
139
|
async (event, filename) => {
|
|
137
|
-
if (filename)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
140
|
+
if (!filename || isStopped || currentBuild) return;
|
|
141
|
+
log.log(`📝 File changed: ${filename}`);
|
|
142
|
+
log.log("🔨 Rebuilding...");
|
|
143
|
+
const buildPromise = build({
|
|
144
|
+
sourceDir: source,
|
|
145
|
+
targetDir: target,
|
|
146
|
+
logger: log,
|
|
147
|
+
});
|
|
148
|
+
currentBuild = buildPromise;
|
|
149
|
+
try {
|
|
150
|
+
await buildPromise;
|
|
151
|
+
} finally {
|
|
152
|
+
if (currentBuild === buildPromise) currentBuild = null;
|
|
150
153
|
}
|
|
154
|
+
if (isStopped) return;
|
|
155
|
+
log.log("✅ Build complete!");
|
|
156
|
+
|
|
157
|
+
reloadClients.forEach((controller) => {
|
|
158
|
+
try {
|
|
159
|
+
controller.enqueue("data: reload\n\n");
|
|
160
|
+
} catch (e) {
|
|
161
|
+
reloadClients.delete(controller);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
151
164
|
},
|
|
152
165
|
);
|
|
153
166
|
|
|
154
167
|
const stop = async () => {
|
|
155
168
|
log.log("\n👋 Shutting down server...");
|
|
169
|
+
isStopped = true;
|
|
156
170
|
watcher.close();
|
|
171
|
+
await currentBuild?.catch(() => {});
|
|
157
172
|
server.stop();
|
|
158
173
|
|
|
159
174
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
package/src/processComTs.ts
CHANGED
|
@@ -14,6 +14,7 @@ const ensureHtmlDocument = (html: string): string => {
|
|
|
14
14
|
|
|
15
15
|
interface ComponentCache {
|
|
16
16
|
componentMap: Map<string, string[]>;
|
|
17
|
+
htmlTemplateMap: Map<string, string[]>;
|
|
17
18
|
contentCache: Map<string, string>;
|
|
18
19
|
transpileCache: Map<string, string>;
|
|
19
20
|
}
|
|
@@ -30,6 +31,18 @@ const buildComponentMap = (rootDir: string): Map<string, string[]> => {
|
|
|
30
31
|
return map;
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
const buildHtmlTemplateMap = (rootDir: string): Map<string, string[]> => {
|
|
35
|
+
const allFiles = getFilePaths(rootDir, "**/*.com.html", true);
|
|
36
|
+
const map = new Map<string, string[]>();
|
|
37
|
+
for (const file of allFiles) {
|
|
38
|
+
const basename = file.split("/").pop()!;
|
|
39
|
+
const tagName = basename.replace(/\.com\.html$/, "");
|
|
40
|
+
if (!map.has(tagName)) map.set(tagName, []);
|
|
41
|
+
map.get(tagName)!.push(file);
|
|
42
|
+
}
|
|
43
|
+
return map;
|
|
44
|
+
};
|
|
45
|
+
|
|
33
46
|
const getCachedContent = async (
|
|
34
47
|
path: string,
|
|
35
48
|
cache: Map<string, string>,
|
|
@@ -69,8 +82,10 @@ export const processComTs = async (
|
|
|
69
82
|
}
|
|
70
83
|
|
|
71
84
|
const componentMap = buildComponentMap(tempDir);
|
|
85
|
+
const htmlTemplateMap = buildHtmlTemplateMap(tempDir);
|
|
72
86
|
const cache: ComponentCache = {
|
|
73
87
|
componentMap,
|
|
88
|
+
htmlTemplateMap,
|
|
74
89
|
contentCache: new Map(),
|
|
75
90
|
transpileCache: new Map(),
|
|
76
91
|
};
|
|
@@ -123,6 +138,18 @@ const resolveComponent = (
|
|
|
123
138
|
return matches[0]!;
|
|
124
139
|
};
|
|
125
140
|
|
|
141
|
+
const resolveHtmlTemplate = (
|
|
142
|
+
tagName: string,
|
|
143
|
+
tsDir: string,
|
|
144
|
+
htmlTemplateMap: Map<string, string[]>,
|
|
145
|
+
): string | null => {
|
|
146
|
+
const matches = htmlTemplateMap.get(tagName);
|
|
147
|
+
if (!matches || matches.length === 0) return null;
|
|
148
|
+
const adjacentPath = join(tsDir, `${tagName}.com.html`);
|
|
149
|
+
if (matches.includes(adjacentPath)) return adjacentPath;
|
|
150
|
+
return matches[0]!;
|
|
151
|
+
};
|
|
152
|
+
|
|
126
153
|
const processComponentsTs = async (
|
|
127
154
|
element: any,
|
|
128
155
|
currentDir: string,
|
|
@@ -209,6 +236,19 @@ const processComponentsTs = async (
|
|
|
209
236
|
);
|
|
210
237
|
}
|
|
211
238
|
|
|
239
|
+
const htmlTemplatePath = resolveHtmlTemplate(
|
|
240
|
+
tagName,
|
|
241
|
+
dirname(componentPath),
|
|
242
|
+
cache.htmlTemplateMap,
|
|
243
|
+
);
|
|
244
|
+
if (htmlTemplatePath) {
|
|
245
|
+
const templateContent = await getCachedContent(
|
|
246
|
+
htmlTemplatePath,
|
|
247
|
+
cache.contentCache,
|
|
248
|
+
);
|
|
249
|
+
com.innerHTML = templateContent;
|
|
250
|
+
}
|
|
251
|
+
|
|
212
252
|
const hasImports = /^\s*import\s+/m.test(originalComponentCode);
|
|
213
253
|
|
|
214
254
|
try {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/activity-feed.com.ts
RENAMED
|
File without changes
|
/package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/page-header.com.html
RENAMED
|
File without changes
|
/package/examples/with_com_mixed_priority/{src → websrc}/users/profiles/profile-actions.com.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|