papercraft 0.21 → 0.24
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 +14 -0
- data/README.md +216 -102
- data/lib/papercraft/extension_proxy.rb +13 -2
- data/lib/papercraft/extensions/soap.rb +46 -0
- data/lib/papercraft/renderer.rb +9 -9
- data/lib/papercraft/tags.rb +35 -10
- data/lib/papercraft/version.rb +1 -1
- data/lib/papercraft.rb +0 -1
- metadata +3 -3
- data/lib/papercraft/encoding.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f90c4ea6ac9d3090ae45d79f7f4a58668ccf7f8ae5d4dfa2a727b44a82699eb9
|
4
|
+
data.tar.gz: 10ff5bc3df10c10b0a968921517d2e0c18a61973dd97b88e95eef38670b9e451
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '02461962ba174678a5b4a6ec550a8faa2f643fe87234e41513f7b49d798e3f3b2ade02adcfb0fa4961124a74484ddddea9437cb02eec98e9e897721729c0ef63'
|
7
|
+
data.tar.gz: f99728bb218382a040f67cbf2fd9652c33b3e0648efefbc695ceee708006758b6ec249748f3e3d41b065bf3b2fb28014b1ae61e02f7d3b01231e928f028e6ebd
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.24 2022-03-19
|
2
|
+
|
3
|
+
- Fix usage of const components (#13)
|
4
|
+
- Fix formatting of HTML/XML attributes for non-string values
|
5
|
+
|
6
|
+
## 0.23 2022-02-15
|
7
|
+
|
8
|
+
- Remove unused `Encoding` module
|
9
|
+
- Add SOAP extension (#11, thanks [@aemadrid](https://github.com/aemadrid))
|
10
|
+
|
11
|
+
## 0.22 2022-02-14
|
12
|
+
|
13
|
+
- Fix behaviour of call to `#p` in an extension (#10)
|
14
|
+
|
1
15
|
## 0.21 2022-02-13
|
2
16
|
|
3
17
|
- Refactor and improve documentation
|
data/README.md
CHANGED
@@ -42,6 +42,10 @@ Papercraft includes built-in support for rendering Markdown (using
|
|
42
42
|
creating template extensions in order to allow the creation of component
|
43
43
|
libraries.
|
44
44
|
|
45
|
+
Papercraft automatically escapes all text emitted in templates according to the
|
46
|
+
template type. For more information see the section on [escaping
|
47
|
+
content](#escaping-content).
|
48
|
+
|
45
49
|
```ruby
|
46
50
|
require 'papercraft'
|
47
51
|
|
@@ -59,27 +63,30 @@ hello.render('world')
|
|
59
63
|
#=> "<html><head><title>Title</title></head><body><h1>Hello, world!</h1></body></html>"
|
60
64
|
```
|
61
65
|
|
62
|
-
## Table of
|
63
|
-
|
64
|
-
- [Installing
|
65
|
-
- [Basic
|
66
|
-
- [Adding
|
67
|
-
- [
|
68
|
-
- [
|
69
|
-
- [Template
|
70
|
-
- [
|
71
|
-
- [Template
|
72
|
-
- [
|
73
|
-
- [
|
74
|
-
- [
|
75
|
-
- [
|
76
|
-
- [
|
66
|
+
## Table of Content
|
67
|
+
|
68
|
+
- [Installing Papercraft](#installing-papercraft)
|
69
|
+
- [Basic Usage](#basic-usage)
|
70
|
+
- [Adding Tags](#adding-tags)
|
71
|
+
- [Tag and Attribute Formatting](#tag-and-attribute-formatting)
|
72
|
+
- [Escaping Content](#escaping-content)
|
73
|
+
- [Template Parameters](#template-parameters)
|
74
|
+
- [Template Logic](#template-logic)
|
75
|
+
- [Template Blocks](#template-blocks)
|
76
|
+
- [Plain Procs as Templates](#plain-procs-as-templates)
|
77
|
+
- [Template Composition](#template-composition)
|
78
|
+
- [Parameter and Block Application](#parameter-and-block-application)
|
79
|
+
- [Higher-Order Templates](#higher-order-templates)
|
80
|
+
- [Layout Template Composition](#layout-template-composition)
|
81
|
+
- [Emitting Raw HTML](#emitting-raw-html)
|
82
|
+
- [Emitting a String with HTML Encoding](#emitting-a-string-with-html-encoding)
|
77
83
|
- [Emitting Markdown](#emitting-markdown)
|
78
|
-
- [Working with MIME
|
79
|
-
- [Deferred
|
80
|
-
- [
|
81
|
-
- [
|
82
|
-
- [
|
84
|
+
- [Working with MIME Types](#working-with-mime-types)
|
85
|
+
- [Deferred Evaluation](#deferred-evaluation)
|
86
|
+
- [XML Templates](#xml-templates)
|
87
|
+
- [JSON Templates](#json-templates)
|
88
|
+
- [Papercraft Extensions](#papercraft-extensions)
|
89
|
+
- [Bundled Extensions](#bundled-extensions)
|
83
90
|
- [API Reference](#api-reference)
|
84
91
|
|
85
92
|
## Installing Papercraft
|
@@ -96,7 +103,7 @@ Or manually:
|
|
96
103
|
$ gem install papercraft
|
97
104
|
```
|
98
105
|
|
99
|
-
## Basic
|
106
|
+
## Basic Usage
|
100
107
|
|
101
108
|
To create an HTML template use `Papercraft.html`:
|
102
109
|
|
@@ -117,7 +124,7 @@ Rendering a template is done using `#render`:
|
|
117
124
|
html.render #=> "<div id="greeter"><p>Hello!</p></div>"
|
118
125
|
```
|
119
126
|
|
120
|
-
## Adding
|
127
|
+
## Adding Tags
|
121
128
|
|
122
129
|
Tags are added using unqualified method calls, and can be nested using blocks:
|
123
130
|
|
@@ -154,7 +161,60 @@ Papercraft.html { img src: '/my.gif' }.render #=> "<img src="/my.gif"/>
|
|
154
161
|
Papercraft.html { p "foobar", class: 'important' }.render #=> "<p class=\"important\">foobar</p>"
|
155
162
|
```
|
156
163
|
|
157
|
-
##
|
164
|
+
## Tag and Attribute Formatting
|
165
|
+
|
166
|
+
Papercraft does not make any presumption about what tags and attributes you can
|
167
|
+
use. You can mix upper and lower case letters, and you can include arbitrary
|
168
|
+
characters in tag and attribute names. However, in order to best adhere to the
|
169
|
+
HTML and XML specs and common practices, tag names and attributes will be
|
170
|
+
formatted according to the following rules, depending on the template type:
|
171
|
+
|
172
|
+
- HTML: underscores are converted to dashes:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
Papercraft.html {
|
176
|
+
foo_bar { p 'Hello', data_name: 'world' }
|
177
|
+
}.render #=> '<foo-bar><p data-name="world">Hello</p></foo-bar>'
|
178
|
+
```
|
179
|
+
|
180
|
+
- XML: underscores are converted to dashes, double underscores are converted to
|
181
|
+
colons:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
Papercraft.xml {
|
185
|
+
soap__Envelope(
|
186
|
+
xmlns__soap: 'http://schemas.xmlsoap.org/soap/envelope/',
|
187
|
+
) { }
|
188
|
+
}.render #=> '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Envelope>'
|
189
|
+
```
|
190
|
+
|
191
|
+
If you need more precise control over tag names, you can use the `#tag` method,
|
192
|
+
which takes the tag name as its first parameter, then the rest of the parameters
|
193
|
+
normally used for tags:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
Papercraft.html {
|
197
|
+
tag 'cra_zy__:!tag', 'foo'
|
198
|
+
}.render #=> '<cra_zy__:!tag>foo</cra_zy__:!tag>'
|
199
|
+
```
|
200
|
+
|
201
|
+
## Escaping Content
|
202
|
+
|
203
|
+
Papercraft automatically escapes all text content emitted in a template. The
|
204
|
+
specific escaping algorithm depends on the template type. For both HTML and XML
|
205
|
+
templates, Papercraft uses
|
206
|
+
[escape_utils](https://github.com/brianmario/escape_utils), specifically:
|
207
|
+
|
208
|
+
- HTML: `escape_utils.escape_html`
|
209
|
+
- XML: `escape_utils.escape_xml`
|
210
|
+
|
211
|
+
In order to emit raw HTML/XML, you can use the `#emit` method as [described
|
212
|
+
below](#emitting-raw-html).
|
213
|
+
|
214
|
+
JSON templates are rendered using the `json` gem bundled with Ruby, which takes
|
215
|
+
care of escaping text values.
|
216
|
+
|
217
|
+
## Template Parameters
|
158
218
|
|
159
219
|
In Papercraft, parameters are always passed explicitly. This means that template
|
160
220
|
parameters are specified as block parameters, and are passed to the template on
|
@@ -172,7 +232,7 @@ greeting = Papercraft.html { |name:| h1 "Hello, #{name}!" }
|
|
172
232
|
greeting.render(name: 'world') #=> "<h1>Hello, world!</h1>"
|
173
233
|
```
|
174
234
|
|
175
|
-
## Template
|
235
|
+
## Template Logic
|
176
236
|
|
177
237
|
Since Papercraft templates are just a bunch of Ruby, you can easily write your
|
178
238
|
view logic right in the template:
|
@@ -187,7 +247,7 @@ Papercraft.html { |user = nil|
|
|
187
247
|
}
|
188
248
|
```
|
189
249
|
|
190
|
-
## Template
|
250
|
+
## Template Blocks
|
191
251
|
|
192
252
|
Templates can also accept and render blocks by using `emit_yield`:
|
193
253
|
|
@@ -202,7 +262,7 @@ page = Papercraft.html {
|
|
202
262
|
page.render { h1 'hi' }
|
203
263
|
```
|
204
264
|
|
205
|
-
## Plain
|
265
|
+
## Plain Procs as Templates
|
206
266
|
|
207
267
|
With Papercraft you can write a template as a plain Ruby proc, and later render
|
208
268
|
it by passing it as a block to `Papercraft.html`:
|
@@ -219,7 +279,7 @@ greeting = ->(name) { h1 "Hello, #{name}!" }
|
|
219
279
|
Papercraft.html(&greeting).render('world')
|
220
280
|
```
|
221
281
|
|
222
|
-
## Template
|
282
|
+
## Template Composition
|
223
283
|
|
224
284
|
Papercraft makes it easy to compose multiple templates into a whole HTML
|
225
285
|
document. A Papercraft template can contain other templates, as the following
|
@@ -269,7 +329,7 @@ Papercraft.html {
|
|
269
329
|
}
|
270
330
|
```
|
271
331
|
|
272
|
-
## Parameter and
|
332
|
+
## Parameter and Block Application
|
273
333
|
|
274
334
|
Parameters and blocks can be applied to a template without it being rendered, by
|
275
335
|
using `#apply`. This mechanism is what allows template composition and the
|
@@ -294,7 +354,7 @@ wrapped_hello_world = div_wrap.apply(&hello_world)
|
|
294
354
|
wrapped_hello_world.render #=> "<div><h1>Hello, world!</h1></div>"
|
295
355
|
```
|
296
356
|
|
297
|
-
## Higher-
|
357
|
+
## Higher-Order Templates
|
298
358
|
|
299
359
|
Papercraft also lets you create higher-order templates, that is,
|
300
360
|
templates that take other templates as parameters, or as blocks. Higher-order
|
@@ -318,7 +378,7 @@ wrapped_greeter = div_wrap.apply { h1 'hi' }
|
|
318
378
|
wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
|
319
379
|
```
|
320
380
|
|
321
|
-
## Layout
|
381
|
+
## Layout Template Composition
|
322
382
|
|
323
383
|
One of the principal uses of higher-order templates is the creation of nested
|
324
384
|
layouts. Suppose we have a website with a number of different layouts, and we'd
|
@@ -351,7 +411,7 @@ article_layout.render(
|
|
351
411
|
)
|
352
412
|
```
|
353
413
|
|
354
|
-
## Emitting
|
414
|
+
## Emitting Raw HTML
|
355
415
|
|
356
416
|
Raw HTML can be emitted using `#emit`:
|
357
417
|
|
@@ -360,13 +420,13 @@ wrapped = Papercraft.html { |html| div { emit html } }
|
|
360
420
|
wrapped.render("<h1>hi</h1>") #=> "<div><h1>hi</h1></div>"
|
361
421
|
```
|
362
422
|
|
363
|
-
## Emitting a
|
423
|
+
## Emitting a String with HTML Encoding
|
364
424
|
|
365
425
|
To emit a string with proper HTML encoding, without wrapping it in an HTML
|
366
426
|
element, use `#text`:
|
367
427
|
|
368
428
|
```ruby
|
369
|
-
Papercraft.html {
|
429
|
+
Papercraft.html { text 'hi&lo' }.render #=> "hi&lo"
|
370
430
|
```
|
371
431
|
|
372
432
|
## Emitting Markdown
|
@@ -415,7 +475,7 @@ The deafult options can be configured by accessing
|
|
415
475
|
Papercraft.default_kramdown_options[:auto_ids] = false
|
416
476
|
```
|
417
477
|
|
418
|
-
## Working with MIME
|
478
|
+
## Working with MIME Types
|
419
479
|
|
420
480
|
Papercraft lets you set and interrogate a template's MIME type, in order to be
|
421
481
|
able to dynamically set the `Content-Type` HTTP response header. A template's
|
@@ -431,7 +491,7 @@ def serve_template(req, template)
|
|
431
491
|
end
|
432
492
|
```
|
433
493
|
|
434
|
-
## Deferred
|
494
|
+
## Deferred Evaluation
|
435
495
|
|
436
496
|
Deferred evaluation allows deferring the rendering of parts of a template until
|
437
497
|
the last moment, thus allowing an inner template to manipulate the state of the
|
@@ -483,7 +543,73 @@ page = default_layout.apply {
|
|
483
543
|
}
|
484
544
|
```
|
485
545
|
|
486
|
-
##
|
546
|
+
## XML Templates
|
547
|
+
|
548
|
+
XML templates behave largely the same as HTML templates, with a few minor
|
549
|
+
differences. XML templates employ a different encoding algorithm, and lack some
|
550
|
+
specific HTML functionality, such as emitting Markdown.
|
551
|
+
|
552
|
+
Here's an example showing how to create an RSS feed:
|
553
|
+
|
554
|
+
```ruby
|
555
|
+
rss = Papercraft.xml(mime_type: 'text/xml; charset=utf-8') { |resource:, **props|
|
556
|
+
rss(version: '2.0', 'xmlns:atom' => 'http://www.w3.org/2005/Atom') {
|
557
|
+
channel {
|
558
|
+
title 'Noteflakes'
|
559
|
+
link 'https://noteflakes.com/'
|
560
|
+
description 'A website by Sharon Rosner'
|
561
|
+
language 'en-us'
|
562
|
+
pubDate Time.now.httpdate
|
563
|
+
emit '<atom:link href="https://noteflakes.com/feeds/rss" rel="self" type="application/rss+xml" />'
|
564
|
+
|
565
|
+
article_entries = resource.page_list('/articles').reverse
|
566
|
+
|
567
|
+
article_entries.each { |e|
|
568
|
+
item {
|
569
|
+
title e[:title]
|
570
|
+
link "https://noteflakes.com#{e[:url]}"
|
571
|
+
guid "https://noteflakes.com#{e[:url]}"
|
572
|
+
pubDate e[:date].to_time.httpdate
|
573
|
+
description e[:html_content]
|
574
|
+
}
|
575
|
+
}
|
576
|
+
}
|
577
|
+
}
|
578
|
+
}
|
579
|
+
```
|
580
|
+
|
581
|
+
## JSON Templates
|
582
|
+
|
583
|
+
JSON templates behave largely the same as HTML and XML templates. The only major
|
584
|
+
difference is that for adding array items you'll need to use the `#item` method:
|
585
|
+
|
586
|
+
```ruby
|
587
|
+
Papercraft.json {
|
588
|
+
item 1
|
589
|
+
item 2
|
590
|
+
item 3
|
591
|
+
}.render #=> "[1,2,3]"
|
592
|
+
```
|
593
|
+
|
594
|
+
Otherwise, you can create arbitrarily complex JSON structures by mixing hashes
|
595
|
+
and arrays:
|
596
|
+
|
597
|
+
```Ruby
|
598
|
+
Papercraft.json {
|
599
|
+
foo {
|
600
|
+
bar {
|
601
|
+
item nil
|
602
|
+
item true
|
603
|
+
item 123.456
|
604
|
+
}
|
605
|
+
}
|
606
|
+
}.render #=> "{\"foo\":{\"bar\":[null,true,123.456]}}"
|
607
|
+
```
|
608
|
+
|
609
|
+
Papercraft uses the [JSON gem](https://rubyapi.org/3.1/o/json) under the hood in
|
610
|
+
order to generate actual JSON.
|
611
|
+
|
612
|
+
## Papercraft Extensions
|
487
613
|
|
488
614
|
Papercraft extensions are modules that contain one or more methods that can be
|
489
615
|
used to render complex HTML components. Extension modules can be used by
|
@@ -513,21 +639,27 @@ and other associated methods:
|
|
513
639
|
|
514
640
|
```ruby
|
515
641
|
module BootstrapComponents
|
516
|
-
|
517
|
-
|
518
|
-
def card(**props)
|
642
|
+
def card(**props, &block)
|
519
643
|
div(class: 'card', **props) {
|
520
|
-
div(class: 'card-body')
|
521
|
-
emit_yield
|
522
|
-
}
|
644
|
+
div(class: 'card-body', &block)
|
523
645
|
}
|
524
646
|
end
|
525
|
-
|
647
|
+
|
526
648
|
def card_title(title)
|
527
|
-
|
649
|
+
h4(title, class: 'card-title')
|
650
|
+
end
|
651
|
+
|
652
|
+
def card_subtitle(subtitle)
|
653
|
+
h5(subtitle, class: 'card-subtitle')
|
528
654
|
end
|
529
655
|
|
530
|
-
|
656
|
+
def card_text(text)
|
657
|
+
p(text, class: 'card-text')
|
658
|
+
end
|
659
|
+
|
660
|
+
def card_link(text, **opts)
|
661
|
+
a(text, class: 'card-link', **opts)
|
662
|
+
end
|
531
663
|
end
|
532
664
|
|
533
665
|
Papercraft.extension(bootstrap: BootstrapComponents)
|
@@ -543,81 +675,63 @@ Papercraft.html {
|
|
543
675
|
bootstrap.card_title 'Card title'
|
544
676
|
bootstrap.card_subtitle 'Card subtitle'
|
545
677
|
bootstrap.card_text 'Some quick example text to build on the card title and make up the bulk of the card''s content.'
|
546
|
-
bootstrap.card_link '
|
547
|
-
bootstrap.card_link '
|
678
|
+
bootstrap.card_link 'Card link', href: '#foo'
|
679
|
+
bootstrap.card_link 'Another link', href: '#bar'
|
548
680
|
}
|
549
681
|
}
|
550
682
|
```
|
551
683
|
|
684
|
+
## Bundled Extensions
|
552
685
|
|
686
|
+
Papercraft comes bundled with a few extensions that address common use cases.
|
687
|
+
All bundled extensions are namespaced under `Papercraft::Extensions`, and must
|
688
|
+
be specifically required in order to be available to templates.
|
553
689
|
|
554
|
-
|
690
|
+
For all bundled Papercraft extensions, there's no need to call
|
691
|
+
`Papercraft.extension`, requiring the extension is sufficient.
|
555
692
|
|
556
|
-
|
557
|
-
differences. XML templates employ a different encoding algorithm, and lack some
|
558
|
-
specific HTML functionality, such as emitting Markdown.
|
693
|
+
### SOAP Extension
|
559
694
|
|
560
|
-
|
695
|
+
> The SOAP extension was contributed by [@aemadrid](https://github.com/aemadrid).
|
561
696
|
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
channel {
|
566
|
-
title 'Noteflakes'
|
567
|
-
link 'https://noteflakes.com/'
|
568
|
-
description 'A website by Sharon Rosner'
|
569
|
-
language 'en-us'
|
570
|
-
pubDate Time.now.httpdate
|
571
|
-
emit '<atom:link href="https://noteflakes.com/feeds/rss" rel="self" type="application/rss+xml" />'
|
572
|
-
|
573
|
-
article_entries = resource.page_list('/articles').reverse
|
697
|
+
The SOAP extension provides common tags for building SOAP payloads. To load the
|
698
|
+
SOAP extensions, require `polyphony/extensions/soap`. The extension provides the
|
699
|
+
following methods:
|
574
700
|
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
guid "https://noteflakes.com#{e[:url]}"
|
580
|
-
pubDate e[:date].to_time.httpdate
|
581
|
-
description e[:html_content]
|
582
|
-
}
|
583
|
-
}
|
584
|
-
}
|
585
|
-
}
|
586
|
-
}
|
587
|
-
```
|
701
|
+
- `soap.Body(...)` - emits a `soap:Body` tag.
|
702
|
+
- `soap.Envelope(...)` - emits a `soap:Envelope` tag.
|
703
|
+
- `soap.Fault(...)` - emits a `soap:Fault` tag.
|
704
|
+
- `soap.Header(...)` - emits a `soap:Header` tag.
|
588
705
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
difference is that for adding array items you'll need to use the `#item` method:
|
706
|
+
As mentioned above, namespaced tags and attributes may be specified by using
|
707
|
+
double underscores for colons. Other tags that contain special characters may be
|
708
|
+
emitted using the `#tag` method:
|
593
709
|
|
594
710
|
```ruby
|
595
|
-
|
596
|
-
item 1
|
597
|
-
item 2
|
598
|
-
item 3
|
599
|
-
}.render #=> "[1,2,3]"
|
600
|
-
```
|
711
|
+
require 'polyphony/extensions/soap'
|
601
712
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
713
|
+
xml = Papercraft.xml {
|
714
|
+
soap.Envelope(
|
715
|
+
xmlns__xsd: 'http://www.w3.org/2001/XMLSchema',
|
716
|
+
xmlns__xsi: 'http://www.w3.org/2001/XMLSchema-instance'
|
717
|
+
) {
|
718
|
+
soap.Body {
|
719
|
+
PosRequest(xmlns: 'http://Some.Site') {
|
720
|
+
tag('Ver1.0') {
|
721
|
+
Header {
|
722
|
+
SecretAPIKey 'some_secret_key'
|
723
|
+
}
|
724
|
+
Transaction {
|
725
|
+
SomeData {}
|
726
|
+
}
|
727
|
+
}
|
728
|
+
}
|
612
729
|
}
|
613
730
|
}
|
614
|
-
}
|
731
|
+
}
|
615
732
|
```
|
616
733
|
|
617
|
-
Papercraft uses the [JSON gem](https://rubyapi.org/3.1/o/json) under the hood in
|
618
|
-
order to generate actual JSON.
|
619
|
-
|
620
734
|
## API Reference
|
621
735
|
|
622
736
|
The API reference for this library can be found
|
623
|
-
[here](https://www.rubydoc.info/gems/papercraft).
|
737
|
+
[here](https://www.rubydoc.info/gems/papercraft).
|
@@ -23,10 +23,21 @@ module Papercraft
|
|
23
23
|
#
|
24
24
|
# @param sym [Symbol] method name
|
25
25
|
# @param *args [Array] arguments
|
26
|
+
# @param *props [Array] named arguments
|
26
27
|
# @param &block [Proc] block
|
27
28
|
# @return void
|
28
|
-
def method_missing(sym, *args, &block)
|
29
|
-
@renderer.send(sym, *args, &block)
|
29
|
+
def method_missing(sym, *args, **props, &block)
|
30
|
+
@renderer.send(sym, *args, **props, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Overrides the `Kernel#p` method to emit a p tag.
|
34
|
+
#
|
35
|
+
# @param *args [Array] arguments
|
36
|
+
# @param *props [Array] named arguments
|
37
|
+
# @param &block [Proc] block
|
38
|
+
# @return void
|
39
|
+
def p(text = nil, **props, &block)
|
40
|
+
@renderer.p(text, **props, &block)
|
30
41
|
end
|
31
42
|
end
|
32
43
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Papercraft
|
4
|
+
module Extensions
|
5
|
+
module Soap
|
6
|
+
# Emits a SOAP XML tag that identifies the XML document as a SOAP message.
|
7
|
+
#
|
8
|
+
# @param **props [Hash] tag attributes
|
9
|
+
# @param &block [Proc] optional inner XML
|
10
|
+
# @return [void]
|
11
|
+
def Envelope(**props, &block)
|
12
|
+
props[:xmlns__soap] ||= 'http://schemas.xmlsoap.org/soap/envelope/'
|
13
|
+
tag('soap:Envelope', **props, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Emits a SOAP XML tag that contains header information.
|
17
|
+
#
|
18
|
+
# @param **props [Hash] tag attributes
|
19
|
+
# @param &block [Proc] optional inner XML
|
20
|
+
# @return [void]
|
21
|
+
def Header(**props, &blk)
|
22
|
+
tag('soap:Header', **props, &blk)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Emits a SOAP XML tag that contains header information.
|
26
|
+
#
|
27
|
+
# @param **props [Hash] tag attributes
|
28
|
+
# @param &block [Proc] optional inner XML
|
29
|
+
# @return [void]
|
30
|
+
def Body(**props, &blk)
|
31
|
+
tag('soap:Body', **props, &blk)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Emits a SOAP XML tag that contains errors and status information.
|
35
|
+
#
|
36
|
+
# @param **props [Hash] tag attributes
|
37
|
+
# @param &block [Proc] optional inner XML
|
38
|
+
# @return [void]
|
39
|
+
def Fault(**props, &blk)
|
40
|
+
tag('soap:Fault', **props, &blk)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Papercraft.extension(soap: Papercraft::Extensions::Soap)
|
data/lib/papercraft/renderer.rb
CHANGED
@@ -47,17 +47,17 @@ module Papercraft
|
|
47
47
|
# components. In cases where method names in the module clash with XML
|
48
48
|
# tag names, you can use the `#tag` method to emit the relevant tag.
|
49
49
|
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
50
|
+
# module ComponentLibrary
|
51
|
+
# def card(title, content)
|
52
|
+
# div(class: 'card') {
|
53
|
+
# h3 title
|
54
|
+
# div(class: 'card-content') { emit_markdown content }
|
55
|
+
# }
|
56
|
+
# end
|
56
57
|
# end
|
57
|
-
# end
|
58
58
|
#
|
59
|
-
#
|
60
|
-
#
|
59
|
+
# Papercraft.extension(components: ComponentLibrary)
|
60
|
+
# Papercraft.html { components.card('Foo', '**Bar**') }
|
61
61
|
#
|
62
62
|
# @param map [Hash] hash mapping methods to extension modules
|
63
63
|
# @return [void]
|
data/lib/papercraft/tags.rb
CHANGED
@@ -160,16 +160,14 @@ module Papercraft
|
|
160
160
|
# @param &block [Proc] block passed to method
|
161
161
|
# @return [void]
|
162
162
|
def method_missing(sym, *args, **opts, &block)
|
163
|
-
# p method_missing: sym, self: self
|
164
163
|
tag = sym.to_s
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
self.class.class_eval(code, __FILE__, S_TAG_METHOD_LINE)
|
164
|
+
if tag =~ /^[A-Z]/ && (Object.const_defined?(tag))
|
165
|
+
define_const_tag_method(tag)
|
166
|
+
# return send(tag, *args, **opts)
|
167
|
+
else
|
168
|
+
define_tag_method(tag)
|
169
|
+
end
|
170
|
+
|
173
171
|
send(sym, *args, **opts, &block)
|
174
172
|
end
|
175
173
|
|
@@ -184,6 +182,33 @@ module Papercraft
|
|
184
182
|
|
185
183
|
private
|
186
184
|
|
185
|
+
# Defines a method that emits the given tag based on a constant. The
|
186
|
+
# constant must be defined on the main (Object) binding.
|
187
|
+
#
|
188
|
+
# @param tag [Symbol, String] tag/method name
|
189
|
+
# @return [void]
|
190
|
+
def define_const_tag_method(tag)
|
191
|
+
const = Object.const_get(tag)
|
192
|
+
self.class.define_method(tag) { |*a, **b, &blk|
|
193
|
+
emit const, *a, **b, &blk
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
# Defines a normal tag method.
|
198
|
+
#
|
199
|
+
# @param tag [Symbol, String] tag/method name
|
200
|
+
# @return [void]
|
201
|
+
def define_tag_method(tag)
|
202
|
+
repr = tag_repr(tag)
|
203
|
+
code = S_TAG_METHOD % {
|
204
|
+
tag: tag,
|
205
|
+
TAG: tag.upcase,
|
206
|
+
tag_pre: "<#{repr}".inspect,
|
207
|
+
tag_close: "</#{repr}>".inspect
|
208
|
+
}
|
209
|
+
self.class.class_eval(code, __FILE__, S_TAG_METHOD_LINE)
|
210
|
+
end
|
211
|
+
|
187
212
|
# Emits an arbitrary object by converting it to string, then adding it to
|
188
213
|
# the internal buffer. This method is called internally by `Renderer#emit`.
|
189
214
|
#
|
@@ -252,7 +277,7 @@ module Papercraft
|
|
252
277
|
# emit nothing
|
253
278
|
else
|
254
279
|
@buffer << S_SPACE << att_repr(k) <<
|
255
|
-
S_EQUAL_QUOTE << v << S_QUOTE
|
280
|
+
S_EQUAL_QUOTE << escape_text(v) << S_QUOTE
|
256
281
|
end
|
257
282
|
end
|
258
283
|
}
|
data/lib/papercraft/version.rb
CHANGED
data/lib/papercraft.rb
CHANGED
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.24'
|
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-
|
11
|
+
date: 2022-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: escape_utils
|
@@ -134,8 +134,8 @@ files:
|
|
134
134
|
- README.md
|
135
135
|
- lib/papercraft.rb
|
136
136
|
- lib/papercraft/compiler.rb
|
137
|
-
- lib/papercraft/encoding.rb
|
138
137
|
- lib/papercraft/extension_proxy.rb
|
138
|
+
- lib/papercraft/extensions/soap.rb
|
139
139
|
- lib/papercraft/html.rb
|
140
140
|
- lib/papercraft/json.rb
|
141
141
|
- lib/papercraft/renderer.rb
|
data/lib/papercraft/encoding.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Papercraft
|
4
|
-
# Papercraft::Encoding includes common encoding methods
|
5
|
-
module Encoding
|
6
|
-
# Encodes the given string to safe HTML text, converting special characters
|
7
|
-
# into the respective HTML entities. If a non-string value is given, it is
|
8
|
-
# converted to `String` using `#to_s`.
|
9
|
-
#
|
10
|
-
# @param text [String] string to be encoded
|
11
|
-
# @return [String] HTML-encoded string
|
12
|
-
def __html_encode__(text)
|
13
|
-
EscapeUtils.escape_html(text.to_s)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Encodes the given string to safe URI component, converting special
|
17
|
-
# characters to URI entities. If a non-string value is given, it is
|
18
|
-
# converted to `String` using `#to_s`.
|
19
|
-
#
|
20
|
-
# @param text [String] string to be encoded
|
21
|
-
# @return [String] URI-encoded string
|
22
|
-
def __uri_encode__(text)
|
23
|
-
EscapeUtils.escape_uri(text.to_s)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|