phlex 2.0.1 → 2.0.3

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: 0712c76cf9aa500d76c2d12b3732f83decaa7d63e8daa436ab021a07c5b1c6e7
4
- data.tar.gz: '08a67945fba53765a3558d652ba2b412591925c2b366456fc883349d594b0cd0'
3
+ metadata.gz: ecf456b3eda7d172d484d81175dbb08c80c9c2387cab5e534cb0f7c31293df88
4
+ data.tar.gz: 402dd5813b07b2a5dbd6120808d3bfca5fe1241704d414339a44e8cddf130639
5
5
  SHA512:
6
- metadata.gz: 776b639fe42f7df74ede2eb210da4e3c5f726ebc5dd8c2a45aa238c5904c1e08fc0ae3c712134641e20bd3a27675e8e359d8b7288cceae87d41f166072841daa
7
- data.tar.gz: 459ac3fb8a6205d87eff0c2369e4355250e297df44dd0da712b29df01d0a16238ce03a2a4ca724aba6d38195e3a6af32d45c48d45ea788b7a943d2c357c76ac7
6
+ metadata.gz: 816fe5523cb3ba2ec4bb953cbcefda9aa2901bd781feb8f0fbcf74f69410606118311aaa893c9c4f7e781e2b2e1a754d07f6df24ba5f80966fe6b12b2dbcf3e4
7
+ data.tar.gz: cbab8596e518be9be3c6cc4496dafb4f3e5862be778fec2aeb619f4866b323e6b65c26db5a8355ceb98084410c7fbab20ed6b00515a567877c8352c06e02a0c7
data/lib/phlex/html.rb CHANGED
@@ -58,7 +58,7 @@ class Phlex::HTML < Phlex::SGML
58
58
  raise Phlex::ArgumentError.new("Expected the tag name to be a Symbol.")
59
59
  end
60
60
 
61
- if (tag = StandardElements.__registered_elements__[name]) || (tag = name.name.tr("_", "-")).include?("-")
61
+ if (tag = StandardElements.__registered_elements__[name]) || ((tag = name.name.tr("_", "-")).include?("-") && tag.match?(/\A[a-z0-9-]+\z/))
62
62
  if attributes.length > 0 # with attributes
63
63
  if block_given # with content block
64
64
  buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
data/lib/phlex/sgml.rb CHANGED
@@ -3,7 +3,13 @@
3
3
  # **Standard Generalized Markup Language** for behaviour common to {HTML} and {SVG}.
4
4
  class Phlex::SGML
5
5
  UNSAFE_ATTRIBUTES = Set.new(%w[srcdoc sandbox http-equiv]).freeze
6
- REF_ATTRIBUTES = Set.new(%w[href src action formaction lowsrc dynsrc background ping]).freeze
6
+ REF_ATTRIBUTES = Set.new(%w[href src action formaction lowsrc dynsrc background ping xlinkhref]).freeze
7
+ NAMED_CHARACTER_REFERENCES = {
8
+ "colon" => ":",
9
+ "tab" => "\t",
10
+ "newline" => "\n",
11
+ }.freeze
12
+ UNSAFE_ATTRIBUTE_NAME_CHARS = %r([<>&"'/=\s\x00])
7
13
 
8
14
  autoload :Elements, "phlex/sgml/elements"
9
15
  autoload :SafeObject, "phlex/sgml/safe_object"
@@ -94,7 +100,19 @@ class Phlex::SGML
94
100
  end
95
101
 
96
102
  def context
97
- @_state.user_context
103
+ if rendering?
104
+ @_state.user_context
105
+ else
106
+ raise Phlex::ArgumentError.new(<<~MESSAGE)
107
+ You can’t access the context before the component has started rendering.
108
+ MESSAGE
109
+ end
110
+ end
111
+
112
+ # Returns `false` before rendering and `true` once the component has started rendering.
113
+ # It will not reset back to false after rendering.
114
+ def rendering?
115
+ !!@_state
98
116
  end
99
117
 
100
118
  # Output plain text.
@@ -465,7 +483,9 @@ class Phlex::SGML
465
483
  if value != true && REF_ATTRIBUTES.include?(normalized_name)
466
484
  case value
467
485
  when String
468
- if value.downcase.delete("^a-z:").start_with?("javascript:")
486
+ decoded_value = decode_html_character_references(value)
487
+
488
+ if decoded_value.downcase.delete("^a-z:").start_with?("javascript:")
469
489
  # We just ignore these because they were likely not specified by the developer.
470
490
  next
471
491
  end
@@ -483,7 +503,7 @@ class Phlex::SGML
483
503
  end
484
504
  end
485
505
 
486
- if name.match?(/[<>&"']/)
506
+ if name.match?(UNSAFE_ATTRIBUTE_NAME_CHARS)
487
507
  raise Phlex::ArgumentError.new("Unsafe attribute name detected: #{k}.")
488
508
  end
489
509
 
@@ -514,7 +534,7 @@ class Phlex::SGML
514
534
  else raise Phlex::ArgumentError.new("Attribute keys should be Strings or Symbols")
515
535
  end
516
536
 
517
- if name.match?(/[<>&"']/)
537
+ if name.match?(UNSAFE_ATTRIBUTE_NAME_CHARS)
518
538
  raise Phlex::ArgumentError.new("Unsafe attribute name detected: #{k}.")
519
539
  end
520
540
 
@@ -590,6 +610,27 @@ class Phlex::SGML
590
610
  buffer.gsub('"', "&quot;")
591
611
  end
592
612
 
613
+ private def decode_html_character_references(value)
614
+ value
615
+ .gsub(/&#x([0-9a-f]+);?/i) {
616
+ begin
617
+ [$1.to_i(16)].pack("U*")
618
+ rescue
619
+ ""
620
+ end
621
+ }
622
+ .gsub(/&#(\d+);?/) {
623
+ begin
624
+ [$1.to_i].pack("U*")
625
+ rescue
626
+ ""
627
+ end
628
+ }
629
+ .gsub(/&([a-z][a-z0-9]+);?/i) {
630
+ NAMED_CHARACTER_REFERENCES[$1.downcase] || ""
631
+ }
632
+ end
633
+
593
634
  # Result is **unsafe**, so it should be escaped!
594
635
  def __styles__(styles)
595
636
  case styles
data/lib/phlex/svg.rb CHANGED
@@ -29,7 +29,7 @@ class Phlex::SVG < Phlex::SGML
29
29
  raise Phlex::ArgumentError.new("Expected the tag name to be a Symbol.")
30
30
  end
31
31
 
32
- if (tag = StandardElements.__registered_elements__[name]) || (tag = name.name.tr("_", "-")).include?("-")
32
+ if (tag = StandardElements.__registered_elements__[name]) || ((tag = name.name.tr("_", "-")).include?("-") && tag.match?(/\A[a-z0-9-]+\z/))
33
33
  if attributes.length > 0 # with attributes
34
34
  if block_given # with content block
35
35
  buffer << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[attributes] ||= __attributes__(attributes)) << ">"
data/lib/phlex/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phlex
4
- VERSION = "2.0.1"
4
+ VERSION = "2.0.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
8
  - Will Cosgrove
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-15 00:00:00.000000000 Z
11
+ date: 2026-02-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Build HTML & SVG view components with Ruby classes.
14
14
  email:
@@ -65,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0'
67
67
  requirements: []
68
- rubygems_version: 3.6.2
68
+ rubygems_version: 3.6.6
69
69
  specification_version: 4
70
70
  summary: Object-oriented views in Ruby.
71
71
  test_files: []