papercraft 0.8.2 → 0.8.3

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: 309174da790e301142b03cc8aad3e966c6b1482d514da8d3910c2e84f6981af6
4
- data.tar.gz: 64fb5b791fce05c0347ba21ccf70160323f70ad708ece9c14222b8544efdf8e0
3
+ metadata.gz: 125df0455a1b4c3373b36b3f52b6d965249a7ddf470439ec48df3f7216ea3991
4
+ data.tar.gz: be9cea2084785a3dc135b852b66f0d91375cafd6050834d06f26f8a6b497f95f
5
5
  SHA512:
6
- metadata.gz: d1f56c25e4854cb6b0ffce1d149d831d51d4141159a44fd6a962c27d9e0878b33e9438d9ad621c0c30a42dfa853b96a26b20c6ebe42243844be2b42d4e2901ef
7
- data.tar.gz: 46952658d3e237f784cfd9b608c82b001fdd188b788c931f0a1a3669d5800d8ed3ef89623f88ff9a617237fbfbbd3a0f9f5b30bfc693b2e6f0b5659f66afa41b
6
+ metadata.gz: f45e9101d8bb14bfdde19958988343d6e4d87e270462a0db13630860aff5d6adc560df90aefd78317642f6987d3853cc68ad8adb7d0b74e381b43930424d7a79
7
+ data.tar.gz: c7a153329948a8fa5dbe90602a293b22e060f0118cc3cdfd629f9af9644f57bea4add8ec13e40a5194178bdebc5dd43a26c0507f03e8dd78e3a3a5662968e390
@@ -14,8 +14,8 @@ module Papercraft
14
14
  # Components are usually created using the global methods `H` or `X`, for HTML
15
15
  # or XML templates, respectively:
16
16
  #
17
- # greeter = H { |name| h1 "Hello, #{name}!" } greeter.render('world') #=>
18
- # "<h1>Hello, world!</h1>"
17
+ # greeter = H { |name| h1 "Hello, #{name}!" }
18
+ # greeter.render('world') #=> "<h1>Hello, world!</h1>"
19
19
  #
20
20
  # Components can also be created using the normal constructor:
21
21
  #
@@ -25,7 +25,10 @@ module Papercraft
25
25
  # In the component block, HTML elements are created by simply calling
26
26
  # unqualified methods:
27
27
  #
28
- # page_layout = H { html5 { head { title 'foo'
28
+ # page_layout = H {
29
+ # html5 {
30
+ # head {
31
+ # title 'foo'
29
32
  # }
30
33
  # body {
31
34
  # h1 "Hello, world!"
@@ -75,7 +78,11 @@ module Papercraft
75
78
  # anchor.apply(uri: '/about', text: 'About')
76
79
  # ])
77
80
  # links_with_anchors.render
81
+ #
78
82
  class Component < Proc
83
+
84
+ # Determines the rendering mode: `:html` or `:xml`.
85
+ attr_accessor :mode
79
86
 
80
87
  # Initializes a component with the given block. The rendering mode (HTML or
81
88
  # XML) can be passed in the `mode:` parameter. If `mode:` is not specified,
@@ -113,15 +120,15 @@ module Papercraft
113
120
  # current one. Application is one of the principal methods of composing
114
121
  # components, particularly when passing inner components as blocks:
115
122
  #
116
- # article_wrapper = H {
117
- # article {
118
- # emit_yield
123
+ # article_wrapper = H {
124
+ # article {
125
+ # emit_yield
126
+ # }
127
+ # }
128
+ # wrapped_article = article_wrapper.apply {
129
+ # h1 'Article title'
119
130
  # }
120
- # }
121
- # wrapped_article = article_wrapper.apply {
122
- # h1 'Article title'
123
- # }
124
- # wrapped_article.render #=> "<article><h1>Article title</h1></article>"
131
+ # wrapped_article.render #=> "<article><h1>Article title</h1></article>"
125
132
  #
126
133
  # @param *a [<any>] normal parameters
127
134
  # @param **b [Hash] named parameters
@@ -3,9 +3,11 @@
3
3
  require_relative './html'
4
4
 
5
5
  module Papercraft
6
- # Markup extensions
6
+
7
+ # HTML Markup extensions
7
8
  module HTML
8
9
  # Emits the p tag (overrides Object#p)
10
+ #
9
11
  # @param text [String] text content of tag
10
12
  # @param props [Hash] tag attributes
11
13
  # @para block [Proc] nested HTML block
@@ -16,7 +18,8 @@ module Papercraft
16
18
 
17
19
  S_HTML5_DOCTYPE = '<!DOCTYPE html>'
18
20
 
19
- # Emits an HTML5 doctype tag and an html tag with the given block
21
+ # Emits an HTML5 doctype tag and an html tag with the given block.
22
+ #
20
23
  # @param block [Proc] nested HTML block
21
24
  # @return [void]
