tkeron 4.0.0-beta.8 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/{readme.md → README.md} +36 -4
  2. package/bun.lock +23 -21
  3. package/changelog.md +292 -8
  4. package/docs/best-practices.md +127 -101
  5. package/docs/cli-reference.md +58 -38
  6. package/docs/components-html.md +30 -24
  7. package/docs/components-typescript.md +110 -79
  8. package/docs/getting-started.md +24 -18
  9. package/docs/mcp-server.md +19 -36
  10. package/docs/overview.md +16 -10
  11. package/docs/pre-rendering.md +163 -157
  12. package/docs/testing.md +331 -0
  13. package/examples/basic_build/src/index.ts +5 -5
  14. package/examples/with_assets/src/index.ts +5 -5
  15. package/examples/with_com_html_priority/src/admin/admin-panel.com.html +1 -1
  16. package/examples/with_com_html_priority/src/admin/dashboard.html +16 -16
  17. package/examples/with_com_html_priority/src/admin/nested-stat.com.html +1 -1
  18. package/examples/with_com_html_priority/src/admin/site-header.com.html +1 -1
  19. package/examples/with_com_html_priority/src/blog/comment-item.com.html +1 -1
  20. package/examples/with_com_html_priority/src/blog/comment-section.com.html +1 -1
  21. package/examples/with_com_html_priority/src/blog/post.html +22 -19
  22. package/examples/with_com_html_priority/src/index.html +15 -15
  23. package/examples/with_com_html_priority/src/info-box.com.html +1 -1
  24. package/examples/with_com_html_priority/src/site-header.com.html +1 -1
  25. package/examples/with_com_mixed_priority/src/dashboard/main.html +17 -17
  26. package/examples/with_com_mixed_priority/src/dashboard/stats-widget.com.ts +1 -1
  27. package/examples/with_com_mixed_priority/src/footer-info.com.html +3 -1
  28. package/examples/with_com_mixed_priority/src/index.html +16 -16
  29. package/examples/with_com_mixed_priority/src/page-header.com.html +8 -1
  30. package/examples/with_com_mixed_priority/src/settings/config.html +16 -16
  31. package/examples/with_com_mixed_priority/src/settings/priority-test.com.html +3 -1
  32. package/examples/with_com_mixed_priority/src/users/profiles/activity-feed.com.ts +7 -3
  33. package/examples/with_com_mixed_priority/src/users/profiles/page-header.com.html +8 -1
  34. package/examples/with_com_mixed_priority/src/users/profiles/profile-actions.com.html +45 -4
  35. package/examples/with_com_mixed_priority/src/users/profiles/user-profile.com.ts +1 -1
  36. package/examples/with_com_mixed_priority/src/users/profiles/view.html +17 -17
  37. package/examples/with_com_ts/src/index.html +15 -11
  38. package/examples/with_com_ts_priority/src/analytics/chart-widget.com.ts +7 -5
  39. package/examples/with_com_ts_priority/src/analytics/report.html +16 -16
  40. package/examples/with_com_ts_priority/src/analytics/user-stats.com.ts +1 -1
  41. package/examples/with_com_ts_priority/src/data-table.com.ts +7 -4
  42. package/examples/with_com_ts_priority/src/index.html +15 -15
  43. package/examples/with_com_ts_priority/src/sales/regional/data-table.com.ts +8 -5
  44. package/examples/with_com_ts_priority/src/sales/regional/overview.html +16 -16
  45. package/examples/with_com_ts_priority/src/sales/regional/sales-summary.com.ts +7 -4
  46. package/examples/with_com_ts_priority/src/user-stats.com.ts +1 -1
  47. package/examples/with_component_iteration/src/card-list.com.ts +40 -12
  48. package/examples/with_component_iteration/src/engagement-meter.com.ts +11 -6
  49. package/examples/with_component_iteration/src/index.html +108 -51
  50. package/examples/with_component_iteration/src/index.ts +1 -1
  51. package/examples/with_component_iteration/src/note-box.com.html +12 -2
  52. package/examples/with_component_iteration/src/status-badge.com.ts +14 -7
  53. package/examples/with_component_iteration/src/user-card.com.ts +10 -9
  54. package/examples/with_pre/src/contact.pre.ts +3 -3
  55. package/examples/with_pre/src/index.ts +5 -5
  56. package/examples/with_pre/src/section/index.pre.ts +2 -4
  57. package/index.ts +31 -40
  58. package/mcp-server.ts +168 -445
  59. package/package.json +19 -8
  60. package/src/banner.ts +5 -4
  61. package/src/build.ts +29 -29
  62. package/src/buildDir.ts +36 -18
  63. package/src/buildEntrypoints.ts +17 -6
  64. package/src/buildWrapper.ts +21 -0
  65. package/src/cleanupOrphanedTempDirs.ts +31 -0
  66. package/src/createTestLogger.ts +24 -0
  67. package/src/develop.ts +47 -46
  68. package/src/getBuildResult.ts +146 -0
  69. package/src/index.ts +7 -0
  70. package/src/init.ts +39 -42
  71. package/src/initWrapper.ts +39 -26
  72. package/src/logger.ts +4 -11
  73. package/src/loggerObj.ts +13 -0
  74. package/src/processCom.ts +137 -110
  75. package/src/processComTs.ts +174 -153
  76. package/src/processPre.ts +24 -27
  77. package/src/promptUser.ts +15 -0
  78. package/src/setupSigintHandler.ts +6 -0
  79. package/src/silentLogger.ts +8 -0
  80. package/tests/test-helpers.ts +30 -0
  81. package/funciones.md +0 -63
@@ -8,9 +8,9 @@ Create a `.pre.ts` file with the same base name as your `.html` file:
8
8
 
9
9
  ```typescript
10
10
  // index.pre.ts
11
- const title = document.querySelector('title');
11
+ const title = document.querySelector("title");
12
12
  if (title) {
13
- title.textContent = 'My Awesome Site';
13
+ title.textContent = "My Awesome Site";
14
14
  }
15
15
  ```
16
16
 
@@ -20,8 +20,10 @@ The corresponding `index.html` is automatically loaded and modified:
20
20
  <!-- index.html - before -->
21
21
  <!DOCTYPE html>
22
22
  <html>
23
- <head><title>Document</title></head>
24
- <body></body>
23
+ <head>
24
+ <title>Document</title>
25
+ </head>
26
+ <body></body>
25
27
  </html>
26
28
  ```
27
29
 
@@ -31,8 +33,10 @@ After build:
31
33
  <!-- index.html - after -->
32
34
  <!DOCTYPE html>
33
35
  <html>
34
- <head><title>My Awesome Site</title></head>
35
- <body></body>
36
+ <head>
37
+ <title>My Awesome Site</title>
38
+ </head>
39
+ <body></body>
36
40
  </html>
37
41
  ```
38
42
 
@@ -42,10 +46,10 @@ After build:
42
46
 
43
47
  Pre-rendering files are paired with HTML files:
44
48
 
45
- | Pre-render File | Processes |
46
- |----------------|-----------|
47
- | `index.pre.ts` | `index.html` |
48
- | `about.pre.ts` | `about.html` |
49
+ | Pre-render File | Processes |
50
+ | ------------------ | ---------------- |
51
+ | `index.pre.ts` | `index.html` |
52
+ | `about.pre.ts` | `about.html` |
49
53
  | `blog/post.pre.ts` | `blog/post.html` |
50
54
 
51
55
  ### The `document` Variable
@@ -54,11 +58,11 @@ Every `.pre.ts` file has access to a special `document` variable:
54
58
 
55
59
  ```typescript
56
60
  // Access the full DOM
57
- document.querySelector('h1')
58
- document.getElementById('content')
59
- document.querySelectorAll('.items')
60
- document.body
61
- document.documentElement
61
+ document.querySelector("h1");
62
+ document.getElementById("content");
63
+ document.querySelectorAll(".items");
64
+ document.body;
65
+ document.documentElement;
62
66
  ```
63
67
 
64
68
  This is the parsed DOM from the corresponding `.html` file.
@@ -82,13 +86,12 @@ If the `.html` file doesn't exist, Tkeron creates a default one:
82
86
  ```html
83
87
  <!DOCTYPE html>
84
88
  <html lang="en">
85
- <head>
86
- <meta charset="UTF-8">
87
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
89
+ <head>
90
+ <meta charset="UTF-8" />
91
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
88
92
  <title>Document</title>
89
- </head>
90
- <body>
91
- </body>
93
+ </head>
94
+ <body></body>
92
95
  </html>
93
96
  ```
94
97
 
@@ -100,9 +103,9 @@ Then your `.pre.ts` file runs on this template.
100
103
 
101
104
  ```typescript
102
105
  // index.pre.ts
103
- const title = document.querySelector('title');
106
+ const title = document.querySelector("title");
104
107
  if (title) {
105
- title.textContent = 'Welcome to My Site';
108
+ title.textContent = "Welcome to My Site";
106
109
  }
107
110
  ```
108
111
 
@@ -110,12 +113,12 @@ if (title) {
110
113
 
111
114
  ```typescript
112
115
  // index.pre.ts
113
- const head = document.querySelector('head');
116
+ const head = document.querySelector("head");
114
117
 
115
118
  if (head) {
116
- const meta = document.createElement('meta');
117
- meta.setAttribute('name', 'description');
118
- meta.setAttribute('content', 'A description of my site');
119
+ const meta = document.createElement("meta");
120
+ meta.setAttribute("name", "description");
121
+ meta.setAttribute("content", "A description of my site");
119
122
  head.appendChild(meta);
120
123
  }
121
124
  ```
@@ -124,11 +127,11 @@ if (head) {
124
127
 
125
128
  ```typescript
126
129
  // index.pre.ts
127
- const body = document.querySelector('body');
130
+ const body = document.querySelector("body");
128
131
 
129
132
  if (body) {
130
- const header = document.createElement('header');
131
- header.innerHTML = '<h1>Welcome!</h1>';
133
+ const header = document.createElement("header");
134
+ header.innerHTML = "<h1>Welcome!</h1>";
132
135
  body.insertBefore(header, body.firstChild);
133
136
  }
134
137
  ```
@@ -137,7 +140,7 @@ if (body) {
137
140
 
138
141
  ```typescript
139
142
  // index.pre.ts
140
- const buildTimeElement = document.getElementById('build-time');
143
+ const buildTimeElement = document.getElementById("build-time");
141
144
 
142
145
  if (buildTimeElement) {
143
146
  const now = new Date();
@@ -172,15 +175,15 @@ interface BlogPost {
172
175
  }
173
176
 
174
177
  const posts: BlogPost[] = [
175
- { title: 'First Post', date: '2025-01-01', excerpt: 'This is my first post' },
176
- { title: 'Second Post', date: '2025-01-15', excerpt: 'Another great post' },
178
+ { title: "First Post", date: "2025-01-01", excerpt: "This is my first post" },
179
+ { title: "Second Post", date: "2025-01-15", excerpt: "Another great post" },
177
180
  ];
178
181
 
179
- const container = document.getElementById('blog-posts');
182
+ const container = document.getElementById("blog-posts");
180
183
 
181
184
  if (container) {
182
- posts.forEach(post => {
183
- const article = document.createElement('article');
185
+ posts.forEach((post) => {
186
+ const article = document.createElement("article");
184
187
  article.innerHTML = `
185
188
  <h2>${post.title}</h2>
186
189
  <time>${post.date}</time>
@@ -195,11 +198,11 @@ if (container) {
195
198
 
196
199
  ```typescript
197
200
  // index.pre.ts
198
- import { getBuildMetadata } from './build-utils';
201
+ import { getBuildMetadata } from "./build-utils";
199
202
 
200
203
  const metadata = await getBuildMetadata();
201
204
 
202
- const footer = document.querySelector('footer');
205
+ const footer = document.querySelector("footer");
203
206
  if (footer) {
204
207
  footer.innerHTML = `
205
208
  <p>Built: ${metadata.timestamp}</p>
@@ -213,7 +216,7 @@ if (footer) {
213
216
  export async function getBuildMetadata() {
214
217
  return {
215
218
  timestamp: new Date().toISOString(),
216
- version: process.env.TKERON_VERSION || 'unknown',
219
+ version: process.env.TKERON_VERSION || "unknown",
217
220
  };
218
221
  }
219
222
  ```
@@ -231,17 +234,17 @@ interface Product {
231
234
  }
232
235
 
233
236
  async function getProducts(): Promise<Product[]> {
234
- const response = await fetch('https://api.example.com/products');
237
+ const response = await fetch("https://api.example.com/products");
235
238
  return response.json();
236
239
  }
237
240
 
238
241
  const products = await getProducts();
239
- const container = document.getElementById('products');
242
+ const container = document.getElementById("products");
240
243
 
241
244
  if (container) {
242
- products.forEach(product => {
243
- const card = document.createElement('div');
244
- card.className = 'product-card';
245
+ products.forEach((product) => {
246
+ const card = document.createElement("div");
247
+ card.className = "product-card";
245
248
  card.innerHTML = `
246
249
  <h3>${product.name}</h3>
247
250
  <p>$${product.price}</p>
@@ -257,15 +260,15 @@ if (container) {
257
260
 
258
261
  ```typescript
259
262
  // blog-post.pre.ts
260
- import { marked } from 'marked';
261
- import { readFileSync } from 'fs';
262
- import { join } from 'path';
263
+ import { marked } from "marked";
264
+ import { readFileSync } from "fs";
265
+ import { join } from "path";
263
266
 
264
- const markdownPath = join(import.meta.dir, 'post-content.md');
265
- const markdown = readFileSync(markdownPath, 'utf-8');
267
+ const markdownPath = join(import.meta.dir, "post-content.md");
268
+ const markdown = readFileSync(markdownPath, "utf-8");
266
269
  const html = marked(markdown);
267
270
 
268
- const article = document.querySelector('article');
271
+ const article = document.querySelector("article");
269
272
  if (article) {
270
273
  article.innerHTML = html;
271
274
  }
@@ -284,9 +287,9 @@ Access environment variables:
284
287
  ```typescript
285
288
  // index.pre.ts
286
289
  const version = process.env.TKERON_VERSION;
287
- const nodeEnv = process.env.NODE_ENV || 'development';
290
+ const nodeEnv = process.env.NODE_ENV || "development";
288
291
 
289
- const versionElement = document.getElementById('version');
292
+ const versionElement = document.getElementById("version");
290
293
  if (versionElement) {
291
294
  versionElement.textContent = `v${version} (${nodeEnv})`;
292
295
  }
@@ -296,7 +299,7 @@ if (versionElement) {
296
299
 
297
300
  ```typescript
298
301
  // index.pre.ts
299
- const buildInfo = document.getElementById('build-info');
302
+ const buildInfo = document.getElementById("build-info");
300
303
 
301
304
  if (buildInfo) {
302
305
  buildInfo.innerHTML = `
@@ -313,11 +316,11 @@ Inject components based on logic:
313
316
 
314
317
  ```typescript
315
318
  // dashboard.pre.ts
316
- const isDevelopment = process.env.NODE_ENV === 'development';
317
- const body = document.querySelector('body');
319
+ const isDevelopment = process.env.NODE_ENV === "development";
320
+ const body = document.querySelector("body");
318
321
 
319
322
  if (body && isDevelopment) {
320
- const debugPanel = document.createElement('debug-panel');
323
+ const debugPanel = document.createElement("debug-panel");
321
324
  body.appendChild(debugPanel);
322
325
  }
323
326
  ```
@@ -340,24 +343,24 @@ interface Post {
340
343
 
341
344
  async function getPosts(): Promise<Post[]> {
342
345
  try {
343
- const response = await fetch('https://api.example.com/posts');
346
+ const response = await fetch("https://api.example.com/posts");
344
347
  return response.json();
345
348
  } catch (error) {
346
- console.warn('Failed to fetch posts, using fallback');
349
+ console.warn("Failed to fetch posts, using fallback");
347
350
  return [];
348
351
  }
349
352
  }
350
353
 
351
354
  const posts = await getPosts();
352
- const blogList = document.getElementById('blog-list');
355
+ const blogList = document.getElementById("blog-list");
353
356
 
354
357
  if (blogList) {
355
358
  if (posts.length === 0) {
356
- blogList.innerHTML = '<p>No posts available</p>';
359
+ blogList.innerHTML = "<p>No posts available</p>";
357
360
  } else {
358
- posts.forEach(post => {
359
- const article = document.createElement('article');
360
- article.className = 'blog-preview';
361
+ posts.forEach((post) => {
362
+ const article = document.createElement("article");
363
+ article.className = "blog-preview";
361
364
  article.innerHTML = `
362
365
  <h2><a href="/blog/${post.slug}">${post.title}</a></h2>
363
366
  <time>${new Date(post.date).toLocaleDateString()}</time>
@@ -381,41 +384,41 @@ interface ProductData {
381
384
  }
382
385
 
383
386
  const productData: ProductData = {
384
- name: 'Amazing Product',
385
- description: 'The best product you can buy',
386
- image: 'https://example.com/product.jpg',
387
+ name: "Amazing Product",
388
+ description: "The best product you can buy",
389
+ image: "https://example.com/product.jpg",
387
390
  price: 99.99,
388
391
  };
389
392
 
390
- const head = document.querySelector('head');
393
+ const head = document.querySelector("head");
391
394
 
392
395
  if (head) {
393
396
  // Title
394
- const title = document.querySelector('title');
397
+ const title = document.querySelector("title");
395
398
  if (title) {
396
399
  title.textContent = `${productData.name} - My Store`;
397
400
  }
398
401
 
399
402
  // Meta description
400
- const metaDesc = document.createElement('meta');
401
- metaDesc.setAttribute('name', 'description');
402
- metaDesc.setAttribute('content', productData.description);
403
+ const metaDesc = document.createElement("meta");
404
+ metaDesc.setAttribute("name", "description");
405
+ metaDesc.setAttribute("content", productData.description);
403
406
  head.appendChild(metaDesc);
404
407
 
405
408
  // Open Graph
406
- const ogTitle = document.createElement('meta');
407
- ogTitle.setAttribute('property', 'og:title');
408
- ogTitle.setAttribute('content', productData.name);
409
+ const ogTitle = document.createElement("meta");
410
+ ogTitle.setAttribute("property", "og:title");
411
+ ogTitle.setAttribute("content", productData.name);
409
412
  head.appendChild(ogTitle);
410
413
 
411
- const ogImage = document.createElement('meta');
412
- ogImage.setAttribute('property', 'og:image');
413
- ogImage.setAttribute('content', productData.image);
414
+ const ogImage = document.createElement("meta");
415
+ ogImage.setAttribute("property", "og:image");
416
+ ogImage.setAttribute("content", productData.image);
414
417
  head.appendChild(ogImage);
415
418
 
416
- const ogPrice = document.createElement('meta');
417
- ogPrice.setAttribute('property', 'og:price:amount');
418
- ogPrice.setAttribute('content', productData.price.toString());
419
+ const ogPrice = document.createElement("meta");
420
+ ogPrice.setAttribute("property", "og:price:amount");
421
+ ogPrice.setAttribute("content", productData.price.toString());
419
422
  head.appendChild(ogPrice);
420
423
  }
421
424
  ```
@@ -425,22 +428,22 @@ if (head) {
425
428
  ```typescript
426
429
  // sitemap.pre.ts
427
430
  const pages = [
428
- { url: '/', priority: 1.0 },
429
- { url: '/about', priority: 0.8 },
430
- { url: '/contact', priority: 0.5 },
431
+ { url: "/", priority: 1.0 },
432
+ { url: "/about", priority: 0.8 },
433
+ { url: "/contact", priority: 0.5 },
431
434
  ];
432
435
 
433
- const urlset = document.createElement('urlset');
434
- urlset.setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
436
+ const urlset = document.createElement("urlset");
437
+ urlset.setAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
435
438
 
436
- pages.forEach(page => {
437
- const url = document.createElement('url');
438
- const loc = document.createElement('loc');
439
+ pages.forEach((page) => {
440
+ const url = document.createElement("url");
441
+ const loc = document.createElement("loc");
439
442
  loc.textContent = `https://example.com${page.url}`;
440
-
441
- const priority = document.createElement('priority');
443
+
444
+ const priority = document.createElement("priority");
442
445
  priority.textContent = page.priority.toString();
443
-
446
+
444
447
  url.appendChild(loc);
445
448
  url.appendChild(priority);
446
449
  urlset.appendChild(url);
@@ -453,13 +456,13 @@ document.documentElement.replaceWith(urlset);
453
456
 
454
457
  ```typescript
455
458
  // documentation.pre.ts
456
- import { readFileSync } from 'fs';
457
- import { join } from 'path';
459
+ import { readFileSync } from "fs";
460
+ import { join } from "path";
458
461
 
459
- const changelogPath = join(import.meta.dir, '..', 'CHANGELOG.md');
460
- const changelog = readFileSync(changelogPath, 'utf-8');
462
+ const changelogPath = join(import.meta.dir, "..", "CHANGELOG.md");
463
+ const changelog = readFileSync(changelogPath, "utf-8");
461
464
 
462
- const changelogElement = document.getElementById('changelog');
465
+ const changelogElement = document.getElementById("changelog");
463
466
  if (changelogElement) {
464
467
  changelogElement.innerHTML = `<pre>${changelog}</pre>`;
465
468
  }
@@ -469,20 +472,21 @@ if (changelogElement) {
469
472
 
470
473
  ```typescript
471
474
  // index.pre.ts
472
- const isProd = process.env.NODE_ENV === 'production';
473
- const body = document.querySelector('body');
475
+ const isProd = process.env.NODE_ENV === "production";
476
+ const body = document.querySelector("body");
474
477
 
475
478
  if (body) {
476
479
  if (isProd) {
477
480
  // Add analytics
478
- const script = document.createElement('script');
479
- script.src = 'https://analytics.example.com/script.js';
481
+ const script = document.createElement("script");
482
+ script.src = "https://analytics.example.com/script.js";
480
483
  body.appendChild(script);
481
484
  } else {
482
485
  // Add development banner
483
- const banner = document.createElement('div');
484
- banner.style.cssText = 'background: #fef2f2; padding: 1rem; text-align: center;';
485
- banner.textContent = '⚠️ Development Mode';
486
+ const banner = document.createElement("div");
487
+ banner.style.cssText =
488
+ "background: #fef2f2; padding: 1rem; text-align: center;";
489
+ banner.textContent = "⚠️ Development Mode";
486
490
  body.insertBefore(banner, body.firstChild);
487
491
  }
488
492
  }
@@ -493,37 +497,37 @@ if (body) {
493
497
  ### Creating Elements
494
498
 
495
499
  ```typescript
496
- const div = document.createElement('div');
497
- div.className = 'container';
498
- div.id = 'main';
499
- div.innerHTML = '<p>Content</p>';
500
+ const div = document.createElement("div");
501
+ div.className = "container";
502
+ div.id = "main";
503
+ div.innerHTML = "<p>Content</p>";
500
504
  ```
501
505
 
502
506
  ### Modifying Attributes
503
507
 
504
508
  ```typescript
505
- const img = document.querySelector('img');
509
+ const img = document.querySelector("img");
506
510
  if (img) {
507
- img.setAttribute('loading', 'lazy');
508
- img.setAttribute('alt', 'Description');
511
+ img.setAttribute("loading", "lazy");
512
+ img.setAttribute("alt", "Description");
509
513
  }
510
514
  ```
511
515
 
512
516
  ### Adding Classes
513
517
 
514
518
  ```typescript
515
- const element = document.getElementById('content');
519
+ const element = document.getElementById("content");
516
520
  if (element) {
517
- element.classList.add('active');
518
- element.classList.remove('hidden');
521
+ element.classList.add("active");
522
+ element.classList.remove("hidden");
519
523
  }
520
524
  ```
521
525
 
522
526
  ### Inserting Content
523
527
 
524
528
  ```typescript
525
- const parent = document.querySelector('.parent');
526
- const child = document.createElement('div');
529
+ const parent = document.querySelector(".parent");
530
+ const child = document.createElement("div");
527
531
 
528
532
  // Append to end
529
533
  parent?.appendChild(child);
@@ -532,19 +536,19 @@ parent?.appendChild(child);
532
536
  parent?.insertBefore(child, parent.firstChild);
533
537
 
534
538
  // Insert before specific element
535
- const ref = document.querySelector('.reference');
539
+ const ref = document.querySelector(".reference");
536
540
  parent?.insertBefore(child, ref);
537
541
  ```
538
542
 
539
543
  ### Removing Elements
540
544
 
541
545
  ```typescript
542
- const element = document.querySelector('.remove-me');
546
+ const element = document.querySelector(".remove-me");
543
547
  element?.remove();
544
548
 
545
549
  // Or via parent
546
- const parent = document.querySelector('.parent');
547
- const child = document.querySelector('.child');
550
+ const parent = document.querySelector(".parent");
551
+ const child = document.querySelector(".child");
548
552
  if (parent && child) {
549
553
  parent.removeChild(child);
550
554
  }
@@ -558,10 +562,10 @@ Pre-rendering runs in Node/Bun, not the browser:
558
562
 
559
563
  ```typescript
560
564
  // ❌ These won't work
561
- window.location
562
- localStorage
563
- sessionStorage
564
- navigator
565
+ window.location;
566
+ localStorage;
567
+ sessionStorage;
568
+ navigator;
565
569
  ```
566
570
 
567
571
  ### ❌ No User Input
@@ -570,7 +574,7 @@ Can't access runtime user data:
570
574
 
571
575
  ```typescript
572
576
  // ❌ No access to form data or user state
573
- const username = document.getElementById('username-input')?.value;
577
+ const username = document.getElementById("username-input")?.value;
574
578
  ```
575
579
 
576
580
  ### ❌ No Event Listeners
@@ -579,8 +583,8 @@ Event listeners are not preserved:
579
583
 
580
584
  ```typescript
581
585
  // ❌ This listener won't exist in the browser
582
- document.querySelector('button')?.addEventListener('click', () => {
583
- console.log('clicked');
586
+ document.querySelector("button")?.addEventListener("click", () => {
587
+ console.log("clicked");
584
588
  });
585
589
  ```
586
590
 
@@ -591,6 +595,7 @@ document.querySelector('button')?.addEventListener('click', () => {
591
595
  ### ✅ Use for Build-Time Data
592
596
 
593
597
  Perfect for:
598
+
594
599
  - Fetching content from CMS/APIs
595
600
  - Generating static content
596
601
  - Injecting build metadata
@@ -603,13 +608,13 @@ Perfect for:
603
608
  // index.pre.ts
604
609
  async function fetchData() {
605
610
  try {
606
- const response = await fetch('https://api.example.com/data');
611
+ const response = await fetch("https://api.example.com/data");
607
612
  if (!response.ok) {
608
613
  throw new Error(`HTTP ${response.status}`);
609
614
  }
610
615
  return response.json();
611
616
  } catch (error) {
612
- console.error('Failed to fetch data:', error);
617
+ console.error("Failed to fetch data:", error);
613
618
  return null;
614
619
  }
615
620
  }
@@ -620,9 +625,9 @@ if (data) {
620
625
  // Use data
621
626
  } else {
622
627
  // Show fallback content
623
- const main = document.querySelector('main');
628
+ const main = document.querySelector("main");
624
629
  if (main) {
625
- main.innerHTML = '<p>Content temporarily unavailable</p>';
630
+ main.innerHTML = "<p>Content temporarily unavailable</p>";
626
631
  }
627
632
  }
628
633
  ```
@@ -631,10 +636,10 @@ if (data) {
631
636
 
632
637
  ```typescript
633
638
  // index.pre.ts
634
- import { renderBlogPosts } from './blog-renderer';
639
+ import { renderBlogPosts } from "./blog-renderer";
635
640
 
636
641
  const posts = await fetchPosts();
637
- const container = document.getElementById('blog');
642
+ const container = document.getElementById("blog");
638
643
 
639
644
  if (container) {
640
645
  renderBlogPosts(container, posts);
@@ -653,9 +658,9 @@ interface Product {
653
658
 
654
659
  function isValidProduct(obj: any): obj is Product {
655
660
  return (
656
- typeof obj.id === 'number' &&
657
- typeof obj.name === 'string' &&
658
- typeof obj.price === 'number' &&
661
+ typeof obj.id === "number" &&
662
+ typeof obj.name === "string" &&
663
+ typeof obj.price === "number" &&
659
664
  obj.price >= 0
660
665
  );
661
666
  }
@@ -667,6 +672,7 @@ const products = rawData.filter(isValidProduct);
667
672
  ### ❌ Don't Overuse
668
673
 
669
674
  If you just need to modify specific elements, consider:
675
+
670
676
  - [HTML components](./components-html.md) for static reusable markup
671
677
  - [TypeScript components](./components-typescript.md) for dynamic elements
672
678
  - Regular TypeScript for browser interactivity
@@ -679,13 +685,13 @@ Pre-rendering is for **document-level** transformations.
679
685
 
680
686
  ```typescript
681
687
  // index.pre.ts
682
- console.log('Pre-rendering index.html');
688
+ console.log("Pre-rendering index.html");
683
689
 
684
- const title = document.querySelector('title');
685
- console.log('Current title:', title?.textContent);
690
+ const title = document.querySelector("title");
691
+ console.log("Current title:", title?.textContent);
686
692
 
687
- title.textContent = 'New Title';
688
- console.log('Updated title:', title.textContent);
693
+ title.textContent = "New Title";
694
+ console.log("Updated title:", title.textContent);
689
695
  ```
690
696
 
691
697
  These logs appear in your terminal during build.
@@ -715,7 +721,7 @@ View the final HTML to confirm your transformations worked.
715
721
  You have access to the `@tkeron/html-parser` package:
716
722
 
717
723
  ```typescript
718
- import { parseHTML } from '@tkeron/html-parser';
724
+ import { parseHTML } from "@tkeron/html-parser";
719
725
 
720
726
  // This is what Tkeron uses internally
721
727
  // You usually don't need it in .pre.ts since 'document' is already parsed
@@ -731,9 +737,9 @@ import { parseHTML } from '@tkeron/html-parser';
731
737
 
732
738
  ```typescript
733
739
  // index.pre.ts
734
- console.log('Tkeron version:', process.env.TKERON_VERSION);
735
- console.log('Node env:', process.env.NODE_ENV);
736
- console.log('Custom var:', process.env.MY_CUSTOM_VAR);
740
+ console.log("Tkeron version:", process.env.TKERON_VERSION);
741
+ console.log("Node env:", process.env.NODE_ENV);
742
+ console.log("Custom var:", process.env.MY_CUSTOM_VAR);
737
743
  ```
738
744
 
739
745
  Run with custom env:
@@ -751,8 +757,8 @@ Generate pages from data:
751
757
  ```typescript
752
758
  // pages.pre.ts
753
759
  const pages = [
754
- { slug: 'about', title: 'About Us', content: '...' },
755
- { slug: 'contact', title: 'Contact', content: '...' },
760
+ { slug: "about", title: "About Us", content: "..." },
761
+ { slug: "contact", title: "Contact", content: "..." },
756
762
  ];
757
763
 
758
764
  // This example shows the concept - in practice, you'd generate
@@ -763,27 +769,27 @@ const pages = [
763
769
 
764
770
  ```typescript
765
771
  // docs.pre.ts
766
- import { readFileSync, readdirSync } from 'fs';
767
- import { join } from 'path';
768
- import { marked } from 'marked';
772
+ import { readFileSync, readdirSync } from "fs";
773
+ import { join } from "path";
774
+ import { marked } from "marked";
769
775
 
770
- const docsDir = join(import.meta.dir, 'docs');
771
- const files = readdirSync(docsDir).filter(f => f.endsWith('.md'));
776
+ const docsDir = join(import.meta.dir, "docs");
777
+ const files = readdirSync(docsDir).filter((f) => f.endsWith(".md"));
772
778
 
773
- const nav = document.getElementById('doc-nav');
774
- const content = document.getElementById('doc-content');
779
+ const nav = document.getElementById("doc-nav");
780
+ const content = document.getElementById("doc-content");
775
781
 
776
782
  if (nav) {
777
- files.forEach(file => {
778
- const li = document.createElement('li');
779
- li.innerHTML = `<a href="#${file}">${file.replace('.md', '')}</a>`;
783
+ files.forEach((file) => {
784
+ const li = document.createElement("li");
785
+ li.innerHTML = `<a href="#${file}">${file.replace(".md", "")}</a>`;
780
786
  nav.appendChild(li);
781
787
  });
782
788
  }
783
789
 
784
790
  if (content) {
785
791
  const firstFile = files[0];
786
- const markdown = readFileSync(join(docsDir, firstFile), 'utf-8');
792
+ const markdown = readFileSync(join(docsDir, firstFile), "utf-8");
787
793
  content.innerHTML = marked(markdown);
788
794
  }
789
795
  ```