papercraft 0.15 → 0.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/README.md +66 -33
- data/lib/papercraft/component.rb +30 -11
- data/lib/papercraft/json.rb +73 -0
- data/lib/papercraft/renderer.rb +11 -6
- data/lib/papercraft/version.rb +1 -1
- data/lib/papercraft.rb +29 -16
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 996d95088c85415ca883c27b6b1c98e65af5c046e3121ea08f092ac7bcdcc588
|
4
|
+
data.tar.gz: 8fe294225c04dcfc82289fd2b9047760260b814712e83e9bf5ea7d361dad6950
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54fdbe164a4a2541153e57b90cdb35ba71b6887fbe2d199505da3389730f1bd937fe0254f8c019b39d81957058c5f51ad71bc900f324e3178b979f368642ee57
|
7
|
+
data.tar.gz: fa05ea9ae79a57a3eace2e708b01fe5f44412591875776cf1a2fe95cc6d9d1586357756e702e8a17e5458b3fa4c3e3224290bc234b71fdcd426db0dedff31dc0
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.16 2022-01-23
|
2
|
+
|
3
|
+
- Implement JSON templating (#7)
|
4
|
+
- Add support for MIME types (#6)
|
5
|
+
- Change entrypoint from `Kernel#H`, `Kernel#X` to `Papercraft.html`, `.xml` (#5)
|
6
|
+
|
1
7
|
## 0.15 2022-01-20
|
2
8
|
|
3
9
|
- Fix tag method line reference
|
@@ -42,7 +48,7 @@
|
|
42
48
|
## 0.8 2021-12-22
|
43
49
|
|
44
50
|
- Cleanup and refactor code
|
45
|
-
- Add
|
51
|
+
- Add Papercraft.xml global method for XML templates
|
46
52
|
- Make `Component` a descendant of `Proc`
|
47
53
|
- Introduce new component API
|
48
54
|
- Rename Rubyoshka to Papercraft
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
Papercraft
|
5
5
|
</h1>
|
6
6
|
|
7
|
-
<h4 align="center">Composable
|
7
|
+
<h4 align="center">Composable templating for Ruby</h4>
|
8
8
|
|
9
9
|
<p align="center">
|
10
10
|
<a href="http://rubygems.org/gems/papercraft">
|
@@ -27,26 +27,28 @@
|
|
27
27
|
```ruby
|
28
28
|
require 'papercraft'
|
29
29
|
|
30
|
-
page =
|
30
|
+
page = Papercraft.html { |*args|
|
31
31
|
html {
|
32
32
|
head { }
|
33
33
|
body { emit_yield *args }
|
34
34
|
}
|
35
35
|
}
|
36
|
+
page.render { p 'foo' }
|
37
|
+
#=> "<html><head/><body><p>foo</p></body></html>"
|
36
38
|
|
37
|
-
hello =
|
39
|
+
hello = page.apply { |name| h1 "Hello, #{name}!" }
|
38
40
|
hello.render('world')
|
39
41
|
#=> "<html><head/><body><h1>Hello, world!</h1></body></html>"
|
40
42
|
```
|
41
43
|
|
42
|
-
Papercraft is
|
43
|
-
features:
|
44
|
+
Papercraft is a templating engine for Ruby that offers the following features:
|
44
45
|
|
45
|
-
- HTML and
|
46
|
+
- HTML, XML and JSON templating using plain Ruby syntax
|
46
47
|
- Minimal boilerplate
|
47
48
|
- Mix logic and tags freely
|
48
49
|
- Automatic HTML and XML escaping
|
49
50
|
- Composable components
|
51
|
+
- Standard or custom MIME types
|
50
52
|
- Explicit parameter passing to nested components
|
51
53
|
- Higher order components
|
52
54
|
- Built-in support for rendering [Markdown](#emitting-markdown)
|
@@ -73,7 +75,7 @@ To create a template use the global method `Kernel#H`:
|
|
73
75
|
```ruby
|
74
76
|
require 'papercraft'
|
75
77
|
|
76
|
-
html =
|
78
|
+
html = Papercraft.html {
|
77
79
|
div(id: 'greeter') { p 'Hello!' }
|
78
80
|
}
|
79
81
|
```
|
@@ -89,7 +91,7 @@ html.render #=> "<div id="greeter"><p>Hello!</p></div>"
|
|
89
91
|
Tags are added using unqualified method calls, and can be nested using blocks:
|
90
92
|
|
91
93
|
```ruby
|
92
|
-
|
94
|
+
Papercraft.html {
|
93
95
|
html {
|
94
96
|
head {
|
95
97
|
title 'page title'
|
@@ -106,19 +108,19 @@ H {
|
|
106
108
|
Tag methods accept a string argument, a block, or no argument at all:
|
107
109
|
|
108
110
|
```ruby
|
109
|
-
|
111
|
+
Papercraft.html { p 'hello' }.render #=> "<p>hello</p>"
|
110
112
|
|
111
|
-
|
113
|
+
Papercraft.html { p { span '1'; span '2' } }.render #=> "<p><span>1</span><span>2</span></p>"
|
112
114
|
|
113
|
-
|
115
|
+
Papercraft.html { hr() }.render #=> "<hr/>"
|
114
116
|
```
|
115
117
|
|
116
118
|
Tag methods also accept tag attributes, given as a hash:
|
117
119
|
|
118
120
|
```ruby
|
119
|
-
|
121
|
+
Papercraft.html { img src: '/my.gif' }.render #=> "<img src="/my.gif"/>
|
120
122
|
|
121
|
-
|
123
|
+
Papercraft.html { p "foobar", class: 'important' }.render #=> "<p class=\"important\">foobar</p>"
|
122
124
|
```
|
123
125
|
|
124
126
|
## Template parameters
|
@@ -128,14 +130,14 @@ parameters are specified as block parameters, and are passed to the template on
|
|
128
130
|
rendering:
|
129
131
|
|
130
132
|
```ruby
|
131
|
-
greeting =
|
133
|
+
greeting = Papercraft.html { |name| h1 "Hello, #{name}!" }
|
132
134
|
greeting.render('world') #=> "<h1>Hello, world!</h1>"
|
133
135
|
```
|
134
136
|
|
135
137
|
Templates can also accept named parameters:
|
136
138
|
|
137
139
|
```ruby
|
138
|
-
greeting =
|
140
|
+
greeting = Papercraft.html { |name:| h1 "Hello, #{name}!" }
|
139
141
|
greeting.render(name: 'world') #=> "<h1>Hello, world!</h1>"
|
140
142
|
```
|
141
143
|
|
@@ -145,7 +147,7 @@ Since Papercraft templates are just a bunch of Ruby, you can easily write your
|
|
145
147
|
view logic right in the template:
|
146
148
|
|
147
149
|
```ruby
|
148
|
-
|
150
|
+
Papercraft.html { |user = nil|
|
149
151
|
if user
|
150
152
|
span "Hello, #{user.name}!"
|
151
153
|
else
|
@@ -159,7 +161,7 @@ H { |user = nil|
|
|
159
161
|
Templates can also accept and render blocks by using `emit_yield`:
|
160
162
|
|
161
163
|
```ruby
|
162
|
-
page =
|
164
|
+
page = Papercraft.html {
|
163
165
|
html {
|
164
166
|
body { emit_yield }
|
165
167
|
}
|
@@ -176,14 +178,14 @@ it by passing it as a block to `H`:
|
|
176
178
|
|
177
179
|
```ruby
|
178
180
|
greeting = proc { |name| h1 "Hello, #{name}!" }
|
179
|
-
|
181
|
+
Papercraft.html(&greeting).render('world')
|
180
182
|
```
|
181
183
|
|
182
184
|
Components can also be expressed using lambda notation:
|
183
185
|
|
184
186
|
```ruby
|
185
187
|
greeting = ->(name) { h1 "Hello, #{name}!" }
|
186
|
-
|
188
|
+
Papercraft.html(&greeting).render('world')
|
187
189
|
```
|
188
190
|
|
189
191
|
## Component composition
|
@@ -210,7 +212,7 @@ ItemList = ->(items) {
|
|
210
212
|
}
|
211
213
|
}
|
212
214
|
|
213
|
-
page =
|
215
|
+
page = Papercraft.html { |title, items|
|
214
216
|
html5 {
|
215
217
|
head { Title(title) }
|
216
218
|
body { ItemList(items) }
|
@@ -229,7 +231,7 @@ non-constant components by invoking the `#emit` method:
|
|
229
231
|
```ruby
|
230
232
|
greeting = -> { span "Hello, world" }
|
231
233
|
|
232
|
-
|
234
|
+
Papercraft.html {
|
233
235
|
div {
|
234
236
|
emit greeting
|
235
237
|
}
|
@@ -247,12 +249,12 @@ or block to the original component:
|
|
247
249
|
|
248
250
|
```ruby
|
249
251
|
# parameter application
|
250
|
-
hello =
|
252
|
+
hello = Papercraft.html { |name| h1 "Hello, #{name}!" }
|
251
253
|
hello_world = hello.apply('world')
|
252
254
|
hello_world.render #=> "<h1>Hello, world!</h1>"
|
253
255
|
|
254
256
|
# block application
|
255
|
-
div_wrap =
|
257
|
+
div_wrap = Papercraft.html { div { emit_yield } }
|
256
258
|
wrapped_h1 = div_wrap.apply { h1 'hi' }
|
257
259
|
wrapped_h1.render #=> "<div><h1>hi</h1></div>"
|
258
260
|
|
@@ -271,8 +273,8 @@ markup, enhancing components or injecting component parameters.
|
|
271
273
|
Here is a HOC that takes a component as parameter:
|
272
274
|
|
273
275
|
```ruby
|
274
|
-
div_wrap =
|
275
|
-
greeter =
|
276
|
+
div_wrap = Papercraft.html { |inner| div { emit inner } }
|
277
|
+
greeter = Papercraft.html { h1 'hi' }
|
276
278
|
wrapped_greeter = div_wrap.apply(greeter)
|
277
279
|
wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
|
278
280
|
```
|
@@ -280,7 +282,7 @@ wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
|
|
280
282
|
The inner component can also be passed as a block, as shown above:
|
281
283
|
|
282
284
|
```ruby
|
283
|
-
div_wrap =
|
285
|
+
div_wrap = Papercraft.html { div { emit_yield } }
|
284
286
|
wrapped_greeter = div_wrap.apply { h1 'hi' }
|
285
287
|
wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
|
286
288
|
```
|
@@ -294,7 +296,7 @@ this by creating a `default` page template that takes a block, then use `#apply`
|
|
294
296
|
to create the other templates:
|
295
297
|
|
296
298
|
```ruby
|
297
|
-
default_layout =
|
299
|
+
default_layout = Papercraft.html { |**params|
|
298
300
|
html5 {
|
299
301
|
head {
|
300
302
|
title: params[:title]
|
@@ -323,7 +325,7 @@ article_layout.render(
|
|
323
325
|
Raw HTML can be emitted using `#emit`:
|
324
326
|
|
325
327
|
```ruby
|
326
|
-
wrapped =
|
328
|
+
wrapped = Papercraft.html { |html| div { emit html } }
|
327
329
|
wrapped.render("<h1>hi</h1>") #=> "<div><h1>hi</h1></div>"
|
328
330
|
```
|
329
331
|
|
@@ -333,7 +335,7 @@ To emit a string with proper HTML encoding, without wrapping it in an HTML
|
|
333
335
|
element, use `#text`:
|
334
336
|
|
335
337
|
```ruby
|
336
|
-
|
338
|
+
Papercraft.html { str 'hi&lo' }.render #=> "hi&lo"
|
337
339
|
```
|
338
340
|
|
339
341
|
## Emitting Markdown
|
@@ -343,7 +345,7 @@ Markdown is rendered using the
|
|
343
345
|
`#emit_markdown`:
|
344
346
|
|
345
347
|
```ruby
|
346
|
-
template =
|
348
|
+
template = Papercraft.html { |md| div { emit_markdown md } }
|
347
349
|
template.render("Here's some *Markdown*") #=> "<div><p>Here's some <em>Markdown</em><p>\n</div>"
|
348
350
|
```
|
349
351
|
|
@@ -352,7 +354,7 @@ options](https://kramdown.gettalong.org/options.html#available-options) can be
|
|
352
354
|
specified by adding them to the `#emit_markdown` call:
|
353
355
|
|
354
356
|
```ruby
|
355
|
-
template =
|
357
|
+
template = Papercraft.html { |md| div { emit_markdown md, auto_ids: false } }
|
356
358
|
template.render("# title") #=> "<div><h1>title</h1></div>"
|
357
359
|
```
|
358
360
|
|
@@ -395,7 +397,7 @@ class that can collect JS and CSS dependencies from the different components
|
|
395
397
|
integrated into the page, and adds them to the page's `<head>` element:
|
396
398
|
|
397
399
|
```ruby
|
398
|
-
default_layout =
|
400
|
+
default_layout = Papercraft.html { |**args|
|
399
401
|
@dependencies = DependencyMananger.new
|
400
402
|
head {
|
401
403
|
defer { emit @dependencies.head_markup }
|
@@ -481,7 +483,7 @@ The call to `Papercraft::extension` lets us access the different methods of
|
|
481
483
|
we'll be able to express the above markup as follows:
|
482
484
|
|
483
485
|
```ruby
|
484
|
-
|
486
|
+
Papercraft.html {
|
485
487
|
bootstrap.card(style: 'width: 18rem') {
|
486
488
|
bootstrap.card_title 'Card title'
|
487
489
|
bootstrap.card_subtitle 'Card subtitle'
|
@@ -492,6 +494,37 @@ H {
|
|
492
494
|
}
|
493
495
|
```
|
494
496
|
|
497
|
+
## JSON templating
|
498
|
+
|
499
|
+
You can create a JSON template using the same API used for HTML and XML
|
500
|
+
templating. The only difference is that for adding array items you'll need to
|
501
|
+
use the `#item` method:
|
502
|
+
|
503
|
+
```ruby
|
504
|
+
Papercraft.json {
|
505
|
+
item 1
|
506
|
+
item 2
|
507
|
+
item 3
|
508
|
+
}.render #=> "[1,2,3]"
|
509
|
+
```
|
510
|
+
|
511
|
+
Otherwise, you can create arbitrarily complex JSON structures by mixing hashes
|
512
|
+
and arrays:
|
513
|
+
|
514
|
+
```Ruby
|
515
|
+
Papercraft.json {
|
516
|
+
foo {
|
517
|
+
bar {
|
518
|
+
item nil
|
519
|
+
item true
|
520
|
+
item 123.456
|
521
|
+
}
|
522
|
+
}
|
523
|
+
}.render #=> "{\"foo\":{\"bar\":[null,true,123.456]}}"
|
524
|
+
```
|
525
|
+
|
526
|
+
Papercraft uses the [JSON gem](https://rubyapi.org/3.1/o/json) under the hood.
|
527
|
+
|
495
528
|
## API Reference
|
496
529
|
|
497
530
|
The API reference for this library can be found
|
data/lib/papercraft/component.rb
CHANGED
@@ -11,21 +11,26 @@ module Papercraft
|
|
11
11
|
# class is simply a special kind of Proc, which has some enhanced
|
12
12
|
# capabilities, allowing it to be easily composed in a variety of ways.
|
13
13
|
#
|
14
|
-
# Components are usually created using the
|
15
|
-
#
|
14
|
+
# Components are usually created using the class methods `html`, `xml` or
|
15
|
+
# `json`, for HTML, XML or JSON templates, respectively:
|
16
16
|
#
|
17
|
-
# greeter =
|
17
|
+
# greeter = Papercraft.html { |name| h1 "Hello, #{name}!" }
|
18
18
|
# greeter.render('world') #=> "<h1>Hello, world!</h1>"
|
19
19
|
#
|
20
20
|
# Components can also be created using the normal constructor:
|
21
21
|
#
|
22
|
-
# greeter = Papercraft::Component.new { |name| h1 "Hello, #{name}!" }
|
22
|
+
# greeter = Papercraft::Component.new(mode: :html) { |name| h1 "Hello, #{name}!" }
|
23
23
|
# greeter.render('world') #=> "<h1>Hello, world!</h1>"
|
24
24
|
#
|
25
|
+
# The different methods for creating components can also take a custom MIME
|
26
|
+
# type, by passing a `mime_type` named argument:
|
27
|
+
#
|
28
|
+
# json = Papercraft.json(mime_type: 'application/feed+json') { ... }
|
29
|
+
#
|
25
30
|
# In the component block, HTML elements are created by simply calling
|
26
31
|
# unqualified methods:
|
27
32
|
#
|
28
|
-
# page_layout =
|
33
|
+
# page_layout = Papercraft.html {
|
29
34
|
# html5 {
|
30
35
|
# head {
|
31
36
|
# title 'foo'
|
@@ -41,7 +46,7 @@ module Papercraft
|
|
41
46
|
# `greeter` template shown above takes a single `name` parameter. Here's how a
|
42
47
|
# anchor component could be implemented with named parameters:
|
43
48
|
#
|
44
|
-
# anchor =
|
49
|
+
# anchor = Papercraft.html { |uri: , text: | a(text, href: uri) }
|
45
50
|
#
|
46
51
|
# The above component could later be rendered by passing the needed arguments:
|
47
52
|
#
|
@@ -51,7 +56,7 @@ module Papercraft
|
|
51
56
|
#
|
52
57
|
# A component can be included in another component using the `emit` method:
|
53
58
|
#
|
54
|
-
# links =
|
59
|
+
# links = Papercraft.html {
|
55
60
|
# emit anchor, uri: '/posts', text: 'Posts'
|
56
61
|
# emit anchor, uri: '/archive', text: 'Archive'
|
57
62
|
# emit anchor, uri: '/about', text: 'About'
|
@@ -60,7 +65,7 @@ module Papercraft
|
|
60
65
|
# Another way of composing components is to pass the components themselves as
|
61
66
|
# parameters:
|
62
67
|
#
|
63
|
-
# links =
|
68
|
+
# links = Papercraft.html { |anchors|
|
64
69
|
# anchors.each { |a| emit a }
|
65
70
|
# }
|
66
71
|
# links.render([
|
@@ -84,14 +89,22 @@ module Papercraft
|
|
84
89
|
# Determines the rendering mode: `:html` or `:xml`.
|
85
90
|
attr_accessor :mode
|
86
91
|
|
92
|
+
STOCK_MIME_TYPE = {
|
93
|
+
html: 'text/html',
|
94
|
+
xml: 'application/xml',
|
95
|
+
json: 'application/json'
|
96
|
+
}.freeze
|
97
|
+
|
87
98
|
# Initializes a component with the given block. The rendering mode (HTML or
|
88
99
|
# XML) can be passed in the `mode:` parameter. If `mode:` is not specified,
|
89
100
|
# the component defaults to HTML.
|
90
101
|
#
|
91
102
|
# @param mode [:html, :xml] rendering mode
|
103
|
+
# @param mime_type [String, nil] the component's mime type (nil for default)
|
92
104
|
# @param block [Proc] nested HTML block
|
93
|
-
def initialize(mode: :html, &block)
|
105
|
+
def initialize(mode: :html, mime_type: nil, &block)
|
94
106
|
@mode = mode
|
107
|
+
@mime_type = mime_type || STOCK_MIME_TYPE[mode]
|
95
108
|
super(&block)
|
96
109
|
end
|
97
110
|
|
@@ -115,7 +128,7 @@ module Papercraft
|
|
115
128
|
# current one. Application is one of the principal methods of composing
|
116
129
|
# components, particularly when passing inner components as blocks:
|
117
130
|
#
|
118
|
-
# article_wrapper =
|
131
|
+
# article_wrapper = Papercraft.html {
|
119
132
|
# article {
|
120
133
|
# emit_yield
|
121
134
|
# }
|
@@ -131,7 +144,7 @@ module Papercraft
|
|
131
144
|
# @return [Papercraft::Component] applied component
|
132
145
|
def apply(*a, **b, &block)
|
133
146
|
template = self
|
134
|
-
Component.new(&proc do |*x, **y|
|
147
|
+
Component.new(mode: @mode, mime_type: @mime_type, &proc do |*x, **y|
|
135
148
|
push_emit_yield_block(block) if block
|
136
149
|
instance_exec(*a, *x, **b, **y, &template)
|
137
150
|
end)
|
@@ -147,10 +160,16 @@ module Papercraft
|
|
147
160
|
HTMLRenderer
|
148
161
|
when :xml
|
149
162
|
XMLRenderer
|
163
|
+
when :json
|
164
|
+
JSONRenderer
|
150
165
|
else
|
151
166
|
raise "Invalid mode #{@mode.inspect}"
|
152
167
|
end
|
153
168
|
end
|
169
|
+
|
170
|
+
def mime_type
|
171
|
+
@mime_type
|
172
|
+
end
|
154
173
|
|
155
174
|
# def compile
|
156
175
|
# Papercraft::Compiler.new.compile(self)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Papercraft
|
6
|
+
# JSON renderer extensions
|
7
|
+
module JSON
|
8
|
+
def object_stack
|
9
|
+
@object_stack ||= [nil]
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_object(&block)
|
13
|
+
object_stack << nil
|
14
|
+
instance_eval(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify_array_target
|
18
|
+
case object_stack[-1]
|
19
|
+
when nil
|
20
|
+
object_stack[-1] = []
|
21
|
+
when Hash
|
22
|
+
raise "Mixing array and hash values"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def verify_hash_target
|
27
|
+
case object_stack[-1]
|
28
|
+
when nil
|
29
|
+
object_stack[-1] = {}
|
30
|
+
when Array
|
31
|
+
raise "Mixing array and hash values"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def push_array_item(value)
|
36
|
+
object_stack[-1] << value
|
37
|
+
end
|
38
|
+
|
39
|
+
def push_kv_item(key, value)
|
40
|
+
object_stack[-1][key] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def enter_object(&block)
|
44
|
+
object_stack << nil
|
45
|
+
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
|
72
|
+
end
|
73
|
+
end
|
data/lib/papercraft/renderer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative './html'
|
4
|
+
require_relative './json'
|
4
5
|
require_relative './extension_proxy'
|
5
6
|
|
6
7
|
module Papercraft
|
@@ -55,7 +56,7 @@ module Papercraft
|
|
55
56
|
# end
|
56
57
|
#
|
57
58
|
# Papercraft.extension(components: ComponentLibrary)
|
58
|
-
#
|
59
|
+
# Papercraft.html { components.card('Foo', '**Bar**') }
|
59
60
|
#
|
60
61
|
# @param map [Hash] hash mapping methods to extension modules
|
61
62
|
# @return [void]
|
@@ -210,11 +211,11 @@ module Papercraft
|
|
210
211
|
# `#to_s` which is then added to the rendering buffer, without any escaping.
|
211
212
|
#
|
212
213
|
# greeter = proc { |name| h1 "Hello, #{name}!" }
|
213
|
-
#
|
214
|
+
# Papercraft.html { emit(greeter, 'world') }.render #=> "<h1>Hello, world!</h1>"
|
214
215
|
#
|
215
|
-
#
|
216
|
+
# Papercraft.html { emit 'hi&<bye>' }.render #=> "hi&<bye>"
|
216
217
|
#
|
217
|
-
#
|
218
|
+
# Papercraft.html { emit nil }.render #=> ""
|
218
219
|
#
|
219
220
|
# @param o [Proc, Papercraft::Component, String] emitted object
|
220
221
|
# @param *a [Array<any>] arguments to pass to a proc
|
@@ -234,7 +235,7 @@ module Papercraft
|
|
234
235
|
|
235
236
|
# Emits a block supplied using `Component#apply` or `Component#render`.
|
236
237
|
#
|
237
|
-
# div_wrap =
|
238
|
+
# div_wrap = Papercraft.html { |*args| div { emit_yield(*args) } }
|
238
239
|
# greeter = div_wrap.apply { |name| h1 "Hello, #{name}!" }
|
239
240
|
# greeter.render('world') #=> "<div><h1>Hello, world!</h1></div>"
|
240
241
|
#
|
@@ -256,7 +257,7 @@ module Papercraft
|
|
256
257
|
# adding elements to the `<head>` section. Here's how a title can be
|
257
258
|
# controlled from a nested component:
|
258
259
|
#
|
259
|
-
# layout =
|
260
|
+
# layout = Papercraft.html {
|
260
261
|
# html {
|
261
262
|
# head {
|
262
263
|
# defer { title @title }
|
@@ -380,4 +381,8 @@ module Papercraft
|
|
380
381
|
EscapeUtils.escape_xml(text.to_s)
|
381
382
|
end
|
382
383
|
end
|
384
|
+
|
385
|
+
class JSONRenderer < Renderer
|
386
|
+
include JSON
|
387
|
+
end
|
383
388
|
end
|
data/lib/papercraft/version.rb
CHANGED
data/lib/papercraft.rb
CHANGED
@@ -25,36 +25,49 @@ module Papercraft
|
|
25
25
|
def self.extension(map)
|
26
26
|
Renderer.extension(map)
|
27
27
|
end
|
28
|
-
end
|
29
28
|
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
#
|
29
|
+
# Creates a new papercraft component. `Papercraft.html` can take either a proc
|
30
|
+
# argument or a block. In both cases, the proc is converted to a
|
31
|
+
# `Papercraft::Component`.
|
32
|
+
#
|
33
|
+
# Papercraft.html(proc { h1 'hi' }).render #=> "<h1>hi</h1>"
|
34
|
+
# Papercraft.html { h1 'hi' }.render #=> "<h1>hi</h1>"
|
35
|
+
#
|
36
|
+
# @param template [Proc] template block
|
37
|
+
# @return [Papercraft::Component] Papercraft component
|
38
|
+
def self.html(o = nil, mime_type: nil, &template)
|
39
|
+
return o if o.is_a?(Papercraft::Component)
|
40
|
+
template ||= o
|
41
|
+
Papercraft::Component.new(mode: :html, mime_type: mime_type, &template)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates a new papercraft component in XML mode. `Papercraft.xml` can take
|
45
|
+
# either a proc argument or a block. In both cases, the proc is converted to a
|
46
|
+
# `Papercraft::Component`.
|
35
47
|
#
|
36
|
-
#
|
37
|
-
#
|
48
|
+
# Papercraft.xml(proc { item 'foo' }).render #=> "<item>foo</item>"
|
49
|
+
# Papercraft.xml { item 'foo' }.render #=> "<item>foo</item>"
|
38
50
|
#
|
39
51
|
# @param template [Proc] template block
|
40
52
|
# @return [Papercraft::Component] Papercraft component
|
41
|
-
def
|
53
|
+
def self.xml(o = nil, mime_type: nil, &template)
|
42
54
|
return o if o.is_a?(Papercraft::Component)
|
43
55
|
template ||= o
|
44
|
-
Papercraft::Component.new(mode: :
|
56
|
+
Papercraft::Component.new(mode: :xml, mime_type: mime_type, &template)
|
45
57
|
end
|
46
58
|
|
47
|
-
# Creates a new papercraft component in
|
48
|
-
# a block. In both cases, the proc is converted to a
|
59
|
+
# Creates a new papercraft component in JSON mode. `Papercraft.json` can take
|
60
|
+
# either a proc argument or a block. In both cases, the proc is converted to a
|
61
|
+
# `Papercraft::Component`.
|
49
62
|
#
|
50
|
-
#
|
51
|
-
#
|
63
|
+
# Papercraft.json(proc { item 42 }).render #=> "[42]"
|
64
|
+
# Papercraft.json { foo 'bar' }.render #=> "{\"foo\": \"bar\"}"
|
52
65
|
#
|
53
66
|
# @param template [Proc] template block
|
54
67
|
# @return [Papercraft::Component] Papercraft component
|
55
|
-
def
|
68
|
+
def self.json(o = nil, mime_type: nil, &template)
|
56
69
|
return o if o.is_a?(Papercraft::Component)
|
57
70
|
template ||= o
|
58
|
-
Papercraft::Component.new(mode: :
|
71
|
+
Papercraft::Component.new(mode: :json, mime_type: mime_type, &template)
|
59
72
|
end
|
60
73
|
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.
|
4
|
+
version: '0.16'
|
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-01-
|
11
|
+
date: 2022-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- lib/papercraft/encoding.rb
|
138
138
|
- lib/papercraft/extension_proxy.rb
|
139
139
|
- lib/papercraft/html.rb
|
140
|
+
- lib/papercraft/json.rb
|
140
141
|
- lib/papercraft/renderer.rb
|
141
142
|
- lib/papercraft/version.rb
|
142
143
|
homepage: http://github.com/digital-fabric/papercraft
|