p2 2.10 → 2.12

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: 14c5c67f786953f8783be2cb53cb1eb4ad54be9f1ce769ce340cdc07d45b7a52
4
- data.tar.gz: 1788cf26c810fa3f4d47b6db4b0de149b223e47d6a8356af7dea580190664da9
3
+ metadata.gz: c26b9c214f11c471fb039fba72fdde0b98f8d7c85864ec9db271a295f2e078fa
4
+ data.tar.gz: 52dc0929deb222d22e496cf451ee927f5047403e1b687f1588e2dccc74f59135
5
5
  SHA512:
6
- metadata.gz: c898b73cbfeffcc1227bc15889d43e78dd03f745a9aee584767f4e8c22ae25d698190454c5cea9600735dddcc2da91a95fb7324b5cf906ef19824ba3dce7020c
7
- data.tar.gz: 6575f62f6158438bc95bea56d60d0f6fe4e11b1e45269584f6a644ffcd3d647e20bd712a869a556d882c4ff00a74a93f1bdefb5e8fe759787588bae9b3ba4abb
6
+ metadata.gz: cb6032e2a12263ca0ff29cf00b677d1aa88dbd2becf57e662d09c857ecc39e4670af18b1b6493e548b83a4e73d010822b3cca4b07b4ed372e5b63d566bd11861
7
+ data.tar.gz: cbdbaf04e4beb275463b38ee453b93dac751a74166f3264a41269177f869a04a2082999dc4f2adca03ef85b075d5726fbc0300bb5ffa9d27041bddaf146b87f3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 2.12 2025-09-11
2
+
3
+ - Add support for injecting location attributes into HTML tags (for debug purposes)
4
+
5
+ # 2.11 2025-09-11
6
+
7
+ - Add mode param to `P2::Template` wrapper class
8
+
1
9
  # 2.10 2025-09-11
2
10
 
3
11
  - Add support for rendering XML, implement `Proc#render_xml`
data/lib/p2/compiler.rb CHANGED
@@ -10,6 +10,12 @@ module P2
10
10
  # A Compiler converts a template into an optimized form that generates HTML
11
11
  # efficiently.
12
12
  class Compiler < Sirop::Sourcifier
13
+ @@html_atts_injector = nil
14
+
15
+ def self.html_atts_injector=(proc)
16
+ @@html_atts_injector = proc
17
+ end
18
+
13
19
  # Compiles the given proc, returning the generated source map and the
14
20
  # generated optimized source code.
15
21
  #
@@ -80,12 +86,12 @@ module P2
80
86
  # @param orig_ast [Prism::Node] template AST
81
87
  # @return [self]
82
88
  def with_source_map(orig_proc, orig_ast)
83
- fn = Compiler.source_location_to_fn(orig_proc.source_location)
89
+ @fn = orig_proc.source_location.first
84
90
  @orig_proc = orig_proc
85
91
  @orig_proc_fn = orig_proc.source_location.first
86
92
  @source_map = {
87
93
  source_fn: orig_proc.source_location.first,
88
- compiled_fn: fn
94
+ compiled_fn: Compiler.source_location_to_fn(orig_proc.source_location)
89
95
  }
90
96
  @source_map_line_ofs = 2
91
97
  self
@@ -155,7 +161,7 @@ module P2
155
161
 
156
162
  # adjust_whitespace(node.location)
157
163
  is_void = is_void_element?(tag)
158
- emit_html(node.tag_location, format_html_tag_open(tag, node.attributes))
164
+ emit_html(node.tag_location, format_html_tag_open(node.tag_location, tag, node.attributes))
159
165
  return if is_void
160
166
 
161
167
  case node.block
@@ -456,13 +462,14 @@ module P2
456
462
 
457
463
  # Formats an open tag with optional attributes.
458
464
  #
465
+ # @param loc [Prism::Location] tag location
459
466
  # @param tag [String, Symbol] HTML tag
460
467
  # @param attributes [Hash, nil] attributes
461
468
  # @return [String] HTML
462
- def format_html_tag_open(tag, attributes)
469
+ def format_html_tag_open(loc, tag, attributes)
463
470
  tag = convert_tag(tag)
464
- if attributes && attributes&.elements.size > 0
465
- "<#{tag} #{format_html_attributes(attributes)}>"
471
+ if attributes && attributes&.elements.size > 0 || @@html_atts_injector
472
+ "<#{tag} #{format_html_attributes(loc, attributes)}>"
466
473
  else
467
474
  "<#{tag}>"
468
475
  end
@@ -551,37 +558,85 @@ module P2
551
558
 
552
559
  # Formats HTML attributes from the given node.
553
560
  #
554
- # @param node [Prism::Node] AST node
561
+ # @param loc [Prism::Location] tag location
562
+ # @param node [Prism::Node] attributes node
555
563
  # @return [String] HTML
556
- def format_html_attributes(node)
557
- elements = node.elements
558
- dynamic_attributes = elements.any? do
559
- it.is_a?(Prism::AssocSplatNode) ||
560
- !is_static_node?(it.key) || !is_static_node?(it.value)
564
+ def format_html_attributes(loc, node)
565
+ elements = node&.elements || []
566
+ if elements.any? { is_dynamic_attribute?(it) }
567
+ return format_html_dynamic_attributes(loc, node)
561
568
  end
