neo.mjs 10.2.1 → 10.3.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 (79) hide show
  1. package/.github/CONCEPT.md +2 -4
  2. package/.github/GETTING_STARTED.md +72 -51
  3. package/.github/RELEASE_NOTES/v10.3.0.md +54 -0
  4. package/.github/epic-string-based-templates.md +690 -0
  5. package/ServiceWorker.mjs +2 -2
  6. package/apps/covid/view/MainContainer.mjs +1 -1
  7. package/apps/covid/view/country/Table.mjs +1 -1
  8. package/apps/portal/index.html +1 -1
  9. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  10. package/apps/portal/view/learn/ContentComponent.mjs +1 -1
  11. package/apps/realworld/api/Base.mjs +2 -2
  12. package/apps/sharedcovid/view/MainContainer.mjs +1 -1
  13. package/apps/sharedcovid/view/MainContainerController.mjs +1 -1
  14. package/buildScripts/buildESModules.mjs +23 -75
  15. package/buildScripts/bundleParse5.mjs +27 -0
  16. package/buildScripts/util/astTemplateProcessor.mjs +210 -0
  17. package/buildScripts/util/templateBuildProcessor.mjs +331 -0
  18. package/buildScripts/util/vdomToString.mjs +46 -0
  19. package/buildScripts/webpack/development/webpack.config.appworker.mjs +11 -0
  20. package/buildScripts/webpack/loader/template-loader.mjs +21 -0
  21. package/buildScripts/webpack/production/webpack.config.appworker.mjs +11 -0
  22. package/examples/README.md +1 -1
  23. package/examples/component/wrapper/googleMaps/MarkerDialog.mjs +2 -2
  24. package/examples/form/field/email/MainContainer.mjs +0 -1
  25. package/examples/form/field/number/MainContainer.mjs +0 -1
  26. package/examples/form/field/picker/MainContainer.mjs +0 -1
  27. package/examples/form/field/time/MainContainer.mjs +0 -1
  28. package/examples/form/field/trigger/copyToClipboard/MainContainer.mjs +0 -1
  29. package/examples/form/field/url/MainContainer.mjs +0 -1
  30. package/examples/functional/nestedTemplateComponent/Component.mjs +100 -0
  31. package/examples/functional/nestedTemplateComponent/MainContainer.mjs +48 -0
  32. package/examples/functional/nestedTemplateComponent/app.mjs +6 -0
  33. package/examples/functional/nestedTemplateComponent/index.html +11 -0
  34. package/examples/functional/nestedTemplateComponent/neo-config.json +6 -0
  35. package/examples/functional/templateComponent/Component.mjs +61 -0
  36. package/examples/functional/templateComponent/MainContainer.mjs +48 -0
  37. package/examples/functional/templateComponent/app.mjs +6 -0
  38. package/examples/functional/templateComponent/index.html +11 -0
  39. package/examples/functional/templateComponent/neo-config.json +6 -0
  40. package/learn/gettingstarted/Setup.md +29 -12
  41. package/learn/guides/fundamentals/ApplicationBootstrap.md +2 -2
  42. package/learn/guides/fundamentals/InstanceLifecycle.md +5 -5
  43. package/learn/guides/uibuildingblocks/HtmlTemplates.md +191 -0
  44. package/learn/guides/uibuildingblocks/HtmlTemplatesUnderTheHood.md +156 -0
  45. package/learn/guides/uibuildingblocks/WorkingWithVDom.md +1 -1
  46. package/learn/tree.json +2 -0
  47. package/package.json +62 -56
  48. package/src/DefaultConfig.mjs +3 -3
  49. package/src/calendar/view/calendars/List.mjs +1 -1
  50. package/src/calendar/view/month/Component.mjs +1 -1
  51. package/src/calendar/view/week/Component.mjs +1 -1
  52. package/src/component/Abstract.mjs +1 -1
  53. package/src/component/Base.mjs +33 -27
  54. package/src/container/Base.mjs +5 -5
  55. package/src/controller/Application.mjs +5 -5
  56. package/src/dialog/Base.mjs +6 -6
  57. package/src/draggable/DragProxyComponent.mjs +4 -4
  58. package/src/form/field/ComboBox.mjs +1 -1
  59. package/src/functional/_export.mjs +2 -1
  60. package/src/functional/component/Base.mjs +142 -93
  61. package/src/functional/util/HtmlTemplateProcessor.mjs +243 -0
  62. package/src/functional/util/html.mjs +24 -67
  63. package/src/list/Base.mjs +2 -2
  64. package/src/manager/Toast.mjs +1 -1
  65. package/src/menu/List.mjs +1 -1
  66. package/src/mixin/VdomLifecycle.mjs +87 -90
  67. package/src/tab/Container.mjs +2 -2
  68. package/src/tooltip/Base.mjs +1 -1
  69. package/src/tree/Accordion.mjs +2 -2
  70. package/src/worker/App.mjs +7 -7
  71. package/test/components/files/component/Base.mjs +1 -1
  72. package/test/siesta/siesta.js +2 -0
  73. package/test/siesta/tests/classic/Button.mjs +5 -5
  74. package/test/siesta/tests/functional/Button.mjs +6 -6
  75. package/test/siesta/tests/functional/HtmlTemplateComponent.mjs +193 -33
  76. package/test/siesta/tests/functional/Parse5Processor.mjs +82 -0
  77. package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +5 -5
  78. package/.github/epic-functional-components.md +0 -498
  79. package/.github/ticket-asymmetric-vdom-updates.md +0 -122
