papercraft 0.20 → 0.21

Sign up to get free protection for your applications and to get access to all the features.
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