Template Parser & Component Loader
lua_spa.loader.ComponentLoader
Reads .lspa files from disk, extracts their sections, and builds the component registry.
Parsing a .lspa file
@import syntax
@import Alias from "./relative/path/To.lspa"
- Must be at the start of a line
- Path is relative to the current component file
- The alias becomes the tag name used in
<template>
Imports are resolved recursively: loading App triggers loading Hero, Nav, etc., populating the full registry before any rendering begins.
<python> block extraction
Regex: <python>(.*?)</python> (case-insensitive, dotall)
The extracted source is:
- Passed to
build_client_script()for JS generation - Stored as
ComponentDefinition.python_blockfor server-sidecontext()calls
<style src="..."> inlining
This happens at load time, so the rendered HTML always contains inline <style> blocks — no external CSS requests.
ComponentLoader API
__init__(components_dir: Path)
load_entry(entry_component: str) → Mapping[str, ComponentDefinition]
Loads the entry component and all its transitive imports. Returns the full registry.
Raises:
FileNotFoundErrorif any.lspafile is missingValueErrorif a<script>tag is found (use<python>instead)
components → Mapping[str, ComponentDefinition]
Read-only view of the loaded registry.
<script> tag restriction
.lspa files must not contain <script> tags. This is enforced at load time:
ValueError: Component 'MyComp' uses <script>; use a <python> block with client() instead
The reason: JavaScript is generated from Python. Mixing hand-written <script> tags would break the hydration contract.