papercraft 0.9 → 0.10

Sign up to get free protection for your applications and to get access to all the features.
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