9. Addressable bodies and projection
Attach renderable content to your own typed data records and render it elsewhere with project — the wskill mechanism.
After this lesson you can
- Declare a custom @block type with a @child("body") content slot - Gather instances with a merging @document - Render each record's body by reference with project
Before you start: Components and repeaters
A body attaches a chunk of renderable content to a data record as a property — the record itself is not a renderable block. Declare your own @block type with a @child("body") … : WdocAddressableBody? slot, plus a merging @document so the document gathers the instances into a list your pages can repeat over.
A project { from = record.body } then renders *that* record's fragment wherever the projection needs it; ${…} inside the body resolves against the record. A body never renders where it is declared, only where projected. This body/project pattern is exactly how a wskill's book projects its concept and fact pages.
§ 1Exercise: A projected fleet page
Declare a server block carrying a body, author two servers, and project each body onto a fleet page.
import <wdoc.wcl>
@block("server")
type Server {
@inline(0) name: identifier
region: utf8?
@child("body") overview: WdocAddressableBody?
}
@document
type FleetDoc {
@children("server") servers: list<Server>
}
server web01 { region = "us-east"
body { p $"Frontend in ." }
}
server web02 { region = "eu-west"
body { p $"Frontend in ." }
}
page fleet { start = true
h1 "Fleet"
wdoc_repeater { each = servers as = :s
h2 $""
project { from = s.overview }
}
}
Expected result
The fleet page shows an h2 per server followed by its projected body — each paragraph naming its own region.
Hint
Your own @document merges with wdoc's, so page blocks stay legal alongside server. The single @child("body") slot means the body needs no name.