@@ -0,0 +1,690 @@
1
+ # Epic: String-Based VDOM Templates
2
+
3
+ This epic covers the exploration and implementation of a new feature allowing developers to use string-based template literals (HTML-like syntax) to define the VDOM for all components (functional and class-based). This will provide a more familiar and intuitive way to structure component views compared to the current JSON-based VDOM approach.
4
+
5
+ An early proof-of-concept (PoC) already exists in the following files:
6
+ - `test/siesta/tests/functional/HtmlTemplateComponent.mjs`
7
+ - `src/functional/component/Base.mjs` (see `enableHtmlTemplates_` config)
8
+ - `src/functional/util/html.mjs`
9
+
10
+ ## Sub-Tasks
11
+
12
+ ### 1. Dev Mode: Main Thread Addon for Live Parsing
13
+
14
+ **Status:** Dropped
15
+
16
+ **Reason:** This approach was superseded by the in-worker parsing strategy (Sub-Task 4). The main thread addon would require an inefficient and slow worker roundtrip for parsing, while the in-worker approach is synchronous and significantly more performant for the zero-builds development mode. The addon and its related tests have been deleted to simplify the codebase.
17
+
18
+ ### 2. Production Mode: Build-Time Parsing with `parse5`
19
+
20
+ **Description:**
21
+ For production builds, parsing HTML strings in the main thread is inefficient. Instead, we will pre-process the source code, identify the templates, and replace them with their JSON VDOM representation directly in the build output.
22
+
23
+ **Implementation Details:**
24
+ - **Tool:** `parse5` (minified size: ~176KB). This is a robust and spec-compliant HTML parser.
25
+ - **Method:**
26
+ 1. During the build process, use a regular expression to identify the tagged template literals (e.g., `html`...``).
27
+ 2. For each match, use `parse5` to parse the string content into an abstract syntax tree (AST).
28
+ 3. Convert the `parse5` AST into the final Neo.mjs VDOM JSON format.
29
+ 4. Replace the original template literal in the source code with the generated JSON object.
30
+
31
+ ### 3. Bundle `parse5` for Browser Compatibility
32
+
33
+ **Status: Done**
34
+
35
+ **Description:**
36
+ To adhere to the framework's "zero builds" development principle, the `parse5` library cannot be imported directly from `node_modules` at runtime. A build step is required to convert it into a browser-compatible ES module. This bundled file will be checked into the `dist` directory and imported by the `HtmlTemplateProcessor`.
37
+
38
+ **Implementation Details:**
39
+ - **Tool:** `esbuild`
40
+ - **Source:** `node_modules/parse5/dist/index.js`
41
+ - **Output:** `dist/parse5.mjs`
42
+ - **Script:** Create a new build script `buildScripts/bundleParse5.mjs` and an associated npm script `bundle-parse5` to perform the bundling and minification.
43
+ - **Outcome:** The `HtmlTemplateProcessor` will be updated to import `../../../dist/parse5.mjs`.
44
+
45
+ ### 4. Alternative Dev Mode: In-Worker Parsing with `parse5`
46
+
47
+ **Status: Done**
48
+
49
+ **Description:**
50
+ As an alternative to the main thread addon, we will evaluate using `parse5` directly within the App worker for dev mode. This approach avoids the complexities and potential race conditions of an asynchronous worker roundtrip for parsing. While it introduces a ~176KB dependency to the dev build, this cost may be acceptable for the significant gain in architectural simplicity and rendering predictability.
51
+
52
+ **Implementation Details:**
53
+ - **Tool:** `parse5` (via the bundled `dist/parse5.mjs`)
54
+ - **Method:**
55
+ 1. Create a new `HtmlTemplateProcessor` utility inside the app worker (`src/functional/util/HtmlTemplateProcessor.mjs`).
56
+ 2. This processor will be lazy-loaded when a component first uses an HTML template.
57
+ 3. The processor will use the bundled `parse5` to synchronously convert the template string into a Neo.mjs VDOM JSON structure.
58
+ 4. The component's lifecycle (`continueUpdateWithVdom` for functional, a new hook for class-based) will then proceed synchronously with the parsed VDOM.
59
+ 5. The existing main thread addon (`Neo.main.addon.HtmlStringToVdom`) and its tests will be kept for comparison and potential future use cases.
60
+
61
+ ### 5. Template Syntax Specification
62
+
63
+ **Status: To Do**
64
+
65
+ **Description:**
66
+ Define a clear and comprehensive specification for the template syntax. This document will serve as the blueprint for the parser implementation and as the primary reference for developers using this feature.
67
+
68
+ **Implementation Details:**
69
+ - Create a new markdown file: `learn/guides/uibuildingblocks/HtmlTemplates.md`.
70
+ - **Conventions:**
71
+ - **Component vs. HTML:** Define the convention for distinguishing neo.mjs components from standard HTML tags (e.g., PascalCase for components: `<MyComponent>`, lowercase for HTML: `<div>`).
72
+ - **Attribute Mapping:** Specify how template attributes map to VDOM config properties (e.g., `class` to `cls`, `style` to `style`).
73
+ - **Data Types:**
74
+ - **Primitives:** How string, number, and boolean attributes are handled.
75
+ - **Objects & Arrays:** The syntax for passing object literals and arrays directly as attributes (e.g., `style="${{color: 'red'}}"`, `items="${['a', 'b']}"`).
76
+ - **Functions:** How to pass non-DOM-event handlers and other function references (e.g., `renderer="${this.myRenderer}"`).
77
+ - **Directives:**
78
+ - **Conditionals:** A mechanism for conditional rendering (e.g., an `n-if` attribute: `<div n-if="${isVisble}">...</div>`).
79
+ - **Loops:** A mechanism for rendering lists from arrays (e.g., an `n-for` attribute: `<li n-for="${item} of ${items}">${item.name}</li>`).
80
+ - **Complex Configs:** Document the recommended approach for handling deeply nested JSON configs, advocating for passing them as interpolated objects to maintain template clarity (e.g., `columns="${gridColumns}"`).
81
+ - **DOM Events (Out of Scope):** Explicitly state that inline DOM event handlers (e.g., `onClick="..."`) are not supported. The framework's global, delegated event system (`domListeners` config or `useEvent()` hook) remains the sole, recommended approach for handling DOM events. This maintains performance and architectural consistency.
82
+
83
+ ### 6. Parser: Interpolation and Data Type Handling
84
+
85
+ **Status: Done**
86
+
87
+ **Description:**
88
+ Enhance the `parse5` processor to correctly handle the mapping of interpolated values from the tagged template literal to their corresponding VDOM properties, respecting their original data types.
89
+
90
+ **Implementation Details:**
91
+ - The parser must receive not only the HTML string but also the array of interpolated values from the template literal.
92
+ - When an attribute value is a placeholder for an interpolated value (e.g., `renderer="$[0]"`, where `$[0]` maps to the first expression), the parser must assign the raw expression value (the function object) to the VDOM config, not the placeholder string.
93
+ - Implement logic to correctly handle and assign functions, objects, arrays, and other non-string data types to the appropriate VDOM properties.
94
+
95
+ ### 7. Parser: Component vs. HTML Tag Recognition
96
+
97
+ **Status: Done**
98
+
99
+ **Description:**
100
+ Implement the logic within the `parse5` processor to differentiate between standard HTML tags and neo.mjs component tags based on the convention defined in the Syntax Specification.
101
+
102
+ **Implementation Details:**
103
+ - When traversing the `parse5` AST, check the tag name of each element.
104
+ - If the tag name follows the component convention (e.g., starts with a capital letter), generate a VDOM object with a `module` or `className` property pointing to the corresponding component class.
105
+ - If it's a standard HTML tag, generate a standard VDOM object with a `tag` property.
106
+ - A mechanism will be needed to resolve the string name (e.g., "GridContainer") to the actual class constructor (`GridContainer`) at runtime. This may involve a component registry or passing a scope object to the template processor.
107
+
108
+ ### 8. Component Resolution Strategy
109
+
110
+ **Status: Done**
111
+
112
+ **Description:**
113
+ Define the official strategy for how component tags in templates are resolved to their corresponding class constructors. This is critical for developer experience and code clarity. The strategy prioritizes explicit imports while allowing a fallback to the global namespace, all while maintaining synchronous parsing.
114
+
115
+ **Resolution Order:**
116
+ 1. **Lexical Scope via Interpolation (Primary):** The recommended method is to pass the imported component constructor directly as the tag name using template interpolation: `<${Button} />`. The processor will identify the interpolated value and use the constructor directly.
117
+ 2. **Global Namespace Fallback:** If the tag is a literal string (e.g., `<Neo.button.Base>`), the processor will attempt to resolve it using `Neo.ns()`. If a valid class constructor is found in the global namespace, it will be used.
118
+ 3. **Error:** If a tag that appears to be a component (PascalCase) cannot be resolved through either of the above methods, the processor will throw an error.
119
+
120
+ ### 9. Enhance Learning Content
121
+
122
+ **Status: To Do**
123
+
124
+ **Description:**
125
+ Create a comprehensive guide to explain the purpose and trade-offs of using HTML templates. The current syntax-only file is insufficient for developers to make an informed decision. This new content should clearly position templates as an alternative to the core JSON VDOM, aimed at developers familiar with string-based syntaxes.
126
+
127
+ **Implementation Details:**
128
+ - **Location:** Enhance the existing file: `learn/guides/uibuildingblocks/HtmlTemplates.md`.
129
+ - **Key Points to Cover:**
130
+ - **The "Why":** Explain that this feature is an alternative, not a replacement, for JSON VDOM, designed to lower the barrier to entry for developers from other framework backgrounds.
131
+ - **The Trade-Offs:** Clearly state that using this feature in development mode requires loading the `parse5` library (~176KB), which has a performance cost compared to the zero-dependency JSON VDOM approach.
132
+ - **Positioning:** Frame it as a "beginner-friendly" or "transitional" option that helps developers get started quickly, while encouraging them to explore the power and performance of the native JSON VDOM as they become more familiar with the framework.
133
+ - **Best Practices:** Provide clear examples of when to use templates and when JSON VDOM might be a better choice (e.g., for highly dynamic or programmatically generated views).
134
+
135
+ ### 10. Expand Test Coverage with Real Components
136
+
137
+ **Status: To Do**
138
+
139
+ **Description:**
140
+ While the mock component tests are a good start, we need to ensure the template processor works correctly in real-world scenarios with actual functional components and their lifecycle. This involves creating more complex integration tests.
141
+
142
+ **Implementation Details:**
143
+ - **Location:** Create new test files or enhance `test/siesta/tests/functional/HtmlTemplateComponent.mjs`.
144
+ - **Scenarios to Test:**
145
+ - Components with nested children defined in the template.
146
+ - Components that use reactive configs passed in via attributes.
147
+ - Templates that include a mix of standard HTML tags and multiple, different neo.mjs components.
148
+ - Edge cases with complex interpolation in attributes and text nodes.
149
+ - Ensure the entire component lifecycle (mount, update, destroy) works as expected when the VDOM is generated from a template.
150
+
151
+ ### 11. Code Quality Refinement
152
+
153
+ **Status: Done**
154
+
155
+ **Description:**
156
+ After the feature is functionally complete and well-tested, refactor the new modules (`HtmlTemplateProcessor`, etc.) to meet the high code quality standards of the neo.mjs framework. This includes adding comprehensive JSDoc comments, ensuring adherence to coding guidelines, and optimizing for clarity and performance.
157
+
158
+ ### 12. Create a Real-World Example
159
+
160
+ **Status: Done**
161
+
162
+ **Description:**
163
+ To showcase the new feature and provide a practical learning resource, create a new, simple example application that is built using a functional component with a string-based template. This will serve as a clear, working demonstration for developers.
164
+
165
+ ### 13. Fix Conditional Rendering and Add Tests
166
+
167
+ **Status: Done**
168
+
169
+ **Description:**
170
+ Ensured that falsy values (e.g., `false`, `null`, `undefined`) in template interpolations do not render any output, which is the correct and expected behavior for conditional rendering. Added a new test case to `test/siesta/tests/functional/HtmlTemplateComponent.mjs` to verify this functionality by toggling a conditional element and asserting its presence and absence in the VDOM.
171
+
172
+ ### 14. Refactor `render` to `initVnode` and `createTemplateVdom` to `render`
173
+
174
+ **Status: Done**
175
+
176
+ **Description:**
177
+ To improve the developer experience for those familiar with React, a major refactoring was undertaken. The framework's core `render()` method was renamed to `initVnode()` to more accurately reflect its purpose of creating the initial VNode and mounting the component. This freed up the `render` name, allowing `createTemplateVdom()` to be renamed to `render()`, providing a more intuitive and familiar API for functional components using HTML templates. This change also included renaming the `rendered` property to `vnodeInitialized`, the `autoRender` config to `autoInitVnode`, and the `rendering` flag to `isVnodeInitializing` to maintain semantic consistency throughout the framework.
178
+
179
+ ### 15. Create a Robust VDOM-to-String Serializer
180
+
181
+ **Status: To Do**
182
+
183
+ **Description:**
184
+ The `JSON.stringify` + regex method for generating the VDOM string during the build process is flawed. It incorrectly handles object keys that are not valid JavaScript identifiers (e.g., `data-foo`) and produces non-idiomatic code (quoted keys). A dedicated serializer is required for correctness and code quality.
185
+
186
+ **Implementation Details:**
187
+ - **Tool:** A new, custom utility module.
188
+ - **Location:** `buildScripts/util/vdomToString.mjs`.
189
+ - **Method:**
190
+ 1. The utility will export a `vdomToString(vdom)` function that recursively traverses the VDOM object.
191
+ 2. It will check if each object key is a valid JavaScript identifier.
192
+ 3. Valid identifiers will be written to the output string without quotes (e.g., `tag:`).
193
+ 4. Invalid identifiers (e.g., `data-foo`) will be correctly wrapped in single quotes (e.g., `'data-foo':`).
194
+ 5. It will handle the build-time placeholders for runtime expressions, outputting them as raw, unquoted code.
195
+ 6. This new utility will completely replace the `JSON.stringify` and subsequent regex calls in the build scripts.
196
+
197
+ ### 16. Refactor Build-Time Parser to be AST-Based for Robustness
198
+
199
+ **Status: To Do**
200
+
201
+ **Description:**
202
+ The current build-time approach, which uses regular expressions to find and replace templates, has proven to be brittle and incorrect. It cannot handle nested `html` templates and can be easily fooled by JSDoc comments or strings that happen to contain the `html`` sequence, leading to build failures. To ensure correctness and consistency with the runtime environment, the build process must be refactored to use a proper JavaScript parser.
203
+
204
+ **Implementation Details:**
205
+ - **Tools:** `acorn` (to parse JS into an Abstract Syntax Tree) and `astring` (to generate JS code from the AST).
206
+ - **Method:**
207
+ 1. In the build script, for each `.mjs` file, use `acorn` to parse the entire file content into an AST.
208
+ 2. Traverse the AST, specifically looking for `TaggedTemplateExpression` nodes where the `tag` is an `Identifier` with the name `html`.
209
+ 3. Process these template nodes recursively (post-order traversal) to correctly handle nested templates from the inside out.
210
+ 4. The logic from `HtmlTemplateProcessorLogic` will be used to convert the template into its VDOM object representation.
211
+ 5. The original `TaggedTemplateExpression` node in the AST will be replaced with a new AST node representing the generated VDOM object (using an object-to-AST converter).
212
+ 6. Finally, use `astring` to generate the final, correct JavaScript code from the modified AST.
213
+ 7. This new, robust process will replace the fragile regex-based `replace` loop.
214
+
215
+ ---
216
+
217
+ ## 17. Sub-Ticket: Build-Time `html` Template to VDOM Conversion
218
+
219
+ **Status:** Done
220
+
221
+ ### 1. Summary
222
+
223
+ Implement a build-time process to convert `html` tagged template literals into JSON-based VDOM structures. This is a critical optimization that removes the need for a client-side HTML parser, leading to smaller bundle sizes and faster initial render times.
224
+
225
+ ### 2. Rationale
226
+
227
+ Pre-processing templates at build time is a best practice in modern web development. It shifts the parsing overhead from the user's browser to the developer's machine, resulting in a better user experience. This also opens the door for more advanced static analysis and optimizations in the future. By converting templates to standard JSON VDOM, we align this new syntax with the core rendering engine of Neo.mjs, ensuring consistency and maintainability.
228
+
229
+ ### 3. Scope & Implementation Plan
230
+
231
+ 1. **Isolate Processor Logic:** Refactor the template parsing logic out of the client-side `HtmlTemplateProcessor` and into a dedicated build script utility (`buildScripts/util/templateBuildProcessor.mjs`).
232
+ 2. **AST-Based Parsing:** Use `acorn` to parse JavaScript files into an Abstract Syntax Tree (AST), providing a robust way to find templates.
233
+ 3. **Find & Process Templates:** Traverse the AST to locate all `TaggedTemplateExpression` nodes tagged with the `html` identifier.
234
+ 4. **Convert to VDOM:** For each found template, use the `templateBuildProcessor` to convert it into a JSON VDOM object. This process correctly handles nested templates and embedded JavaScript expressions.
235
+ 5. **Rename `render` to `createVdom`:** While traversing the AST, if an `html` template is found within a method or object property named `render`, rename that method/property to `createVdom`.
236
+ 6. **Replace in AST:** Replace the original `TaggedTemplateExpression` node in the AST with the newly generated VDOM object (represented as an AST `ObjectExpression`).
237
+ 7. **Generate Final Code:** Use `astring` to generate the final, modified JavaScript code from the updated AST.
238
+ 8. **Integrate into Build:** Incorporate this AST-based transformation into the `buildSingleFile.mjs` and `buildESModules.mjs` scripts.
239
+
240
+ ### 4. Definition of Done
241
+
242
+ - The build process correctly identifies and converts `html` templates to VDOM objects.
243
+ - The `render` method/property is automatically renamed to `createVdom` when it contains an `html` template.
244
+ - The final minified output contains JSON VDOM, not template literals.
245
+ - The client-side `HtmlTemplateProcessor` is no longer required for production builds using this feature.
246
+ - The logic is cleanly separated, with no build-time code included in client-side bundles.
247
+ ---
248
+
249
+ ## 18. Sub-Ticket: Finalize and Integrate AST-based Build Process
250
+
251
+ **Status:** Done
252
+
253
+ ### 1. Summary
254
+
255
+ This ticket covers the final integration of the robust, AST-based template processing into the main `build-es-modules` script, and the subsequent cleanup of temporary development scripts.
256
+
257
+ ### 2. Rationale
258
+
259
+ After proving the AST-based approach in a dedicated script (`buildSingleFile.mjs`), it was necessary to merge this superior logic into the primary build script (`buildESModules.mjs`) that processes the entire project. This ensures that all files benefit from the robust template conversion. Consolidating the logic also simplifies the build toolchain.
260
+
261
+ ### 3. Scope & Implementation Plan
262
+
263
+ 1. **Integrate Logic:** The `minifyFile` function from `buildSingleFile.mjs`, containing the full AST parsing, transformation, and code generation logic, was moved into `buildESModules.mjs`, replacing the older, less robust implementation.
264
+ 2. **Cleanup:** The temporary `buildSingleFile.mjs` script was deleted from the repository.
265
+ 3. **Rename Script:** For improved clarity and consistency, the `build-es-modules` npm script in `package.json` was renamed to `build-dist-esm`.
266
+
267
+ ### 4. Definition of Done
268
+
269
+ - The `buildESModules.mjs` script now uses the AST-based approach for all files.
270
+ - The temporary `buildSingleFile.mjs` script has been removed.
271
+ - The corresponding npm script has been renamed to `build-dist-esm`.
272
+ - The full build process runs successfully, correctly transforming all `html` templates across the project.
273
+
274
+ ## 19. Sub-Ticket: Showcase Nested Templates and Component Usage
275
+
276
+ **Status:** Done
277
+
278
+ ### 1. Summary
279
+
280
+ Created a new example application to demonstrate the capabilities of string-based templates, specifically focusing on nested templates and the inclusion of other Neo.mjs components directly within the template.
281
+
282
+ ### 2. Rationale
283
+
284
+ A practical example is crucial for developers to understand how to leverage the new HTML template feature effectively. This example highlights advanced usage patterns like template nesting and component composition, which are common in real-world applications. It also serves as a confirmation that the build process (specifically `buildScripts/buildESModules.mjs`) correctly handles these complex scenarios, converting them into optimized JSON VDOM.
285
+
286
+ ### 3. Scope & Implementation Plan
287
+
288
+ 1. **Create Example Component:** Develop a new functional component at `examples/functional/nestedTemplateComponent/Component.mjs`.
289
+ 2. **Implement Nested Templates:** Within the example component, define and use a separate `html` template literal that is then conditionally included within the main component's `html` template.
290
+ 3. **Integrate Another Component:** Demonstrate how to include another Neo.mjs component (e.g., `Neo.button.Base`) directly within the `html` template using template interpolation (`<${Button} />`).
291
+ 4. **Verify Build Process:** Confirm that the `buildScripts/buildESModules.mjs` script correctly processes this example, converting the nested templates and embedded components into the appropriate JSON VDOM structure during the build.
292
+
293
+ ### 4. Definition of Done
294
+
295
+ - A new example component `examples/functional/nestedTemplateComponent/Component.mjs` exists.
296
+ - The example successfully demonstrates nested `html` templates.
297
+ - The example successfully demonstrates the inclusion of another Neo.mjs component within an `html` template.
298
+ - The build process correctly converts this complex template structure into optimized JSON VDOM, as verified by inspecting the `dist/esm` output.
299
+
300
+ ### 20. Introduce `attributeNameMap` for Robust Attribute Handling
301
+
302
+ **Status:** Done
303
+
304
+ ### 1. Summary
305
+
306
+ Refactored `src/functional/util/HtmlTemplateProcessor.mjs` to use an `attributeNameMap` instead of a flat array for storing original attribute names. This change ensures correct mapping of dynamic values to their corresponding attributes, especially in complex scenarios involving nested templates and conditional rendering.
307
+
308
+ ### 2. Rationale
309
+
310
+ Previously, the `HtmlTemplateProcessor` relied on a simple array (`attributeNames`) to track the original, case-sensitive names of attributes associated with dynamic values. This approach was prone to index shifting issues when falsy values were skipped or when nested templates were flattened, leading to incorrect attribute assignments (e.g., `handler` being mapped to `style`). By introducing an `attributeNameMap` that directly associates the dynamic value's index with its attribute name, we eliminate these synchronization problems, making the attribute parsing robust and reliable.
311
+
312
+ ### 3. Scope & Implementation Plan
313
+
314
+ 1. **Modify `flattenTemplate`:** Change its return type to include an `attributeNameMap` (an object) instead of an `attributeNames` array.
315
+ 2. **Populate `attributeNameMap`:** Store `dynamicValueIndex: attributeName` pairs in the map within `flattenTemplate`, ensuring the `attrMatch` is recorded at the precise index where its corresponding dynamic value is pushed to `flatValues`.
316
+ 3. **Handle Nested Templates:** When flattening nested templates, adjust the keys of the nested `attributeNameMap` before merging them into the parent's map to maintain unique and correct indices across the entire flattened structure.
317
+ 4. **Update `convertNodeToVdom`:** Modify this method to retrieve the correct attribute name from the `attributeNameMap` using the dynamic value's index, rather than relying on a sequential `attrNameIndex`.
318
+ 5. **Update JSDoc:** Ensure all relevant JSDoc comments reflect the change from `attributeNames` to `attributeNameMap`.
319
+
320
+ ### 4. Definition of Done
321
+
322
+ - `src/functional/util/HtmlTemplateProcessor.mjs` uses `attributeNameMap` for attribute name tracking.
323
+ - The `style` vs `handler` bug (and similar attribute mapping issues) is resolved.
324
+ - The attribute mapping logic is robust against nested templates and conditional rendering.
325
+ - All related JSDoc comments are updated to reflect the new `attributeNameMap` parameter.
326
+ ---
327
+
328
+ ### 21. Fix Self-Closing Custom Component Tags
329
+
330
+ **Status:** Done
331
+
332
+ #### 1. Summary
333
+
334
+ Implemented a lightweight fix in `HtmlTemplateProcessor.mjs` to correctly handle self-closing custom component tags (e.g., `<MyComponent />` or `<${Button} />`).
335
+
336
+ #### 2. Rationale
337
+
338
+ The `parse5` library, while robust for HTML, does not correctly parse self-closing tags for custom elements that are not standard HTML void elements. This would lead to incorrect VDOM structures. The initial thought was to use a full JS parser like `acorn` to identify these, but that would add a significant overhead (~120KB) to the zero-builds development environment. The chosen solution is much more efficient.
339
+
340
+ #### 3. Scope & Implementation Plan
341
+
342
+ 1. **Identify the Issue:** Confirmed that `parse5` fails to create a proper AST for templates containing self-closing custom component tags.
343
+ 2. **Implement Regex Pre-processing:**
344
+ - A new regular expression (`selfClosingComponentRegex`) was added to `HtmlTemplateProcessor.mjs`.
345
+ - This regex specifically finds component tags (identified by starting with a capital letter or being a `neotag` placeholder) that are self-closed (`/>`).
346
+ - Before passing the template string to `parse5`, a `replace()` call uses this regex to convert the self-closing tag into a standard tag with an explicit closing tag (e.g., `<MyComponent />` becomes `<MyComponent></MyComponent>`).
347
+ 3. **Ensure Specificity:** The regex is carefully crafted to *not* affect standard HTML void elements (like `<br>`, `<img>`), ensuring correct HTML parsing is preserved.
348
+ 4. **Cleanup:** Removed unused imports for `acorn` and `astring` from `HtmlTemplateProcessor.mjs` as they were no longer needed.
349
+
350
+ #### 4. Definition of Done
351
+
352
+ - `HtmlTemplateProcessor.mjs` now correctly parses templates containing self-closing custom components.
353
+ - The fix is implemented with a minimal performance footprint, avoiding large new dependencies in the development build.
354
+ - Standard HTML void elements are unaffected and continue to parse correctly.
355
+ - Unnecessary `acorn` and `astring` imports have been removed from the processor.
356
+
357
+ ---
358
+
359
+ ### 22. Fix Build-Time Conditional Template Rendering
360
+
361
+ **Status:** Done
362
+
363
+ #### 1. Summary
364
+
365
+ Corrected a subtle bug in the build-time parser (`buildScripts/util/templateBuildProcessor.mjs`) that caused it to incorrectly handle conditionally rendered nested templates.
366
+
367
+ #### 2. Rationale
368
+
369
+ The build-time parser was wrapping raw JavaScript expressions (like `showDetails && detailsTemplate`) inside a VDOM text node (`{vtype: 'text', text: '...'}`). This prevented the expression from being correctly evaluated at runtime, leading to incorrect output. The client-side parser handled this correctly because it evaluates the expression *before* parsing. The build-time parser needed to be adjusted to produce an equivalent VDOM structure.
370
+
371
+ #### 3. Scope & Implementation Plan
372
+
373
+ 1. **Identify the Bug:** Pinpointed the difference in logic between the client-side and build-time `convertNodeToVdom` functions. The build-time version was too aggressive in wrapping dynamic placeholders in text nodes.
374
+ 2. **Modify `convertNodeToVdom`:**
375
+ - The logic in `buildScripts/util/templateBuildProcessor.mjs` was changed.
376
+ - When the parser encounters a text node that consists *only* of a single dynamic value placeholder (e.g., `${showDetails && detailsTemplate}`), it now returns the raw placeholder value itself (e.g., `##__NEO_EXPR__showDetails && detailsTemplate##__NEO_EXPR__##`).
377
+ - This ensures the raw expression is inserted directly into the `cn` (children) array of the VDOM, allowing it to be properly evaluated at runtime.
378
+ 3. **Align with Client-Side Behavior:** This change brings the build-time parser's output in line with the correct behavior of the client-side parser, ensuring consistency between development and production environments.
379
+
380
+ #### 4. Definition of Done
381
+
382
+ - The build-time parser now correctly handles conditionally rendered nested `html` templates.
383
+ - Expressions that resolve to a template or a falsy value are correctly represented in the final VDOM.
384
+ - The build output for components using this pattern is now functionally correct and matches the client-side rendering logic.
385
+
386
+ ### 23. Finalize Build-Time AST Transformation
387
+
388
+ **Status:** Done
389
+
390
+ #### 1. Summary
391
+
392
+ This ticket addresses the final, robust implementation of the build-time HTML-to-VDOM conversion. Previous attempts using regex and incomplete AST patching have proven to be brittle. This task will implement a full, proper AST transformation pipeline to ensure correctness and handle all edge cases, including nested templates, complex expressions, and conditional rendering.
393
+
394
+ #### 2. Rationale
395
+
396
+ The core problem is that the build process must reliably convert an `html` tagged template literal into a standard JavaScript object (the VDOM) within the source code itself. The process must correctly handle interpolated expressions, converting them into valid AST nodes that can be integrated back into the main file's AST. The previous failures were due to improper string manipulation and parsing, leading to syntax errors. A full AST-based approach is the only way to guarantee a syntactically correct and robust transformation.
397
+
398
+ #### 3. Scope & Implementation Plan
399
+
400
+ This task will replace the existing template processing logic in `buildScripts/buildESModules.mjs` with the following, more robust pipeline:
401
+
402
+ 1. **Parse to AST:** For each input file, use `acorn` to parse the entire source code into a complete Abstract Syntax Tree (AST). Add parent pointers to each node during a walk for easier tree manipulation.
403
+
404
+ 2. **Post-Order Traversal:** Traverse the AST in post-order (children first). This is critical for correctly handling nested `html` templates, as it ensures the innermost templates are processed and replaced before their parents.
405
+
406
+ 3. **Identify `html` Templates:** During the traversal, identify all `TaggedTemplateExpression` nodes whose tag is an `Identifier` with the name `html`.
407
+
408
+ 4. **Process Template to JSON VDOM:** For each identified template node:
409
+ * Extract the raw strings and the source code of the interpolated expressions.
410
+ * Use the existing `buildScripts/util/templateBuildProcessor.mjs` to convert this into a serializable JSON VDOM object. This utility is already effective at this specific step, creating placeholders like `##__NEO_EXPR__...##` for dynamic parts.
411
+
412
+ 5. **Convert JSON VDOM to AST Node:** This is the most critical step. Create a new, robust `jsonToAst` function inside `buildScripts/buildESModules.mjs` that recursively converts the JSON VDOM object from the previous step into a valid `acorn` AST `ObjectExpression` node. This function will:
413
+ * Correctly handle primitives (string, number, boolean) by creating `Literal` nodes.
414
+ * Correctly handle arrays by creating `ArrayExpression` nodes.
415
+ * When it encounters a string that is a placeholder (e.g., `##__NEO_EXPR__(...)##__NEO_EXPR__##`), it will extract the inner expression string, parse *only that expression* with `acorn.parse()`, and insert the resulting `Expression` node directly into the AST. This avoids all previous syntax errors.
416
+ * When it encounters a component placeholder (`{__neo_component_name__: 'MyComponent'}`), it will create an `Identifier` node.
417
+
418
+ 6. **Replace Node in Main AST:** Replace the original `TaggedTemplateExpression` node in the main AST with the newly generated `ObjectExpression` node from the previous step.
419
+
420
+ 7. **Rename `render` method:** As part of the same traversal, if a processed `html` template was inside a method definition or object property named `render`, rename that key to `createVdom`.
421
+
422
+ 8. **Generate Final Code:** After the traversal and all replacements are complete, use `astring` to generate the final, correct, and human-readable JavaScript code from the modified AST.
423
+
424
+ 9. **Minify:** Pass the generated code to `Terser` for final minification.
425
+
426
+ #### 4. Definition of Done
427
+
428
+ - The build process no longer produces any parsing or syntax errors related to template conversion.
429
+ - The `buildESModules.mjs` script is updated to use the full AST transformation pipeline described above.
430
+ - The final `dist/esm` output for components with `html` templates is syntactically correct and functionally equivalent to the client-side parsed version.
431
+ - All previous edge cases (conditional rendering, mixed static/dynamic text, self-closing tags) are handled correctly.
432
+
433
+ UPDATE on 23:
434
+
435
+ // Helper to create a context for vm
436
+ function createVmContext(scope) {
437
+ const context = vm.createContext(scope);
438
+ return context;
439
+ }
440
+
441
+ // Helper to evaluate code in a given context
442
+ function evaluateInContext(code, context) {
443
+ try {
444
+ return vm.runInContext(code, context);
445
+ } catch (e) {
446
+ console.error('Error evaluating code in VM:', e);
447
+ return null;
448
+ }
449
+ }
450
+
451
+ This is a great starting point. The existing buildESModules.mjs already has a full AST pipeline: it uses acorn to parse, walks the
452
+ tree, finds html templates, and has a jsonToAst function to convert the processed VDOM back into an AST node.
453
+
454
+ However, the core processing logic in buildScripts/util/templateBuildProcessor.mjs is flawed for build-time execution. It uses
455
+ vm.runInContext to evaluate the template expressions. This is fundamentally incorrect for the build script because it cannot (and
456
+ should not) know the runtime values of variables like showDetails or isActive. This approach will fail for any component with
457
+ state-dependent logic.
458
+
459
+ The goal is to preserve the expressions, not evaluate them.
460
+
461
+ Here is the new plan, which refines sub-task #23 with the knowledge of the existing code:
462
+
463
+ 1. Remove `vm` from `templateBuildProcessor.mjs`: The entire vm.runInContext logic is wrong for this use case and must be removed. The
464
+ processor should work with the raw expression strings directly.
465
+
466
+ 2. Refactor `processHtmlTemplateLiteral`:
467
+ * It will accept strings and expressionCodeStrings as it does now.
468
+ * Instead of evaluating expressionCodeStrings, it will wrap them in the ##__NEO_EXPR__...## placeholder format.
469
+ * It will then call a new version of flattenTemplate that works with these placeholders.
470
+
471
+ 3. Refactor `flattenTemplate`:
472
+ * This function needs to correctly handle nested templates. When it encounters a value that is another template (which will already
473
+ be a VDOM object at build time, thanks to post-order traversal), it needs to embed that object directly.
474
+ * For conditional expressions like showDetails && detailsTemplate, it must preserve the entire expression as a single placeholder:
475
+ ##__NEO_EXPR__showDetails && detailsTemplate##__NEO_EXPR__##.
476
+
477
+ 4. Refactor `convertNodeToVdom` (in the build processor):
478
+ * This is the most critical part. When it encounters a text node in the parse5 AST that is a placeholder for an expression (e.g.,
479
+ the result of ${showDetails && detailsTemplate}), it must not wrap it in a VDOM text node. Instead, it should return the raw
480
+ placeholder string itself (##__NEO_EXPR__...##). This raw placeholder will then be placed directly into the cn array of its
481
+ parent VDOM node.
482
+
483
+ 5. Enhance `jsonToAst` (in `buildESModules.mjs`):
484
+ * The existing function is a good starting point. It already handles the ##__NEO_EXPR__...## placeholder by parsing the inner
485
+ content with acorn. This is correct.
486
+ * It needs to be robust enough to handle all valid JavaScript expressions that might appear inside a template.
487
+
488
+ 6. Fix Post-Order Traversal in `buildESModules.mjs`:
489
+ * The current implementation walks the tree and collects all nodes, then processes them. This is not a true post-order traversal. A
490
+ proper recursive, post-order traversal is needed to ensure nested templates are processed before their parents.
491
+
492
+ I will now begin implementing these changes. I'll start by modifying buildScripts/buildESModules.mjs to implement a correct post-order
493
+ traversal and then refactor the processor logic.
494
+
495
+ ---
496
+
497
+ ### 24. Create a Reusable, AST-Based Build-Time Processor
498
+
499
+ **Status:** Done
500
+
501
+ #### 1. Summary
502
+
503
+ Refactor the entire build-time template transformation pipeline out of `buildScripts/buildESModules.mjs` and into a new, self-contained, reusable utility module.
504
+
505
+ #### 2. Rationale
506
+
507
+ Currently, the logic for finding and transforming `html` templates is tightly coupled to the `buildESModules.mjs` script. To support template transformation in other build environments (like the Webpack-based `dist/dev` and `dist/production`), this logic must be extracted. Creating a single, reusable processor ensures consistency, reduces code duplication, and makes the build system more modular and maintainable.
508
+
509
+ #### 3. Scope & Implementation Plan
510
+
511
+ 1. **Create New Utility:** Create a new file at `buildScripts/util/astTemplateProcessor.mjs`.
512
+ 2. **Move Core Logic:**
513
+ * Move the `jsonToAst` function from `buildESModules.mjs` into the new utility.
514
+ * Create and export a primary function, e.g., `processFileContent(fileContent)`.
515
+ * This function will encapsulate the entire transformation pipeline:
516
+ * Parsing the input string with `acorn`.
517
+ * Performing the post-order traversal to find `html` templates.
518
+ * Calling `processHtmlTemplateLiteral()` from `templateBuildProcessor.mjs` to get the VDOM object.
519
+ * Using the moved `jsonToAst` to convert the VDOM object back into an AST node.
520
+ * Replacing the original template node in the main AST.
521
+ * Generating the final, transformed code string with `astring`.
522
+ 3. **Refactor `buildESModules.mjs`:**
523
+ * Remove the moved logic (`jsonToAst`, the traversal, etc.).
524
+ * Import the new `processFileContent` function from `astTemplateProcessor.mjs`.
525
+ * In the `minifyFile` function, call `processFileContent()` to transform the file's content before passing it to Terser.
526
+
527
+ #### 4. Definition of Done
528
+
529
+ - The new `buildScripts/util/astTemplateProcessor.mjs` module exists and contains the full transformation logic.
530
+ - `buildESModules.mjs` is simplified and correctly uses the new reusable utility.
531
+ - Running `npm run build-dist-esm` produces the exact same correct output as it does now, confirming the refactoring was successful.
532
+
533
+ ---
534
+
535
+ ### 25. Optimize Build Process with a Pre-emptive Regex Check
536
+
537
+ **Status:** Done
538
+
539
+ #### 1. Summary
540
+
541
+ Before running the full, expensive AST parsing pipeline on a file, perform a quick regular expression check to see if the file likely contains an `html` template.
542
+
543
+ #### 2. Rationale
544
+
545
+ The current process parses every single `.mjs` file with `acorn`, which is computationally expensive. The vast majority of files in the project do not use `html` templates. By adding a quick pre-check, we can skip the entire AST transformation process for most files, significantly speeding up the overall build time.
546
+
547
+ #### 3. Scope & Implementation Plan
548
+
549
+ 1. **Define Regex:** Create a simple, fast regex (e.g., `/html\s*`/`) to detect the presence of a tagged template literal.
550
+ 2. **Implement Check:** In `buildESModules.mjs`, inside the `minifyFile` function, add a conditional check:
551
+ * `if (regex.test(content)) { ... }`
552
+ 3. **Conditional Processing:** Only if the regex test passes, call the `processFileContent()` function from the new `astTemplateProcessor`. If it fails, the content can be passed directly to the next step (Terser minification).
553
+
554
+ #### 4. Definition of Done
555
+
556
+ - The regex check is implemented in `buildESModules.mjs`.
557
+ - Files that do not contain `html` templates are no longer processed by the `astTemplateProcessor`.
558
+ - Files that *do* contain `html` templates are still transformed correctly.
559
+ - The overall build time is measurably reduced.
560
+
561
+ ---
562
+
563
+ ### 26. Integrate Template Processing into `dist/development` Build
564
+
565
+ **Status:** Done
566
+
567
+ #### 1. Summary
568
+
569
+ Use the new reusable `astTemplateProcessor` to enable build-time `html` template transformation for the `dist/development` Webpack environment.
570
+
571
+ #### 2. Rationale
572
+
573
+ To ensure feature parity and a consistent developer experience, `html` templates must be correctly processed in the `dist/development` environment. This allows developers who use this environment (e.g., for TypeScript or specific debugging scenarios) to use the template syntax.
574
+
575
+ #### 3. Scope & Implementation Plan
576
+
577
+ 1. **Create Webpack Loader:** Create a custom Webpack loader (e.g., `buildScripts/webpack/loader/template-loader.mjs`).
578
+ 2. **Implement Loader Logic:**
579
+ * The loader will receive the file content.
580
+ * It will perform the same pre-emptive regex check from sub-task #25.
581
+ * If the check passes, it will import and call the `processFileContent()` function from `astTemplateProcessor.mjs`.
582
+ * It will return the transformed code (or the original code if the check fails) to the Webpack compilation chain.
583
+ 3. **Configure Webpack:** Update the Webpack configuration for `dist/development` to use this new loader for all `.mjs` files.
584
+
585
+ #### 4. Definition of Done
586
+
587
+ - The custom Webpack loader is created and functional.
588
+ - The `dist/development` build process correctly transforms `html` templates into VDOM objects.
589
+ - Applications running in `dist/development` mode render components using `html` templates correctly.
590
+
591
+ ---
592
+
593
+ ### 27. Integrate Template Processing into `dist/production` Build
594
+
595
+ **Status:** Done
596
+
597
+ #### 1. Summary
598
+
599
+ Use the new reusable `astTemplateProcessor` to enable build-time `html` template transformation for the `dist/production` Webpack environment.
600
+
601
+ #### 2. Rationale
602
+
603
+ This is the final step to ensure `html` templates are a fully supported, production-ready feature. The transformation must be applied to the `dist/production` build to gain the performance benefits of pre-compilation in the most optimized deployment environment.
604
+
605
+ #### 3. Scope & Implementation Plan
606
+
607
+ 1. **Reuse Webpack Loader:** The same custom Webpack loader created for sub-task #26 can be used.
608
+ 2. **Configure Webpack:** Update the Webpack configuration for `dist/production` to apply the `template-loader.mjs` to all `.mjs` files before they are passed to other loaders like Babel or Terser.
609
+
610
+ #### 4. Definition of Done
611
+
612
+ - The `dist/production` build process correctly transforms `html` templates into VDOM objects.
613
+ - The final, minified production bundles contain optimized VDOM, not raw `html` template strings.
614
+ - Applications running in `dist/production` mode render components using `html` templates correctly.
615
+
616
+ ---
617
+
618
+ ### 28. Add Error Resilience to AST Processor
619
+
620
+ **Status:** Done
621
+
622
+ #### 1. Summary
623
+
624
+ Wrap the core AST processing logic within `astTemplateProcessor.mjs` in a `try...catch` block to prevent a single file's parsing error from crashing the entire build process.
625
+
626
+ #### 2. Rationale
627
+
628
+ The AST transformation is complex. If an edge case or a bug in the processor causes an error while parsing a specific file, the current implementation would throw an exception and halt the entire build. By adding error handling, we can isolate the failure. The processor will log the error for later inspection but return the original, untransformed content for the problematic file, allowing the build to complete successfully for all other files.
629
+
630
+ #### 3. Scope & Implementation Plan
631
+
632
+ 1. **Modify `processFileContent`:** In `buildScripts/util/astTemplateProcessor.mjs`, wrap the entire block of code following the initial regex check in a `try...catch (e)` block.
633
+ 2. **Implement Error Handling:**
634
+ * Inside the `catch` block, log a detailed error message to the console, including the error `e` and ideally the path of the file being processed (though we might need to pass the file path into the function for that).
635
+ * Crucially, the `catch` block should return the original, unmodified `fileContent`, ensuring the build can continue.
636
+ 3. **Update Return Value:** Ensure the function signature and return value (`{ content: fileContent, hasChanges: false }`) are consistent in the `catch` path.
637
+
638
+ #### 4. Definition of Done
639
+
640
+ - The `try...catch` block is implemented in `processFileContent`.
641
+ - A parsing error in one file logs a console error but does not stop the build.
642
+ - The file that caused the error is passed through the build untransformed.
643
+
644
+ ---
645
+ ### 29. Create "Under the Hood: HTML Templates" Guide
646
+
647
+ Status: To Do
648
+
649
+ #### 1. Summary
650
+
651
+ Create a new, in-depth guide that explains the technical implementation of the HTML template feature across all of Neo.mjs's environments. This will
652
+ serve as a companion to the existing "Using HTML Templates" guide.
653
+
654
+ #### 2. Rationale
655
+
656
+ While the existing guide explains how to use templates, it's important to document how they work to highlight the framework's architectural strengths.
657
+ This new guide will explain the different processing mechanisms for the zero-builds dev mode versus the production builds, clarifying the performance
658
+ trade-offs and showcasing the power of the build-time AST transformation.
659
+
660
+ #### 3. Scope & Implementation Plan
661
+
662
+ 1. Create New File: Create a new markdown file at learn/guides/uibuildingblocks/HtmlTemplatesUnderTheHood.md.
663
+ 2. Write Content: The guide will be structured as follows:
664
+ * Introduction: Briefly state the guide's purpose – to explain the mechanics behind the html template feature. Link back to the "Using" guide for
665
+ syntax and best practices.
666
+ * The Core Challenge: Explain the fundamental problem: converting a standard JavaScript tagged template literal into a Neo.mjs VDOM object.
667
+ * Mechanism 1: Zero-Builds Development Mode (Live Parsing):
668
+ * Explain that in dev mode, the parse5 library is loaded directly into the App worker.
669
+ * Describe the process: the html tag function triggers the HtmlTemplateProcessor, which uses parse5 to create an AST from the template string
670
+ at runtime.
671
+ * Clearly state the trade-off: the convenience of live parsing comes at the cost of loading the ~176KB parse5 library.
672
+ * Mechanism 2: Production Builds (`dist/esm`, `dist/dev`, `dist/prod`):
673
+ * Explain that for all production builds, the parse5 dependency is completely eliminated from the client-side code.
674
+ * Describe the build-time AST transformation process:
675
+ * The build script (astTemplateProcessor.mjs) finds all html templates.
676
+ * It uses acorn to parse the file into a JavaScript AST.
677
+ * It converts the template into a VDOM object and then into an AST ObjectExpression.
678
+ * The original template is replaced with the VDOM object in the source code itself before minification.
679
+ * Emphasize the benefit: The browser receives pre-compiled, highly optimized VDOM, resulting in zero runtime parsing overhead and maximum
680
+ performance.
681
+ * Conclusion: Summarize the two approaches, reinforcing that Neo.mjs provides both instant feedback for development and maximum performance for
682
+ production.
683
+ 3. Update `tree.json`: Add a new entry to learn/tree.json to make the new guide discoverable in the documentation navigation. It should be placed
684
+ directly after the existing "HTML Templates" entry.
685
+
686
+ #### 4. Definition of Done
687
+
688
+ - The new guide learn/guides/uibuildingblocks/HtmlTemplatesUnderTheHood.md is created with the specified content.
689
+ - The learn/tree.json file is updated to include a link to the new guide.
690
+ - The documentation now clearly separates the "how-to" from the "how-it-works" for the HTML templates feature.