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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a84949b86e99acbe131d37cb624dbf60010fe720ce27081d5e5652b33f2de004
4
- data.tar.gz: c03bef8c358bae1536c04739c2fa67bd3ce6e879fd036f2e7352c6291677b888
3
+ metadata.gz: bda78e0c4b37c895274b5d357022f3f491bf6b1fdab4d52cdc4e7aa7660f2f6a
4
+ data.tar.gz: f9e1295f3208cb6b734d65d20afa41fcb46803b37b51b7d801ab56715fe24db8
5
5
  SHA512:
6
- metadata.gz: 2993a42368846048e02ca7cb01d2ba6f7be013870a5f39597478442d16659b730356443b1b77ee8bb36c6b9a3942bde7d8ef19e66ad087d2a69d9b686d5cc706
7
- data.tar.gz: 7739be72dd3bdf195188339509a21e24bccbae6ac8efb140a16780445f71b60fea12ab0a87831f117422b620102c277391f33db944b94b7945088f16cf099d73
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?query=workflow%3ATests">
14
- <img src="https://github.com/digital-fabric/p2/workflows/Tests/badge.svg" alt="Tests">
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
- - [API Reference](#api-reference)
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&amp;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
- ## HTML Utility methods
611
+ ## Cached Rendering
630
612
 
631
- HTML templates include a few HTML-specific methods to facilitate writing modern
632
- HTML:
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
- - `html5 { ... }` - emits an HTML 5 DOCTYPE (`<!DOCTYPE html>`)
635
- - `import_map(root_path, root_url)` - emits an import map including all files
636
- matching `<root_path>/*.js`, based on the given `root_url`
637
- - `js_module(js)` - emits a `<script type="module">` element
638
- - `link_stylesheet(href, **attributes)` - emits a `<link rel="stylesheet" ...>`
639
- element
640
- - `script(js, **attributes)` - emits an inline `<script>` element
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
- to_s = is_string_type_node?(node.inner_text) ? '' : '.to_s'
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)}.to_s)"))
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
- emit("; __buffer__ << #{q}#{part}#{q}")
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module P2
4
- VERSION = '2.8'
4
+ VERSION = '2.9'
5
5
  end
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
- # require relevant deps on use
105
- require 'kramdown'
106
- require 'rouge'
107
- require 'kramdown-parser-gfm'
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: p2
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.8'
4
+ version: '2.9'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner