papercraft 0.19 → 0.20

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: f0f4910bd26625ca0349b1c471338fb4d13e8055e88367b5cad16f91cdee7531
4
- data.tar.gz: 38e43978278ba069e3767abd94d83c676f42692f5eb55f1be4b4067fae2f935e
3
+ metadata.gz: 2eaf6ba31b9300176af0bf55b76f7bbdc16508d0e495ed1d76f9f273ea88f250
4
+ data.tar.gz: 90e132928ebfe78e577e71c8dc498f0ce1b1f2c58f453fbedaad96121c448a48
5
5
  SHA512:
6
- metadata.gz: b096452cebe7b6bb34a428f4920a5940e5b745c86b54188a984a77df6175145cf6645753e6ae58b3df89813919920a17a96610e010724bc50077c6f9accc7293
7
- data.tar.gz: 8d1cd5b2d6b70ee9ef0a748a064bbd6d1630cfa926663aded95a01c26ce289a159e2548068bf8210c5e8d37ba26c9671eb4a00fe4790a47bec6dd822b4de5d5d
6
+ metadata.gz: fcada325a3f8cd1c4cbe38674efaf6a86d0eb947ad5815d07778e2a09a54bee2c7d6b731e87d110390e9c87abc0a61f81cbc4cb30fdce11a4fc8a8cd322466a0
7
+ data.tar.gz: 031c86f7dade95af3dca979b4543fcb26e1fab2eb98c5642746d6efcf8b4bd56fe30b70f2f5aa8309352f421cae9f116a901f464216f54a0be50630dcc52815f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.20 2022-02-13
2
+
3
+ - Add support for XML namespaced tags and attributes (#9)
4
+ - Move and refactor HTML/XML common code to Tags module
5
+
1
6
  ## 0.19 2022-02-05
2
7
 
3
8
  - Rename `Papercraft::Component` to `Papercraft::Template`
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './tags'
4
+
3
5
  module Papercraft
4
6
  # HTML Markup extensions
5
7
  module HTML
8
+ include Tags
9
+
6
10
  # Emits the p tag (overrides Object#p)
7
11
  #
8
12
  # @param text [String] text content of tag
@@ -81,5 +85,12 @@ module Papercraft
81
85
  def emit_markdown(markdown, **opts)
82
86
  emit Papercraft.markdown(markdown, **opts)
83
87
  end
88
+
89
+ private
90
+
91
+ # Escapes the given text using XML entities.
92
+ def escape_text(text)
93
+ EscapeUtils.escape_html(text.to_s)
94
+ end
84
95
  end
85
96
  end
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'escape_utils'
4
-
5
3
  require_relative './html'
4
+ require_relative './xml'
6
5
  require_relative './json'
7
6
  require_relative './extension_proxy'
8
7
 
@@ -10,7 +9,7 @@ module Papercraft
10
9
 
11
10
  # A Renderer renders a Papercraft template into a string
12
11
  class Renderer
13
-
12
+
14
13
  class << self
15
14
 
16
15
  # Verifies that the given template proc can be called with the given
@@ -45,7 +44,7 @@ module Papercraft
45
44
  # methods to extension modules. The methods will be available to all
46
45
  # Papercraft templates. Extension methods are executed in the context of
47
46
  # the the renderer instance, so they can look just like normal proc
48
- # components. In cases where method names in the module clash with HTML
47
+ # components. In cases where method names in the module clash with XML
49
48
  # tag names, you can use the `#tag` method to emit the relevant tag.
50
49
  #
51
50
  # module ComponentLibrary
@@ -113,99 +112,6 @@ module Papercraft
113
112
  @buffer
114
113
  end
115
114
 
116
- # The tag method template below is optimized for performance. Do not touch!
117
-
118
- S_TAG_METHOD_LINE = __LINE__ + 2
119
- S_TAG_METHOD = <<~EOF
120
- S_TAG_%<TAG>s_PRE = %<tag_pre>s
121
- S_TAG_%<TAG>s_CLOSE = %<tag_close>s
122
-
123
- def %<tag>s(text = nil, **props, &block)
124
- if text.is_a?(Hash) && props.empty?
125
- props = text
126
- text = nil
127
- end
128
-
129
- @buffer << S_TAG_%<TAG>s_PRE
130
- emit_props(props) unless props.empty?
131
-
132
- if block
133
- @buffer << S_GT
134
- instance_eval(&block)
135
- @buffer << S_TAG_%<TAG>s_CLOSE
136
- elsif Proc === text
137
- @buffer << S_GT
138
- emit(text)
139
- @buffer << S_TAG_%<TAG>s_CLOSE
140
- elsif text
141
- @buffer << S_GT << escape_text(text.to_s) << S_TAG_%<TAG>s_CLOSE
142
- else
143
- @buffer << S_SLASH_GT
144
- end
145
- end
146
- EOF
147
-
148
- # Emits an HTML tag with the given content, properties and optional block.
149
- # This method is an alternative to emitting HTML tags using dynamically
150
- # created methods. This is particularly useful when using extensions that
151
- # have method names that clash with HTML tags, such as `button` or `a`, or
152
- # when you need to override the behaviour of a particular HTML tag.
153
- #
154
- # The following two method calls have the same effect:
155
- #
156
- # button 'text', id: 'button1'
157
- # tag :button, 'text', id: 'button1'
158
- #
159
- # @param sym [Symbol, String] HTML tag
160
- # @param text [String, nil] tag content
161
- # @param **props [Hash] tag attributes
162
- # @param &block [Proc] optional inner HTML
163
- # @return [void]
164
- def tag(sym, text = nil, **props, &block)
165
- if text.is_a?(Hash) && props.empty?
166
- props = text
167
- text = nil
168
- end
169
-
170
- tag = sym.to_s.tr('_', '-')
171
-
172
- @buffer << S_LT << tag
173
- emit_props(props) unless props.empty?
174
-
175
- if block
176
- @buffer << S_GT
177
- instance_eval(&block)
178
- @buffer << S_LT_SLASH << tag << S_GT
179
- elsif Proc === text
180
- @buffer << S_GT
181
- emit(text)
182
- @buffer << S_LT_SLASH << tag << S_GT
183
- elsif text
184
- @buffer << S_GT << escape_text(text.to_s) << S_LT_SLASH << tag << S_GT
185
- else
186
- @buffer << S_SLASH_GT
187
- end
188
- end
189
-
190
- # Catches undefined tag method call and handles it by defining the method.
191
- #
192
- # @param sym [Symbol] HTML tag or component identifier
193
- # @param args [Array] method arguments
194
- # @param opts [Hash] named method arguments
195
- # @param &block [Proc] block passed to method
196
- # @return [void]
197
- def method_missing(sym, *args, **opts, &block)
198
- tag = sym.to_s
199
- code = S_TAG_METHOD % {
200
- tag: tag,
201
- TAG: tag.upcase,
202
- tag_pre: "<#{tag.tr('_', '-')}".inspect,
203
- tag_close: "</#{tag.tr('_', '-')}>".inspect
204
- }
205
- self.class.class_eval(code, __FILE__, S_TAG_METHOD_LINE)
206
- send(sym, *args, **opts, &block)
207
- end
208
-
209
115
  # Emits the given object into the rendering buffer. If the given object is a
210
116
  # proc or a component, `emit` will passes any additional arguments and named
211
117
  # arguments to the object when rendering it. If the given object is nil,
@@ -256,7 +162,7 @@ module Papercraft
256
162
  # Papercraft templates to inject state into sibling components, regardless
257
163
  # of the component's order in the container component. For example, a nested
258
164
  # component may set an instance variable used by another component. This is
259
- # an elegant solution to the problem of setting the HTML page's title, or
165
+ # an elegant solution to the problem of setting the XML page's title, or
260
166
  # adding elements to the `<head>` section. Here's how a title can be
261
167
  # controlled from a nested component:
262
168
  #
@@ -288,24 +194,6 @@ module Papercraft
288
194
  @buffer = String.new(capacity: INITIAL_BUFFER_CAPACITY)
289
195
  end
290
196
 
291
- S_LT = '<'
292
- S_GT = '>'
293
- S_LT_SLASH = '</'
294
- S_SPACE_LT_SLASH = ' </'
295
- S_SLASH_GT = '/>'
296
- S_SPACE = ' '
297
- S_EQUAL_QUOTE = '="'
298
- S_QUOTE = '"'
299
-
300
- # Emits text into the rendering buffer, escaping any special characters to
301
- # the respective HTML entities.
302
- #
303
- # @param data [String] text
304
- # @return [void]
305
- def text(data)
306
- @buffer << escape_text(data)
307
- end
308
-
309
197
  private
310
198
 
311
199
  # Escapes text. This method must be overriden in descendant classes.
@@ -322,29 +210,6 @@ module Papercraft
322
210
  (@emit_yield_stack ||= []) << block
323
211
  end
324
212
 
325
- # Emits tag attributes into the rendering buffer
326
- # @param props [Hash] tag attributes
327
- # @return [void]
328
- def emit_props(props)
329
- props.each { |k, v|
330
- case k
331
- when :src, :href
332
- @buffer << S_SPACE << k.to_s << S_EQUAL_QUOTE <<
333
- EscapeUtils.escape_uri(v) << S_QUOTE
334
- else
335
- case v
336
- when true
337
- @buffer << S_SPACE << k.to_s.tr('_', '-')
338
- when false, nil
339
- # emit nothing
340
- else
341
- @buffer << S_SPACE << k.to_s.tr('_', '-') <<
342
- S_EQUAL_QUOTE << v << S_QUOTE
343
- end
344
- end
345
- }
346
- end
347
-
348
213
  # Renders a deferred proc by evaluating it, then adding the rendered result
349
214
  # to the buffer.
350
215
  #
@@ -366,23 +231,11 @@ module Papercraft
366
231
  # Implements an HTML renderer
367
232
  class HTMLRenderer < Renderer
368
233
  include HTML
369
-
370
- private
371
-
372
- # Escapes the given text using HTML entities.
373
- def escape_text(text)
374
- EscapeUtils.escape_html(text.to_s)
375
- end
376
234
  end
377
235
 
378
236
  # Implements an XML renderer
379
237
  class XMLRenderer < Renderer
380
- private
381
-
382
- # Escapes the given text using XML entities.
383
- def escape_text(text)
384
- EscapeUtils.escape_xml(text.to_s)
385
- end
238
+ include XML
386
239
  end
387
240
 
388
241
  class JSONRenderer < Renderer
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Papercraft
4
+ # Markup (HTML/XML) extensions
5
+ module Tags
6
+ S_LT = '<'
7
+ S_GT = '>'
8
+ S_LT_SLASH = '</'
9
+ S_SPACE_LT_SLASH = ' </'
10
+ S_SLASH_GT = '/>'
11
+ S_SPACE = ' '
12
+ S_EQUAL_QUOTE = '="'
13
+ S_QUOTE = '"'
14
+
15
+ # The tag method template below is optimized for performance. Do not touch!
16
+
17
+ S_TAG_METHOD_LINE = __LINE__ + 2
18
+ S_TAG_METHOD = <<~EOF
19
+ S_TAG_%<TAG>s_PRE = %<tag_pre>s
20
+ S_TAG_%<TAG>s_CLOSE = %<tag_close>s
21
+
22
+ def %<tag>s(text = nil, **props, &block)
23
+ if text.is_a?(Hash) && props.empty?
24
+ props = text
25
+ text = nil
26
+ end
27
+
28
+ @buffer << S_TAG_%<TAG>s_PRE
29
+ emit_props(props) unless props.empty?
30
+
31
+ if block
32
+ @buffer << S_GT
33
+ instance_eval(&block)
34
+ @buffer << S_TAG_%<TAG>s_CLOSE
35
+ elsif Proc === text
36
+ @buffer << S_GT
37
+ emit(text)
38
+ @buffer << S_TAG_%<TAG>s_CLOSE
39
+ elsif text
40
+ @buffer << S_GT << escape_text(text.to_s) << S_TAG_%<TAG>s_CLOSE
41
+ else
42
+ @buffer << S_SLASH_GT
43
+ end
44
+ end
45
+ EOF
46
+
47
+ # Emits an XML tag with the given content, properties and optional block.
48
+ # This method is an alternative to emitting XML tags using dynamically
49
+ # created methods. This is particularly useful when using extensions that
50
+ # have method names that clash with XML tags, such as `button` or `a`, or
51
+ # when you need to override the behaviour of a particular XML tag.
52
+ #
53
+ # The following two method calls have the same effect:
54
+ #
55
+ # button 'text', id: 'button1'
56
+ # tag :button, 'text', id: 'button1'
57
+ #
58
+ # @param sym [Symbol, String] XML tag
59
+ # @param text [String, nil] tag content
60
+ # @param **props [Hash] tag attributes
61
+ # @param &block [Proc] optional inner XML
62
+ # @return [void]
63
+ def tag(sym, text = nil, **props, &block)
64
+ if text.is_a?(Hash) && props.empty?
65
+ props = text
66
+ text = nil
67
+ end
68
+
69
+ tag = tag_repr(sym)
70
+
71
+ @buffer << S_LT << tag
72
+ emit_props(props) unless props.empty?
73
+
74
+ if block
75
+ @buffer << S_GT
76
+ instance_eval(&block)
77
+ @buffer << S_LT_SLASH << tag << S_GT
78
+ elsif Proc === text
79
+ @buffer << S_GT
80
+ emit(text)
81
+ @buffer << S_LT_SLASH << tag << S_GT
82
+ elsif text
83
+ @buffer << S_GT << escape_text(text.to_s) << S_LT_SLASH << tag << S_GT
84
+ else
85
+ @buffer << S_SLASH_GT
86
+ end
87
+ end
88
+
89
+ # Catches undefined tag method call and handles it by defining the method.
90
+ #
91
+ # @param sym [Symbol] XML tag or component identifier
92
+ # @param args [Array] method arguments
93
+ # @param opts [Hash] named method arguments
94
+ # @param &block [Proc] block passed to method
95
+ # @return [void]
96
+ def method_missing(sym, *args, **opts, &block)
97
+ # p method_missing: sym, self: self
98
+ tag = sym.to_s
99
+ repr = tag_repr(tag)
100
+ code = S_TAG_METHOD % {
101
+ tag: tag,
102
+ TAG: tag.upcase,
103
+ tag_pre: "<#{repr}".inspect,
104
+ tag_close: "</#{repr}>".inspect
105
+ }
106
+ self.class.class_eval(code, __FILE__, S_TAG_METHOD_LINE)
107
+ send(sym, *args, **opts, &block)
108
+ end
109
+
110
+ # Emits text into the rendering buffer, escaping any special characters to
111
+ # the respective XML entities.
112
+ #
113
+ # @param data [String] text
114
+ # @return [void]
115
+ def text(data)
116
+ @buffer << escape_text(data)
117
+ end
118
+
119
+ private
120
+
121
+ def tag_repr(tag)
122
+ tag.to_s.tr('_', '-')
123
+ end
124
+
125
+ def att_repr(att)
126
+ att.to_s.tr('_', '-')
127
+ end
128
+
129
+ # Emits tag attributes into the rendering buffer
130
+ # @param props [Hash] tag attributes
131
+ # @return [void]
132
+ def emit_props(props)
133
+ props.each { |k, v|
134
+ case k
135
+ when :src, :href
136
+ @buffer << S_SPACE << k.to_s << S_EQUAL_QUOTE <<
137
+ EscapeUtils.escape_uri(v) << S_QUOTE
138
+ else
139
+ case v
140
+ when true
141
+ @buffer << S_SPACE << att_repr(k)
142
+ when false, nil
143
+ # emit nothing
144
+ else
145
+ @buffer << S_SPACE << att_repr(k) <<
146
+ S_EQUAL_QUOTE << v << S_QUOTE
147
+ end
148
+ end
149
+ }
150
+ end
151
+ end
152
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Papercraft
4
- VERSION = '0.19'
4
+ VERSION = '0.20'
5
5
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'escape_utils'
4
+ require_relative './tags'
5
+
6
+ module Papercraft
7
+ # XML renderer extensions
8
+ module XML
9
+ include Tags
10
+
11
+ private
12
+
13
+ def tag_repr(tag)
14
+ tag.to_s.gsub('__', ':').tr('_', '-')
15
+ end
16
+
17
+ def att_repr(att)
18
+ att.to_s.gsub('__', ':').tr('_', '-')
19
+ end
20
+
21
+ # Escapes the given text using XML entities.
22
+ def escape_text(text)
23
+ EscapeUtils.escape_xml(text.to_s)
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papercraft
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.19'
4
+ version: '0.20'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-05 00:00:00.000000000 Z
11
+ date: 2022-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: escape_utils
@@ -139,8 +139,10 @@ files:
139
139
  - lib/papercraft/html.rb
140
140
  - lib/papercraft/json.rb
141
141
  - lib/papercraft/renderer.rb
142
+ - lib/papercraft/tags.rb
142
143
  - lib/papercraft/template.rb
143
144
  - lib/papercraft/version.rb
145
+ - lib/papercraft/xml.rb
144
146
  - papercraft.png
145
147
  homepage: http://github.com/digital-fabric/papercraft
146
148
  licenses: