A server-rendering pack for wanderland-core engines. It turns a YAML layout plus resolved data into an HTML page: layouts are trees of components, each component is a server-side painter that emits HTML (the grin), and a browser enhances the result on the client (the cat). This is the Ruby realization of the lantern-component-framework design for wanderland-core.
The gem lives at wanderland-lantern-pack and mirrors the structure of
wanderland-aws-pack: a gemspec, an entry file that requires the library, and
boundaries that self-register on load.
In an engine's Gemfile:
gem "wanderland-lantern-pack"
Require it before Wanderland.boot (the wanderland binary's
Bundler.require(:default) does this automatically):
require "wanderland-core"
require "wanderland-lantern-pack"
Loading the pack registers the lantern_html formatter (serves: "text/html")
and the built-in component painters.
A page is { layout, data, title }. The lantern_html formatter receives this
as the principal result and composes it into a full HTML page.
A layout is a tree. A node is either a container or a component:
type: vlayout # or hlayout — stacks its children
children:
- component: header
bind: header # dotted path selecting the data slice this component paints
- component: kv-table
args: { title: metadata } # literal props
bind: meta
- component: link-list
args: { title: "Depends on" }
bind: out
bind selects a slice of data by dotted path (header, meta, node.attrs);
args are literal properties. The renderer passes each painter a props hash:
the literal args plus data (the bound slice).
Domain-agnostic painters. An engine binds its own data into these, or registers its own painters alongside them.
| Component | data shape it paints |
|---|---|
header |
{ kind, title, tags: [..] } — an identity header |
kv-table |
a flat { key: value } hash — a metadata table (args.title) |
link-list |
[{ label, href, note }] — a list of links (args.title) |
markdown |
a markdown string — rendered body (args.title) |
raw |
an HTML string — passthrough |
A component is a painter registered by name. props["data"] is the bound slice;
the rest are literal layout args.
Wanderland::Lantern.register("badge") do |props|
d = props["data"] || {}
%(<span class="badge #{Wanderland::Lantern.h(d["status"])}">#{Wanderland::Lantern.h(d["label"])}</span>)
end
Wanderland::Lantern.h is the shared HTML-escape helper. All meaning belongs in
the painted HTML — a web component's enhance() grants liveness, never content.
Wanderland::Lantern::Page.frame(title, body, data) wraps a composed body in the
HTML shell with the stylesheet and a data carrier: a
<script type="application/json"> holding the resolved data. A machine reads a
complete, addressable, JavaScript-free page; a browser enhances from the same
carrier. The body never depends on JavaScript to mean something.
boundary :lantern_html, serves: "text/html"
It renders a { layout, data, title } principal into a page, and falls back to a
framed JSON dump for any other shape. Because formatter registration is keyed by
MIME and last-write-wins, an engine that loads this pack serves text/html
through lantern_html. Boot loads core boundaries (including the core
html_formatter) after gems are required, so an engine pins the formatter from a
boundary_path file — which loads after core during boot — with
Wanderland::Formatters.register("text/html", :lantern_html).
lib/wanderland-lantern-pack.rb entry — requires the library + formatter
lib/wanderland/lantern.rb component registry + h() escape
lib/wanderland/lantern/renderer.rb compose(layout, data) → HTML; render_page
lib/wanderland/lantern/components.rb built-in painters
lib/wanderland/lantern/page.rb Page.frame — shell, CSS, data carrier
lib/wanderland/lantern/boundaries/lantern_html.rb the text/html formatter
Dark Lantern renders graph nodes through the pack. Its graph_page boundary
pulls a node and its edges from the dependency graph, shapes them for header /
kv-table / link-list, loads the page layout from
resources/layouts/node.yml, and returns { layout, data, title }. The route
GET /node/*path serves a node page; each edge renders as a link to the other
node's page, so the graph is walkable by clicking. See dark-lantern.
Implemented: the render model, the five built-in components, the page frame and
data carrier, and the text/html formatter. The lantern-component-framework
design names a wider vocabulary — modeline projections (row / card / bar /
panel), record-list, filter-bar, oculus-button, and a layout-resource page
chain (yaml_loader → data_fetch → variable_resolve → layout_compose → frame_assemble). Those land as the component set grows. Markdown rendering with
fence execution arrives by mixing in the loom pack.