562
569
 
563
- return interpolated("P2.format_tag_attrs(#{format_code(node)})") if dynamic_attributes
570
+ injected_atts = format_injected_attributes(loc)
571
+ parts = elements.map { format_attribute(it.key, it.value) }
572
+ (injected_atts + parts).compact.join(' ')
573
+ end
574
+
575
+ # Formats dynamic HTML attributes from the given node.
576
+ #
577
+ # @param loc [Prism::Location] tag location
578
+ # @param node [Prism::Node] attributes node
579
+ # @return [String] HTML
580
+ def format_html_dynamic_attributes(loc, node)
581
+ injected_atts = compute_injected_attributes(loc)
582
+ if injected_atts.empty?
583
+ return interpolated("P2.format_tag_attrs(#{format_code(node)})")
584
+ else
585
+ return interpolated("P2.format_tag_attrs(#{injected_atts.inspect}.merge(#{format_code(node)}))")
586
+ end
587
+ end
564
588
 
565
- parts = elements.map do
566
- key = it.key
567
- value = it.value
568
- case value
569
- when Prism::TrueNode
570
- format_literal(key)
571
- when Prism::FalseNode, Prism::NilNode
572
- nil
589
+ # Returns true if the given node is a dynamic node.
590
+ #
591
+ # @param node [Prism::Node] attributes node
592
+ # @return [bool] is node dynamic
593
+ def is_dynamic_attribute?(node)
594
+ node.is_a?(Prism::AssocSplatNode) || !is_static_node?(node.key) || !is_static_node?(node.value)
595
+ end
596
+
597
+ # Computes injected attributes for the given tag location.
598
+ #
599
+ # @param loc [Prism::Location] tag location
600
+ # @return [Hash] injected attributes hash
601
+ def compute_injected_attributes(loc)
602
+ return {} if (@mode == :xml) || !@@html_atts_injector
603
+
604
+ loc = loc_start(loc)
605
+ @@html_atts_injector&.(@fn, loc[0], loc[1] + 1)
606
+ end
607
+
608
+ # Computes injected attributes for the given tag location.
609
+ #
610
+ # @param loc [Prism::Location] tag location
611
+ # @return [Array<String>] array of attribute strings
612
+ def format_injected_attributes(loc)
613
+ atts = compute_injected_attributes(loc)
614
+ atts.map { |k, v| format_attribute(k, v) }
615
+ end
616
+
617
+ # Formats a tag attribute with the given key and value. A nil, or false
618
+ # value will return nil.
619
+ #
620
+ # @param key [any] attribute key
621
+ # @param value [any] attribute value
622
+ # @return [String, nil] formatted attribute
623
+ def format_attribute(key, value)
624
+ case value
625
+ when Prism::TrueNode
626
+ format_literal(key)
627
+ when Prism::FalseNode, Prism::NilNode
628
+ nil
629
+ when String
630
+ "#{P2.underscores_to_dashes(key)}=\\\"#{value}\\\""
631
+ else
632
+ key = format_literal(key)
633
+ if is_static_node?(value)
634
+ value = format_literal(value)
635
+ "#{P2.underscores_to_dashes(key)}=\\\"#{value}\\\""
573
636
  else
574
- k = format_literal(key)
575
- if is_static_node?(value)
576
- value = format_literal(value)
577
- "#{P2.underscores_to_dashes(k)}=\\\"#{value}\\\""
578
- else
579
- "#{P2.underscores_to_dashes(k)}=\\\"#\{#{format_code(value)}}\\\""
580
- end
637
+ "#{P2.underscores_to_dashes(key)}=\\\"#\{#{format_code(value)}}\\\""
581
638
  end
582
639
  end
583
-
584
- parts.compact.join(' ')
585
640
  end
586
641
 
587
642
  # Emits HTML into the pending HTML buffer.
data/lib/p2/template.rb CHANGED
@@ -4,10 +4,25 @@ module P2
4
4
  # Template wrapper class. This class can be used to distinguish between P2
5
5
  # templates and other kinds of procs.
6
6
  class Template
7
- attr_reader :proc
8
- def initialize(proc) = @proc = proc
9
- def render(*, **, &) = @proc.render(*, **, &)
10
- def apply(*, **, &) = Template.new(@proc.apply(*, **, &))
11
- def compiled_proc = @proc.compiled_proc
7
+ attr_reader :proc, :mode
8
+
9
+ # @param proc [Proc] template proc
10
+ # @param mode [Symbol] mode (:html, :xml)
11
+ def initialize(proc, mode: :html)
12
+ @proc = proc
13
+ @mode = mode
14
+ end
15
+
16
+ def render(*, **, &)
17
+ (mode == :xml) ? @proc.render_xml(*, **, &) : @proc.render(*, **, &)
18
+ end
19
+
20
+ def apply(*, **, &)
21
+ Template.new(@proc.apply(*, **, &), mode: @mode)
22
+ end
23
+
24
+ def compiled_proc
25
+ @proc.compiled_proc(mode: @mode)
26
+ end
12
27
  end
13
28
  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.10'
4
+ VERSION = '2.12'
5
5
  end
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.10'
4
+ version: '2.12'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner