papercraft 0.20 → 0.21

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2eaf6ba31b9300176af0bf55b76f7bbdc16508d0e495ed1d76f9f273ea88f250
4
- data.tar.gz: 90e132928ebfe78e577e71c8dc498f0ce1b1f2c58f453fbedaad96121c448a48
3
+ metadata.gz: a23bf614d84747a18eecf84545604c9c2f58710dc3fa0e0c651a863a53c919b0
4
+ data.tar.gz: 6b1ca8f4a90801beff11807dd357ce801b7526b5d114d5cca5f41f41aec69958
5
5
  SHA512:
6
- metadata.gz: fcada325a3f8cd1c4cbe38674efaf6a86d0eb947ad5815d07778e2a09a54bee2c7d6b731e87d110390e9c87abc0a61f81cbc4cb30fdce11a4fc8a8cd322466a0
7
- data.tar.gz: 031c86f7dade95af3dca979b4543fcb26e1fab2eb98c5642746d6efcf8b4bd56fe30b70f2f5aa8309352f421cae9f116a901f464216f54a0be50630dcc52815f
6
+ metadata.gz: dcd7eada8280cb0fcd68528eaea0d2500ff99ac149c8495dd5a3955a93c3f181301a4decc9eeb4d7efdd8cfe2c4f6047c9f838e5084b413c1118a76d6abc4252
7
+ data.tar.gz: 840ce0fc2a83de9b5a83bb10a5f4ed98986f7201737d6e31a4e89877aeb6bb22b2f2449c6efa08302473c073e26c830cfbe9e267456b450a56222b57a429fd15
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.21 2022-02-13
2
+
3
+ - Refactor and improve documentation
4
+
1
5
  ## 0.20 2022-02-13
2
6
 
