p2 2.11 → 2.13

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: f9f7d2a86ea17670a7bcc69301db096ec2a2b667c7eb8f2c0df1ac28178eb823
4
- data.tar.gz: 6dd4d03825d1a881fd7b721fea58af43b7c2f2c68f7ceb8bd8031a2fbfdab0de
3
+ metadata.gz: ba1f3d8dbb8965fd65ec2d047c69679a4a07b994495422eb3cf09ca39c47c338
4
+ data.tar.gz: 7247dff71984c7903de1043383ef4049f8e6e6149962aa9ec5600a490da2a0c9
5
5
  SHA512:
6
- metadata.gz: 6cf0579fe72241ae904f417d1fd2f6e97ef347d8a3106b7069c232b8332440ef3eea5dc8b7c059516d3ad17903d207941d3e4c795768943950295fd345304248
7
- data.tar.gz: 0b44037b06cc328543ed6809a5f5c0b675318902fcb36800559d1b100bf190f42e56d9249905a0ee50dd59cf0006a3fb4f17a31dcff10d6d86b70b9608d31842
6
+ metadata.gz: e9c51b267d5e350b4806de9d2f27ea03680ccfa985d237e4909614ec8f384c304c67bde8981d3a7cc20e5c8ed3cdeb1066bad068847652f3073f7dc7b1023ad0
7
+ data.tar.gz: 4adbb063d72b4d52c61df05512a19a8845ada41cd7c958e6d66677876401de53804a95a3f66d520f16b40e55ad8c625de92c2d0755b8a1169e70fc00a9708136
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 2.13 2025-09-11
2
+
3
+ - Pass level to HTML debug attribute injection proc
4
+
5
+ # 2.12 2025-09-11
6
+
7
+ - Add support for injecting location attributes into HTML tags (for debug purposes)
8
+
1
9
  # 2.11 2025-09-11
2
10
 
3
11
  - Add mode param to `P2::Template` wrapper class
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_debug_attribute_injector = nil
14
+
15
+ def self.html_debug_attribute_injector=(proc)
16
+ @@html_debug_attribute_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
  #
@@ -72,6 +78,7 @@ module P2
72
78
  super(**)
73
79
  @mode = mode
74
80
  @pending_html_parts = []
81
+ @level = 0
75
82
  end
76
83
 
77
84
  # Initializes a source map.
@@ -80,12 +87,12 @@ module P2
80
87
  # @param orig_ast [Prism::Node] template AST
81
88
  # @return [self]
82
89
  def with_source_map(orig_proc, orig_ast)
83
- fn = Compiler.source_location_to_fn(orig_proc.source_location)
90
+ @fn = orig_proc.source_location.first
84
91
  @orig_proc = orig_proc
85
92
  @orig_proc_fn = orig_proc.source_location.first
86
93
  @source_map = {
87
94
  source_fn: orig_proc.source_location.first,
88
- compiled_fn: fn
95
+ compiled_fn: Compiler.source_location_to_fn(orig_proc.source_location)
89
96
  }
90
97
  @source_map_line_ofs = 2
91
98
  self
@@ -151,11 +158,12 @@ module P2
151
158
  # @param node [P2::TagNode] node
152
159
  # @return [void]
153
160
  def visit_tag_node(node)
161
+ @level += 1
154
162
  tag = node.tag
155
163
 
156
164
  # adjust_whitespace(node.location)
157
165
  is_void = is_void_element?(tag)
158
- emit_html(node.tag_location, format_html_tag_open(tag, node.attributes))
166
+ emit_html(node.tag_location, format_html_tag_open(node.tag_location, tag, node.attributes))
159
167
  return if is_void
160
168
 
161
169
  case node.block
@@ -175,6 +183,8 @@ module P2
175
183
  end
176
184
  end
177
185
  emit_html(node.location, format_html_tag_close(tag))
186
+ ensure
187
+ @level -= 1
178
188
  end
179
189
 
180
190
  # Visits a const tag node.
@@ -456,13 +466,14 @@ module P2
456
466
 
457
467
  # Formats an open tag with optional attributes.
458
468
  #
469
+ # @param loc [Prism::Location] tag location
459
470
  # @param tag [String, Symbol] HTML tag
460
471
  # @param attributes [Hash, nil] attributes
461
472
  # @return [String] HTML
462
- def format_html_tag_open(tag, attributes)
473
+ def format_html_tag_open(loc, tag, attributes)
463
474
  tag = convert_tag(tag)
