p2 2.8 → 2.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 +4 -4
- data/CHANGELOG.md +19 -6
- data/README.md +20 -39
- data/lib/p2/compiler/tag_translator.rb +1 -1
- data/lib/p2/compiler.rb +32 -18
- data/lib/p2/proc_ext.rb +40 -22
- data/lib/p2/version.rb +1 -1
- data/lib/p2.rb +6 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14c5c67f786953f8783be2cb53cb1eb4ad54be9f1ce769ce340cdc07d45b7a52
|
4
|
+
data.tar.gz: 1788cf26c810fa3f4d47b6db4b0de149b223e47d6a8356af7dea580190664da9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c898b73cbfeffcc1227bc15889d43e78dd03f745a9aee584767f4e8c22ae25d698190454c5cea9600735dddcc2da91a95fb7324b5cf906ef19824ba3dce7020c
|
7
|
+
data.tar.gz: 6575f62f6158438bc95bea56d60d0f6fe4e11b1e45269584f6a644ffcd3d647e20bd712a869a556d882c4ff00a74a93f1bdefb5e8fe759787588bae9b3ba4abb
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,20 @@
|
|
1
|
+
# 2.10 2025-09-11
|
2
|
+
|
3
|
+
- Add support for rendering XML, implement `Proc#render_xml`
|
4
|
+
- Fix handling of literal strings with double quotes
|
5
|
+
- Improve error handling for `P2::Error` exceptions
|
6
|
+
|
7
|
+
# 2.9 2025-09-02
|
8
|
+
|
9
|
+
- Tweak generated code to incorporate @byroot's
|
10
|
+
[recommendations](https://www.reddit.com/r/ruby/comments/1mtj7bx/comment/n9ckbvt/):
|
11
|
+
- Remove call to to_s coercion before calling html_escape
|
12
|
+
- Chain calls to `#<<` with emitted HTML parts
|
13
|
+
|
1
14
|
# 2.8 2025-08-17
|
2
15
|
|
3
|
-
- Add render_children builtin
|
4
|
-
- Rename emit_yield to render_yield
|
16
|
+
- Add `#render_children` builtin
|
17
|
+
- Rename `#emit_yield` to `#render_yield`
|
5
18
|
- Add `Proc#render_cached` for caching render result
|
6
19
|
|
7
20
|
# 2.7 2025-08-17
|
@@ -12,13 +25,13 @@
|
|
12
25
|
|
13
26
|
# 2.6 2025-08-16
|
14
27
|
|
15
|
-
- Add support for block invocation
|
28
|
+
- Add support for block invocation
|
16
29
|
|
17
30
|
# 2.5 2025-08-15
|
18
31
|
|
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
|
32
|
+
- Translate backtrace for exceptions raised in `#render_to_buffer`
|
33
|
+
- Improve display of backtrace when source map is missing entries
|
34
|
+
- Improve handling of ArgumentError raised on calling the template
|
22
35
|
- Add `Template#apply`, `Template#compiled_proc` methods
|
23
36
|
|
24
37
|
# 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
@@ -14,15 +14,16 @@ module P2
|
|
14
14
|
# generated optimized source code.
|
15
15
|
#
|
16
16
|
# @param proc [Proc] template
|
17
|
+
# @param mode [Symbol] compilation mode (:html, :xml)
|
17
18
|
# @param wrap [bool] whether to wrap the generated code with a literal Proc definition
|
18
19
|
# @return [Array] array containing the source map and generated code
|
19
|
-
def self.compile_to_code(proc, wrap: true)
|
20
|
+
def self.compile_to_code(proc, mode: :html, wrap: true)
|
20
21
|
ast = Sirop.to_ast(proc)
|
21
22
|
|
22
23
|
# adjust ast root if proc is defined with proc {} / lambda {} syntax
|
23
24
|
ast = ast.block if ast.is_a?(Prism::CallNode)
|
24
25
|
|
25
|
-
compiler = new.with_source_map(proc, ast)
|
26
|
+
compiler = new(mode:).with_source_map(proc, ast)
|
26
27
|
transformed_ast = TagTranslator.transform(ast.body, ast)
|
27
28
|
compiler.format_compiled_template(transformed_ast, ast, wrap:, binding: proc.binding)
|
28
29
|
[compiler.source_map, compiler.buffer]
|
@@ -37,10 +38,11 @@ module P2
|
|
37
38
|
# compiled.render #=> '<h1>Hello, world!'
|
38
39
|
#
|
39
40
|
# @param proc [Proc] template
|
41
|
+
# @param mode [Symbol] compilation mode (:html, :xml)
|
40
42
|
# @param wrap [bool] whether to wrap the generated code with a literal Proc definition
|
41
43
|
# @return [Proc] compiled proc
|
42
|
-
def self.compile(proc, wrap: true)
|
43
|
-
source_map, code = compile_to_code(proc, wrap:)
|
44
|
+
def self.compile(proc, mode: :html, wrap: true)
|
45
|
+
source_map, code = compile_to_code(proc, mode:, wrap:)
|
44
46
|
if ENV['DEBUG'] == '1'
|
45
47
|
puts '*' * 40
|
46
48
|
puts code
|
@@ -66,8 +68,9 @@ module P2
|
|
66
68
|
attr_reader :source_map
|
67
69
|
|
68
70
|
# Initializes a compiler.
|
69
|
-
def initialize(**)
|
71
|
+
def initialize(mode:, **)
|
70
72
|
super(**)
|
73
|
+
@mode = mode
|
71
74
|
@pending_html_parts = []
|
72
75
|
end
|
73
76
|
|
@@ -168,9 +171,7 @@ module P2
|
|
168
171
|
if is_static_node?(node.inner_text)
|
169
172
|
emit_html(node.location, ERB::Escape.html_escape(format_literal(node.inner_text)))
|
170
173
|
else
|
171
|
-
|
172
|
-
|
173
|
-
emit_html(node.location, interpolated("ERB::Escape.html_escape((#{format_code(node.inner_text)})#{to_s})"))
|
174
|
+
emit_html(node.location, interpolated("ERB::Escape.html_escape((#{format_code(node.inner_text)}))"))
|
174
175
|
end
|
175
176
|
end
|
176
177
|
emit_html(node.location, format_html_tag_close(tag))
|
@@ -230,7 +231,7 @@ module P2
|
|
230
231
|
if is_static_node?(first_arg)
|
231
232
|
emit_html(node.location, ERB::Escape.html_escape(format_literal(first_arg)))
|
232
233
|
else
|
233
|
-
emit_html(node.location, interpolated("ERB::Escape.html_escape(#{format_code(first_arg)}
|
234
|
+
emit_html(node.location, interpolated("ERB::Escape.html_escape(#{format_code(first_arg)})"))
|
234
235
|
end
|
235
236
|
else
|
236
237
|
raise "Don't know how to compile #{node}"
|
@@ -338,7 +339,7 @@ module P2
|
|
338
339
|
block_params << format_code(params.keyword_rest) if params.keyword_rest
|
339
340
|
end
|
340
341
|
block_params = block_params.empty? ? '' : ", #{block_params.join(', ')}"
|
341
|
-
|
342
|
+
|
342
343
|
emit(", &(proc { |__buffer__#{block_params}| #{block_body} }).compiled!")
|
343
344
|
end
|
344
345
|
emit(")")
|
@@ -423,11 +424,11 @@ module P2
|
|
423
424
|
# @param node [Prism::Node] AST
|
424
425
|
# @return [String] generated source code
|
425
426
|
def format_code(node)
|
426
|
-
Compiler.new(minimize_whitespace: true).to_source(node)
|
427
|
+
Compiler.new(mode: @mode, minimize_whitespace: true).to_source(node)
|
427
428
|
end
|
428
429
|
|
429
430
|
def format_inline_block(node)
|
430
|
-
Compiler.new(minimize_whitespace: true).format_compiled_template(node, node, wrap: false, binding: @binding)
|
431
|
+
Compiler.new(mode: @mode, minimize_whitespace: true).format_compiled_template(node, node, wrap: false, binding: @binding)
|
431
432
|
end
|
432
433
|
|
433
434
|
# Formats a comma separated list of AST nodes. Used for formatting partial
|
@@ -436,7 +437,7 @@ module P2
|
|
436
437
|
# @param list [Array<Prism::Node>] node list
|
437
438
|
# @return [String] generated source code
|
438
439
|
def format_code_comma_separated_nodes(list)
|
439
|
-
compiler =
|
440
|
+
compiler = Compiler.new(mode: @mode, minimize_whitespace: true)
|
440
441
|
compiler.visit_comma_separated_nodes(list)
|
441
442
|
compiler.buffer
|
442
443
|
end
|
@@ -448,6 +449,8 @@ module P2
|
|
448
449
|
# @param tag [String, Symbol] HTML tag
|
449
450
|
# @return [bool] void or not
|
450
451
|
def is_void_element?(tag)
|
452
|
+
return false if @mode == :xml
|
453
|
+
|
451
454
|
VOID_TAGS.include?(tag.to_s)
|
452
455
|
end
|
453
456
|
|
@@ -497,7 +500,9 @@ module P2
|
|
497
500
|
def format_literal(node)
|
498
501
|
case node
|
499
502
|
when Prism::SymbolNode, Prism::StringNode
|
500
|
-
|
503
|
+
# since the value is copied verbatim into a quoted string, we need to
|
504
|
+
# add a backslash before any double quote.
|
505
|
+
node.unescaped.gsub('"', '\"')
|
501
506
|
when Prism::IntegerNode, Prism::FloatNode
|
502
507
|
node.value.to_s
|
503
508
|
when Prism::InterpolatedStringNode
|
@@ -597,14 +602,16 @@ module P2
|
|
597
602
|
return if @pending_html_parts.empty?
|
598
603
|
|
599
604
|
adjust_whitespace(@html_loc_start, advance_to_end: false)
|
605
|
+
emit('; __buffer__')
|
600
606
|
concatenated = +''
|
601
607
|
|
602
608
|
last_loc = @html_loc_start
|
603
609
|
@pending_html_parts.each do |(loc, part)|
|
604
610
|
if (m = part.match(/^#\{(.+)\}$/m))
|
611
|
+
# interpolated part
|
605
612
|
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])
|
613
|
+
# adjust_whitespace(loc, advance_to_end: false)
|
614
|
+
emit_html_buffer_push(m[1], loc:)
|
608
615
|
else
|
609
616
|
concatenated << part
|
610
617
|
end
|
@@ -628,11 +635,18 @@ module P2
|
|
628
635
|
# @param part [String] HTML part
|
629
636
|
# @param quotes [bool] whether to wrap emitted HTML in double quotes
|
630
637
|
# @return [void]
|
631
|
-
def emit_html_buffer_push(part, quotes: false)
|
638
|
+
def emit_html_buffer_push(part, quotes: false, loc: nil)
|
632
639
|
return if part.empty?
|
633
640
|
|
634
641
|
q = quotes ? '"' : ''
|
635
|
-
|
642
|
+
if loc
|
643
|
+
emit(".<<(")
|
644
|
+
adjust_whitespace(loc, advance_to_end: false)
|
645
|
+
emit("#{q}#{part}#{q}")
|
646
|
+
emit(")")
|
647
|
+
else
|
648
|
+
emit(".<<(#{q}#{part}#{q})")
|
649
|
+
end
|
636
650
|
part.clear
|
637
651
|
end
|
638
652
|
|
data/lib/p2/proc_ext.rb
CHANGED
@@ -2,34 +2,40 @@
|
|
2
2
|
|
3
3
|
require_relative './compiler'
|
4
4
|
|
5
|
-
# Extensions to the Proc class
|
5
|
+
# Extensions to the Proc class.
|
6
6
|
class ::Proc
|
7
|
-
# Returns the compiled form code for the proc
|
7
|
+
# Returns the compiled form code for the proc.
|
8
8
|
#
|
9
9
|
# @return [String] compiled proc code
|
10
10
|
def compiled_code
|
11
11
|
P2::Compiler.compile_to_code(self).last
|
12
12
|
end
|
13
13
|
|
14
|
+
# Returns the source map for the compiled proc.
|
15
|
+
#
|
16
|
+
# @return [Array<String>] source map
|
14
17
|
def source_map
|
15
18
|
loc = source_location
|
16
19
|
fn = compiled? ? loc.first : P2::Compiler.source_location_to_fn(loc)
|
17
20
|
P2::Compiler.source_map_store[fn]
|
18
21
|
end
|
19
22
|
|
23
|
+
# Returns the AST for the proc.
|
24
|
+
#
|
25
|
+
# @return [Prism::Node] AST root
|
20
26
|
def ast
|
21
27
|
Sirop.to_ast(self)
|
22
28
|
end
|
23
29
|
|
24
|
-
# Returns true if proc is marked as compiled
|
30
|
+
# Returns true if proc is marked as compiled.
|
25
31
|
#
|
26
32
|
# @return [bool] is the proc marked as compiled
|
27
33
|
def compiled?
|
28
34
|
@is_compiled
|
29
35
|
end
|
30
36
|
|
31
|
-
#
|
32
|
-
# buffer as first argument
|
37
|
+
# Marks the proc as compiled, i.e. can render directly and takes a string
|
38
|
+
# buffer as first argument.
|
33
39
|
#
|
34
40
|
# @return [self]
|
35
41
|
def compiled!
|
@@ -40,34 +46,43 @@ class ::Proc
|
|
40
46
|
# Returns the compiled proc for the given proc. If marked as compiled, returns
|
41
47
|
# self.
|
42
48
|
#
|
49
|
+
# @param mode [Symbol] compilation mode (:html, :xml)
|
43
50
|
# @return [Proc] compiled proc or self
|
44
|
-
def compiled_proc
|
45
|
-
@compiled_proc ||= @is_compiled ? self : compile
|
51
|
+
def compiled_proc(mode: :html)
|
52
|
+
@compiled_proc ||= @is_compiled ? self : compile(mode:)
|
46
53
|
end
|
47
54
|
|
48
|
-
# Compiles the proc into the compiled form
|
55
|
+
# Compiles the proc into the compiled form.
|
49
56
|
#
|
57
|
+
# @param mode [Symbol] compilation mode (:html, :xml)
|
50
58
|
# @return [Proc] compiled proc
|
51
|
-
def compile
|
52
|
-
P2::Compiler.compile(self).compiled!
|
53
|
-
rescue Sirop::Error
|
54
|
-
puts '!' * 40
|
55
|
-
p self
|
56
|
-
p e
|
59
|
+
def compile(mode: :html)
|
60
|
+
P2::Compiler.compile(self, mode:).compiled!
|
61
|
+
rescue Sirop::Error
|
57
62
|
raise P2::Error, "Dynamically defined procs cannot be compiled"
|
58
63
|
end
|
59
64
|
|
60
|
-
# Renders the proc to HTML with the given arguments
|
65
|
+
# Renders the proc to HTML with the given arguments.
|
61
66
|
#
|
62
67
|
# @return [String] HTML string
|
63
68
|
def render(*a, **b, &c)
|
64
69
|
compiled_proc.(+'', *a, **b, &c)
|
65
70
|
rescue Exception => e
|
66
|
-
raise P2.translate_backtrace(e)
|
71
|
+
e.is_a?(P2::Error) ? raise : raise(P2.translate_backtrace(e))
|
67
72
|
end
|
68
73
|
|
69
|
-
# Renders the proc
|
74
|
+
# Renders the proc to XML with the given arguments.
|
70
75
|
#
|
76
|
+
# @return [String] XML string
|
77
|
+
def render_xml(*a, **b, &c)
|
78
|
+
compiled_proc(mode: :xml).(+'', *a, **b, &c)
|
79
|
+
rescue Exception => e
|
80
|
+
e.is_a?(P2::Error) ? raise : raise(P2.translate_backtrace(e))
|
81
|
+
end
|
82
|
+
|
83
|
+
# Renders the proc to HTML with the given arguments into the given buffer.
|
84
|
+
#
|
85
|
+
# @param buf [String] buffer
|
71
86
|
# @return [String] HTML string
|
72
87
|
def render_to_buffer(buf, *a, **b, &c)
|
73
88
|
compiled_proc.(buf, *a, **b, &c)
|
@@ -75,7 +90,7 @@ class ::Proc
|
|
75
90
|
raise P2.translate_backtrace(e)
|
76
91
|
end
|
77
92
|
|
78
|
-
# Returns a proc that applies the given arguments to the original proc
|
93
|
+
# Returns a proc that applies the given arguments to the original proc.
|
79
94
|
#
|
80
95
|
# @return [Proc] applied proc
|
81
96
|
def apply(*a, **b, &c)
|
@@ -91,10 +106,13 @@ class ::Proc
|
|
91
106
|
}.compiled!
|
92
107
|
end
|
93
108
|
|
94
|
-
# Caches and returns
|
95
|
-
|
109
|
+
# Caches and returns the rendered HTML for the template with the given
|
110
|
+
# arguments.
|
111
|
+
#
|
112
|
+
# @return [String] HTML string
|
113
|
+
def render_cached(*args, **kargs, &block)
|
96
114
|
@render_cache ||= {}
|
97
|
-
key = args.empty? && kargs.empty? ? nil : [args, kargs]
|
98
|
-
@render_cache[key] ||= render(*args, **kargs)
|
115
|
+
key = args.empty? && kargs.empty? && !block ? nil : [args, kargs, block&.source_location]
|
116
|
+
@render_cache[key] ||= render(*args, **kargs, &block)
|
99
117
|
end
|
100
118
|
end
|
data/lib/p2/version.rb
CHANGED
data/lib/p2.rb
CHANGED
@@ -16,7 +16,7 @@ module P2
|
|
16
16
|
Extensions = {}
|
17
17
|
|
18
18
|
# Registers extensions to the P2 syntax.
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# @param spec [Hash] hash mapping symbols to procs
|
21
21
|
# @return [self]
|
22
22
|
def extension(spec)
|
@@ -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
|
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.
|
4
|
+
version: '2.10'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '0'
|
137
137
|
requirements: []
|
138
|
-
rubygems_version: 3.
|
138
|
+
rubygems_version: 3.7.0.dev
|
139
139
|
specification_version: 4
|
140
140
|
summary: 'P2: component-based HTML templating for Ruby'
|
141
141
|
test_files: []
|