3
7
  - Add support for XML namespaced tags and attributes (#9)
@@ -10,6 +10,7 @@ module Papercraft
10
10
  class ExtensionProxy
11
11
 
12
12
  # Initializes a new ExtensionProxy.
13
+ #
13
14
  # @param renderer [Papercraft::Renderer] renderer to proxy to
14
15
  # @param mod [Module] extension module
15
16
  # @return [void]
@@ -18,7 +19,8 @@ module Papercraft
18
19
  extend(mod)
19
20
  end
20
21
 
21
- # Proxies missing methods to the renderer
22
+ # Proxies missing methods to the renderer.
23
+ #
22
24
  # @param sym [Symbol] method name
23
25
  # @param *args [Array] arguments
24
26
  # @param &block [Proc] block
@@ -88,9 +88,30 @@ module Papercraft
88
88
 
89
89
  private
90
90
 
91
- # Escapes the given text using XML entities.
91
+ # Escapes the given text using HTML entities.
92
+ #
93
+ # @param text [String] text
94
+ # @return [String] escaped text
92
95
  def escape_text(text)
93
96
  EscapeUtils.escape_html(text.to_s)
94
97
  end
98
+
99
+ # Converts a tag to its string representation. Underscores will be converted
100
+ # to dashes.
101
+ #
102
+ # @param tag [Symbol, String] tag
103
+ # @return [String] tag string
104
+ def tag_repr(tag)
105
+ tag.to_s.tr('_', '-')
106
+ end
107
+
108
+ # Converts an attribute to its string representation. Underscores will be
109
+ # converted to dashes.
110
+ #
111
+ # @param att [Symbol, String] attribute
112
+ # @return [String] attribute string
113
+ def att_repr(att)
114
+ att.to_s.tr('_', '-')
115
+ end
95
116
  end
96
117
  end
@@ -5,69 +5,122 @@ require 'json'
5
5
  module Papercraft
6
6
  # JSON renderer extensions
7
7
  module JSON
8
- def object_stack
9
- @object_stack ||= [nil]
8
+ # Initializes a JSON renderer, setting up an object stack.
9
+ def initialize(&template)
10
+ @object_stack = [nil]
11
+ super
10
12
  end
11
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
+ # @param value [Object] item
19
+ # @param &block [Proc] template block
20
+ # @return [void]
21
+ def item(value = nil, &block)
22
+ verify_array_target
23
+ if block
24
+ value = enter_object(&block)
25
+ end
26
+ push_array_item(value)
27
+ end
28
+
29
+ # Adds a key-value item to the current object target. If a block is given,
30
+ # the block is evaulated against a new object target, then used as the
31
+ # value.
32
+ #
33
+ # @param key [Object] key
34
+ # @param value [Object] value
35
+ # @param &block [Proc] template block
36
+ # @return [void]
37
+ def kv(key, value = nil, &block)
38
+ verify_hash_target
39
+ if block
40
+ value = enter_object(&block)
41
+ end
42
+ push_kv_item(key, value)
43
+ end
44
+
45
+ # Intercepts method calls by adding key-value pairs to the current object
46
+ # target.
47
+ #
48
+ # @param key [Object] key
49
+ # @param value [Object] value
50
+ # @param &block [Proc] template block
51
+ # @return [void]
52
+ def method_missing(sym, value = nil, &block)
53
+ kv(sym, value, &block)
54
+ end
55
+
56
+ # Converts the root object target to JSON.
57
+ #
58
+ # @return [String] JSON template result
59
+ def to_s
60
+ @object_stack[0].to_json
61
+ end
62
+
63
+ private
64
+
65
+ # Adds a new entry to the object stack and evaluates the given block.
66
+ #
67
+ # @param &block [Proc] template block
68
+ # @return [void]
12
69
  def with_object(&block)
13
- object_stack << nil
70
+ @object_stack << nil
14
71
  instance_eval(&block)
15
72
  end
16
73
 
74
+ # Verifies that the current object target is not a hash.
75
+ #
76
+ # @return [bool]
17
77
  def verify_array_target
18
- case object_stack[-1]
78
+ case @object_stack[-1]
19
79
  when nil
20
- object_stack[-1] = []
80
+ @object_stack[-1] = []
21
81
  when Hash
22
82
  raise "Mixing array and hash values"
23
83
  end
24
84
  end
25
85
 
86
+ # Verifies that the current object target is not an array.
87
+ #
88
+ # @return [bool]
26
89
  def verify_hash_target
27
- case object_stack[-1]
90
+ case @object_stack[-1]
28
91
  when nil
29
- object_stack[-1] = {}
92
+ @object_stack[-1] = {}
30
93
  when Array
31
94
  raise "Mixing array and hash values"
32
95
  end
33
96
  end
34
97
 
98
+ # Pushes an array item to the current object target.
99
+ #
100
+ # @param value [Object] item
101
+ # @return [void]
35
102
  def push_array_item(value)
36
- object_stack[-1] << value
103
+ @object_stack[-1] << value
37
104
  end
38
105
 
106
+ # Pushes a key value into the current object target.
107
+ #
108
+ # @param key [Object] key
109
+ # @param value [Object] value
110
+ # @return [void]
39
111
  def push_kv_item(key, value)
40
- object_stack[-1][key] = value
112
+ @object_stack[-1][key] = value
41
113
  end
42
114
 
115
+ # Adds a new object to the object stack, evaluates the given template block,
116
+ # then pops the object off the stack.
117
+ #
118
+ # @param &block [Proc] template block
119
+ # @return [void]
43
120
  def enter_object(&block)
44
- object_stack << nil
121
+ @object_stack << nil
45
122
  instance_eval(&block)
46
- object_stack.pop
47
- end
48
-
49
- def item(value = nil, &block)
50
- verify_array_target
51
- if block
52
- value = enter_object(&block)
53
- end
54
- push_array_item(value)
55
- end
56
-
57
- def kv(key, value, &block)
58
- verify_hash_target
59
- if block
60
- value = enter_object(&block)
61
- end
62
- push_kv_item(key, value)
63
- end
64
-
65
- def method_missing(sym, value = nil, &block)
66
- kv(sym, value, &block)
67
- end
68
-
69
- def to_s
70
- object_stack[0].to_json
71
- end
123
+ @object_stack.pop
124
+ end
72
125
  end
73
126
  end
@@ -80,38 +80,14 @@ module Papercraft
80
80
  end
81
81
  end
82
82
 
83
- INITIAL_BUFFER_CAPACITY = 8192
84
-
85
83
  # Initializes the renderer and evaulates the given template in the
86
84
  # renderer's scope.
87
85
  #
88
86
  # @param &template [Proc] template block
89
87
  def initialize(&template)
90
- @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
91
88
  instance_eval(&template)
92
89
  end
93
90
 
94
- # Returns the rendered template.
95
- #
96
- # @return [String]
97
- def to_s
98
- if @parts
99
- last = @buffer
100
- @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
101
- parts = @parts
102
- @parts = nil
103
- parts.each do |p|
104
- if Proc === p
105
- render_deferred_proc(&p)
106
- else
107
- @buffer << p
108
- end
109
- end
110
- @buffer << last unless last.empty?
111
- end
112
- @buffer
113
- end
114
-
115
91
  # Emits the given object into the rendering buffer. If the given object is a
116
92
  # proc or a component, `emit` will passes any additional arguments and named
117
93
  # arguments to the object when rendering it. If the given object is nil,
@@ -136,8 +112,9 @@ module Papercraft
136
112
  push_emit_yield_block(block) if block
137
113
  instance_exec(*a, **b, &o)
138
114
  when nil
115
+ # do nothing
139
116
  else
140
- @buffer << o.to_s
117
+ emit_object(o)
141
118
  end
142
119
  end
143
120
  alias_method :e, :emit
@@ -157,75 +134,15 @@ module Papercraft
157
134
 
158
135
  instance_exec(*a, **b, &block)
159
136
  end
160
-
161
- # Defers the given block to be evaluated later. Deferred evaluation allows
162
- # Papercraft templates to inject state into sibling components, regardless
163
- # of the component's order in the container component. For example, a nested
164
- # component may set an instance variable used by another component. This is
165
- # an elegant solution to the problem of setting the XML page's title, or
166
- # adding elements to the `<head>` section. Here's how a title can be
167
- # controlled from a nested component:
168
- #
169
- # layout = Papercraft.html {
170
- # html {
171
- # head {
172
- # defer { title @title }
173
- # }
174
- # body {
175
- # emit_yield
176
- # }
177
- # }
178
- # }
179
- #
180
- # html.render {
181
- # @title = 'My super page'
182
- # h1 'content'
183
- # }
184
- #
185
- # @param &block [Proc] Deferred block to be emitted
186
- # @return [void]
187
- def defer(&block)
188
- if !@parts
189
- @parts = [@buffer, block]
190
- else
191
- @parts << @buffer unless @buffer.empty?
192
- @parts << block
193
- end
194
- @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
195
- end
196
137
 
197
138
  private
198
139
 
199
- # Escapes text. This method must be overriden in descendant classes.
200
- #
201
- # @param text [String] text to be escaped
202
- def escape_text(text)
203
- raise NotImplementedError
204
- end
205
-
206
140
  # Pushes the given block onto the emit_yield stack.
207
141
  #
208
142
  # @param block [Proc] block
209
143
  def push_emit_yield_block(block)
210
144
  (@emit_yield_stack ||= []) << block
211
145
  end
212
-
213
- # Renders a deferred proc by evaluating it, then adding the rendered result
214
- # to the buffer.
215
- #
216
- # @param &block [Proc] deferred proc
217
- # @return [void]
218
- def render_deferred_proc(&block)
219
- old_buffer = @buffer
220
-
221
- @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
222
- @parts = nil
223
-
224
- instance_eval(&block)
225
-
226
- old_buffer << to_s
227
- @buffer = old_buffer
228
- end
229
146
  end
230
147
 
231
148
  # Implements an HTML renderer
@@ -238,6 +155,7 @@ module Papercraft
238
155
  include XML
239
156
  end
240
157
 
158
+ # Implements a JSON renderer
241
159
  class JSONRenderer < Renderer
242
160
  include JSON
243
161
  end
@@ -44,6 +44,72 @@ module Papercraft
44
44
  end
45
45
  EOF
46
46
 
47
+ INITIAL_BUFFER_CAPACITY = 8192
48
+
49
+ # Initializes a tag renderer.
50
+ def initialize(&template)
51
+ @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
52
+ super
53
+ end
54
+
55
+ # Returns the rendered template.
56
+ #
57
+ # @return [String]
58
+ def to_s
59
+ if @parts
60
+ last = @buffer
61
+ @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
62
+ parts = @parts
63
+ @parts = nil
64
+ parts.each do |p|
65
+ if Proc === p
66
+ render_deferred_proc(&p)
67
+ else
68
+ @buffer << p
69
+ end
70
+ end
71
+ @buffer << last unless last.empty?
72
+ end
73
+ @buffer
74
+ end
75
+
76
+ # Defers the given block to be evaluated later. Deferred evaluation allows
77
+ # Papercraft templates to inject state into sibling components, regardless
78
+ # of the component's order in the container component. For example, a nested
79
+ # component may set an instance variable used by another component. This is
80
+ # an elegant solution to the problem of setting the XML page's title, or
81
+ # adding elements to the `<head>` section. Here's how a title can be
82
+ # controlled from a nested component:
83
+ #
84
+ # layout = Papercraft.html {
85
+ # html {
86
+ # head {
87
+ # defer { title @title }
88
+ # }
89
+ # body {
90
+ # emit_yield
91
+ # }
92
+ # }
93
+ # }
94
+ #
95
+ # html.render {
96
+ # @title = 'My super page'
97
+ # h1 'content'
98
+ # }
99
+ #
100
+ # @param &block [Proc] Deferred block to be emitted
101
+ # @return [void]
102
+ def defer(&block)
103
+ if !@parts
104
+ @parts = [@buffer, block]
105
+ else
106
+ @parts << @buffer unless @buffer.empty?
107
+ @parts << block
108
+ end
109
+ @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
110
+ end
111
+
112
+
47
113
  # Emits an XML tag with the given content, properties and optional block.
48
114
  # This method is an alternative to emitting XML tags using dynamically
49
115
  # created methods. This is particularly useful when using extensions that
@@ -118,15 +184,58 @@ module Papercraft
118
184
 
119
185
  private
120
186
 
187
+ # Emits an arbitrary object by converting it to string, then adding it to
188
+ # the internal buffer. This method is called internally by `Renderer#emit`.
189
+ #
190
+ # @param obj [Object] emitted object
191
+ # @return [void]
192
+ def emit_object(obj)
193
+ @buffer << obj.to_s
194
+ end
195
+
196
+ # Renders a deferred proc by evaluating it, then adding the rendered result
197
+ # to the buffer.
198
+ #
199
+ # @param &block [Proc] deferred proc
200
+ # @return [void]
201
+ def render_deferred_proc(&block)
202
+ old_buffer = @buffer
203
+
204
+ @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
205
+ @parts = nil
206
+
207
+ instance_eval(&block)
208
+
209
+ old_buffer << to_s
210
+ @buffer = old_buffer
211
+ end
212
+
213
+ # Escapes text. This method must be overriden in Renderers which include
214
+ # this module.
215
+ #
216
+ # @param text [String] text to be escaped
217
+ def escape_text(text)
218
+ raise NotImplementedError
219
+ end
220
+
221
+ # Converts a tag to its string representation. This method must be overriden
222
+ # in Renderers which include this module.
223
+ #
224
+ # @param tag [Symbol, String] tag
121
225
  def tag_repr(tag)
122
- tag.to_s.tr('_', '-')
226
+ raise NotImplementedError
123
227
  end
124
228
 
229
+ # Converts an attribute to its string representation. This method must be
230
+ # overriden in Renderers which include this module.
231
+ #
232
+ # @param att [Symbol, String] attribute
125
233
  def att_repr(att)
126
- att.to_s.tr('_', '-')
234
+ raise NotImplementedError
127
235
  end
128
236
 
129
- # Emits tag attributes into the rendering buffer
237
+ # Emits tag attributes into the rendering buffer.
238
+ #
130
239
  # @param props [Hash] tag attributes
131
240
  # @return [void]
132
241
  def emit_props(props)
@@ -167,6 +167,9 @@ module Papercraft
167
167
  end
168
168
  end
169
169
 
170
+ # Returns the template's associated MIME type.
171
+ #
172
+ # @return [String] MIME type
170
173
  def mime_type
171
174
  @mime_type
172
175
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Papercraft
4
- VERSION = '0.20'
4
+ VERSION = '0.21'
5
5
  end
@@ -10,15 +10,28 @@ module Papercraft
10
10
 
11
11
  private
12
12
 
13
+ # Converts a tag to its string representation. Underscores will be converted
14
+ # to dashes, double underscores will be converted to colon.
15
+ #
16
+ # @param tag [Symbol, String] tag
17
+ # @return [String] tag string
13
18
  def tag_repr(tag)
14
19
  tag.to_s.gsub('__', ':').tr('_', '-')
15
20
  end
16
21
 
22
+ # Converts an attribute to its string representation. Underscores will be
23
+ # converted to dashes, double underscores will be converted to colon.
24
+ #
25
+ # @param att [Symbol, String] attribute
26
+ # @return [String] attribute string
17
27
  def att_repr(att)
18
28
  att.to_s.gsub('__', ':').tr('_', '-')
19
29
  end
20
30
 
21
31
  # Escapes the given text using XML entities.
32
+ #
33
+ # @param text [String] text
34
+ # @return [String] escaped text
22
35
  def escape_text(text)
23
36
  EscapeUtils.escape_xml(text.to_s)
24
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papercraft
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.20'
4
+ version: '0.21'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner