p2 2.8 → 2.9
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 +13 -6
- data/README.md +20 -39
- data/lib/p2/compiler.rb +14 -8
- data/lib/p2/proc_ext.rb +3 -3
- data/lib/p2/version.rb +1 -1
- data/lib/p2.rb +5 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bda78e0c4b37c895274b5d357022f3f491bf6b1fdab4d52cdc4e7aa7660f2f6a
|
4
|
+
data.tar.gz: f9e1295f3208cb6b734d65d20afa41fcb46803b37b51b7d801ab56715fe24db8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80891d65d533e7fabac367d342c3884c0da607e5c815821ace691fe62e5ae393983e89c60cc226b69627b0ebb66bf7f1d91ae89f8be6d8baca9620498364c756
|
7
|
+
data.tar.gz: 3e969bb24fbc9ec1668757e5ac152baf0052928937bd18d8c708a2031c416d8752cf8b85f3047427de82eafd008abd6126d212e3265fcfbfd9275b6ed4bc0b95
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
+
# 2.9 2025-09-02
|
2
|
+
|
3
|
+
- Tweak generated code to incorporate @byroot's
|
4
|
+
[recommendations](https://www.reddit.com/r/ruby/comments/1mtj7bx/comment/n9ckbvt/):
|
5
|
+
- Remove call to to_s coercion before calling html_escape
|
6
|
+
- Chain calls to `#<<` with emitted HTML parts
|
7
|
+
|
1
8
|
# 2.8 2025-08-17
|
2
9
|
|
3
|
-
- Add render_children builtin
|
4
|
-
- Rename emit_yield to render_yield
|
10
|
+
- Add `#render_children` builtin
|
11
|
+
- Rename `#emit_yield` to `#render_yield`
|
5
12
|
- Add `Proc#render_cached` for caching render result
|
6
13
|
|
7
14
|
# 2.7 2025-08-17
|
@@ -12,13 +19,13 @@
|
|
12
19
|
|
13
20
|
# 2.6 2025-08-16
|
14
21
|
|
15
|
-
- Add support for block invocation
|
22
|
+
- Add support for block invocation
|
16
23
|
|
17
24
|
# 2.5 2025-08-15
|
18
25
|
|
19
|
-
- Translate backtrace for exceptions raised in `#render_to_buffer
|
20
|
-
- Improve display of backtrace when source map is missing entries
|
21
|
-
- Improve handling of ArgumentError raised on calling the template
|
26
|
+
- Translate backtrace for exceptions raised in `#render_to_buffer`
|
27
|
+
- Improve display of backtrace when source map is missing entries
|
28
|
+
- Improve handling of ArgumentError raised on calling the template
|
22
29
|
- Add `Template#apply`, `Template#compiled_proc` methods
|
23
30
|
|
24
31
|
# 2.4 2025-08-10
|
data/README.md
CHANGED
@@ -10,8 +10,8 @@
|
|
10
10
|
<a href="http://rubygems.org/gems/p2">
|
11
11
|
<img src="https://badge.fury.io/rb/p2.svg" alt="Ruby gem">
|
12
12
|
</a>
|
13
|
-
<a href="https://github.com/digital-fabric/p2/actions
|
14
|
-
<img src="https://github.com/digital-fabric/p2/workflows/
|
13
|
+
<a href="https://github.com/digital-fabric/p2/actions/workflows/test.yml">
|
14
|
+
<img src="https://github.com/digital-fabric/p2/actions/workflows/test.yml/badge.svg" alt="Tests">
|
15
15
|
</a>
|
16
16
|
<a href="https://github.com/digital-fabric/p2/blob/master/LICENSE">
|
17
17
|
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
|
@@ -39,7 +39,6 @@ page.render {
|
|
39
39
|
#=> "<html><head><title>Title</title></head><body><p>foo</p></body></html>"
|
40
40
|
```
|
41
41
|
|
42
|
-
|
43
42
|
P2 is a templating engine for dynamically producing HTML in Ruby apps. P2
|
44
43
|
templates are expressed as Ruby procs, leading to easier debugging, better
|
45
44
|
protection against HTML injection attacks, and better code reuse.
|
@@ -90,7 +89,7 @@ P2 features:
|
|
90
89
|
## Table of Content
|
91
90
|
|
92
91
|
- [Getting Started](#getting-started)
|
93
|
-
- [Basic Markup](#markup)
|
92
|
+
- [Basic Markup](#basic-markup)
|
94
93
|
- [Builtin Methods](#builtin-methods)
|
95
94
|
- [Template Parameters](#template-parameters)
|
96
95
|
- [Template Logic](#template-logic)
|
@@ -99,11 +98,12 @@ P2 features:
|
|
99
98
|
- [Parameter and Block Application](#parameter-and-block-application)
|
100
99
|
- [Higher-Order Templates](#higher-order-templates)
|
101
100
|
- [Layout Template Composition](#layout-template-composition)
|
102
|
-
- [Emitting Raw HTML](#emitting-raw-html)
|
103
|
-
- [Emitting a String with HTML Escaping](#emitting-a-string-with-html-escaping)
|
104
101
|
- [Emitting Markdown](#emitting-markdown)
|
105
102
|
- [Deferred Evaluation](#deferred-evaluation)
|
106
|
-
- [
|
103
|
+
- [Cached Rendering](#cached-rendering)
|
104
|
+
|
105
|
+
A typical example for a dashboard-type app markup can be found here:
|
106
|
+
https://github.com/digital-fabric/p2/blob/master/examples/dashboard.rb
|
107
107
|
|
108
108
|
## Getting Started
|
109
109
|
|
@@ -123,7 +123,7 @@ require 'p2'
|
|
123
123
|
html.render #=> "<div id="greeter"><p>Hello!</p></div>"
|
124
124
|
```
|
125
125
|
|
126
|
-
## Markup
|
126
|
+
## Basic Markup
|
127
127
|
|
128
128
|
Tags are added using unqualified method calls, and can be nested using blocks:
|
129
129
|
|
@@ -511,24 +511,6 @@ article_layout.render(
|
|
511
511
|
)
|
512
512
|
```
|
513
513
|
|
514
|
-
## Emitting Raw HTML
|
515
|
-
|
516
|
-
Raw HTML can be emitted using `#raw`:
|
517
|
-
|
518
|
-
```ruby
|
519
|
-
wrapped = -> { |html| div { raw html } }
|
520
|
-
wrapped.render("<h1>hi</h1>") #=> "<div><h1>hi</h1></div>"
|
521
|
-
```
|
522
|
-
|
523
|
-
## Emitting a String with HTML Escaping
|
524
|
-
|
525
|
-
To emit a string with proper HTML escaping, without wrapping it in an HTML
|
526
|
-
element, use `#text`:
|
527
|
-
|
528
|
-
```ruby
|
529
|
-
-> { text 'hi&lo' }.render #=> "hi&lo"
|
530
|
-
```
|
531
|
-
|
532
514
|
## Emitting Markdown
|
533
515
|
|
534
516
|
Markdown is rendered using the
|
@@ -626,18 +608,17 @@ page = default_layout.apply {
|
|
626
608
|
}
|
627
609
|
```
|
628
610
|
|
629
|
-
##
|
611
|
+
## Cached Rendering
|
630
612
|
|
631
|
-
|
632
|
-
|
613
|
+
P2 provides a simple API for caching the result of a rendering. The cache stores
|
614
|
+
renderings of a template respective to the given arguments. To automatically
|
615
|
+
retrieve the cached rendered HTML, or generate it for the first time, use
|
616
|
+
`Proc#render_cached`:
|
633
617
|
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
- `style(css, **attributes)` - emits an inline `<style>` element
|
642
|
-
- `versioned_file_href(href, root_path, root_url)` - calculates a versioned href
|
643
|
-
for the given file
|
618
|
+
```ruby
|
619
|
+
template = ->(title) { div { h1 title } }
|
620
|
+
template.render_cached('foo') #=> <div><h1>foo</h1></div>
|
621
|
+
template.render_cached('foo') #=> <div><h1>foo</h1></div> (from cache)
|
622
|
+
template.render_cached('bar') #=> <div><h1>bar</h1></div>
|
623
|
+
template.render_cached('bar') #=> <div><h1>bar</h1></div> (from cache)
|
624
|
+
```
|
data/lib/p2/compiler.rb
CHANGED
@@ -168,9 +168,7 @@ module P2
|
|
168
168
|
if is_static_node?(node.inner_text)
|
169
169
|
emit_html(node.location, ERB::Escape.html_escape(format_literal(node.inner_text)))
|
170
170
|
else
|
171
|
-
|
172
|
-
|
173
|
-
emit_html(node.location, interpolated("ERB::Escape.html_escape((#{format_code(node.inner_text)})#{to_s})"))
|
171
|
+
emit_html(node.location, interpolated("ERB::Escape.html_escape((#{format_code(node.inner_text)}))"))
|
174
172
|
end
|
175
173
|
end
|
176
174
|
emit_html(node.location, format_html_tag_close(tag))
|
@@ -230,7 +228,7 @@ module P2
|
|
230
228
|
if is_static_node?(first_arg)
|
231
229
|
emit_html(node.location, ERB::Escape.html_escape(format_literal(first_arg)))
|
232
230
|
else
|
233
|
-
emit_html(node.location, interpolated("ERB::Escape.html_escape(#{format_code(first_arg)}
|
231
|
+
emit_html(node.location, interpolated("ERB::Escape.html_escape(#{format_code(first_arg)})"))
|
234
232
|
end
|
235
233
|
else
|
236
234
|
raise "Don't know how to compile #{node}"
|
@@ -597,14 +595,15 @@ module P2
|
|
597
595
|
return if @pending_html_parts.empty?
|
598
596
|
|
599
597
|
adjust_whitespace(@html_loc_start, advance_to_end: false)
|
598
|
+
emit('; __buffer__')
|
600
599
|
concatenated = +''
|
601
600
|
|
602
601
|
last_loc = @html_loc_start
|
603
602
|
@pending_html_parts.each do |(loc, part)|
|
604
603
|
if (m = part.match(/^#\{(.+)\}$/m))
|
605
604
|
emit_html_buffer_push(concatenated, quotes: true) if !concatenated.empty?
|
606
|
-
adjust_whitespace(loc, advance_to_end: false)
|
607
|
-
emit_html_buffer_push(m[1])
|
605
|
+
# adjust_whitespace(loc, advance_to_end: false)
|
606
|
+
emit_html_buffer_push(m[1], loc:)
|
608
607
|
else
|
609
608
|
concatenated << part
|
610
609
|
end
|
@@ -628,11 +627,18 @@ module P2
|
|
628
627
|
# @param part [String] HTML part
|
629
628
|
# @param quotes [bool] whether to wrap emitted HTML in double quotes
|
630
629
|
# @return [void]
|
631
|
-
def emit_html_buffer_push(part, quotes: false)
|
630
|
+
def emit_html_buffer_push(part, quotes: false, loc: nil)
|
632
631
|
return if part.empty?
|
633
632
|
|
634
633
|
q = quotes ? '"' : ''
|
635
|
-
|
634
|
+
if loc
|
635
|
+
emit(".<<(")
|
636
|
+
adjust_whitespace(loc, advance_to_end: false)
|
637
|
+
emit("#{q}#{part}#{q}")
|
638
|
+
emit(")")
|
639
|
+
else
|
640
|
+
emit(".<<(#{q}#{part}#{q})")
|
641
|
+
end
|
636
642
|
part.clear
|
637
643
|
end
|
638
644
|
|
data/lib/p2/proc_ext.rb
CHANGED
@@ -92,9 +92,9 @@ class ::Proc
|
|
92
92
|
end
|
93
93
|
|
94
94
|
# Caches and returns
|
95
|
-
def render_cached(*args, **kargs)
|
95
|
+
def render_cached(*args, **kargs, &block)
|
96
96
|
@render_cache ||= {}
|
97
|
-
key = args.empty? && kargs.empty? ? nil : [args, kargs]
|
98
|
-
@render_cache[key] ||= render(*args, **kargs)
|
97
|
+
key = args.empty? && kargs.empty? && !block ? nil : [args, kargs, block&.source_location]
|
98
|
+
@render_cache[key] ||= render(*args, **kargs, &block)
|
99
99
|
end
|
100
100
|
end
|
data/lib/p2/version.rb
CHANGED
data/lib/p2.rb
CHANGED
@@ -101,10 +101,11 @@ module P2
|
|
101
101
|
# @param opts [Hash] Kramdown option overrides
|
102
102
|
# @return [String] HTML
|
103
103
|
def markdown(markdown, **opts)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
@markdown_deps_loaded ||= true.tap do
|
105
|
+
require 'kramdown'
|
106
|
+
require 'rouge'
|
107
|
+
require 'kramdown-parser-gfm'
|
108
|
+
end
|
108
109
|
|
109
110
|
opts = default_kramdown_options.merge(opts)
|
110
111
|
Kramdown::Document.new(markdown, **opts).to_html
|