Class: Weft::Page
- Inherits:
-
Arbre::Component
- Object
- Arbre::Component
- Weft::Page
- Extended by:
- Registry::Eligibility
- Includes:
- Context::Interception, Context::Traversal, DSL::Containers, DSL::Params, DSL::Recoveries, Assets, Head
- Defined in:
- lib/weft/page.rb,
lib/weft/page/head.rb,
lib/weft/page/assets.rb
Overview
Document shell component. Renders the full HTML skeleton (doctype,
head, body); the head surface — the title verb and the registered
scripts and stylesheets — lives in Page::Head and Page::Assets.
Subclass to add application-specific assets and CSS.
Pages auto-route via page_path declarations or class-name inference. The Router serves them as full documents at the resolved URL patterns.
class OrderDetailPage < Weft::Page
self.page_path = "/orders/:order_id"
param :order_id
end
Subclasses without an explicit page_path auto-infer one from the class name: the demodulized name, snake-cased, with any trailing "Page" suffix stripped (DashboardPage and Dashboard both route at "/dashboard"). Use abstract! to opt out — typical for an intermediate base class that hosts shared assets and helpers but isn't itself a destination.
Direct Known Subclasses
Defined Under Namespace
Constant Summary
Constants included from Assets
Assets::HTMX_ATTRS, Assets::HTMX_SRC, Assets::HTMX_SSE_ATTRS, Assets::HTMX_SSE_SRC
Class Attribute Summary collapse
-
.page_path ⇒ Object
Class-level page path pattern.
Attributes included from DSL::Params
Class Method Summary collapse
-
.inferred_routable? ⇒ Boolean
Inferred routability from declared state, ignoring any explicit override.
- .inherited(subclass) ⇒ Object
- .path_param_keys ⇒ Object
-
.redirect_url(params = {}) ⇒ Object
Build a redirect URL targeting this page with the given params.
-
.render(**wire_params) ⇒ Object
Render this page as a full HTML document outside any Arbre DSL context.
-
.resolve_page_path(params = {}) ⇒ Object
Resolve the page path by interpolating params into the pattern.
Instance Method Summary collapse
- #add_child(child) ⇒ Object
- #build(attributes = {}) ⇒ Object
-
#initialize ⇒ Page
constructor
Params resolve at construction (see Weft::Component#initialize) so user build bodies can read them before super — e.g.
- #tag_name ⇒ Object
- #to_s ⇒ Object
-
#weft_page(*args, &block) ⇒ Object
private
Arbre builder for the Weft page element.
Methods included from Registry::Eligibility
abstract!, routable!, routable?
Methods included from Head
Methods included from Assets
Methods included from Context::Traversal
#closest, #closest!, #enclosing, #enclosing!
Methods included from DSL::Containers
Methods included from DSL::Recoveries
Methods included from DSL::Params
included, #serializable_params, warned_collisions
Methods included from Context::Interception
Constructor Details
#initialize ⇒ Page
Params resolve at construction (see Weft::Component#initialize) so user build bodies can read them before super — e.g. computing body chrome from a record looked up by param.
157 158 159 160 |
# File 'lib/weft/page.rb', line 157 def initialize(*) super @params = assembled_params if self.class.declared_keys.any? end |
Class Attribute Details
.page_path ⇒ Object
Class-level page path pattern. Sinatra-style string with :param segments. Bidirectional: forward (interpolate params → URL) and reverse (match request → params).
self.page_path = "/orders/:order_id"
59 60 61 62 63 64 65 |
# File 'lib/weft/page.rb', line 59 def page_path if instance_variable_defined?(:@page_path) @page_path elsif superclass.respond_to?(:page_path) superclass.page_path end end |
Class Method Details
.inferred_routable? ⇒ Boolean
Inferred routability from declared state, ignoring any explicit override. Subclasses fall back to this when they have no override of their own, so an abstract parent does not disable concrete children.
A page is inferred-routable if it has an explicit page_path, or if its class name yields a usable default — i.e. the demodulized name has a non-empty stem after stripping any trailing "Page" suffix. The suffix is optional: FooBarPage and BazBar both route. Pages with params are not inferred-routable; they require an explicit page_path (a parameterized route can't be derived from the name; see default_page_path).
109 110 111 112 113 114 |
# File 'lib/weft/page.rb', line 109 def inferred_routable? return true if instance_variable_defined?(:@page_path) return false if params.any? !name.to_s.delete_suffix("Page").demodulize.empty? end |
.inherited(subclass) ⇒ Object
116 117 118 119 |
# File 'lib/weft/page.rb', line 116 def inherited(subclass) super Weft.registry.register_page(subclass) end |
.path_param_keys ⇒ Object
94 95 96 97 |
# File 'lib/weft/page.rb', line 94 def path_param_keys pattern = page_path || default_page_path pattern.scan(/:(\w+)/).flatten.map(&:to_sym) end |
.redirect_url(params = {}) ⇒ Object
Build a redirect URL targeting this page with the given params. Path :param segments interpolate from params; declared-but-not-path params become query string entries. Anything not in the page's declared schema is discarded — never leaks into the URL.
class OrderDetailPage < Weft::Page
self.page_path = "/orders/:order_id"
param :order_id
param :highlight_section
end
OrderDetailPage.redirect_url(order_id: 42, highlight_section: "items", junk: "x")
# => "/orders/42?highlight_section=items"
88 89 90 91 92 |
# File 'lib/weft/page.rb', line 88 def redirect_url(params = {}) path = resolve_page_path(params) query = params.slice(*(self.params.keys - path_param_keys)).compact query.empty? ? path : "#{path}?#{::URI.encode_www_form(query)}" end |
.render(**wire_params) ⇒ Object
Render this page as a full HTML document outside any Arbre DSL context. The kwargs are pseudo-wire: exactly what a request's query/path params would carry. Used by the Router for full-document responses, and available to users for testing or standalone rendering.
125 126 127 128 129 130 |
# File 'lib/weft/page.rb', line 125 def render(**wire_params) klass = self Weft::Context.new({}, nil, wire_params: wire_params) do insert_tag(klass) end.to_s end |
.resolve_page_path(params = {}) ⇒ Object
Resolve the page path by interpolating params into the pattern. OrderDetailPage.resolve_page_path(order_id: "42") # => "/orders/42"
71 72 73 74 |
# File 'lib/weft/page.rb', line 71 def resolve_page_path(params = {}) pattern = page_path || default_page_path pattern.gsub(/:(\w+)/) { params[::Regexp.last_match(1).to_sym] || ":#{::Regexp.last_match(1)}" } end |
Instance Method Details
#add_child(child) ⇒ Object
173 174 175 |
# File 'lib/weft/page.rb', line 173 def add_child(child) @body_el ? (@body_el << child) : super end |
#build(attributes = {}) ⇒ Object
162 163 164 165 166 167 |
# File 'lib/weft/page.rb', line 162 def build(attributes = {}) warn_declared_chrome_collisions(attributes) super build_head @body_el = insert_tag(Arbre::HTML::Body) end |
#tag_name ⇒ Object
169 170 171 |
# File 'lib/weft/page.rb', line 169 def tag_name "html" end |
#to_s ⇒ Object
177 178 179 |
# File 'lib/weft/page.rb', line 177 def to_s "<!DOCTYPE html>\n#{super}" end |
#weft_page(*args, &block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Arbre builder for the Weft page element. Internal plumbing — authors subclass Weft::Page and render via the Router; they do not call this.
52 |
# File 'lib/weft/page.rb', line 52 builder_method :weft_page |