464
- if attributes && attributes&.elements.size > 0
465
- "<#{tag} #{format_html_attributes(attributes)}>"
475
+ if attributes && attributes&.elements.size > 0 || @@html_debug_attribute_injector
476
+ "<#{tag} #{format_html_attributes(loc, attributes)}>"
466
477
  else
467
478
  "<#{tag}>"
468
479
  end
@@ -551,37 +562,85 @@ module P2
551
562
 
552
563
  # Formats HTML attributes from the given node.
553
564
  #
554
- # @param node [Prism::Node] AST node
565
+ # @param loc [Prism::Location] tag location
566
+ # @param node [Prism::Node] attributes node
555
567
  # @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)
568
+ def format_html_attributes(loc, node)
569
+ elements = node&.elements || []
570
+ if elements.any? { is_dynamic_attribute?(it) }
571
+ return format_html_dynamic_attributes(loc, node)
561
572
  end
562
573
 
563
- return interpolated("P2.format_tag_attrs(#{format_code(node)})") if dynamic_attributes
574
+ injected_atts = format_injected_attributes(loc)
575
+ parts = elements.map { format_attribute(it.key, it.value) }
576
+ (injected_atts + parts).compact.join(' ')
577
+ end
578
+
579
+ # Formats dynamic HTML attributes from the given node.
580
+ #
581
+ # @param loc [Prism::Location] tag location
582
+ # @param node [Prism::Node] attributes node
583
+ # @return [String] HTML
584
+ def format_html_dynamic_attributes(loc, node)
585
+ injected_atts = compute_injected_attributes(loc)
586
+ if injected_atts.empty?
587
+ return interpolated("P2.format_tag_attrs(#{format_code(node)})")
588
+ else
589
+ return interpolated("P2.format_tag_attrs(#{injected_atts.inspect}.merge(#{format_code(node)}))")
590
+ end
591
+ end
564
592
 
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
593
+ # Returns true if the given node is a dynamic node.
594
+ #
595
+ # @param node [Prism::Node] attributes node
596
+ # @return [bool] is node dynamic
597
+ def is_dynamic_attribute?(node)
598
+ node.is_a?(Prism::AssocSplatNode) || !is_static_node?(node.key) || !is_static_node?(node.value)
599
+ end
600
+
601
+ # Computes injected attributes for the given tag location.
602
+ #
603
+ # @param loc [Prism::Location] tag location
604
+ # @return [Hash] injected attributes hash
605
+ def compute_injected_attributes(loc)
606
+ return {} if (@mode == :xml) || !@@html_debug_attribute_injector
607
+
608
+ loc = loc_start(loc)
609
+ @@html_debug_attribute_injector&.(@level, @fn, loc[0], loc[1] + 1)
610
+ end
611
+
612
+ # Computes injected attributes for the given tag location.
613
+ #
614
+ # @param loc [Prism::Location] tag location
615
+ # @return [Array<String>] array of attribute strings
616
+ def format_injected_attributes(loc)
617
+ atts = compute_injected_attributes(loc)
618
+ atts.map { |k, v| format_attribute(k, v) }
619
+ end
620
+
621
+ # Formats a tag attribute with the given key and value. A nil, or false
622
+ # value will return nil.
623
+ #
624
+ # @param key [any] attribute key
625
+ # @param value [any] attribute value
626
+ # @return [String, nil] formatted attribute
627
+ def format_attribute(key, value)
628
+ case value
629
+ when Prism::TrueNode
630
+ format_literal(key)
631
+ when Prism::FalseNode, Prism::NilNode
632
+ nil
633
+ when String, Integer, Float, Symbol
634
+ "#{P2.underscores_to_dashes(key)}=\\\"#{value}\\\""
635
+ else
636
+ key = format_literal(key)
637
+ if is_static_node?(value)
638
+ value = format_literal(value)
639
+ "#{P2.underscores_to_dashes(key)}=\\\"#{value}\\\""
573
640
  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
641
+ "#{P2.underscores_to_dashes(key)}=\\\"#\{#{format_code(value)}}\\\""
581
642
  end
582
643
  end
583
-
584
- parts.compact.join(' ')
585
644
  end
586
645
 
587
646
  # Emits HTML into the pending HTML buffer.
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.11'
4
+ VERSION = '2.13'
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.11'
4
+ version: '2.13'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner