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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1f7aa5872a78830c1a5662f055639ae2012b5b9d0f029640dce041f58d1ef4e
4
- data.tar.gz: 0c5acc8b14254c63db2132caab42ce003a8ae4713ae6daea7225d0390a420219
3
+ metadata.gz: a7d34aa76efd449fc6a63182195e8353886887e13963b79439a19dc3b0f9a9d2
4
+ data.tar.gz: e199245d969426b75627401b7c57fe1a01e7121a656ece8cd97b004a22b3ab2e
5
5
  SHA512:
6
- metadata.gz: 02bf1f7bc1300f4fa7871a6942c6a2eae2dd2f8202c7f3cc354171806f82e8a68262c3ca5e2232b7b6dcf6788a33b134b5811641561fa5baba3b7c342643b082
7
- data.tar.gz: 97a68a0f854f631a6a36b52a350faae4b1da1e337b27701209c6eec9dc16c62856555fdff3ab3d8f33e144e7fed8dc892b22433f38dd3f951a04010f710b63c4
6
+ metadata.gz: 75d5dd94c26d1ee15b11f8a439ff1c26cd7336c60ce609e334f3c0e823e8813f67923b79e8f023e9d1bcc3f2af20b5fffc93196ba5731d1cea42b2e0f75f3102
7
+ data.tar.gz: 7bdcbfa67dabec451c00f006256b16b9875d60fc726d295135db5de94a5b8854e3bdf648410d6ef6e7a7b76766c6c07d21ebb4da9788cab45fcb67a8c9d6b221
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.10 2021-12-25
2
+
3
+ - Add support for extensions
4
+
1
5
  ## 0.9 2021-12-23
2
6
 
3
7
  - Add support for emitting Markdown
data/README.md CHANGED
@@ -1,8 +1,26 @@
1
- # Papercraft - Composable HTML templating for Ruby
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
- [INSTALL](#installing-papercraft) |
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 use Papercraft in your code just require it:
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 'hello' }
77
+ div(id: 'greeter') { p 'Hello!' }
68
78
  }
69
79
  ```
70
80
 
71
- ## Rendering a template
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 = H {
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 are nested using blocks:
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
- ## Documentation
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 complete documentation for this library can be found
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Papercraft
4
- VERSION = '0.9'
4
+ VERSION = '0.10'
5
5
  end
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.9'
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-23 00:00:00.000000000 Z
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