tkeron 5.0.0 → 5.0.2
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 +2 -2
- package/changelog.md +30 -0
- package/docs/best-practices.md +3 -6
- package/docs/cli-reference.md +11 -7
- package/docs/common-issues.md +20 -13
- package/docs/components-html.md +10 -8
- package/docs/components-markdown.md +5 -5
- package/docs/components-typescript.md +1 -1
- package/docs/getting-started.md +3 -2
- package/docs/overview.md +5 -3
- package/docs/pre-rendering.md +7 -4
- package/package.json +2 -2
- package/src/processCom.ts +90 -52
- package/src/processComMd.ts +90 -48
- package/src/processComTs.ts +110 -52
- package/src/processPre.ts +10 -2
package/README.md
CHANGED
|
@@ -82,8 +82,8 @@ document.getElementById("quote").textContent = data.content;
|
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
tk init <name> # Initialize new project
|
|
85
|
-
tk build
|
|
86
|
-
tk dev [
|
|
85
|
+
tk build # Build project (websrc → web)
|
|
86
|
+
tk dev [port] [host] # Dev server with hot reload (default: localhost:3000)
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
**Aliases:** `tk i`, `tk b`, `tk d`
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
# v5.0.2
|
|
2
|
+
|
|
3
|
+
## Performance: component processing optimization
|
|
4
|
+
|
|
5
|
+
- Perf: single glob scan per build pass to pre-load all component paths into a `Map<tagName, filePath[]>` — eliminates O(pages × components) filesystem scans in `processCom`, `processComTs`, `processComMd`
|
|
6
|
+
- Perf: `Map<path, content>` cache avoids redundant disk reads when the same component is used across multiple pages
|
|
7
|
+
- Perf: `Map<code, jsCode>` transpilation cache in `processComTs` — `Bun.Transpiler.transformSync` result reused for unchanged `.com.ts` files
|
|
8
|
+
- Perf: parallel page processing via `Promise.all` instead of sequential `for...of` — independent pages now process concurrently
|
|
9
|
+
- Perf: lazy `package.json` read in `processPre` — removed top-level `await` that ran on module import regardless of whether pre-rendering was needed
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# v5.0.1
|
|
14
|
+
|
|
15
|
+
## Documentation fixes and dependency updates
|
|
16
|
+
|
|
17
|
+
- Fix: `tk build` and `tk dev` CLI signatures corrected in README (removed wrong `[src] [out]` args, aligned with v5.0 breaking change)
|
|
18
|
+
- Fix: Component resolution docs updated to reflect actual glob search behavior (not limited to root `websrc/`)
|
|
19
|
+
- Fix: Build process docs updated to include `.com.md` processing step and iterative loop (up to 10 iterations)
|
|
20
|
+
- Fix: `tsconfig.json` example corrected to match real config (`lib: ["ESNext", "DOM"]`, removed `types: ["bun-types"]`)
|
|
21
|
+
- Fix: TypeScript compilation docs clarified — Bun transpiler does NOT type-check, only transpiles
|
|
22
|
+
- Fix: Broken link `tkeron.dev/docs` → `tkeron.com`
|
|
23
|
+
- Fix: `components-html.md` quick start used `<button>` (reserved HTML tag, no hyphen) — replaced with `<my-button>`
|
|
24
|
+
- Fix: `best-practices.md` Summary had orphaned/corrupted code fragment — removed
|
|
25
|
+
- Fix: Added `.com.md` to all feature lists, tables, and build process diagrams across all docs
|
|
26
|
+
- Fix: `package.json` description updated to reflect actual purpose
|
|
27
|
+
- Deps: `bun update --latest` — updated all dependencies
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
1
31
|
# v5.0.0
|
|
2
32
|
|
|
3
33
|
## Breaking: sourceDir and targetDir removed as CLI arguments
|
package/docs/best-practices.md
CHANGED
|
@@ -231,23 +231,20 @@ document.getElementById("stars").textContent = data.public_repos;
|
|
|
231
231
|
|
|
232
232
|
- HTML components: static markup
|
|
233
233
|
- TypeScript components: dynamic generation
|
|
234
|
+
- Markdown components: content in Markdown
|
|
234
235
|
- Pre-rendering: DOM manipulation at build time
|
|
235
236
|
- Browser code: regular TypeScript/JavaScript
|
|
236
237
|
- No bundling of npm packages
|
|
237
238
|
- No type checking (use `tsc --noEmit`)
|
|
238
239
|
- Powered by Bun
|
|
239
|
-
document.querySelectorAll('.my-button').forEach(btn => {
|
|
240
|
-
btn.addEventListener('click', handleClick);
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
240
|
|
|
244
|
-
|
|
241
|
+
---
|
|
245
242
|
|
|
246
243
|
```typescript
|
|
247
244
|
// ❌ Don't try to maintain state
|
|
248
245
|
let count = 0; // This is meaningless
|
|
249
246
|
com.innerHTML = `<button>Count: ${count}</button>`;
|
|
250
|
-
|
|
247
|
+
```
|
|
251
248
|
|
|
252
249
|
**Solution:** Use client-side JavaScript for stateful UI.
|
|
253
250
|
|
package/docs/cli-reference.md
CHANGED
|
@@ -75,16 +75,20 @@ tk b
|
|
|
75
75
|
1. Creates temporary directory as sibling to source
|
|
76
76
|
2. Copies source to temp directory
|
|
77
77
|
3. Runs `.pre.ts` files (pre-rendering)
|
|
78
|
-
4.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
4. Iterative component processing (up to 10 iterations):
|
|
79
|
+
- Processes `.com.ts` components (TypeScript components)
|
|
80
|
+
- Processes `.com.html` components (HTML components)
|
|
81
|
+
- Processes `.com.md` components (Markdown components)
|
|
82
|
+
- Repeats until no changes are detected
|
|
83
|
+
5. Compiles TypeScript to JavaScript
|
|
84
|
+
6. Copies result to target directory
|
|
85
|
+
7. Cleans up temporary directory
|
|
83
86
|
|
|
84
87
|
**Files Excluded from Output:**
|
|
85
88
|
|
|
86
89
|
- `*.com.html` - HTML components (inlined)
|
|
87
90
|
- `*.com.ts` - TypeScript components (inlined)
|
|
91
|
+
- `*.com.md` - Markdown components (inlined)
|
|
88
92
|
- `*.pre.ts` - Pre-rendering scripts (executed)
|
|
89
93
|
|
|
90
94
|
**Exit Codes:**
|
|
@@ -448,8 +452,8 @@ Tkeron doesn't require a `tsconfig.json`, but you can add one for editor support
|
|
|
448
452
|
"compilerOptions": {
|
|
449
453
|
"target": "ESNext",
|
|
450
454
|
"module": "ESNext",
|
|
455
|
+
"lib": ["ESNext", "DOM"],
|
|
451
456
|
"moduleResolution": "bundler",
|
|
452
|
-
"types": ["bun-types"],
|
|
453
457
|
"strict": true,
|
|
454
458
|
"skipLibCheck": true
|
|
455
459
|
},
|
|
@@ -635,7 +639,7 @@ tk
|
|
|
635
639
|
This document! Also available at:
|
|
636
640
|
|
|
637
641
|
- [GitHub Repository](https://github.com/tkeron/tkeron)
|
|
638
|
-
- [Documentation Site](https://tkeron.
|
|
642
|
+
- [Documentation Site](https://tkeron.com)
|
|
639
643
|
|
|
640
644
|
### Report Issues
|
|
641
645
|
|
package/docs/common-issues.md
CHANGED
|
@@ -125,9 +125,9 @@ blog-post.com.ts → <blog-post>
|
|
|
125
125
|
|
|
126
126
|
## TypeScript Compilation
|
|
127
127
|
|
|
128
|
-
### Issue: TypeScript Errors
|
|
128
|
+
### Issue: TypeScript Errors in Source
|
|
129
129
|
|
|
130
|
-
**Problem:**
|
|
130
|
+
**Problem:** TypeScript code has type errors
|
|
131
131
|
|
|
132
132
|
```typescript
|
|
133
133
|
// ❌ WRONG
|
|
@@ -135,18 +135,24 @@ const user = { name: "Alice" };
|
|
|
135
135
|
user.age = 30; // Error: Property 'age' does not exist
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
**Why this
|
|
138
|
+
**Why this matters:**
|
|
139
139
|
|
|
140
|
-
- Tkeron uses Bun's TypeScript transpiler
|
|
141
|
-
- Type errors
|
|
142
|
-
-
|
|
140
|
+
- Tkeron uses Bun's TypeScript transpiler, which **does NOT type-check** — it only transpiles
|
|
141
|
+
- Type errors won't prevent the build from running
|
|
142
|
+
- However, type errors may indicate real bugs in your code
|
|
143
|
+
- Missing types for global variables can confuse your IDE
|
|
143
144
|
|
|
144
145
|
**Solution:**
|
|
145
146
|
|
|
147
|
+
- Run `tsc --noEmit` separately to catch type errors before building
|
|
146
148
|
- Use `tkeron.d.ts` for global type declarations
|
|
147
|
-
- Fix type errors before building
|
|
148
149
|
- Use `any` strategically if types are complex
|
|
149
150
|
|
|
151
|
+
```bash
|
|
152
|
+
# Check types, then build
|
|
153
|
+
tsc --noEmit && tk build
|
|
154
|
+
```
|
|
155
|
+
|
|
150
156
|
```typescript
|
|
151
157
|
// ✅ CORRECT
|
|
152
158
|
const user: { name: string; age?: number } = { name: "Alice" };
|
|
@@ -166,16 +172,17 @@ user.age = 30; // OK
|
|
|
166
172
|
|
|
167
173
|
**Why this happens:**
|
|
168
174
|
|
|
169
|
-
- Tkeron searches in 2
|
|
175
|
+
- Tkeron searches in 2 ways:
|
|
170
176
|
1. Same directory as HTML file
|
|
171
|
-
2.
|
|
172
|
-
-
|
|
177
|
+
2. Glob search across the entire source tree
|
|
178
|
+
- If no match is found in either, the element remains unchanged
|
|
173
179
|
|
|
174
180
|
**Solution:**
|
|
175
|
-
|
|
181
|
+
Place the component file anywhere in the source tree — Tkeron will find it via glob search. For clarity, common locations:
|
|
176
182
|
|
|
177
|
-
- In `blog/user-card.com.html` (next to `post.html`)
|
|
178
|
-
-
|
|
183
|
+
- In `blog/user-card.com.html` (next to `post.html` — higher priority)
|
|
184
|
+
- In `websrc/user-card.com.html` (root)
|
|
185
|
+
- In `websrc/components/user-card.com.html` (organized in a subfolder)
|
|
179
186
|
|
|
180
187
|
## Build Performance
|
|
181
188
|
|
package/docs/components-html.md
CHANGED
|
@@ -7,7 +7,7 @@ HTML components (`.com.html` files) are the simplest way to create reusable piec
|
|
|
7
7
|
Create a file named with `.com.html` extension:
|
|
8
8
|
|
|
9
9
|
```html
|
|
10
|
-
<!-- button.com.html -->
|
|
10
|
+
<!-- my-button.com.html -->
|
|
11
11
|
<button class="btn">Click me</button>
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ Use it with a matching custom element:
|
|
|
15
15
|
|
|
16
16
|
```html
|
|
17
17
|
<!-- index.html -->
|
|
18
|
-
<button></button>
|
|
18
|
+
<my-button></my-button>
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Build, and the custom element is replaced with the component's content.
|
|
@@ -36,7 +36,7 @@ Component filenames must:
|
|
|
36
36
|
| -------------------- | -------------- | ------------------------- |
|
|
37
37
|
| `user-card.com.html` | `<user-card>` | ✅ Yes |
|
|
38
38
|
| `nav-menu.com.html` | `<nav-menu>` | ✅ Yes |
|
|
39
|
-
| `
|
|
39
|
+
| `card.com.html` | `<card>` | ❌ No (no hyphen) |
|
|
40
40
|
| `UserCard.com.html` | `<user-card>` | ✅ Yes (case-insensitive) |
|
|
41
41
|
|
|
42
42
|
### 2. Component Resolution
|
|
@@ -44,23 +44,25 @@ Component filenames must:
|
|
|
44
44
|
Tkeron looks for components in this order:
|
|
45
45
|
|
|
46
46
|
1. **Same directory** as the file using it
|
|
47
|
-
2. **
|
|
47
|
+
2. **Any directory** in the source tree (via glob search)
|
|
48
48
|
|
|
49
49
|
**Example structure:**
|
|
50
50
|
|
|
51
51
|
```
|
|
52
52
|
websrc/
|
|
53
53
|
├── index.html
|
|
54
|
-
├── header.com.html
|
|
54
|
+
├── site-header.com.html # Available to all files
|
|
55
|
+
├── components/
|
|
56
|
+
│ └── blog-comment.com.html # Also available to all files
|
|
55
57
|
├── blog/
|
|
56
58
|
│ ├── post.html
|
|
57
|
-
│ └── comment.com.html
|
|
59
|
+
│ └── blog-comment.com.html # Takes priority for blog/post.html
|
|
58
60
|
```
|
|
59
61
|
|
|
60
62
|
In `blog/post.html`:
|
|
61
63
|
|
|
62
|
-
- `<comment>` → Finds `blog/comment.com.html` first
|
|
63
|
-
- `<header>` →
|
|
64
|
+
- `<blog-comment>` → Finds `blog/blog-comment.com.html` first (same directory)
|
|
65
|
+
- `<site-header>` → Found via glob search in the source tree
|
|
64
66
|
|
|
65
67
|
### 3. Build Process
|
|
66
68
|
|
|
@@ -50,23 +50,23 @@ Component filenames must:
|
|
|
50
50
|
Tkeron looks for components in this order:
|
|
51
51
|
|
|
52
52
|
1. **Same directory** as the file using it
|
|
53
|
-
2. **
|
|
53
|
+
2. **Any directory** in the source tree (via glob search)
|
|
54
54
|
|
|
55
55
|
**Example structure:**
|
|
56
56
|
|
|
57
57
|
```
|
|
58
58
|
websrc/
|
|
59
59
|
├── index.html
|
|
60
|
-
├── site-intro.com.md
|
|
60
|
+
├── site-intro.com.md # Available to all files
|
|
61
61
|
├── blog/
|
|
62
62
|
│ ├── post.html
|
|
63
|
-
│ └── post-footer.com.md
|
|
63
|
+
│ └── post-footer.com.md # Takes priority for blog/post.html
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
In `blog/post.html`:
|
|
67
67
|
|
|
68
|
-
- `<post-footer>` → Finds `blog/post-footer.com.md` first
|
|
69
|
-
- `<site-intro>` →
|
|
68
|
+
- `<post-footer>` → Finds `blog/post-footer.com.md` first (same directory)
|
|
69
|
+
- `<site-intro>` → Found via glob search in the source tree
|
|
70
70
|
|
|
71
71
|
### 3. Component Priority
|
|
72
72
|
|
|
@@ -84,7 +84,7 @@ Custom elements in HTML must contain at least one hyphen to distinguish them fro
|
|
|
84
84
|
Same as HTML components:
|
|
85
85
|
|
|
86
86
|
1. **Same directory** as the file using it
|
|
87
|
-
2. **
|
|
87
|
+
2. **Any directory** in the source tree (via glob search)
|
|
88
88
|
|
|
89
89
|
### IDE Support & IntelliSense
|
|
90
90
|
|
package/docs/getting-started.md
CHANGED
|
@@ -88,7 +88,7 @@ web/
|
|
|
88
88
|
└── ... # Other processed files
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
Notice that `.com.html`, `.com.ts`, and `.pre.ts` files are **not** copied to output - they're processed and inlined.
|
|
91
|
+
Notice that `.com.html`, `.com.ts`, `.com.md`, and `.pre.ts` files are **not** copied to output - they're processed and inlined.
|
|
92
92
|
|
|
93
93
|
## Start Development Server
|
|
94
94
|
|
|
@@ -198,6 +198,7 @@ Open `web/index.html` in your browser. You'll see the greeting component inlined
|
|
|
198
198
|
| `.ts` / `.js` | Scripts for pages | ✅ Yes (compiled) |
|
|
199
199
|
| `.com.html` | HTML components | ❌ No (inlined) |
|
|
200
200
|
| `.com.ts` | TypeScript components | ❌ No (inlined) |
|
|
201
|
+
| `.com.md` | Markdown components | ❌ No (inlined) |
|
|
201
202
|
| `.pre.ts` | Pre-rendering scripts | ❌ No (executed) |
|
|
202
203
|
| `.css` | Stylesheets | ✅ Yes |
|
|
203
204
|
| Images, fonts, etc. | Static assets | ✅ Yes |
|
|
@@ -271,4 +272,4 @@ tk dev 3001
|
|
|
271
272
|
|
|
272
273
|
- Component names **must** contain a hyphen: `user-card`, not `usercard`
|
|
273
274
|
- File must be named exactly: `user-card.com.html`
|
|
274
|
-
- Component files
|
|
275
|
+
- Component files can be anywhere in the source tree — Tkeron searches the same directory first, then the entire source via glob
|
package/docs/overview.md
CHANGED
|
@@ -11,6 +11,7 @@ Powered by [Bun](https://bun.sh).
|
|
|
11
11
|
- Compiles TypeScript to JavaScript
|
|
12
12
|
- Inlines HTML components (`.com.html`)
|
|
13
13
|
- Executes TypeScript components (`.com.ts`) at build time
|
|
14
|
+
- Renders Markdown components (`.com.md`) at build time
|
|
14
15
|
- Runs pre-rendering scripts (`.pre.ts`)
|
|
15
16
|
- Copies assets
|
|
16
17
|
- Dev server with hot reload
|
|
@@ -107,11 +108,12 @@ websrc/ Build Steps web/
|
|
|
107
108
|
├── index.html → 1. .pre.ts → ├── index.html
|
|
108
109
|
├── index.ts 2. .com.ts ├── index.js
|
|
109
110
|
├── index.pre.ts 3. .com.html
|
|
110
|
-
├── nav.com.html 4.
|
|
111
|
-
|
|
111
|
+
├── nav.com.html 4. .com.md
|
|
112
|
+
├── card.com.ts 5. TypeScript
|
|
113
|
+
└── info.com.md 6. Assets
|
|
112
114
|
```
|
|
113
115
|
|
|
114
|
-
Component files (`.com.html`, `.com.ts`, `.pre.ts`) are not copied to output.
|
|
116
|
+
Component files (`.com.html`, `.com.ts`, `.com.md`, `.pre.ts`) are not copied to output.
|
|
115
117
|
|
|
116
118
|
---
|
|
117
119
|
|
package/docs/pre-rendering.md
CHANGED
|
@@ -71,10 +71,13 @@ This is the parsed DOM from the corresponding `.html` file.
|
|
|
71
71
|
|
|
72
72
|
```
|
|
73
73
|
1. Run .pre.ts files → Modify HTML documents
|
|
74
|
-
2.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
2. Iterative component processing (up to 10 iterations):
|
|
75
|
+
a. Process .com.ts → Replace TypeScript components
|
|
76
|
+
b. Process .com.html → Replace HTML components
|
|
77
|
+
c. Process .com.md → Replace Markdown components
|
|
78
|
+
d. Repeat until no changes
|
|
79
|
+
3. Compile .ts to .js → TypeScript compilation
|
|
80
|
+
4. Copy to output → Final build
|
|
78
81
|
```
|
|
79
82
|
|
|
80
83
|
Pre-rendering happens **first**, so you can inject components dynamically.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tkeron",
|
|
3
|
-
"version": "5.0.
|
|
4
|
-
"description": "CLI tool for
|
|
3
|
+
"version": "5.0.2",
|
|
4
|
+
"description": "CLI build tool for vanilla web development with TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
7
7
|
"exports": {
|
package/src/processCom.ts
CHANGED
|
@@ -12,10 +12,50 @@ const ensureHtmlDocument = (html: string): string => {
|
|
|
12
12
|
return `${DOCTYPE}<html><head></head><body>${html}</body></html>`;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
interface ComponentCache {
|
|
16
|
+
componentMap: Map<string, string[]>;
|
|
17
|
+
contentCache: Map<string, string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const buildComponentMap = (rootDir: string): Map<string, string[]> => {
|
|
21
|
+
const allFiles = getFilePaths(rootDir, "**/*.com.html", true);
|
|
22
|
+
const map = new Map<string, string[]>();
|
|
23
|
+
for (const file of allFiles) {
|
|
24
|
+
const basename = file.split("/").pop()!;
|
|
25
|
+
const tagName = basename.replace(/\.com\.html$/, "");
|
|
26
|
+
if (!map.has(tagName)) map.set(tagName, []);
|
|
27
|
+
map.get(tagName)!.push(file);
|
|
28
|
+
}
|
|
29
|
+
return map;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getCachedContent = async (
|
|
33
|
+
path: string,
|
|
34
|
+
cache: Map<string, string>,
|
|
35
|
+
): Promise<string> => {
|
|
36
|
+
const cached = cache.get(path);
|
|
37
|
+
if (cached !== undefined) return cached;
|
|
38
|
+
const content = await Bun.file(path).text();
|
|
39
|
+
cache.set(path, content);
|
|
40
|
+
return content;
|
|
41
|
+
};
|
|
42
|
+
|
|
15
43
|
export interface ProcessComOptions {
|
|
16
44
|
logger?: Logger;
|
|
17
45
|
}
|
|
18
46
|
|
|
47
|
+
const resolveComponent = (
|
|
48
|
+
tagName: string,
|
|
49
|
+
currentDir: string,
|
|
50
|
+
componentMap: Map<string, string[]>,
|
|
51
|
+
): string | null => {
|
|
52
|
+
const matches = componentMap.get(tagName);
|
|
53
|
+
if (!matches || matches.length === 0) return null;
|
|
54
|
+
const localPath = join(currentDir, `${tagName}.com.html`);
|
|
55
|
+
if (matches.includes(localPath)) return localPath;
|
|
56
|
+
return matches[0]!;
|
|
57
|
+
};
|
|
58
|
+
|
|
19
59
|
export const processCom = async (
|
|
20
60
|
tempDir: string,
|
|
21
61
|
options: ProcessComOptions = {},
|
|
@@ -27,37 +67,45 @@ export const processCom = async (
|
|
|
27
67
|
return false;
|
|
28
68
|
}
|
|
29
69
|
|
|
70
|
+
const componentMap = buildComponentMap(tempDir);
|
|
71
|
+
const cache: ComponentCache = {
|
|
72
|
+
componentMap,
|
|
73
|
+
contentCache: new Map(),
|
|
74
|
+
};
|
|
75
|
+
|
|
30
76
|
const htmlFiles = getFilePaths(tempDir, "**/*.html", true).filter(
|
|
31
77
|
(p) => !p.endsWith(".com.html"),
|
|
32
78
|
);
|
|
33
79
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
80
|
+
const results = await Promise.all(
|
|
81
|
+
htmlFiles.map(async (htmlFile) => {
|
|
82
|
+
const htmlContent = await Bun.file(htmlFile).text();
|
|
83
|
+
const document = parseHTML(ensureHtmlDocument(htmlContent));
|
|
84
|
+
|
|
85
|
+
const htmlElement =
|
|
86
|
+
document.querySelector("html") || document.documentElement;
|
|
87
|
+
let changed = false;
|
|
88
|
+
if (htmlElement) {
|
|
89
|
+
changed = await processComponents(
|
|
90
|
+
htmlElement,
|
|
91
|
+
dirname(htmlFile),
|
|
92
|
+
tempDir,
|
|
93
|
+
[],
|
|
94
|
+
0,
|
|
95
|
+
log,
|
|
96
|
+
cache,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
53
99
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
100
|
+
const output =
|
|
101
|
+
DOCTYPE +
|
|
102
|
+
(htmlElement?.outerHTML || document.documentElement?.outerHTML || "");
|
|
103
|
+
await Bun.write(htmlFile, output);
|
|
104
|
+
return changed;
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
59
107
|
|
|
60
|
-
return
|
|
108
|
+
return results.some(Boolean);
|
|
61
109
|
};
|
|
62
110
|
|
|
63
111
|
const processComponents = async (
|
|
@@ -67,6 +115,7 @@ const processComponents = async (
|
|
|
67
115
|
componentStack: string[],
|
|
68
116
|
depth: number = 0,
|
|
69
117
|
log: Logger = silentLogger,
|
|
118
|
+
cache: ComponentCache,
|
|
70
119
|
): Promise<boolean> => {
|
|
71
120
|
let hasChanges = false;
|
|
72
121
|
const MAX_DEPTH = 50;
|
|
@@ -82,13 +131,10 @@ const processComponents = async (
|
|
|
82
131
|
|
|
83
132
|
if (tagName) {
|
|
84
133
|
if (!tagName.includes("-")) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
true,
|
|
90
|
-
);
|
|
91
|
-
if ((await Bun.file(localPath).exists()) || globMatches.length > 0) {
|
|
134
|
+
const matches = cache.componentMap.get(tagName);
|
|
135
|
+
if (matches && matches.length > 0) {
|
|
136
|
+
const localPath = join(currentDir, `${tagName}.com.html`);
|
|
137
|
+
const filePath = matches.includes(localPath) ? localPath : matches[0];
|
|
92
138
|
log.error(
|
|
93
139
|
`\n❌ Error: Component name '${tagName}' must contain at least one hyphen.`,
|
|
94
140
|
);
|
|
@@ -96,30 +142,17 @@ const processComponents = async (
|
|
|
96
142
|
log.error(
|
|
97
143
|
` Rename '${tagName}.com.html' to 'tk-${tagName}.com.html' or similar.`,
|
|
98
144
|
);
|
|
99
|
-
log.error(
|
|
100
|
-
` File: ${(await Bun.file(localPath).exists()) ? localPath : globMatches[0]}\n`,
|
|
101
|
-
);
|
|
145
|
+
log.error(` File: ${filePath}\n`);
|
|
102
146
|
throw new Error(
|
|
103
147
|
`Component name '${tagName}' must contain at least one hyphen`,
|
|
104
148
|
);
|
|
105
149
|
}
|
|
106
150
|
} else {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
componentPath = localPath;
|
|
113
|
-
} else {
|
|
114
|
-
const globMatches = getFilePaths(
|
|
115
|
-
rootDir,
|
|
116
|
-
`**/${tagName}.com.html`,
|
|
117
|
-
true,
|
|
118
|
-
);
|
|
119
|
-
if (globMatches.length > 0) {
|
|
120
|
-
componentPath = globMatches[0];
|
|
121
|
-
}
|
|
122
|
-
}
|
|
151
|
+
const componentPath = resolveComponent(
|
|
152
|
+
tagName,
|
|
153
|
+
currentDir,
|
|
154
|
+
cache.componentMap,
|
|
155
|
+
);
|
|
123
156
|
|
|
124
157
|
if (componentPath) {
|
|
125
158
|
hasChanges = true;
|
|
@@ -137,7 +170,10 @@ const processComponents = async (
|
|
|
137
170
|
throw new Error(`Circular dependency: ${chain}`);
|
|
138
171
|
}
|
|
139
172
|
|
|
140
|
-
const componentHtml = await
|
|
173
|
+
const componentHtml = await getCachedContent(
|
|
174
|
+
componentPath,
|
|
175
|
+
cache.contentCache,
|
|
176
|
+
);
|
|
141
177
|
|
|
142
178
|
const tempDoc = parseHTML(
|
|
143
179
|
`<html><body><div id="__tkeron_component_root__">${componentHtml}</div></body></html>`,
|
|
@@ -182,6 +218,7 @@ const processComponents = async (
|
|
|
182
218
|
nextStack,
|
|
183
219
|
depth + 1,
|
|
184
220
|
log,
|
|
221
|
+
cache,
|
|
185
222
|
);
|
|
186
223
|
hasChanges = hasChanges || nestedChanged;
|
|
187
224
|
}
|
|
@@ -197,6 +234,7 @@ const processComponents = async (
|
|
|
197
234
|
componentStack,
|
|
198
235
|
depth,
|
|
199
236
|
log,
|
|
237
|
+
cache,
|
|
200
238
|
);
|
|
201
239
|
hasChanges = hasChanges || childChanged;
|
|
202
240
|
}
|
package/src/processComMd.ts
CHANGED
|
@@ -12,10 +12,50 @@ const ensureHtmlDocument = (html: string): string => {
|
|
|
12
12
|
return `${DOCTYPE}<html><head></head><body>${html}</body></html>`;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
interface ComponentCache {
|
|
16
|
+
componentMap: Map<string, string[]>;
|
|
17
|
+
contentCache: Map<string, string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const buildComponentMap = (rootDir: string): Map<string, string[]> => {
|
|
21
|
+
const allFiles = getFilePaths(rootDir, "**/*.com.md", true);
|
|
22
|
+
const map = new Map<string, string[]>();
|
|
23
|
+
for (const file of allFiles) {
|
|
24
|
+
const basename = file.split("/").pop()!;
|
|
25
|
+
const tagName = basename.replace(/\.com\.md$/, "");
|
|
26
|
+
if (!map.has(tagName)) map.set(tagName, []);
|
|
27
|
+
map.get(tagName)!.push(file);
|
|
28
|
+
}
|
|
29
|
+
return map;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getCachedContent = async (
|
|
33
|
+
path: string,
|
|
34
|
+
cache: Map<string, string>,
|
|
35
|
+
): Promise<string> => {
|
|
36
|
+
const cached = cache.get(path);
|
|
37
|
+
if (cached !== undefined) return cached;
|
|
38
|
+
const content = await Bun.file(path).text();
|
|
39
|
+
cache.set(path, content);
|
|
40
|
+
return content;
|
|
41
|
+
};
|
|
42
|
+
|
|
15
43
|
export interface ProcessComMdOptions {
|
|
16
44
|
logger?: Logger;
|
|
17
45
|
}
|
|
18
46
|
|
|
47
|
+
const resolveComponent = (
|
|
48
|
+
tagName: string,
|
|
49
|
+
currentDir: string,
|
|
50
|
+
componentMap: Map<string, string[]>,
|
|
51
|
+
): string | null => {
|
|
52
|
+
const matches = componentMap.get(tagName);
|
|
53
|
+
if (!matches || matches.length === 0) return null;
|
|
54
|
+
const localPath = join(currentDir, `${tagName}.com.md`);
|
|
55
|
+
if (matches.includes(localPath)) return localPath;
|
|
56
|
+
return matches[0]!;
|
|
57
|
+
};
|
|
58
|
+
|
|
19
59
|
export const processComMd = async (
|
|
20
60
|
tempDir: string,
|
|
21
61
|
options: ProcessComMdOptions = {},
|
|
@@ -27,37 +67,45 @@ export const processComMd = async (
|
|
|
27
67
|
return false;
|
|
28
68
|
}
|
|
29
69
|
|
|
70
|
+
const componentMap = buildComponentMap(tempDir);
|
|
71
|
+
const cache: ComponentCache = {
|
|
72
|
+
componentMap,
|
|
73
|
+
contentCache: new Map(),
|
|
74
|
+
};
|
|
75
|
+
|
|
30
76
|
const htmlFiles = getFilePaths(tempDir, "**/*.html", true).filter(
|
|
31
77
|
(p) => !p.endsWith(".com.html"),
|
|
32
78
|
);
|
|
33
79
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
80
|
+
const results = await Promise.all(
|
|
81
|
+
htmlFiles.map(async (htmlFile) => {
|
|
82
|
+
const htmlContent = await Bun.file(htmlFile).text();
|
|
83
|
+
const document = parseHTML(ensureHtmlDocument(htmlContent));
|
|
84
|
+
|
|
85
|
+
const htmlElement =
|
|
86
|
+
document.querySelector("html") || document.documentElement;
|
|
87
|
+
let changed = false;
|
|
88
|
+
if (htmlElement) {
|
|
89
|
+
changed = await processComponents(
|
|
90
|
+
htmlElement,
|
|
91
|
+
dirname(htmlFile),
|
|
92
|
+
tempDir,
|
|
93
|
+
[],
|
|
94
|
+
0,
|
|
95
|
+
log,
|
|
96
|
+
cache,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
53
99
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
100
|
+
const output =
|
|
101
|
+
DOCTYPE +
|
|
102
|
+
(htmlElement?.outerHTML || document.documentElement?.outerHTML || "");
|
|
103
|
+
await Bun.write(htmlFile, output);
|
|
104
|
+
return changed;
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
59
107
|
|
|
60
|
-
return
|
|
108
|
+
return results.some(Boolean);
|
|
61
109
|
};
|
|
62
110
|
|
|
63
111
|
const processComponents = async (
|
|
@@ -67,6 +115,7 @@ const processComponents = async (
|
|
|
67
115
|
componentStack: string[],
|
|
68
116
|
depth: number = 0,
|
|
69
117
|
log: Logger = silentLogger,
|
|
118
|
+
cache: ComponentCache,
|
|
70
119
|
): Promise<boolean> => {
|
|
71
120
|
let hasChanges = false;
|
|
72
121
|
const MAX_DEPTH = 50;
|
|
@@ -82,9 +131,10 @@ const processComponents = async (
|
|
|
82
131
|
|
|
83
132
|
if (tagName) {
|
|
84
133
|
if (!tagName.includes("-")) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
134
|
+
const matches = cache.componentMap.get(tagName);
|
|
135
|
+
if (matches && matches.length > 0) {
|
|
136
|
+
const localPath = join(currentDir, `${tagName}.com.md`);
|
|
137
|
+
const filePath = matches.includes(localPath) ? localPath : matches[0];
|
|
88
138
|
log.error(
|
|
89
139
|
`\n❌ Error: Component name '${tagName}' must contain at least one hyphen.`,
|
|
90
140
|
);
|
|
@@ -92,30 +142,17 @@ const processComponents = async (
|
|
|
92
142
|
log.error(
|
|
93
143
|
` Rename '${tagName}.com.md' to 'tk-${tagName}.com.md' or similar.`,
|
|
94
144
|
);
|
|
95
|
-
log.error(
|
|
96
|
-
` File: ${(await Bun.file(localPath).exists()) ? localPath : globMatches[0]}\n`,
|
|
97
|
-
);
|
|
145
|
+
log.error(` File: ${filePath}\n`);
|
|
98
146
|
throw new Error(
|
|
99
147
|
`Component name '${tagName}' must contain at least one hyphen`,
|
|
100
148
|
);
|
|
101
149
|
}
|
|
102
150
|
} else {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
componentPath = localPath;
|
|
109
|
-
} else {
|
|
110
|
-
const globMatches = getFilePaths(
|
|
111
|
-
rootDir,
|
|
112
|
-
`**/${tagName}.com.md`,
|
|
113
|
-
true,
|
|
114
|
-
);
|
|
115
|
-
if (globMatches.length > 0) {
|
|
116
|
-
componentPath = globMatches[0];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
151
|
+
const componentPath = resolveComponent(
|
|
152
|
+
tagName,
|
|
153
|
+
currentDir,
|
|
154
|
+
cache.componentMap,
|
|
155
|
+
);
|
|
119
156
|
|
|
120
157
|
if (componentPath) {
|
|
121
158
|
hasChanges = true;
|
|
@@ -131,7 +168,10 @@ const processComponents = async (
|
|
|
131
168
|
throw new Error(`Circular dependency: ${chain}`);
|
|
132
169
|
}
|
|
133
170
|
|
|
134
|
-
const mdContent = await
|
|
171
|
+
const mdContent = await getCachedContent(
|
|
172
|
+
componentPath,
|
|
173
|
+
cache.contentCache,
|
|
174
|
+
);
|
|
135
175
|
const componentHtml = Bun.markdown.html(mdContent);
|
|
136
176
|
|
|
137
177
|
const tempDoc = parseHTML(
|
|
@@ -177,6 +217,7 @@ const processComponents = async (
|
|
|
177
217
|
nextStack,
|
|
178
218
|
depth + 1,
|
|
179
219
|
log,
|
|
220
|
+
cache,
|
|
180
221
|
);
|
|
181
222
|
hasChanges = hasChanges || nestedChanged;
|
|
182
223
|
}
|
|
@@ -192,6 +233,7 @@ const processComponents = async (
|
|
|
192
233
|
componentStack,
|
|
193
234
|
depth,
|
|
194
235
|
log,
|
|
236
|
+
cache,
|
|
195
237
|
);
|
|
196
238
|
hasChanges = hasChanges || childChanged;
|
|
197
239
|
}
|
package/src/processComTs.ts
CHANGED
|
@@ -12,6 +12,47 @@ const ensureHtmlDocument = (html: string): string => {
|
|
|
12
12
|
return `${DOCTYPE}<html><head></head><body>${html}</body></html>`;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
interface ComponentCache {
|
|
16
|
+
componentMap: Map<string, string[]>;
|
|
17
|
+
contentCache: Map<string, string>;
|
|
18
|
+
transpileCache: Map<string, string>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const buildComponentMap = (rootDir: string): Map<string, string[]> => {
|
|
22
|
+
const allFiles = getFilePaths(rootDir, "**/*.com.ts", true);
|
|
23
|
+
const map = new Map<string, string[]>();
|
|
24
|
+
for (const file of allFiles) {
|
|
25
|
+
const basename = file.split("/").pop()!;
|
|
26
|
+
const tagName = basename.replace(/\.com\.ts$/, "");
|
|
27
|
+
if (!map.has(tagName)) map.set(tagName, []);
|
|
28
|
+
map.get(tagName)!.push(file);
|
|
29
|
+
}
|
|
30
|
+
return map;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getCachedContent = async (
|
|
34
|
+
path: string,
|
|
35
|
+
cache: Map<string, string>,
|
|
36
|
+
): Promise<string> => {
|
|
37
|
+
const cached = cache.get(path);
|
|
38
|
+
if (cached !== undefined) return cached;
|
|
39
|
+
const content = await Bun.file(path).text();
|
|
40
|
+
cache.set(path, content);
|
|
41
|
+
return content;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getCachedTranspile = (
|
|
45
|
+
tsCode: string,
|
|
46
|
+
cache: Map<string, string>,
|
|
47
|
+
): string => {
|
|
48
|
+
const cached = cache.get(tsCode);
|
|
49
|
+
if (cached !== undefined) return cached;
|
|
50
|
+
const transpiler = new Bun.Transpiler({ loader: "ts" });
|
|
51
|
+
const jsCode = transpiler.transformSync(tsCode);
|
|
52
|
+
cache.set(tsCode, jsCode);
|
|
53
|
+
return jsCode;
|
|
54
|
+
};
|
|
55
|
+
|
|
15
56
|
export interface ProcessComTsOptions {
|
|
16
57
|
logger?: Logger;
|
|
17
58
|
}
|
|
@@ -27,38 +68,59 @@ export const processComTs = async (
|
|
|
27
68
|
return false;
|
|
28
69
|
}
|
|
29
70
|
|
|
71
|
+
const componentMap = buildComponentMap(tempDir);
|
|
72
|
+
const cache: ComponentCache = {
|
|
73
|
+
componentMap,
|
|
74
|
+
contentCache: new Map(),
|
|
75
|
+
transpileCache: new Map(),
|
|
76
|
+
};
|
|
77
|
+
|
|
30
78
|
const htmlFiles = getFilePaths(tempDir, "**/*.html", true).filter(
|
|
31
79
|
(p) => !p.endsWith(".com.html"),
|
|
32
80
|
);
|
|
33
81
|
|
|
34
|
-
|
|
82
|
+
const results = await Promise.all(
|
|
83
|
+
htmlFiles.map(async (htmlFile) => {
|
|
84
|
+
const htmlContent = await Bun.file(htmlFile).text();
|
|
85
|
+
const document = parseHTML(ensureHtmlDocument(htmlContent));
|
|
86
|
+
|
|
87
|
+
const htmlElement =
|
|
88
|
+
document.querySelector("html") || document.documentElement;
|
|
89
|
+
let changed = false;
|
|
90
|
+
if (htmlElement) {
|
|
91
|
+
changed = await processComponentsTs(
|
|
92
|
+
htmlElement,
|
|
93
|
+
dirname(htmlFile),
|
|
94
|
+
tempDir,
|
|
95
|
+
[],
|
|
96
|
+
0,
|
|
97
|
+
log,
|
|
98
|
+
options,
|
|
99
|
+
cache,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
35
102
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const changed = await processComponentsTs(
|
|
44
|
-
htmlElement,
|
|
45
|
-
dirname(htmlFile),
|
|
46
|
-
tempDir,
|
|
47
|
-
[],
|
|
48
|
-
0,
|
|
49
|
-
log,
|
|
50
|
-
options,
|
|
51
|
-
);
|
|
52
|
-
hasChanges = hasChanges || changed;
|
|
53
|
-
}
|
|
103
|
+
const output =
|
|
104
|
+
DOCTYPE +
|
|
105
|
+
(htmlElement?.outerHTML || document.documentElement?.outerHTML || "");
|
|
106
|
+
await Bun.write(htmlFile, output);
|
|
107
|
+
return changed;
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
54
110
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
(htmlElement?.outerHTML || document.documentElement?.outerHTML || "");
|
|
58
|
-
await Bun.write(htmlFile, output);
|
|
59
|
-
}
|
|
111
|
+
return results.some(Boolean);
|
|
112
|
+
};
|
|
60
113
|
|
|
61
|
-
|
|
114
|
+
const resolveComponent = (
|
|
115
|
+
tagName: string,
|
|
116
|
+
currentDir: string,
|
|
117
|
+
componentMap: Map<string, string[]>,
|
|
118
|
+
): string | null => {
|
|
119
|
+
const matches = componentMap.get(tagName);
|
|
120
|
+
if (!matches || matches.length === 0) return null;
|
|
121
|
+
const localPath = join(currentDir, `${tagName}.com.ts`);
|
|
122
|
+
if (matches.includes(localPath)) return localPath;
|
|
123
|
+
return matches[0]!;
|
|
62
124
|
};
|
|
63
125
|
|
|
64
126
|
const processComponentsTs = async (
|
|
@@ -69,6 +131,7 @@ const processComponentsTs = async (
|
|
|
69
131
|
depth: number = 0,
|
|
70
132
|
log: Logger = silentLogger,
|
|
71
133
|
options: ProcessComTsOptions = {},
|
|
134
|
+
cache: ComponentCache,
|
|
72
135
|
): Promise<boolean> => {
|
|
73
136
|
let hasChanges = false;
|
|
74
137
|
const MAX_DEPTH = 50;
|
|
@@ -84,9 +147,10 @@ const processComponentsTs = async (
|
|
|
84
147
|
|
|
85
148
|
if (tagName) {
|
|
86
149
|
if (!tagName.includes("-")) {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
150
|
+
const matches = cache.componentMap.get(tagName);
|
|
151
|
+
if (matches && matches.length > 0) {
|
|
152
|
+
const localPath = join(currentDir, `${tagName}.com.ts`);
|
|
153
|
+
const filePath = matches.includes(localPath) ? localPath : matches[0];
|
|
90
154
|
log.error(
|
|
91
155
|
`\n❌ Error: Component name '${tagName}' must contain at least one hyphen.`,
|
|
92
156
|
);
|
|
@@ -94,30 +158,17 @@ const processComponentsTs = async (
|
|
|
94
158
|
log.error(
|
|
95
159
|
` Rename '${tagName}.com.ts' to 'tk-${tagName}.com.ts' or similar.`,
|
|
96
160
|
);
|
|
97
|
-
log.error(
|
|
98
|
-
` File: ${(await Bun.file(localPath).exists()) ? localPath : globMatches[0]}\n`,
|
|
99
|
-
);
|
|
161
|
+
log.error(` File: ${filePath}\n`);
|
|
100
162
|
throw new Error(
|
|
101
163
|
`Component name '${tagName}' must contain at least one hyphen`,
|
|
102
164
|
);
|
|
103
165
|
}
|
|
104
166
|
} else {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
componentPath = localPath;
|
|
111
|
-
} else {
|
|
112
|
-
const globMatches = getFilePaths(
|
|
113
|
-
rootDir,
|
|
114
|
-
`**/${tagName}.com.ts`,
|
|
115
|
-
true,
|
|
116
|
-
);
|
|
117
|
-
if (globMatches.length > 0) {
|
|
118
|
-
componentPath = globMatches[0];
|
|
119
|
-
}
|
|
120
|
-
}
|
|
167
|
+
const componentPath = resolveComponent(
|
|
168
|
+
tagName,
|
|
169
|
+
currentDir,
|
|
170
|
+
cache.componentMap,
|
|
171
|
+
);
|
|
121
172
|
|
|
122
173
|
if (componentPath) {
|
|
123
174
|
hasChanges = true;
|
|
@@ -133,7 +184,10 @@ const processComponentsTs = async (
|
|
|
133
184
|
throw new Error(`Circular dependency: ${chain}`);
|
|
134
185
|
}
|
|
135
186
|
|
|
136
|
-
const originalComponentCode = await
|
|
187
|
+
const originalComponentCode = await getCachedContent(
|
|
188
|
+
componentPath,
|
|
189
|
+
cache.contentCache,
|
|
190
|
+
);
|
|
137
191
|
|
|
138
192
|
const elementHTML = (child as any).outerHTML;
|
|
139
193
|
|
|
@@ -187,13 +241,15 @@ ${codeWithoutImports}
|
|
|
187
241
|
await module.component(com);
|
|
188
242
|
} finally {
|
|
189
243
|
try {
|
|
190
|
-
const
|
|
191
|
-
await
|
|
244
|
+
const { unlink } = await import("fs/promises");
|
|
245
|
+
await unlink(tempPath);
|
|
192
246
|
} catch {}
|
|
193
247
|
}
|
|
194
248
|
} else {
|
|
195
|
-
const
|
|
196
|
-
|
|
249
|
+
const jsCode = getCachedTranspile(
|
|
250
|
+
originalComponentCode,
|
|
251
|
+
cache.transpileCache,
|
|
252
|
+
);
|
|
197
253
|
const AsyncFunction = Object.getPrototypeOf(
|
|
198
254
|
async function () {},
|
|
199
255
|
).constructor;
|
|
@@ -232,6 +288,7 @@ ${codeWithoutImports}
|
|
|
232
288
|
depth + 1,
|
|
233
289
|
log,
|
|
234
290
|
options,
|
|
291
|
+
cache,
|
|
235
292
|
);
|
|
236
293
|
|
|
237
294
|
const nodesToInsert = Array.from((div as any).childNodes || []).map(
|
|
@@ -266,6 +323,7 @@ ${codeWithoutImports}
|
|
|
266
323
|
depth,
|
|
267
324
|
log,
|
|
268
325
|
options,
|
|
326
|
+
cache,
|
|
269
327
|
);
|
|
270
328
|
hasChanges = hasChanges || childChanged;
|
|
271
329
|
}
|
package/src/processPre.ts
CHANGED
|
@@ -4,8 +4,14 @@ import type { Logger } from "@tkeron/tools";
|
|
|
4
4
|
import { silentLogger } from "@tkeron/tools";
|
|
5
5
|
|
|
6
6
|
const packageJsonPath = join(import.meta.dir, "..", "package.json");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
let _tkeronVersion: string | null = null;
|
|
9
|
+
const getTkeronVersion = async (): Promise<string> => {
|
|
10
|
+
if (_tkeronVersion) return _tkeronVersion;
|
|
11
|
+
const packageJson = await Bun.file(packageJsonPath).json();
|
|
12
|
+
_tkeronVersion = packageJson.version;
|
|
13
|
+
return _tkeronVersion!;
|
|
14
|
+
};
|
|
9
15
|
|
|
10
16
|
const HTML_PARSER_PATH = import.meta.resolve("@tkeron/html-parser");
|
|
11
17
|
|
|
@@ -40,6 +46,8 @@ export const processPre = async (
|
|
|
40
46
|
|
|
41
47
|
const hasChanges = preFiles.length > 0;
|
|
42
48
|
|
|
49
|
+
const TKERON_VERSION = hasChanges ? await getTkeronVersion() : "";
|
|
50
|
+
|
|
43
51
|
for (const preFile of preFiles) {
|
|
44
52
|
const htmlFile = preFile.replace(/\.pre\.ts$/, ".html");
|
|
45
53
|
|