papercraft 0.15 → 0.16
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 +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
|