22
25
  def html5(&block)
@@ -24,6 +27,11 @@ module Papercraft
24
27
  self.html(&block)
25
28
  end
26
29
 
30
+ # Emits a link element with a stylesheet.
31
+ #
32
+ # @param href [String] stylesheet URL
33
+ # @param custom_attributes [Hash] optional custom attributes for the link element
34
+ # @return [void]
27
35
  def link_stylesheet(href, custom_attributes = nil)
28
36
  attributes = {
29
37
  rel: 'stylesheet',
@@ -3,9 +3,19 @@
3
3
  require_relative './html'
4
4
 
5
5
  module Papercraft
6
+
6
7
  # A Renderer renders a Papercraft component into a string
7
8
  class Renderer
9
+
8
10
  class << self
11
+
12
+ # Verifies that the given template proc can be called with the given
13
+ # arguments and named arguments. If the proc demands named argument keys
14
+ # that do not exist in `named_args`, `Papercraft::Error` is raised.
15
+ #
16
+ # @param template [Proc] proc to verify
17
+ # @param args [Array<any>] arguments passed to proc
18
+ # @param named_args [Hash] named arguments passed to proc
9
19
  def verify_proc_parameters(template, args, named_args)
10
20
  param_count = 0
11
21
  template.parameters.each do |(type, name)|
@@ -24,31 +34,22 @@ module Papercraft
24
34
  end
25
35
  end
26
36
 
27
- attr_reader :context
28
-
29
- # Initializes attributes and renders the given block
30
- # @param context [Hash] rendering context
31
- # @param block [Proc] template block
32
- # @return [void]
37
+ # Initializes the renderer and evaulates the given template in the
38
+ # renderer's scope.
39
+ #
40
+ # @param &template [Proc] template block
33
41
  def initialize(&template)
34
42
  @buffer = +''
35
43
  instance_eval(&template)
36
44
  end
37
45
 
38
- # Returns the result of the rendering
46
+ # Returns the rendered template.
47
+ #
39
48
  # @return [String]
40
49
  def to_s
41
50
  @buffer
42
51
  end
43
52
 
44
- def escape_text(text)
45
- raise NotImplementedError
46
- end
47
-
48
- def escape_uri(uri)
49
- EscapeUtils.escape_uri(v)
50
- end
51
-
52
53
  S_TAG_METHOD_LINE = __LINE__ + 1
53
54
  S_TAG_METHOD = <<~EOF
54
55
  S_TAG_%<TAG>s_PRE = '<%<tag>s'.tr('_', '-')
@@ -74,10 +75,12 @@ module Papercraft
74
75
  end
75
76
  EOF
76
77
 
77
- # Catches undefined tag method call and handles them by defining the method
78
+ # Catches undefined tag method call and handles it by defining the method.
79
+ #
78
80
  # @param sym [Symbol] HTML tag or component identifier
79
- # @param args [Array] method call arguments
80
- # @param block [Proc] block passed to method call
81
+ # @param args [Array] method arguments
82
+ # @param opts [Hash] named method arguments
83
+ # @param &block [Proc] block passed to method
81
84
  # @return [void]
82
85
  def method_missing(sym, *args, **opts, &block)
83
86
  value = @local && @local[sym]
@@ -89,18 +92,28 @@ module Papercraft
89
92
  send(sym, *args, **opts, &block)
90
93
  end
91
94
 
92
- # Emits the given object into the rendering buffer
95
+ # Emits the given object into the rendering buffer. If the given object is a
96
+ # proc or a component, `emit` will passes any additional arguments and named
97
+ # arguments to the object when rendering it. If the given object is nil,
98
+ # nothing is emitted. Otherwise, the object is converted into a string using
99
+ # `#to_s` which is then added to the rendering buffer, without any escaping.
100
+ #
101
+ # greeter = proc { |name| h1 "Hello, #{name}!" }
102
+ # H { emit(greeter, 'world') }.render #=> "<h1>Hello, world!</h1>"
103
+ #
104
+ # H { emit 'hi&<bye>' }.render #=> "hi&<bye>"
105
+ #
106
+ # H { emit nil }.render #=> ""
107
+ #
93
108
  # @param o [Proc, Papercraft::Component, String] emitted object
109
+ # @param *a [Array<any>] arguments to pass to a proc
110
+ # @param **b [Hash] named arguments to pass to a proc
94
111
  # @return [void]
95
112
  def emit(o, *a, **b)
96
113
  case o
97
114
  when ::Proc
98
115
  Renderer.verify_proc_parameters(o, a, b)
99
116
  instance_exec(*a, **b, &o)
100
- # when Papercraft::Component
101
- # o = o.template
102
- # Renderer.verify_proc_parameters(o, a, b)
103
- # instance_exec(*a, **b, &o)
104
117
  when nil
105
118
  else
106
119
  @buffer << o.to_s
@@ -108,14 +121,15 @@ module Papercraft
108
121
  end
109
122
  alias_method :e, :emit
110
123
 
111
- def with_block(block, &run_block)
112
- old_block = @inner_block
113
- @inner_block = block
114
- instance_eval(&run_block)
115
- ensure
116
- @inner_block = old_block
117
- end
118
-
124
+ # Emits a block supplied using `Component#apply` or `Component#render`.
125
+ #
126
+ # div_wrap = H { |*args| div { emit_yield(*args) } }
127
+ # greeter = div_wrap.apply { |name| h1 "Hello, #{name}!" }
128
+ # greeter.render('world') #=> "<div><h1>Hello, world!</h1></div>"
129
+ #
130
+ # @param *a [Array<any>] arguments to pass to a proc
131
+ # @param **b [Hash] named arguments to pass to a proc
132
+ # @return [void]
119
133
  def emit_yield(*a, **b)
120
134
  raise Papercraft::Error, "No block given" unless @inner_block
121
135
 
@@ -131,6 +145,31 @@ module Papercraft
131
145
  S_EQUAL_QUOTE = '="'
132
146
  S_QUOTE = '"'
133
147
 
148
+ # Emits text into the rendering buffer, escaping any special characters to
149
+ # the respective HTML entities.
150
+ #
151
+ # @param data [String] text
152
+ # @return [void]
153
+ def text(data)
154
+ @buffer << escape_text(data)
155
+ end
156
+
157
+ private
158
+
159
+ # Escapes text. This method must be overriden in descendant classes.
160
+ def escape_text(text)
161
+ raise NotImplementedError
162
+ end
163
+
164
+ # Sets up a block to be called with `#emit_yield`
165
+ def with_block(block, &run_block)
166
+ old_block = @inner_block
167
+ @inner_block = block
168
+ instance_eval(&run_block)
169
+ ensure
170
+ @inner_block = old_block
171
+ end
172
+
134
173
  # Emits tag attributes into the rendering buffer
135
174
  # @param props [Hash] tag attributes
136
175
  # @return [void]
@@ -153,23 +192,23 @@ module Papercraft
153
192
  end
154
193
  }
