phlex 1.10.3 → 1.11.1

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: 4a86bca32b72f150179b586843c71432ebfea0d892ad70b426ef0f8ce6d58f3f
4
- data.tar.gz: 235a24dc555ffcb1598660c9c5d539a5b050780a1ccec4d81b8b5115ea5b7f0e
3
+ metadata.gz: b009908cf2bca382857d9e6adaf26040bbc72df73b4227546e48888d508552f0
4
+ data.tar.gz: 560928a3386b32c8f0a94a31462d29b9ff73bcbeb9ecad1171399c1f749be871
5
5
  SHA512:
6
- metadata.gz: 0b4ab7f24ba4955cc0622da21a363436a0b54cae4505ec0fd599dd2ddd53731175386b5fc9f62981807f7836d34edd7de851dd662a18b1e01c3935aa37956454
7
- data.tar.gz: eb0b42b41d70b8fb28ae3c9134f0ecddcc517698ac812c2f1c69b05c4b41d7d9148aca244d88b1bb8e8d817abcfafa9ac6968342890584b9b6cf539b320e2b27
6
+ metadata.gz: eb282ecd7594914cd485309e270748d64e3b74bed6fd49ec98244ea34e1fb90cbba0ff542909ee59d3347dce6cde47604aeb67efae605ccfa554473ed8934f61
7
+ data.tar.gz: 05ff1300599f9360d07d249e27ee3ef84667c77268bbe25c92a0609686e594f45aa377068714690ca55ee925548d85406b84aa3b3bad26d2eb2c6beb2dd12bf4
data/lib/phlex/kit.rb CHANGED
@@ -1,31 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phlex::Kit
4
- def self.extended(mod)
5
- warn "⚠️ [WARNING] Phlex::Kit is experimental and may be removed from future versions of Phlex."
6
- super
4
+ module LazyLoader
5
+ def method_missing(name, *args, **kwargs, &block)
6
+ if name[0] == name[0].upcase && __phlex_kit_constants__.include?(name) && __get_phlex_kit_constant__(name) && methods.include?(name)
7
+ public_send(name, *args, **kwargs, &block)
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ def respond_to_missing?(name, include_private = false)
14
+ if name[0] == name[0].upcase && __phlex_kit_constants__.include?(name) && __get_phlex_kit_constant__(name) && methods.include?(name)
15
+ true
16
+ else
17
+ super
18
+ end
19
+ end
7
20
  end
8
21
 
9
- # When a kit is included in a module, we need to load all of its components.
10
- def included(mod)
11
- constants.each { |c| const_get(c) if autoload?(c) }
12
- super
22
+ include LazyLoader
23
+
24
+ def self.extended(mod)
25
+ mod.include(LazyLoader)
26
+ mod.define_method(:__phlex_kit_constants__) { mod.__phlex_kit_constants__ }
27
+ mod.define_method(:__get_phlex_kit_constant__) { |name| mod.__get_phlex_kit_constant__(name) }
13
28
  end
14
29
 
15
- def method_missing(name, *args, **kwargs, &block)
16
- if name[0] == name[0].upcase && constants.include?(name) && const_get(name) && methods.include?(name)
17
- public_send(name, *args, **kwargs, &block)
18
- else
19
- super
20
- end
30
+ def __phlex_kit_constants__
31
+ constants
21
32
  end
22
33
 
23
- def respond_to_missing?(name, include_private = false)
24
- if name[0] == name[0].upcase && constants.include?(name) && const_get(name) && methods.include?(name)
25
- true
26
- else
27
- super
28
- end
34
+ def __get_phlex_kit_constant__(name)
35
+ const_get(name)
29
36
  end
30
37
 
31
38
  def const_added(name)
data/lib/phlex/sgml.rb CHANGED
@@ -4,6 +4,13 @@ module Phlex
4
4
  # **Standard Generalized Markup Language** for behaviour common to {HTML} and {SVG}.
5
5
  class SGML
6
6
  include Helpers
