Class: Weft::Page

Inherits:
Arbre::Component
  • Object
show all
Extended by:
Registry::Eligibility
Includes:
Context::Interception, DSL::Attributes, DSL::Containers, DSL::Recoveries
Defined in:
lib/weft/page.rb

Overview

Document shell component. Renders the full HTML skeleton (doctype, head, body) with registered scripts and stylesheets. 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"
attribute :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

Defaults::ErrorPage, Defaults::NotFoundPage

Constant Summary collapse

HTMX_SRC =
"https://unpkg.com/htmx.org@2.0.4"
HTMX_ATTRS =
{
  integrity: "sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+",
  crossorigin: "anonymous"
}.freeze
HTMX_SSE_SRC =
"https://unpkg.com/htmx-ext-sse@2.2.2/sse.js"
HTMX_SSE_ATTRS =
{
  integrity: "sha384-fw+eTlCc7suMV/1w/7fr2/PmwElUIt5i82bi+qTiLXvjRXZ2/FkiTNA/w0MhXnGI",
  crossorigin: "anonymous"
}.freeze

Class Attribute Summary collapse

Attributes included from DSL::Attributes

#attrs

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Registry::Eligibility

abstract!, routable!, routable?, stale?

Methods included from DSL::Containers

behavior_for, included

Methods included from DSL::Recoveries

included

Methods included from DSL::Attributes

included

Methods included from Context::Interception

#insert_tag

Class Attribute Details

.page_pathObject

Class-level page path pattern. Sinatra-style string with :param segments. Bidirectional: forward (interpolate attrs → URL) and reverse (match request → params).

self.page_path = "/orders/:order_id"


53
54
55
56
57
58
59
# File 'lib/weft/page.rb', line 53

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 attributes are not inferred-routable; they require an explicit page_path (a parameterized route can't be derived from the name; see default_page_path).

Returns:

  • (Boolean)


103
104
105
106
107
108
# File 'lib/weft/page.rb', line 103

def inferred_routable?
  return true if instance_variable_defined?(:@page_path)
  return false if attributes.any?

  !name.to_s.delete_suffix("Page").demodulize.empty?
end

.inherited(subclass) ⇒ Object



110
111
112
113
# File 'lib/weft/page.rb', line 110

def inherited(subclass)
  super
  Weft.registry.register_page(subclass)
end

.inline_cssObject

All registered inline CSS blocks (own + inherited).



181
182
183
184
185
186
187
# File 'lib/weft/page.rb', line 181

def inline_css
  if superclass.respond_to?(:inline_css)
    superclass.inline_css + own_inline_css
  else
    own_inline_css.dup
  end
end

.path_param_keysObject



88
89
90
91
# File 'lib/weft/page.rb', line 88

def path_param_keys
  pattern = page_path || default_page_path
  pattern.scan(/:(\w+)/).flatten.map(&:to_sym)
end

.redirect_url(attrs = {}) ⇒ Object

Build a redirect URL targeting this page with the given attrs. Path :param segments interpolate from attrs; declared-but-not-param attrs 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"
attribute :order_id
attribute :highlight_section
end
OrderDetailPage.redirect_url(order_id: 42, highlight_section: "items", junk: "x")
# => "/orders/42?highlight_section=items"


82
83
84
85
86
# File 'lib/weft/page.rb', line 82

def redirect_url(attrs = {})
  path = resolve_page_path(attrs)
  query = attrs.slice(*(attributes.keys - path_param_keys)).compact
  query.empty? ? path : "#{path}?#{::URI.encode_www_form(query)}"
end

.register_css(css) ⇒ Object

Register a block of inline CSS to include in the page head. Each registered string emits as its own