-
Notifications
You must be signed in to change notification settings - Fork 0
Compiler flow
Sad Gabi edited this page Jul 23, 2026
·
4 revisions
index.js — the public API. Exports app.build(rootDir, srcDir) which delegates to compiler/index.js.
loadConfig(rootDir) reads chocola.config.json (via utils.js) and merges with defaults:
| Key | Default | Description |
|---|---|---|
srcDir |
"src" |
Source directory |
outDir |
"dist" |
Output directory |
libDir |
"lib" |
Components directory (inside srcDir) |
emptyOutDir |
true |
Whether to clean output before build |
resolvePaths() resolves absolute paths for outDir, src, and components.
- Clears output directory if
emptyOutDiris enabled - Loads the source index file (
index.htmlor.chocofromsrcDir) - Discovers and loads all components from
src/lib/
getComponents(libDir):
- Reads all
.jsfiles in the components directory - Only processes files starting with an uppercase letter (e.g.,
Button.js) - Imports each module (inlining
.html/.cssimports vialoadWithAssets) - Calls the default export function to get the component instance
- Stores
__sourceFileon each instance for error reporting - Returns a
Map<lowercase-filename, instance>
- Creates a JSDOM instance from the index file
- Validates an
<app>root element exists - Extracts all child elements inside
<app>for component processing - Extracts
<link>elements (stylesheets, icons) for asset processing
For each element inside <app>:
- Match — checks if tag name corresponds to a loaded component
-
Context — extracts attributes as context (
ctx.*) -
Chain validation — validates
if/elif/else/del-ifstructure on both slot content and component body separately before slot replacement, throwing withfile:lineon violation - Template — renders component body via JSDOM fragment
-
Slots — replaces
<slot>elements with the original inner HTML -
Attribute interpolation — evaluates
{expr}in attributes usingwith(ctx) -
Conditionals — evaluates
if,del-if,elif,elseattributes-
if={expr}— hides element (display: none) when falsy -
del-if={expr}— removes element when falsy -
elif={expr}— alternative condition in a chain -
else— fallback in a chain - Chained via
condChainstate tracked per-parent in aMap -
elsecloses the chain; non-conditional elements reset it -
elif/elsewithout a precedingif/del-ifthrows an error
-
-
Void elements —
<void>is a transparent conditional wrapper:-
<void if={expr}>— renders children unwrapped when truthy -
<void elif={expr}>— chain-aware alternative -
<void else>— chain-aware fallback -
<void>— always renders children unwrapped (fragment-like)
-
-
Runtime ID — if the component has
scriptoreffects, assigns a uniquechidattribute -
CSS Scoping — if the component has
styles, generates a scoped CSS class and rewrites selectors:- Simple selectors (
.foo) generate both AND-scoped (.cssId.foo) and descendant-scoped (.cssId .foo) variants - Selectors with combinators use descendant scoping only
-
:rootand:root.classscope to the root element only
- Simple selectors (
-
Runtime Chunk — generates a runtime function call:
aRUNTIME(el, ctx) -
Recursion — processes nested components within the current component (with cycle detection via
renderChain)
Wraps all runtime chunks in DOMContentLoaded and writes to run-<random>.js.
-
Stylesheets — copies local CSS files to output with random filenames, updates
<link>hrefs - Icons — copies icon files to output
-
Scoped CSS — writes component-scoped CSS to
sc-<random>.css, appends<link>to document head -
Resources — scans output HTML and CSS for local file references (
src,href,url()), copies them to output preserving directory structure
- Appends runtime
<script>tag to document body - Serializes and beautifies the final HTML
- Writes
index.htmlto output directory - Writes generated CSS and JS files alongside it
index.js
└─ compiler/index.js
├─ config.js → loadConfig + resolvePaths
├─ pipeline.js → getComponents, getSrcIndex, processStylesheet, processIcons, copyResources
├─ dom-processor.js → createDOM, validateAppContainer, getAppElements, serializeDOM, writeHTMLOutput, appendRuntimeScript
├─ component-processor.js → validateChainStructure, processAllComponents, processComponentElement, scopeCss
└─ runtime-generator.js → generateRuntimeScript
-
Components: ES modules with default export returning
{ body, script, styles, effects } -
Asset inlining:
.html/.cssimports in components are inlined at build time vialoadWithAssets - CSS Scoping: Component styles are scoped by rewriting selectors under a unique CSS class ID. Both root and descendant matching via dual selectors (AND + descendant).
- Runtime scripts: Components with dynamic behavior get a unique ID and a runtime call that re-attaches event listeners/effects on page load
-
Conditional chains:
if/del-if/elif/elseform sibling chains tracked per-parent; validated structurally before rendering withfile:lineerror reporting -
Void elements:
<void>acts as a transparent wrapper that never renders itself; useful for conditional rendering without extra DOM nodes