155
194
  end
156
-
157
- # Emits text into the rendering buffer
158
- # @param data [String] text
159
- def text(data)
160
- @buffer << escape_text(data)
161
- end
162
195
  end
163
196
 
197
+ # Implements an HTML renderer
164
198
  class HTMLRenderer < Renderer
165
199
  include HTML
166
200
 
201
+ private
202
+
167
203
  def escape_text(text)
168
204
  EscapeUtils.escape_html(text.to_s)
169
205
  end
170
206
  end
171
207
 
208
+ # Implements an XML renderer
172
209
  class XMLRenderer < Renderer
210
+ private
211
+
173
212
  def escape_text(text)
174
213
  EscapeUtils.escape_xml(text.to_s)
175
214
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Papercraft
4
- VERSION = '0.8.2'
4
+ VERSION = '0.8.3'
5
5
  end
data/lib/papercraft.rb CHANGED
@@ -15,20 +15,32 @@ end
15
15
 
16
16
  # Kernel extensions
17
17
  module ::Kernel
18
- # Convenience method for creating a new Papercraft
19
- # @param ctx [Hash] local context
18
+
19
+ # Creates a new papercraft component. `#H` can take either a proc argument or
20
+ # a block. In both cases, the proc is converted to a `Papercraft::Component`.
21
+ #
22
+ # H(proc { h1 'hi' }).render #=> "<h1>hi</h1>"
23
+ # H { h1 'hi' }.render #=> "<h1>hi</h1>"
24
+ #
20
25
  # @param template [Proc] template block
21
- # @return [Papercraft] Papercraft template
22
- def H(&template)
23
- Papercraft::Component.new(&template)
26
+ # @return [Papercraft::Component] Papercraft component
27
+ def H(o = nil, &template)
28
+ return o if o.is_a?(Papercraft::Component)
29
+ template ||= o
30
+ Papercraft::Component.new(mode: :html, &template)
24
31
  end
25
32
 
26
- def X(&template)
33
+ # Creates a new papercraft component in XML mode. `#X` can take either a proc argument or
34
+ # a block. In both cases, the proc is converted to a `Papercraft::Component`.
35
+ #
36
+ # X(proc { item 'foo' }).render #=> "<item>foo</item>"
37
+ # X { item 'foo' }.render #=> "<item>foo</item>"
38
+ #
39
+ # @param template [Proc] template block
40
+ # @return [Papercraft::Component] Papercraft component
41
+ def X(o = nil, &template)
42
+ return o if o.is_a?(Papercraft::Component)
43
+ template ||= o
27
44
  Papercraft::Component.new(mode: :xml, &template)
28
45
  end
29
46
  end
30
-
31
- # Object extensions
32
- class Object
33
- include Papercraft::Encoding
34
- 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.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner