Class: Papercraft::Template
- Inherits:
-
Proc
- Object
- Proc
- Papercraft::Template
- Defined in:
- lib/papercraft/template.rb
Overview
Template represents a distinct, reusable HTML template. A template can include other templates, and also be nested inside other templates.
Since in Papercraft HTML is expressed using blocks (or procs,) the Template class is simply a special kind of Proc, which has some enhanced capabilities, allowing it to be easily composed in a variety of ways.
Templates are usually created using the class methods ‘html`, `xml` or `json`, for HTML, XML or JSON templates, respectively:
greeter = Papercraft.html { |name| h1 "Hello, #{name}!" }
greeter.render('world') #=> "<h1>Hello, world!</h1>"
Templates can also be created using the normal constructor:
greeter = Papercraft::Template.new(mode: :html) { |name| h1 "Hello, #{name}!" }
greeter.render('world') #=> "<h1>Hello, world!</h1>"
The different methods for creating templates can also take a custom MIME type, by passing a ‘mime_type` named argument:
json = Papercraft.json(mime_type: 'application/feed+json') { ... }
In the template block, HTML elements are created by simply calling unqualified methods:
page_layout = Papercraft.html {
html5 {
head {
title 'foo'
}
body {
h1 "Hello, world!"
}
}
}
Papercraft templates can take explicit parameters in order to render dynamic content. This can be in the form of regular or named parameters. The ‘greeter` template shown above takes a single `name` parameter. Here’s how a anchor template could be implemented with named parameters:
anchor = Papercraft.html { |uri: , text: | a(text, href: uri) }
The above template could later be rendered by passing the needed arguments:
anchor.render(uri: 'https://example.com', text: 'Example')
## Template Composition
A template can be included in another template using the ‘emit` method:
links = Papercraft.html {
emit anchor, uri: '/posts', text: 'Posts'
emit anchor, uri: '/archive', text: 'Archive'
emit anchor, uri: '/about', text: 'About'
}
Another way of composing templates is to pass the templates themselves as parameters:
links = Papercraft.html { |anchors|
anchors.each { |a| emit a }
}
links.render([
anchor.apply(uri: '/posts', text: 'Posts'),
anchor.apply(uri: '/archive', text: 'Archive'),
anchor.apply(uri: '/about', text: 'About')
])
The ‘#apply` method creates a new template, applying the given parameters such that the template can be rendered without parameters:
links_with_anchors = links.apply([
anchor.apply(uri: '/posts', text: 'Posts'),
anchor.apply(uri: '/archive', text: 'Archive'),
anchor.apply(uri: '/about', text: 'About')
])
links_with_anchors.render
Constant Summary collapse
- STOCK_MIME_TYPE =
{ html: 'text/html', xml: 'application/xml', json: 'application/json' }.freeze
- H_EMPTY =
{}.freeze
Instance Attribute Summary collapse
-
#mode ⇒ Object
Determines the rendering mode: ‘:html` or `:xml`.
Instance Method Summary collapse
-
#apply(*a, **b, &block) ⇒ Papercraft::Template
Creates a new template, applying the given parameters and or block to the current one.
-
#initialize(mode: :html, mime_type: nil, &block) ⇒ Template
constructor
Initializes a template with the given block.
-
#mime_type ⇒ String
Returns the template’s associated MIME type.
-
#render(*a, **b, &block) ⇒ String
Renders the template with the given parameters and or block, and returns the string result.
-
#render_fragment(name, *a, **b, &block) ⇒ String
Renders a template fragment.
-
#renderer_class ⇒ Papercraft::Renderer
Returns the Renderer class used for rendering the templates, according to the template’s mode.
Constructor Details
#initialize(mode: :html, mime_type: nil, &block) ⇒ Template
Initializes a template with the given block. The rendering mode (HTML or XML) can be passed in the ‘mode:` parameter. If `mode:` is not specified, the template defaults to HTML.
105 106 107 108 109 |
# File 'lib/papercraft/template.rb', line 105 def initialize(mode: :html, mime_type: nil, &block) @mode = mode @mime_type = mime_type || STOCK_MIME_TYPE[mode] super(&block) end |
Instance Attribute Details
#mode ⇒ Object
Determines the rendering mode: ‘:html` or `:xml`.
90 91 92 |
# File 'lib/papercraft/template.rb', line 90 def mode @mode end |
Instance Method Details
#apply(*a, **b, &block) ⇒ Papercraft::Template
Creates a new template, applying the given parameters and or block to the current one. Application is one of the principal methods of composing templates, particularly when passing inner templates as blocks:
article_wrapper = Papercraft.html {
article {
emit_yield
}
}
wrapped_article = article_wrapper.apply {
h1 'Article title'
}
wrapped_article.render #=> "<article><h1>Article title</h1></article>"
171 172 173 174 175 176 177 |
# File 'lib/papercraft/template.rb', line 171 def apply(*a, **b, &block) template = self Template.new(mode: @mode, mime_type: @mime_type, &proc do |*x, **y| push_emit_yield_block(block) if block instance_exec(*a, *x, **b, **y, &template) end) end |
#mime_type ⇒ String
Returns the template’s associated MIME type.
199 200 201 |
# File 'lib/papercraft/template.rb', line 199 def mime_type @mime_type end |
#render(*a, **b, &block) ⇒ String
Renders the template with the given parameters and or block, and returns the string result.
119 120 121 122 123 124 125 126 |
# File 'lib/papercraft/template.rb', line 119 def render(*a, **b, &block) template = self Renderer.verify_proc_parameters(template, a, b) renderer_class.new do push_emit_yield_block(block) if block instance_exec(*a, **b, &template) end.to_s end |
#render_fragment(name, *a, **b, &block) ⇒ String
Renders a template fragment. Any given parameters are passed to the template just like with #render. See also / HTMX template fragments.
form = Papercraft.html { |action|
h1 'Hello'
fragment(:buttons) {
action
'Cancel'
}
}
form.render_fragment(:buttons, 'foo') #=> "<button>foo</button><button>Cancel</buttons>"
145 146 147 148 149 150 151 152 |
# File 'lib/papercraft/template.rb', line 145 def render_fragment(name, *a, **b, &block) template = self Renderer.verify_proc_parameters(template, a, b) renderer_class.new(name) do push_emit_yield_block(block) if block instance_exec(*a, **b, &template) end.to_s end |
#renderer_class ⇒ Papercraft::Renderer
Returns the Renderer class used for rendering the templates, according to the template’s mode.
183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/papercraft/template.rb', line 183 def renderer_class case @mode when :html HTMLRenderer when :xml XMLRenderer when :json JSONRenderer else raise "Invalid mode #{@mode.inspect}" end end |