papercraft 0.18 → 0.19
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 +4 -0
- data/README.md +23 -23
- data/lib/papercraft/renderer.rb +4 -4
- data/lib/papercraft/{component.rb → template.rb} +26 -26
- data/lib/papercraft/version.rb +1 -1
- data/lib/papercraft.rb +17 -17
- data/papercraft.png +0 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0f4910bd26625ca0349b1c471338fb4d13e8055e88367b5cad16f91cdee7531
|
4
|
+
data.tar.gz: 38e43978278ba069e3767abd94d83c676f42692f5eb55f1be4b4067fae2f935e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b096452cebe7b6bb34a428f4920a5940e5b745c86b54188a984a77df6175145cf6645753e6ae58b3df89813919920a17a96610e010724bc50077c6f9accc7293
|
7
|
+
data.tar.gz: 8d1cd5b2d6b70ee9ef0a748a064bbd6d1630cfa926663aded95a01c26ce289a159e2548068bf8210c5e8d37ba26c9671eb4a00fe4790a47bec6dd822b4de5d5d
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -70,7 +70,7 @@ hello.render('world')
|
|
70
70
|
- [Plain procs as templates](#plain-procs-as-templates)
|
71
71
|
- [Template composition](#template-composition)
|
72
72
|
- [Parameter and block application](#parameter-and-block-application)
|
73
|
-
- [Higher-order
|
73
|
+
- [Higher-order templates](#higher-order-templates)
|
74
74
|
- [Layout template composition](#layout-template-composition)
|
75
75
|
- [Emitting raw HTML](#emitting-raw-html)
|
76
76
|
- [Emitting a string with HTML Encoding](#emitting-a-string-with-html-encoding)
|
@@ -221,8 +221,8 @@ Papercraft.html(&greeting).render('world')
|
|
221
221
|
|
222
222
|
## Template composition
|
223
223
|
|
224
|
-
Papercraft makes it easy to compose multiple
|
225
|
-
document. A Papercraft
|
224
|
+
Papercraft makes it easy to compose multiple templates into a whole HTML
|
225
|
+
document. A Papercraft template can contain other templates, as the following
|
226
226
|
example shows.
|
227
227
|
|
228
228
|
```ruby
|
@@ -250,14 +250,14 @@ page = Papercraft.html { |title, items|
|
|
250
250
|
}
|
251
251
|
}
|
252
252
|
|
253
|
-
page.render('Hello from
|
253
|
+
page.render('Hello from composed templates', [
|
254
254
|
{ id: 1, text: 'foo', checked: false },
|
255
255
|
{ id: 2, text: 'bar', checked: true }
|
256
256
|
])
|
257
257
|
```
|
258
258
|
|
259
|
-
In addition to using
|
260
|
-
non-constant
|
259
|
+
In addition to using templates defined as constants, you can also use
|
260
|
+
non-constant templates by invoking the `#emit` method:
|
261
261
|
|
262
262
|
```ruby
|
263
263
|
greeting = -> { span "Hello, world" }
|
@@ -272,11 +272,11 @@ Papercraft.html {
|
|
272
272
|
## Parameter and block application
|
273
273
|
|
274
274
|
Parameters and blocks can be applied to a template without it being rendered, by
|
275
|
-
using `#apply`. This mechanism is what allows
|
276
|
-
creation of higher-order
|
275
|
+
using `#apply`. This mechanism is what allows template composition and the
|
276
|
+
creation of higher-order templates.
|
277
277
|
|
278
|
-
The `#apply` method returns a new
|
279
|
-
or block to the original
|
278
|
+
The `#apply` method returns a new template which applies the given parameters and
|
279
|
+
or block to the original template:
|
280
280
|
|
281
281
|
```ruby
|
282
282
|
# parameter application
|
@@ -289,19 +289,19 @@ div_wrap = Papercraft.html { div { emit_yield } }
|
|
289
289
|
wrapped_h1 = div_wrap.apply { h1 'hi' }
|
290
290
|
wrapped_h1.render #=> "<div><h1>hi</h1></div>"
|
291
291
|
|
292
|
-
# wrap a
|
292
|
+
# wrap a template
|
293
293
|
wrapped_hello_world = div_wrap.apply(&hello_world)
|
294
294
|
wrapped_hello_world.render #=> "<div><h1>Hello, world!</h1></div>"
|
295
295
|
```
|
296
296
|
|
297
|
-
## Higher-order
|
297
|
+
## Higher-order templates
|
298
298
|
|
299
|
-
Papercraft also lets you create higher-order
|
300
|
-
|
301
|
-
|
302
|
-
markup, enhancing
|
299
|
+
Papercraft also lets you create higher-order templates, that is,
|
300
|
+
templates that take other templates as parameters, or as blocks. Higher-order
|
301
|
+
templates are handy for creating layouts, wrapping templates in arbitrary
|
302
|
+
markup, enhancing templates or injecting template parameters.
|
303
303
|
|
304
|
-
Here is a
|
304
|
+
Here is a higher-order template that takes a template as parameter:
|
305
305
|
|
306
306
|
```ruby
|
307
307
|
div_wrap = Papercraft.html { |inner| div { emit inner } }
|
@@ -310,7 +310,7 @@ wrapped_greeter = div_wrap.apply(greeter)
|
|
310
310
|
wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
|
311
311
|
```
|
312
312
|
|
313
|
-
The inner
|
313
|
+
The inner template can also be passed as a block, as shown above:
|
314
314
|
|
315
315
|
```ruby
|
316
316
|
div_wrap = Papercraft.html { div { emit_yield } }
|
@@ -320,7 +320,7 @@ wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
|
|
320
320
|
|
321
321
|
## Layout template composition
|
322
322
|
|
323
|
-
One of the principal uses of higher-order
|
323
|
+
One of the principal uses of higher-order templates is the creation of nested
|
324
324
|
layouts. Suppose we have a website with a number of different layouts, and we'd
|
325
325
|
like to avoid having to repeat the same code in the different layouts. We can do
|
326
326
|
this by creating a `default` page template that takes a block, then use `#apply`
|
@@ -434,8 +434,8 @@ end
|
|
434
434
|
## Deferred evaluation
|
435
435
|
|
436
436
|
Deferred evaluation allows deferring the rendering of parts of a template until
|
437
|
-
the last moment, thus allowing an inner
|
438
|
-
outer
|
437
|
+
the last moment, thus allowing an inner template to manipulate the state of the
|
438
|
+
outer template. To in order to defer a part of a template, use `#defer`, and
|
439
439
|
include any markup in the provided block. This technique, in in conjunction with
|
440
440
|
holding state in instance variables, is an alternative to passing parameters,
|
441
441
|
which can be limiting in some situations.
|
@@ -444,11 +444,11 @@ A few use cases for deferred evaulation come to mind:
|
|
444
444
|
|
445
445
|
- Setting the page title.
|
446
446
|
- Adding a flash message to a page.
|
447
|
-
- Using
|
447
|
+
- Using templates that dynamically add static dependencies (JS and CSS) to the
|
448
448
|
page.
|
449
449
|
|
450
450
|
The last use case is particularly interesting. Imagine a `DependencyMananger`
|
451
|
-
class that can collect JS and CSS dependencies from the different
|
451
|
+
class that can collect JS and CSS dependencies from the different templates
|
452
452
|
integrated into the page, and adds them to the page's `<head>` element:
|
453
453
|
|
454
454
|
```ruby
|
data/lib/papercraft/renderer.rb
CHANGED
@@ -8,7 +8,7 @@ require_relative './extension_proxy'
|
|
8
8
|
|
9
9
|
module Papercraft
|
10
10
|
|
11
|
-
# A Renderer renders a Papercraft
|
11
|
+
# A Renderer renders a Papercraft template into a string
|
12
12
|
class Renderer
|
13
13
|
|
14
14
|
class << self
|
@@ -43,7 +43,7 @@ module Papercraft
|
|
43
43
|
#
|
44
44
|
# Installs the given extensions, passed in the form of a Ruby hash mapping
|
45
45
|
# methods to extension modules. The methods will be available to all
|
46
|
-
# Papercraft
|
46
|
+
# Papercraft templates. Extension methods are executed in the context of
|
47
47
|
# the the renderer instance, so they can look just like normal proc
|
48
48
|
# components. In cases where method names in the module clash with HTML
|
49
49
|
# tag names, you can use the `#tag` method to emit the relevant tag.
|
@@ -219,7 +219,7 @@ module Papercraft
|
|
219
219
|
#
|
220
220
|
# Papercraft.html { emit nil }.render #=> ""
|
221
221
|
#
|
222
|
-
# @param o [Proc, Papercraft::
|
222
|
+
# @param o [Proc, Papercraft::Template, String] emitted object
|
223
223
|
# @param *a [Array<any>] arguments to pass to a proc
|
224
224
|
# @param **b [Hash] named arguments to pass to a proc
|
225
225
|
# @return [void]
|
@@ -253,7 +253,7 @@ module Papercraft
|
|
253
253
|
end
|
254
254
|
|
255
255
|
# Defers the given block to be evaluated later. Deferred evaluation allows
|
256
|
-
# Papercraft
|
256
|
+
# Papercraft templates to inject state into sibling components, regardless
|
257
257
|
# of the component's order in the container component. For example, a nested
|
258
258
|
# component may set an instance variable used by another component. This is
|
259
259
|
# an elegant solution to the problem of setting the HTML page's title, or
|
@@ -4,30 +4,30 @@ require_relative './html'
|
|
4
4
|
|
5
5
|
module Papercraft
|
6
6
|
|
7
|
-
#
|
8
|
-
# include other
|
7
|
+
# Template represents a distinct, reusable HTML template. A template can
|
8
|
+
# include other templates, and also be nested inside other templates.
|
9
9
|
#
|
10
|
-
# Since in Papercraft HTML is expressed using blocks (or procs,) the
|
10
|
+
# Since in Papercraft HTML is expressed using blocks (or procs,) the Template
|
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
|
-
#
|
14
|
+
# Templates are usually created using the class methods `html`, `xml` or
|
15
15
|
# `json`, for HTML, XML or JSON templates, respectively:
|
16
16
|
#
|
17
17
|
# greeter = Papercraft.html { |name| h1 "Hello, #{name}!" }
|
18
18
|
# greeter.render('world') #=> "<h1>Hello, world!</h1>"
|
19
19
|
#
|
20
|
-
#
|
20
|
+
# Templates can also be created using the normal constructor:
|
21
21
|
#
|
22
|
-
# greeter = Papercraft::
|
22
|
+
# greeter = Papercraft::Template.new(mode: :html) { |name| h1 "Hello, #{name}!" }
|
23
23
|
# greeter.render('world') #=> "<h1>Hello, world!</h1>"
|
24
24
|
#
|
25
|
-
# The different methods for creating
|
25
|
+
# The different methods for creating templates can also take a custom MIME
|
26
26
|
# type, by passing a `mime_type` named argument:
|
27
27
|
#
|
28
28
|
# json = Papercraft.json(mime_type: 'application/feed+json') { ... }
|
29
29
|
#
|
30
|
-
# In the
|
30
|
+
# In the template block, HTML elements are created by simply calling
|
31
31
|
# unqualified methods:
|
32
32
|
#
|
33
33
|
# page_layout = Papercraft.html {
|
@@ -41,20 +41,20 @@ module Papercraft
|
|
41
41
|
# }
|
42
42
|
# }
|
43
43
|
#
|
44
|
-
# Papercraft
|
44
|
+
# Papercraft templates can take explicit parameters in order to render
|
45
45
|
# dynamic content. This can be in the form of regular or named parameters. The
|
46
46
|
# `greeter` template shown above takes a single `name` parameter. Here's how a
|
47
|
-
# anchor
|
47
|
+
# anchor template could be implemented with named parameters:
|
48
48
|
#
|
49
49
|
# anchor = Papercraft.html { |uri: , text: | a(text, href: uri) }
|
50
50
|
#
|
51
|
-
# The above
|
51
|
+
# The above template could later be rendered by passing the needed arguments:
|
52
52
|
#
|
53
53
|
# anchor.render(uri: 'https://example.com', text: 'Example')
|
54
54
|
#
|
55
|
-
# ##
|
55
|
+
# ## Template Composition
|
56
56
|
#
|
57
|
-
# A
|
57
|
+
# A template can be included in another template using the `emit` method:
|
58
58
|
#
|
59
59
|
# links = Papercraft.html {
|
60
60
|
# emit anchor, uri: '/posts', text: 'Posts'
|
@@ -62,7 +62,7 @@ module Papercraft
|
|
62
62
|
# emit anchor, uri: '/about', text: 'About'
|
63
63
|
# }
|
64
64
|
#
|
65
|
-
# Another way of composing
|
65
|
+
# Another way of composing templates is to pass the templates themselves as
|
66
66
|
# parameters:
|
67
67
|
#
|
68
68
|
# links = Papercraft.html { |anchors|
|
@@ -74,8 +74,8 @@ module Papercraft
|
|
74
74
|
# anchor.apply(uri: '/about', text: 'About')
|
75
75
|
# ])
|
76
76
|
#
|
77
|
-
# The `#apply` method creates a new
|
78
|
-
# such that the
|
77
|
+
# The `#apply` method creates a new template, applying the given parameters
|
78
|
+
# such that the template can be rendered without parameters:
|
79
79
|
#
|
80
80
|
# links_with_anchors = links.apply([
|
81
81
|
# anchor.apply(uri: '/posts', text: 'Posts'),
|
@@ -84,7 +84,7 @@ module Papercraft
|
|
84
84
|
# ])
|
85
85
|
# links_with_anchors.render
|
86
86
|
#
|
87
|
-
class
|
87
|
+
class Template < Proc
|
88
88
|
|
89
89
|
# Determines the rendering mode: `:html` or `:xml`.
|
90
90
|
attr_accessor :mode
|
@@ -95,12 +95,12 @@ module Papercraft
|
|
95
95
|
json: 'application/json'
|
96
96
|
}.freeze
|
97
97
|
|
98
|
-
# Initializes a
|
98
|
+
# Initializes a template with the given block. The rendering mode (HTML or
|
99
99
|
# XML) can be passed in the `mode:` parameter. If `mode:` is not specified,
|
100
|
-
# the
|
100
|
+
# the template defaults to HTML.
|
101
101
|
#
|
102
102
|
# @param mode [:html, :xml] rendering mode
|
103
|
-
# @param mime_type [String, nil] the
|
103
|
+
# @param mime_type [String, nil] the template's mime type (nil for default)
|
104
104
|
# @param block [Proc] nested HTML block
|
105
105
|
def initialize(mode: :html, mime_type: nil, &block)
|
106
106
|
@mode = mode
|
@@ -124,9 +124,9 @@ module Papercraft
|
|
124
124
|
end.to_s
|
125
125
|
end
|
126
126
|
|
127
|
-
# Creates a new
|
127
|
+
# Creates a new template, applying the given parameters and or block to the
|
128
128
|
# current one. Application is one of the principal methods of composing
|
129
|
-
#
|
129
|
+
# templates, particularly when passing inner templates as blocks:
|
130
130
|
#
|
131
131
|
# article_wrapper = Papercraft.html {
|
132
132
|
# article {
|
@@ -141,19 +141,19 @@ module Papercraft
|
|
141
141
|
# @param *a [<any>] normal parameters
|
142
142
|
# @param **b [Hash] named parameters
|
143
143
|
# @param &block [Proc] inner block
|
144
|
-
# @return [Papercraft::
|
144
|
+
# @return [Papercraft::Template] applied template
|
145
145
|
def apply(*a, **b, &block)
|
146
146
|
template = self
|
147
|
-
|
147
|
+
Template.new(mode: @mode, mime_type: @mime_type, &proc do |*x, **y|
|
148
148
|
push_emit_yield_block(block) if block
|
149
149
|
instance_exec(*a, *x, **b, **y, &template)
|
150
150
|
end)
|
151
151
|
end
|
152
152
|
|
153
153
|
# Returns the Renderer class used for rendering the templates, according to
|
154
|
-
# the
|
154
|
+
# the template's mode.
|
155
155
|
#
|
156
|
-
# @return [Papercraft::Renderer] Renderer used for rendering the
|
156
|
+
# @return [Papercraft::Renderer] Renderer used for rendering the template
|
157
157
|
def renderer_class
|
158
158
|
case @mode
|
159
159
|
when :html
|
data/lib/papercraft/version.rb
CHANGED
data/lib/papercraft.rb
CHANGED
@@ -4,13 +4,13 @@ require 'kramdown'
|
|
4
4
|
require 'rouge'
|
5
5
|
require 'kramdown-parser-gfm'
|
6
6
|
|
7
|
-
require_relative 'papercraft/
|
7
|
+
require_relative 'papercraft/template'
|
8
8
|
require_relative 'papercraft/renderer'
|
9
9
|
require_relative 'papercraft/encoding'
|
10
10
|
# require_relative 'papercraft/compiler'
|
11
11
|
|
12
12
|
|
13
|
-
# Papercraft is a
|
13
|
+
# Papercraft is a composable templating library
|
14
14
|
module Papercraft
|
15
15
|
# Exception class used to signal templating-related errors
|
16
16
|
class Error < RuntimeError; end
|
@@ -31,49 +31,49 @@ module Papercraft
|
|
31
31
|
Renderer.extension(map)
|
32
32
|
end
|
33
33
|
|
34
|
-
# Creates a new papercraft
|
34
|
+
# Creates a new papercraft template. `Papercraft.html` can take either a proc
|
35
35
|
# argument or a block. In both cases, the proc is converted to a
|
36
|
-
# `Papercraft::
|
36
|
+
# `Papercraft::Template`.
|
37
37
|
#
|
38
38
|
# Papercraft.html(proc { h1 'hi' }).render #=> "<h1>hi</h1>"
|
39
39
|
# Papercraft.html { h1 'hi' }.render #=> "<h1>hi</h1>"
|
40
40
|
#
|
41
41
|
# @param template [Proc] template block
|
42
|
-
# @return [Papercraft::
|
42
|
+
# @return [Papercraft::Template] Papercraft template
|
43
43
|
def html(o = nil, mime_type: nil, &template)
|
44
|
-
return o if o.is_a?(Papercraft::
|
44
|
+
return o if o.is_a?(Papercraft::Template)
|
45
45
|
template ||= o
|
46
|
-
Papercraft::
|
46
|
+
Papercraft::Template.new(mode: :html, mime_type: mime_type, &template)
|
47
47
|
end
|
48
48
|
|
49
|
-
# Creates a new
|
49
|
+
# Creates a new Papercraft template in XML mode. `Papercraft.xml` can take
|
50
50
|
# either a proc argument or a block. In both cases, the proc is converted to a
|
51
|
-
# `Papercraft::
|
51
|
+
# `Papercraft::Template`.
|
52
52
|
#
|
53
53
|
# Papercraft.xml(proc { item 'foo' }).render #=> "<item>foo</item>"
|
54
54
|
# Papercraft.xml { item 'foo' }.render #=> "<item>foo</item>"
|
55
55
|
#
|
56
56
|
# @param template [Proc] template block
|
57
|
-
# @return [Papercraft::
|
57
|
+
# @return [Papercraft::Template] Papercraft template
|
58
58
|
def xml(o = nil, mime_type: nil, &template)
|
59
|
-
return o if o.is_a?(Papercraft::
|
59
|
+
return o if o.is_a?(Papercraft::Template)
|
60
60
|
template ||= o
|
61
|
-
Papercraft::
|
61
|
+
Papercraft::Template.new(mode: :xml, mime_type: mime_type, &template)
|
62
62
|
end
|
63
63
|
|
64
|
-
# Creates a new
|
64
|
+
# Creates a new Papercraft template in JSON mode. `Papercraft.json` can take
|
65
65
|
# either a proc argument or a block. In both cases, the proc is converted to a
|
66
|
-
# `Papercraft::
|
66
|
+
# `Papercraft::Template`.
|
67
67
|
#
|
68
68
|
# Papercraft.json(proc { item 42 }).render #=> "[42]"
|
69
69
|
# Papercraft.json { foo 'bar' }.render #=> "{\"foo\": \"bar\"}"
|
70
70
|
#
|
71
71
|
# @param template [Proc] template block
|
72
|
-
# @return [Papercraft::
|
72
|
+
# @return [Papercraft::Template] Papercraft template
|
73
73
|
def json(o = nil, mime_type: nil, &template)
|
74
|
-
return o if o.is_a?(Papercraft::
|
74
|
+
return o if o.is_a?(Papercraft::Template)
|
75
75
|
template ||= o
|
76
|
-
Papercraft::
|
76
|
+
Papercraft::Template.new(mode: :json, mime_type: mime_type, &template)
|
77
77
|
end
|
78
78
|
|
79
79
|
# Renders Markdown into HTML. The `opts` argument will be merged with the
|
data/papercraft.png
ADDED
Binary file
|
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.19'
|
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-
|
11
|
+
date: 2022-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -128,18 +128,20 @@ executables: []
|
|
128
128
|
extensions: []
|
129
129
|
extra_rdoc_files:
|
130
130
|
- README.md
|
131
|
+
- papercraft.png
|
131
132
|
files:
|
132
133
|
- CHANGELOG.md
|
133
134
|
- README.md
|
134
135
|
- lib/papercraft.rb
|
135
136
|
- lib/papercraft/compiler.rb
|
136
|
-
- lib/papercraft/component.rb
|
137
137
|
- lib/papercraft/encoding.rb
|
138
138
|
- lib/papercraft/extension_proxy.rb
|
139
139
|
- lib/papercraft/html.rb
|
140
140
|
- lib/papercraft/json.rb
|
141
141
|
- lib/papercraft/renderer.rb
|
142
|
+
- lib/papercraft/template.rb
|
142
143
|
- lib/papercraft/version.rb
|
144
|
+
- papercraft.png
|
143
145
|
homepage: http://github.com/digital-fabric/papercraft
|
144
146
|
licenses:
|
145
147
|
- MIT
|