papercraft 0.9 → 0.10
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 +96 -32
- data/lib/papercraft/extension_proxy.rb +30 -0
- data/lib/papercraft/renderer.rb +26 -4
- data/lib/papercraft/version.rb +1 -1
- data/lib/papercraft.rb +8 -0
- 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: a7d34aa76efd449fc6a63182195e8353886887e13963b79439a19dc3b0f9a9d2
|
4
|
+
data.tar.gz: e199245d969426b75627401b7c57fe1a01e7121a656ece8cd97b004a22b3ab2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75d5dd94c26d1ee15b11f8a439ff1c26cd7336c60ce609e334f3c0e823e8813f67923b79e8f023e9d1bcc3f2af20b5fffc93196ba5731d1cea42b2e0f75f3102
|
7
|
+
data.tar.gz: 7bdcbfa67dabec451c00f006256b16b9875d60fc726d295135db5de94a5b8854e3bdf648410d6ef6e7a7b76766c6c07d21ebb4da9788cab45fcb67a8c9d6b221
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,26 @@
|
|
1
|
-
|
1
|
+
<h1 align="center">
|
2
|
+
Papercraft
|
3
|
+
</h1>
|
4
|
+
|
5
|
+
<h4 align="center">Composable HTML templating for Ruby</h4>
|
6
|
+
|
7
|
+
<p align="center">
|
8
|
+
<a href="http://rubygems.org/gems/papercraft">
|
9
|
+
<img src="https://badge.fury.io/rb/papercraft.svg" alt="Ruby gem">
|
10
|
+
</a>
|
11
|
+
<a href="https://github.com/digital-fabric/papercraft/actions?query=workflow%3ATests">
|
12
|
+
<img src="https://github.com/digital-fabric/papercraft/workflows/Tests/badge.svg" alt="Tests">
|
13
|
+
</a>
|
14
|
+
<a href="https://github.com/digital-fabric/papercraft/blob/master/LICENSE">
|
15
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
|
16
|
+
</a>
|
17
|
+
</p>
|
18
|
+
|
19
|
+
<p align="center">
|
20
|
+
<a href="https://www.rubydoc.info/gems/papercraft">API reference</a>
|
21
|
+
</p>
|
2
22
|
|
3
|
-
|
4
|
-
[TUTORIAL](#getting-started) |
|
5
|
-
[DOCS](https://www.rubydoc.info/gems/papercraft)
|
23
|
+
# Papercraft - Composable HTML templating for Ruby
|
6
24
|
|
7
25
|
## What is Papercraft?
|
8
26
|
|
@@ -32,9 +50,7 @@ features:
|
|
32
50
|
- Explicit parameter passing to nested components
|
33
51
|
- Higher order components
|
34
52
|
- Built-in support for rendering [Markdown](#emitting-markdown)
|
35
|
-
|
36
|
-
With Papercraft you can structure your templates as nested HTML components, in a
|
37
|
-
somewhat similar fashion to React.
|
53
|
+
- Support for namespaced extensions
|
38
54
|
|
39
55
|
## Installing Papercraft
|
40
56
|
|
@@ -52,43 +68,25 @@ $ gem install papercraft
|
|
52
68
|
|
53
69
|
## Getting started
|
54
70
|
|
55
|
-
To
|
71
|
+
To create a template use the global method `Kernel#H`:
|
56
72
|
|
57
73
|
```ruby
|
58
74
|
require 'papercraft'
|
59
|
-
```
|
60
|
-
|
61
|
-
To create a template use `Papercraft::Component.new` or the global method
|
62
|
-
`Kernel#H`:
|
63
75
|
|
64
|
-
```ruby
|
65
|
-
# can also use Papercraft.new
|
66
76
|
html = H {
|
67
|
-
div { p '
|
77
|
+
div(id: 'greeter') { p 'Hello!' }
|
68
78
|
}
|
69
79
|
```
|
70
80
|
|
71
|
-
|
72
|
-
|
73
|
-
To render a Papercraft template use the `#render` method:
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
H { span 'best span' }.render #=> "<span>best span</span>"
|
77
|
-
```
|
78
|
-
|
79
|
-
The render method accepts an arbitrary context variable:
|
81
|
+
Rendering a template is done using `#render`:
|
80
82
|
|
81
83
|
```ruby
|
82
|
-
html
|
83
|
-
h1 context[:title]
|
84
|
-
}
|
85
|
-
|
86
|
-
html.render(title: 'My title') #=> "<h1>My title</h1>"
|
84
|
+
html.render #=> "<div id="greeter"><p>Hello!</p></div>"
|
87
85
|
```
|
88
86
|
|
89
87
|
## All about tags
|
90
88
|
|
91
|
-
Tags are added using unqualified method calls, and
|
89
|
+
Tags are added using unqualified method calls, and can be nested using blocks:
|
92
90
|
|
93
91
|
```ruby
|
94
92
|
H {
|
@@ -376,7 +374,73 @@ The deafult options can be configured by accessing
|
|
376
374
|
Papercraft::HTML.kramdown_options[:auto_ids] = false
|
377
375
|
```
|
378
376
|
|
379
|
-
##
|
377
|
+
## Papercraft extensions
|
378
|
+
|
379
|
+
Papercraft extensions are modules that contain one or more methods that can be
|
380
|
+
used to render complex HTML components. Extension modules can be used by
|
381
|
+
installing them as a namespaced extension using `Papercraft.extension`.
|
382
|
+
Extensions are particularly useful when you work with CSS frameworks such as
|
383
|
+
[Bootstrap](https://getbootstrap.com/), [Tailwind](https://tailwindui.com/) or
|
384
|
+
[Primer](https://primer.style/).
|
385
|
+
|
386
|
+
For example, to create a Bootstrap card component, the following HTML markup is
|
387
|
+
needed (example taken from the [Bootstrap
|
388
|
+
docs](https://getbootstrap.com/docs/5.1/components/card/#titles-text-and-links)):
|
389
|
+
|
390
|
+
```html
|
391
|
+
<div class="card" style="width: 18rem;">
|
392
|
+
<div class="card-body">
|
393
|
+
<h5 class="card-title">Card title</h5>
|
394
|
+
<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
|
395
|
+
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
|
396
|
+
<a href="#" class="card-link">Card link</a>
|
397
|
+
<a href="#" class="card-link">Another link</a>
|
398
|
+
</div>
|
399
|
+
</div>
|
400
|
+
```
|
401
|
+
|
402
|
+
With Papercraft, we could create a `Bootstrap` extension with a `#card` method
|
403
|
+
and other associated methods:
|
404
|
+
|
405
|
+
```ruby
|
406
|
+
module BootstrapComponents
|
407
|
+
...
|
408
|
+
|
409
|
+
def card(**props)
|
410
|
+
div(class: 'card', **props) {
|
411
|
+
div(class: 'card-body') {
|
412
|
+
emit_yield
|
413
|
+
}
|
414
|
+
}
|
415
|
+
end
|
416
|
+
|
417
|
+
def card_title(title)
|
418
|
+
h5 title, class: 'card-title'
|
419
|
+
end
|
420
|
+
|
421
|
+
...
|
422
|
+
end
|
423
|
+
|
424
|
+
Papercraft.extension(bootstrap: BootstrapComponents)
|
425
|
+
```
|
426
|
+
|
427
|
+
The call to `Papercraft.extension` lets us access the different methods of
|
428
|
+
`BootstrapComponents` by calling `#bootstrap` inside a template. With this,
|
429
|
+
we'll be able to express the above markup as follows:
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
H {
|
433
|
+
bootstrap.card(style: 'width: 18rem') {
|
434
|
+
bootstrap.card_title 'Card title'
|
435
|
+
bootstrap.card_subtitle 'Card subtitle'
|
436
|
+
bootstrap.card_text 'Some quick example text to build on the card title and make up the bulk of the card''s content.'
|
437
|
+
bootstrap.card_link '#', 'Card link'
|
438
|
+
bootstrap.card_link '#', 'Another link'
|
439
|
+
}
|
440
|
+
}
|
441
|
+
```
|
442
|
+
|
443
|
+
## API Reference
|
380
444
|
|
381
|
-
The
|
445
|
+
The API reference for this library can be found
|
382
446
|
[here](https://www.rubydoc.info/gems/papercraft).
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Papercraft
|
4
|
+
|
5
|
+
# An ExtensionProxy proxies method calls to a renderer. Extension proxies are
|
6
|
+
# used to provide an namespaced interface to Papercraft extensions. When an
|
7
|
+
# extension is installed using `Papercraft.extension`, a corresponding method
|
8
|
+
# is defined on the `Papercraft::Renderer` class that creates an extension
|
9
|
+
# proxy that gives access to the different extension methods.
|
10
|
+
class ExtensionProxy
|
11
|
+
|
12
|
+
# Initializes a new ExtensionProxy.
|
13
|
+
# @param renderer [Papercraft::Renderer] renderer to proxy to
|
14
|
+
# @param mod [Module] extension module
|
15
|
+
# @return [void]
|
16
|
+
def initialize(renderer, mod)
|
17
|
+
@renderer = renderer
|
18
|
+
extend(mod)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Proxies missing methods to the renderer
|
22
|
+
# @param sym [Symbol] method name
|
23
|
+
# @param *args [Array] arguments
|
24
|
+
# @param &block [Proc] block
|
25
|
+
# @return void
|
26
|
+
def method_missing(sym, *args, &block)
|
27
|
+
@renderer.send(sym, *args, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
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 './extension_proxy'
|
4
5
|
|
5
6
|
module Papercraft
|
6
7
|
|
@@ -31,7 +32,29 @@ module Papercraft
|
|
31
32
|
if param_count > args.size
|
32
33
|
raise Papercraft::Error, "Missing template parameters"
|
33
34
|
end
|
34
|
-
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Installs the given extensions, mapping a method name to the extension
|
38
|
+
# module.
|
39
|
+
# @param map [Hash] hash mapping methods to extension modules
|
40
|
+
# @return [void]
|
41
|
+
def extension(map)
|
42
|
+
map.each do |sym, mod|
|
43
|
+
define_extension_method(sym, mod)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Defines a method returning an extension proxy for the given module
|
50
|
+
# @param sym [Symbol] method name
|
51
|
+
# @param mod [Module] extension module
|
52
|
+
# @return [void]
|
53
|
+
def define_extension_method(sym, mod)
|
54
|
+
define_method(sym) do
|
55
|
+
(@extension_proxies ||= {})[mod] ||= ExtensionProxy.new(self, mod)
|
56
|
+
end
|
57
|
+
end
|
35
58
|
end
|
36
59
|
|
37
60
|
# Initializes the renderer and evaulates the given template in the
|
@@ -83,9 +106,6 @@ module Papercraft
|
|
83
106
|
# @param &block [Proc] block passed to method
|
84
107
|
# @return [void]
|
85
108
|
def method_missing(sym, *args, **opts, &block)
|
86
|
-
value = @local && @local[sym]
|
87
|
-
return value if value
|
88
|
-
|
89
109
|
tag = sym.to_s
|
90
110
|
code = S_TAG_METHOD % { tag: tag, TAG: tag.upcase }
|
91
111
|
self.class.class_eval(code, __FILE__, S_TAG_METHOD_LINE)
|
@@ -200,6 +220,7 @@ module Papercraft
|
|
200
220
|
|
201
221
|
private
|
202
222
|
|
223
|
+
# Escapes the given text using HTML entities.
|
203
224
|
def escape_text(text)
|
204
225
|
EscapeUtils.escape_html(text.to_s)
|
205
226
|
end
|
@@ -209,6 +230,7 @@ module Papercraft
|
|
209
230
|
class XMLRenderer < Renderer
|
210
231
|
private
|
211
232
|
|
233
|
+
# Escapes the given text using XML entities.
|
212
234
|
def escape_text(text)
|
213
235
|
EscapeUtils.escape_xml(text.to_s)
|
214
236
|
end
|
data/lib/papercraft/version.rb
CHANGED
data/lib/papercraft.rb
CHANGED
@@ -11,6 +11,14 @@ require_relative 'papercraft/encoding'
|
|
11
11
|
module Papercraft
|
12
12
|
# Exception class used to signal templating-related errors
|
13
13
|
class Error < RuntimeError; end
|
14
|
+
|
15
|
+
# Installs one or more extensions. Extensions enhance templating capabilities
|
16
|
+
# by adding namespaced methods to emplates. An extension is implemented as a
|
17
|
+
# Ruby module containing one or more methods. Each method in the extension
|
18
|
+
# module can be used to render a specific HTML element or a set of elements.
|
19
|
+
def self.extension(map)
|
20
|
+
Renderer.extension(map)
|
21
|
+
end
|
14
22
|
end
|
15
23
|
|
16
24
|
# Kernel extensions
|
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.10'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -135,6 +135,7 @@ files:
|
|
135
135
|
- lib/papercraft/compiler.rb
|
136
136
|
- lib/papercraft/component.rb
|
137
137
|
- lib/papercraft/encoding.rb
|
138
|
+
- lib/papercraft/extension_proxy.rb
|
138
139
|
- lib/papercraft/html.rb
|
139
140
|
- lib/papercraft/renderer.rb
|
140
141
|
- lib/papercraft/version.rb
|