7
+ REF_ATTRIBUTES = Set.new(%w[href src action formaction lowsrc dynsrc background ping xlinkhref]).freeze
8
+ NAMED_CHARACTER_REFERENCES = {
9
+ "colon" => ":",
10
+ "tab" => "\t",
11
+ "newline" => "\n",
12
+ }.freeze
13
+ UNSAFE_ATTRIBUTE_NAME_CHARS = %r([<>&"'/=\s\x00])
7
14
 
8
15
  class << self
9
16
  # Render the view to a String. Arguments are delegated to {.new}.
@@ -71,7 +78,7 @@ module Phlex
71
78
 
72
79
  def self.method_added(method_name)
73
80
  if method_name == :template
74
- Kernel.warn "⚠️ [DEPRECATION] Defining the `template` method on a Phlex component will not be supported in Phlex 2.0. Please rename the method to `view_template` instead."
81
+ Kernel.warn "⚠️ [DEPRECATION] Defining the `template` method on a Phlex component will not be supported in Phlex 2.0. Please rename `#{name}#template` to `#{name}#view_template` instead."
75
82
  end
76
83
  end
77
84
 
@@ -105,6 +112,11 @@ module Phlex
105
112
  @_context = context
106
113
  @_view_context = view_context
107
114
  @_parent = parent
115
+ if @_rendered
116
+ warn "⚠️ [WARNING] You are rendering a component #{self.class.name} twice. This is not supported in Phlex 2.0."
117
+ end
118
+ @_rendered = true
119
+
108
120
  if fragments
109
121
  warn "⚠️ [WARNING] Selective Rendering is experimental, incomplete, and may change in future versions."
110
122
  @_context.target_fragments(fragments)
@@ -416,6 +428,27 @@ module Phlex
416
428
  buffer
417
429
  end
418
430
 
431
+ def decode_html_character_references(value)
432
+ value
433
+ .gsub(/&#x([0-9a-f]+);?/i) {
434
+ begin
435
+ [$1.to_i(16)].pack("U*")
436
+ rescue
437
+ ""
438
+ end
439
+ }
440
+ .gsub(/&#(\d+);?/) {
441
+ begin
442
+ [$1.to_i].pack("U*")
443
+ rescue
444
+ ""
445
+ end
446
+ }
447
+ .gsub(/&([a-z][a-z0-9]+);?/i) {
448
+ NAMED_CHARACTER_REFERENCES[$1.downcase] || ""
449
+ }
450
+ end
451
+
419
452
  # @api private
420
453
  def __build_attributes__(attributes, buffer:)
421
454
  attributes.each do |k, v|
@@ -428,13 +461,28 @@ module Phlex
428
461
  end
429
462
 
430
463
  lower_name = name.downcase
431
- next if lower_name == "href" && v.to_s.downcase.tr("^a-z:", "").start_with?("javascript:")
464
+ normalized_name = lower_name.delete("^a-z")
465
+
466
+ if REF_ATTRIBUTES.include?(normalized_name)
467
+ decoded_value = case v
468
+ when String then decode_html_character_references(v)
469
+ when Symbol then decode_html_character_references(v.name)
470
+ end
471
+
472
+ if decoded_value && decoded_value.downcase.tr("^a-z:", "").start_with?("javascript:")
473
+ next
474
+ end
475
+ end
432
476
 
433
477
  # Detect unsafe attribute names. Attribute names are considered unsafe if they match an event attribute or include unsafe characters.
434
- if HTML::EVENT_ATTRIBUTES.include?(lower_name.tr("^a-z-", "")) || name.match?(/[<>&"']/)
478
+ if HTML::EVENT_ATTRIBUTES.include?(lower_name.tr("^a-z-", "")) || name.match?(UNSAFE_ATTRIBUTE_NAME_CHARS)
435
479
  raise ArgumentError, "Unsafe attribute name detected: #{k}."
436
480
  end
437
481
 
482
+ if lower_name.to_sym == :id && k != :id
483
+ warn "⚠️ [WARNING] Starting 2.0 Phlex will raise on non lowercase or string :id attribute."
484
+ end
485
+
438
486
  case v
439
487
  when true
440
488
  buffer << " " << name
data/lib/phlex/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phlex
4
- VERSION = "1.10.3"
4
+ VERSION = "1.11.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlex
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.3
4
+ version: 1.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-01 00:00:00.000000000 Z
10
+ date: 2026-02-06 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: A high-performance view framework optimised for fun.
14
13
  email:
@@ -47,7 +46,6 @@ metadata:
47
46
  changelog_uri: https://github.com/phlex-ruby/phlex/blob/main/CHANGELOG.md
48
47
  funding_uri: https://github.com/sponsors/joeldrapper
49
48
  rubygems_mfa_required: 'true'
50
- post_install_message:
51
49
  rdoc_options: []
52
50
  require_paths:
53
51
  - lib
@@ -62,8 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
60
  - !ruby/object:Gem::Version
63
61
  version: '0'
64
62
  requirements: []
65
- rubygems_version: 3.5.3
66
- signing_key:
63
+ rubygems_version: 3.6.2
67
64
  specification_version: 4
68
65
  summary: A fun framework for building views in Ruby.
69
66
  test_files: []