papercraft 1.3 → 2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +93 -0
- data/README.md +246 -617
- data/lib/papercraft/compiler/nodes.rb +223 -0
- data/lib/papercraft/compiler/tag_translator.rb +93 -0
- data/lib/papercraft/compiler.rb +657 -201
- data/lib/papercraft/proc_ext.rb +118 -0
- data/lib/papercraft/template.rb +16 -195
- data/lib/papercraft/version.rb +1 -1
- data/lib/papercraft.rb +113 -89
- metadata +11 -64
- data/lib/papercraft/compiler_old.rb +0 -701
- data/lib/papercraft/extension_proxy.rb +0 -41
- data/lib/papercraft/extensions/soap.rb +0 -42
- data/lib/papercraft/html.rb +0 -173
- data/lib/papercraft/json.rb +0 -128
- data/lib/papercraft/renderer.rb +0 -190
- data/lib/papercraft/tags.rb +0 -408
- data/lib/papercraft/xml.rb +0 -47
- data/lib/tilt/papercraft.rb +0 -25
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Papercraft
|
4
|
-
|
5
|
-
# An ExtensionProxy proxies method calls to a renderer. Extension proxies are
|
6
|
-
# used to provide an namespaced interface to Papercraft extensions. When an
|
7
|
-
# extension is installed using `Papercraft.extension`, a corresponding method
|
8
|
-
# is defined on the `Papercraft::Renderer` class that creates an extension
|
9
|
-
# proxy that gives access to the different extension methods.
|
10
|
-
class ExtensionProxy
|
11
|
-
|
12
|
-
# Initializes a new ExtensionProxy.
|
13
|
-
#
|
14
|
-
# @param renderer [Papercraft::Renderer] renderer to proxy to
|
15
|
-
# @param mod [Module] extension module
|
16
|
-
# @return [void]
|
17
|
-
def initialize(renderer, mod)
|
18
|
-
@renderer = renderer
|
19
|
-
extend(mod)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Proxies missing methods to the renderer.
|
23
|
-
#
|
24
|
-
# @param sym [Symbol] method name
|
25
|
-
# @param *args [Array] arguments
|
26
|
-
# @param *props [Array] named arguments
|
27
|
-
# @return void
|
28
|
-
def method_missing(sym, *args, **props, &block)
|
29
|
-
@renderer.send(sym, *args, **props, &block)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Overrides the `Kernel#p` method to emit a p tag.
|
33
|
-
#
|
34
|
-
# @param *args [Array] arguments
|
35
|
-
# @param *props [Array] named arguments
|
36
|
-
# @return void
|
37
|
-
def p(text = nil, **props, &block)
|
38
|
-
@renderer.p(text, **props, &block)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Papercraft
|
4
|
-
module Extensions
|
5
|
-
module Soap
|
6
|
-
# Emits a SOAP XML tag that identifies the XML document as a SOAP message.
|
7
|
-
#
|
8
|
-
# @param **props [Hash] tag attributes
|
9
|
-
# @return [void]
|
10
|
-
def Envelope(**props, &block)
|
11
|
-
props[:xmlns__soap] ||= 'http://schemas.xmlsoap.org/soap/envelope/'
|
12
|
-
tag('soap:Envelope', **props, &block)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Emits a SOAP XML tag that contains header information.
|
16
|
-
#
|
17
|
-
# @param **props [Hash] tag attributes
|
18
|
-
# @return [void]
|
19
|
-
def Header(**props, &blk)
|
20
|
-
tag('soap:Header', **props, &blk)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Emits a SOAP XML tag that contains header information.
|
24
|
-
#
|
25
|
-
# @param **props [Hash] tag attributes
|
26
|
-
# @return [void]
|
27
|
-
def Body(**props, &blk)
|
28
|
-
tag('soap:Body', **props, &blk)
|
29
|
-
end
|
30
|
-
|
31
|
-
# Emits a SOAP XML tag that contains errors and status information.
|
32
|
-
#
|
33
|
-
# @param **props [Hash] tag attributes
|
34
|
-
# @return [void]
|
35
|
-
def Fault(**props, &blk)
|
36
|
-
tag('soap:Fault', **props, &blk)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
Papercraft.extension(soap: Papercraft::Extensions::Soap)
|
data/lib/papercraft/html.rb
DELETED
@@ -1,173 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './tags'
|
4
|
-
require 'cgi'
|
5
|
-
|
6
|
-
module Papercraft
|
7
|
-
# HTML Markup extensions
|
8
|
-
module HTML
|
9
|
-
include Tags
|
10
|
-
|
11
|
-
# Emits the p tag (overrides Object#p)
|
12
|
-
#
|
13
|
-
# @param text [String] text content of tag
|
14
|
-
# @param **attributes [Hash] tag attributes
|
15
|
-
# @para block [Proc] nested HTML block
|
16
|
-
# @return [void]
|
17
|
-
def p(text = nil, **attributes, &block)
|
18
|
-
method_missing(:p, text, **attributes, &block)
|
19
|
-
end
|
20
|
-
|
21
|
-
S_HTML5_DOCTYPE = '<!DOCTYPE html>'
|
22
|
-
|
23
|
-
# Emits an HTML5 doctype tag and an html tag with the given block.
|
24
|
-
#
|
25
|
-
# @param block [Proc] nested HTML block
|
26
|
-
# @return [void]
|
27
|
-
def html5(&block)
|
28
|
-
@buffer << S_HTML5_DOCTYPE
|
29
|
-
self.html(&block)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Emits a link element with a stylesheet.
|
33
|
-
#
|
34
|
-
# @param href [String] stylesheet URL
|
35
|
-
# @param custom_attributes [Hash] optional custom attributes for the link element
|
36
|
-
# @return [void]
|
37
|
-
def link_stylesheet(href, custom_attributes = nil)
|
38
|
-
attributes = {
|
39
|
-
rel: 'stylesheet',
|
40
|
-
href: href
|
41
|
-
}
|
42
|
-
if custom_attributes
|
43
|
-
attributes = custom_attributes.merge(attributes)
|
44
|
-
end
|
45
|
-
link(**attributes)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Emits an inline CSS style element.
|
49
|
-
#
|
50
|
-
# @param css [String] CSS code
|
51
|
-
# @param **attributes [Hash] optional element attributes
|
52
|
-
# @return [void]
|
53
|
-
def style(css, **attributes, &block)
|
54
|
-
@buffer << '<style'
|
55
|
-
emit_attributes(attributes) unless attributes.empty?
|
56
|
-
|
57
|
-
@buffer << '>' << css << '</style>'
|
58
|
-
end
|
59
|
-
|
60
|
-
# Emits an inline JS script element.
|
61
|
-
#
|
62
|
-
# @param js [String, nil] Javascript code
|
63
|
-
# @param **attributes [Hash] optional element attributes
|
64
|
-
# @return [void]
|
65
|
-
def script(js = nil, **attributes, &block)
|
66
|
-
@buffer << '<script'
|
67
|
-
emit_attributes(attributes) unless attributes.empty?
|
68
|
-
|
69
|
-
if js
|
70
|
-
@buffer << '>' << js << '</script>'
|
71
|
-
else
|
72
|
-
@buffer << '></script>'
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Returns a versioned URL for the given file spec.
|
77
|
-
#
|
78
|
-
# @param href [String] relative file path
|
79
|
-
# @param root_path [String] root path for file
|
80
|
-
# @param root_url [String] root URL
|
81
|
-
# @return [String] versioned URL
|
82
|
-
def versioned_file_href(href, root_path, root_url = '')
|
83
|
-
fn = File.join(root_path, href)
|
84
|
-
version = File.stat(fn).mtime.to_i rescue 0
|
85
|
-
"#{root_url}/#{href}?v=#{version}"
|
86
|
-
end
|
87
|
-
|
88
|
-
# Emits an import map scrit tag. If a hash is given, emits the hash as is.
|
89
|
-
# If a string is given, searches for all *.js files under the given path,
|
90
|
-
# and emits an import map including all found files, with versioned URLs.
|
91
|
-
#
|
92
|
-
# @param root_path [String, Hash] root path or hash
|
93
|
-
# @param root_url [String] root URL to construct URLs against
|
94
|
-
# @return [void]
|
95
|
-
def import_map(root_path, root_url = '')
|
96
|
-
if root_path.is_a?(Hash)
|
97
|
-
script(root_path.to_json, type: 'importmap')
|
98
|
-
else
|
99
|
-
map = Dir["#{root_path}/*.js"].sort.each_with_object({}) do |fn, h|
|
100
|
-
name = File.basename(fn)
|
101
|
-
m = fn.match(/\/([^\/]+)\.js$/)
|
102
|
-
h[m[1]] = versioned_file_href(name, root_path, root_url)
|
103
|
-
end
|
104
|
-
script(map.to_json, type: 'importmap')
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Emits a script tag with type attribute set to module.
|
109
|
-
#
|
110
|
-
# @param code [String] JS code
|
111
|
-
# @return [void]
|
112
|
-
def js_module(code)
|
113
|
-
script code, type: 'module'
|
114
|
-
end
|
115
|
-
|
116
|
-
# Converts and emits the given markdown. Papercraft uses
|
117
|
-
# [Kramdown](https://github.com/gettalong/kramdown/) to do the Markdown to
|
118
|
-
# HTML conversion. Optional Kramdown settings can be provided in order to
|
119
|
-
# control the conversion. Those are merged with the default Kramdown
|
120
|
-
# settings, which can be controlled using
|
121
|
-
# `Papercraft::HTML.kramdown_options`.
|
122
|
-
#
|
123
|
-
# @param markdown [String] Markdown content
|
124
|
-
# @param **opts [Hash] Kramdown options
|
125
|
-
# @return [void]
|
126
|
-
def emit_markdown(markdown, **opts)
|
127
|
-
emit Papercraft.markdown(markdown, **opts)
|
128
|
-
end
|
129
|
-
|
130
|
-
private
|
131
|
-
|
132
|
-
# Returns true if the given tag is a void element, in order to render a self
|
133
|
-
# closing tag. See spec: https://html.spec.whatwg.org/multipage/syntax.html#void-elements.
|
134
|
-
#
|
135
|
-
# @param tag [String] tag
|
136
|
-
# @return [Bool] is it a void element
|
137
|
-
def is_void_element_tag?(tag)
|
138
|
-
case tag
|
139
|
-
#
|
140
|
-
when 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr'
|
141
|
-
true
|
142
|
-
else
|
143
|
-
false
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# Escapes the given text using HTML entities.
|
148
|
-
#
|
149
|
-
# @param text [String] text
|
150
|
-
# @return [String] escaped text
|
151
|
-
def escape_text(text)
|
152
|
-
CGI.escapeHTML(text.to_s)
|
153
|
-
end
|
154
|
-
|
155
|
-
# Converts a tag to its string representation. Underscores will be converted
|
156
|
-
# to dashes.
|
157
|
-
#
|
158
|
-
# @param tag [Symbol, String] tag
|
159
|
-
# @return [String] tag string
|
160
|
-
def tag_repr(tag)
|
161
|
-
tag.to_s.tr('_', '-')
|
162
|
-
end
|
163
|
-
|
164
|
-
# Converts an attribute to its string representation. Underscores will be
|
165
|
-
# converted to dashes.
|
166
|
-
#
|
167
|
-
# @param att [Symbol, String] attribute
|
168
|
-
# @return [String] attribute string
|
169
|
-
def att_repr(att)
|
170
|
-
att.to_s.tr('_', '-')
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
data/lib/papercraft/json.rb
DELETED
@@ -1,128 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
module Papercraft
|
6
|
-
# JSON renderer extensions
|
7
|
-
module JSON
|
8
|
-
# Initializes a JSON renderer, setting up an object stack.
|
9
|
-
def initialize(&template)
|
10
|
-
@object_stack = [nil]
|
11
|
-
super
|
12
|
-
end
|
13
|
-
|
14
|
-
# Adds an array item to the current object target. If a block is given, the
|
15
|
-
# block is evaulated against a new object target, then added to the current
|
16
|
-
# array.
|
17
|
-
#
|
18
|
-
# Papercraft.json {
|
19
|
-
# item 'foo'
|
20
|
-
# item 'bar'
|
21
|
-
# }.render #=> "[\"foo\", \"bar\"]"
|
22
|
-
#
|
23
|
-
# @param value [Object] item
|
24
|
-
# @return [void]
|
25
|
-
def item(value = nil, _for: nil, &block)
|
26
|
-
return _for.each { |*a| item(value) { block.(*a)} } if _for
|
27
|
-
|
28
|
-
verify_array_target
|
29
|
-
if block
|
30
|
-
value = enter_object(&block)
|
31
|
-
end
|
32
|
-
push_array_item(value)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Adds a key-value item to the current object target. If a block is given,
|
36
|
-
# the block is evaulated against a new object target, then used as the
|
37
|
-
# value.
|
38
|
-
#
|
39
|
-
# @param key [Object] key
|
40
|
-
# @param value [Object] value
|
41
|
-
# @return [void]
|
42
|
-
def kv(key, value = nil, &block)
|
43
|
-
verify_hash_target
|
44
|
-
if block
|
45
|
-
value = enter_object(&block)
|
46
|
-
end
|
47
|
-
push_kv_item(key, value)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Intercepts method calls by adding key-value pairs to the current object
|
51
|
-
# target.
|
52
|
-
#
|
53
|
-
# @param key [Symbol] key
|
54
|
-
# @param value [Object] value
|
55
|
-
# @return [void]
|
56
|
-
def method_missing(key, value = nil, &block)
|
57
|
-
kv(key, value, &block)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Converts the root object target to JSON.
|
61
|
-
#
|
62
|
-
# @return [String] JSON template result
|
63
|
-
def to_s
|
64
|
-
@object_stack[0].to_json
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# Adds a new entry to the object stack and evaluates the given block.
|
70
|
-
#
|
71
|
-
# @return [void]
|
72
|
-
def with_object(&block)
|
73
|
-
@object_stack << nil
|
74
|
-
instance_eval(&block)
|
75
|
-
end
|
76
|
-
|
77
|
-
# Verifies that the current object target is not a hash.
|
78
|
-
#
|
79
|
-
# @return [bool]
|
80
|
-
def verify_array_target
|
81
|
-
case @object_stack[-1]
|
82
|
-
when nil
|
83
|
-
@object_stack[-1] = []
|
84
|
-
when Hash
|
85
|
-
raise "Mixing array and hash values"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Verifies that the current object target is not an array.
|
90
|
-
#
|
91
|
-
# @return [bool]
|
92
|
-
def verify_hash_target
|
93
|
-
case @object_stack[-1]
|
94
|
-
when nil
|
95
|
-
@object_stack[-1] = {}
|
96
|
-
when Array
|
97
|
-
raise "Mixing array and hash values"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# Pushes an array item to the current object target.
|
102
|
-
#
|
103
|
-
# @param value [Object] item
|
104
|
-
# @return [void]
|
105
|
-
def push_array_item(value)
|
106
|
-
@object_stack[-1] << value
|
107
|
-
end
|
108
|
-
|
109
|
-
# Pushes a key value into the current object target.
|
110
|
-
#
|
111
|
-
# @param key [Object] key
|
112
|
-
# @param value [Object] value
|
113
|
-
# @return [void]
|
114
|
-
def push_kv_item(key, value)
|
115
|
-
@object_stack[-1][key] = value
|
116
|
-
end
|
117
|
-
|
118
|
-
# Adds a new object to the object stack, evaluates the given template block,
|
119
|
-
# then pops the object off the stack.
|
120
|
-
#
|
121
|
-
# @return [void]
|
122
|
-
def enter_object(&block)
|
123
|
-
@object_stack << nil
|
124
|
-
instance_eval(&block)
|
125
|
-
@object_stack.pop
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
data/lib/papercraft/renderer.rb
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './html'
|
4
|
-
require_relative './xml'
|
5
|
-
require_relative './json'
|
6
|
-
require_relative './extension_proxy'
|
7
|
-
|
8
|
-
module Papercraft
|
9
|
-
|
10
|
-
# A Renderer renders a Papercraft template into a string
|
11
|
-
class Renderer
|
12
|
-
|
13
|
-
class << self
|
14
|
-
|
15
|
-
# Verifies that the given template proc can be called with the given
|
16
|
-
# arguments and named arguments. If the proc demands named argument keys
|
17
|
-
# that do not exist in `named_args`, `Papercraft::Error` is raised.
|
18
|
-
#
|
19
|
-
# @param template [Proc] proc to verify
|
20
|
-
# @param args [Array<any>] arguments passed to proc
|
21
|
-
# @param named_args [Hash] named arguments passed to proc
|
22
|
-
def verify_proc_parameters(template, args, named_args)
|
23
|
-
param_count = 0
|
24
|
-
template.parameters.each do |(type, name)|
|
25
|
-
case type
|
26
|
-
when :req
|
27
|
-
param_count += 1
|
28
|
-
when :keyreq
|
29
|
-
if !named_args.has_key?(name)
|
30
|
-
raise Papercraft::Error, "Missing template parameter #{name.inspect}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
if param_count > args.size
|
35
|
-
raise Papercraft::Error, "Missing template parameters"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# call_seq:
|
40
|
-
# Papercraft::Renderer.extension(name => mod, ...)
|
41
|
-
# Papercraft.extension(name => mod, ...)
|
42
|
-
#
|
43
|
-
# Installs the given extensions, passed in the form of a Ruby hash mapping
|
44
|
-
# methods to extension modules. The methods will be available to all
|
45
|
-
# Papercraft templates. Extension methods are executed in the context of
|
46
|
-
# the the renderer instance, so they can look just like normal proc
|
47
|
-
# components. In cases where method names in the module clash with XML
|
48
|
-
# tag names, you can use the `#tag` method to emit the relevant tag.
|
49
|
-
#
|
50
|
-
# module ComponentLibrary
|
51
|
-
# def card(title, content)
|
52
|
-
# div(class: 'card') {
|
53
|
-
# h3 title
|
54
|
-
# div(class: 'card-content') { emit_markdown content }
|
55
|
-
# }
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# Papercraft.extension(components: ComponentLibrary)
|
60
|
-
# Papercraft.html { components.card('Foo', '**Bar**') }
|
61
|
-
#
|
62
|
-
# @param map [Hash] hash mapping methods to extension modules
|
63
|
-
# @return [void]
|
64
|
-
def extension(map)
|
65
|
-
map.each do |sym, mod|
|
66
|
-
define_extension_method(sym, mod)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
# Defines a method returning an extension proxy for the given module
|
73
|
-
# @param sym [Symbol] method name
|
74
|
-
# @param mod [Module] extension module
|
75
|
-
# @return [void]
|
76
|
-
def define_extension_method(sym, mod)
|
77
|
-
define_method(sym) do
|
78
|
-
(@extension_proxies ||= {})[mod] ||= ExtensionProxy.new(self, mod)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Initializes the renderer and evaulates the given template in the
|
84
|
-
# renderer's scope.
|
85
|
-
#
|
86
|
-
# @param &template [Proc] template block
|
87
|
-
def initialize(render_fragment = nil, &template)
|
88
|
-
@render_fragment = render_fragment
|
89
|
-
instance_eval(&template)
|
90
|
-
end
|
91
|
-
|
92
|
-
# Emits the given object into the rendering buffer. If the given object is a
|
93
|
-
# proc or a component, `emit` will passes any additional arguments and named
|
94
|
-
# arguments to the object when rendering it. If the given object is nil,
|
95
|
-
# nothing is emitted. Otherwise, the object is converted into a string using
|
96
|
-
# `#to_s` which is then added to the rendering buffer, without any escaping.
|
97
|
-
#
|
98
|
-
# greeter = proc { |name| h1 "Hello, #{name}!" }
|
99
|
-
# Papercraft.html { emit(greeter, 'world') }.render #=> "<h1>Hello, world!</h1>"
|
100
|
-
#
|
101
|
-
# Papercraft.html { emit 'hi&<bye>' }.render #=> "hi&<bye>"
|
102
|
-
#
|
103
|
-
# Papercraft.html { emit nil }.render #=> ""
|
104
|
-
#
|
105
|
-
# @param o [Proc, Papercraft::Template, String] emitted object
|
106
|
-
# @param *a [Array<any>] arguments to pass to a proc
|
107
|
-
# @param **b [Hash] named arguments to pass to a proc
|
108
|
-
# @return [void]
|
109
|
-
def emit(o, *a, **b, &block)
|
110
|
-
case o
|
111
|
-
when ::Proc
|
112
|
-
Renderer.verify_proc_parameters(o, a, b)
|
113
|
-
push_emit_yield_block(block) if block
|
114
|
-
instance_exec(*a, **b, &o)
|
115
|
-
when nil
|
116
|
-
# do nothing
|
117
|
-
else
|
118
|
-
emit_object(o)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
alias_method :e, :emit
|
122
|
-
|
123
|
-
# Emits a block supplied using {Template#apply} or {Template#render}.
|
124
|
-
#
|
125
|
-
# div_wrap = Papercraft.html { |*args| div { emit_yield(*args) } }
|
126
|
-
# greeter = div_wrap.apply { |name| h1 "Hello, #{name}!" }
|
127
|
-
# greeter.render('world') #=> "<div><h1>Hello, world!</h1></div>"
|
128
|
-
#
|
129
|
-
# @param *a [Array<any>] arguments to pass to a proc
|
130
|
-
# @param **b [Hash] named arguments to pass to a proc
|
131
|
-
# @return [void]
|
132
|
-
def emit_yield(*a, **b)
|
133
|
-
block = @emit_yield_stack&.pop
|
134
|
-
raise Papercraft::Error, "No block given" unless block
|
135
|
-
|
136
|
-
instance_exec(*a, **b, &block)
|
137
|
-
end
|
138
|
-
|
139
|
-
# Defines a named template fragment. Template fragments allow rendering
|
140
|
-
# specific parts of the same template. A template fragment can be rendered
|
141
|
-
# using {Template#render_fragment}. See also
|
142
|
-
# {https://htmx.org/essays/template-fragments/ HTMX template fragments}.
|
143
|
-
#
|
144
|
-
# form = Papercraft.html {
|
145
|
-
# h1 'Hello'
|
146
|
-
# fragment(:buttons) {
|
147
|
-
# button 'OK'
|
148
|
-
# button 'Cancel'
|
149
|
-
# }
|
150
|
-
# }
|
151
|
-
# form.render_fragment(:buttons) #=> "<button>OK</button><button>Cancel</buttons>"
|
152
|
-
#
|
153
|
-
# @param name [Symbol, String] fragment name
|
154
|
-
# @return [void]
|
155
|
-
def fragment(name, &block)
|
156
|
-
raise Papercraft::Error, "Already in fragment" if @fragment
|
157
|
-
|
158
|
-
begin
|
159
|
-
@fragment = name
|
160
|
-
emit(block)
|
161
|
-
ensure
|
162
|
-
@fragment = nil
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
private
|
167
|
-
|
168
|
-
# Pushes the given block onto the emit_yield stack.
|
169
|
-
#
|
170
|
-
# @param block [Proc] block
|
171
|
-
def push_emit_yield_block(block)
|
172
|
-
(@emit_yield_stack ||= []) << block
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
# Implements an HTML renderer
|
177
|
-
class HTMLRenderer < Renderer
|
178
|
-
include HTML
|
179
|
-
end
|
180
|
-
|
181
|
-
# Implements an XML renderer
|
182
|
-
class XMLRenderer < Renderer
|
183
|
-
include XML
|
184
|
-
end
|
185
|
-
|
186
|
-
# Implements a JSON renderer
|
187
|
-
class JSONRenderer < Renderer
|
188
|
-
include JSON
|
189
|
-
end
|
190
|
-
end
|