phlex 1.6.0 β†’ 1.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of phlex might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eeac8033b47d1e0cf99832bc7a42a7777ca44643dd503f3cb08087666b08d4f7
4
- data.tar.gz: 6f7e786e982dcc9133c40179d4bb582d9d45bb610814020e916a2afbf17cb0d0
3
+ metadata.gz: 5c0002c77419906adab684bd6e3bcb0ad2d5b7084aeb4e62f89c4f15a1da6001
4
+ data.tar.gz: dea42d460e9cce5f3a4001dbe5d6cbfd155f2bafe725ed0a21f3bfc9bb050a39
5
5
  SHA512:
6
- metadata.gz: 037caf900c1155b1e9095588a30dff67a7f224b6e16365d417dc7412e34822cb1368a194a4e48de65c20a838b91f671e7e53fca7a0f0e973852d84ebc7c03d3c
7
- data.tar.gz: 85ad16185650ff8aa04831c745ac6709ae35913863af0fef5a70d671d75dbbdf389005db6480cb5c4533ad9e3106379cb6aa2015b64194ca78a2dd8b61cd3993
6
+ metadata.gz: 22d4b19c21a14a60f8ff8cb2418bea2d553768b219cc9d491b44181580af17f4aeb804e0e4e0a875f959c74ab96b556f95fc5958e5ff4423f893cd7f07498a99
7
+ data.tar.gz: 8512284569af79d553d74e16539292f1e68d10aad9224f0c1ec9698ef6d38c025bf20aa3a6c8b0db3533e21c03978980472d7c016148a9605e6fbf72caa0f0fe
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.1
1
+ 3.2.2
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --private --no-private --hide-api private --markup markdown
data/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
+
5
+ ## 1.7.0
6
+
7
+ ### Added
8
+
9
+ - Experimental Smart chunking.
10
+
11
+ ### Changed
12
+
13
+ - Improved YARD documentation, which is now available here https://rubydoc.info/gems/phlex
14
+ - `SGML#render` can now render lambdas with zero or one arguments. Previously, it could only render lambdas with exactly one argument, although it could always render Procs with any number of arguments. When an argument is accepted, the `self` of the component rendering it is yielded to the Proc.
15
+ - Raise an error when outputting an unknown object using `SGML#plain`.
16
+ - Raise an error when using attribute keys that aren't Strings or Symbols.
17
+ - Support Array and Set values for HTML/SVG attributes.
18
+
19
+ ### Removed
20
+
21
+ - Removed the `menuitem` element as it's a deprecated HTML element.
22
+
23
+ ***
24
+
25
+ Before this changelog was introduced, changes were logged in the [release notes](https://github.com/phlex-ruby/phlex/releases).
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ gemspec
8
8
  gem "rubocop"
9
9
  gem "sus"
10
10
  gem "benchmark-ips"
11
+ gem "yard"
11
12
 
12
13
  group :test do
13
14
  gem "i18n"
data/README.md CHANGED
@@ -1,47 +1,6 @@
1
- <a href="https://www.phlex.fun"><img alt="Phlex logo" src="phlex_logo.png" width="180" /></a>
1
+ <a href="https://www.phlex.fun"><img alt="Phlex logo" src="https://www.phlex.fun/assets/logo.png" width="180" /></a>
2
2
 
3
- Phlex lets you compose web views in pure Ruby. It’s super-fast, thread-safe and supports TruffleRuby v22.2+, JRuby v9.2+ and MRI v2.7+.
4
-
5
- ### Documentation πŸ“—
6
-
7
- Documentation can be found at [www.phlex.fun](https://www.phlex.fun).
8
-
9
- ### Support βœ‹
10
-
11
- If you run into any trouble, please [start a discussion](https://github.com/joeldrapper/phlex/discussions/new), or [open an issue](https://github.com/joeldrapper/phlex/issues/new) if you think you’ve found a bug.
12
-
13
- ### Ecosystem 🌱
14
- - [joeldrapper/phlex-rails](https://github.com/joeldrapper/phlex-rails) β€” Ruby on Rails integration
15
- - [joeldrapper/phlex.fun](https://github.com/joeldrapper/phlex.fun) β€” Docs Website
16
- - [joeldrapper/phlex-markdown](https://github.com/joeldrapper/phlex-markdown) β€” Markdown to HTML using Phlex
17
- - [joeldrapper/phlex-compiler](https://github.com/joeldrapper/phlex-compiler) β€” A compiler for Phlex
18
- - [joeldrapper/phlex-translation](https://github.com/joeldrapper/phlex-translation) β€” I18n Support for Phlex
19
- - [joeldrapper/phlex-testing-nokogiri](https://github.com/joeldrapper/phlex-testing-nokogiri) β€” Nokogiri support
20
- - [joeldrapper/phlex-testing-capybara](https://github.com/joeldrapper/phlex-testing-capybara) β€” Capybara support
21
- - [marcoroth/phlexing](https://github.com/marcoroth/phlexing) β€” ERB β†’ Phlex converter
22
- - [ViewComponent/lookbook](https://github.com/ViewComponent/lookbook) β€”Β Document and preview Phlex components in Rails (v2 beta only)
23
-
24
- ### Community πŸ™Œ
25
-
26
- Everyone interacting in Phlex codebases, issue trackers or chat rooms is expected to follow the [code of conduct](https://github.com/joeldrapper/phlex/blob/main/CODE_OF_CONDUCT.md).
27
-
28
- ### Who uses Phlex?
29
-
30
- - [Clearscope](https://www.clearscope.io)
31
-
32
- *If you’re using Phlex in production, please open a PR to list it here.*
33
-
34
- ### Sponsorship πŸ’–
35
-
36
- Maintaining a library is a lot of work. If your company benefits from this work or is likely to benefit from it in the future, please consider [sponsorship](https://github.com/sponsors/joeldrapper). Phlex is actively developed and maintained by **[Joel Drapper](https://github.com/sponsors/joeldrapper)**.
37
-
38
- ### Security 🚨
39
-
40
- If you’ve found a potential security issue, please email [security@phlex.fun](mailto:security@phlex.fun).
41
-
42
- ### Thanks πŸ™
43
-
44
- Thanks [Logology](https://www.logology.co) for sponsoring our logo.
3
+ Phlex lets you compose web views in pure Ruby β€” kind of like JSX, but not really anything like JSX. It’s super-fast, thread-safe and supports TruffleRuby v22.2+, JRuby v9.2+ and MRI v2.7+. Phlex currently supports [HTML](https://rubydoc.info/gems/phlex/Phlex/HTML) and [SVG](https://rubydoc.info/gems/phlex/Phlex/SVG) views, and we’re exploring JSON and XML.
45
4
 
46
5
  ### Prior Art 🎨
47
6
 
@@ -55,3 +14,4 @@ Thanks [Logology](https://www.logology.co) for sponsoring our logo.
55
14
  - [hyperstack](https://github.com/hyperstack-org/hyperstack)
56
15
  - [clearwater](https://github.com/clearwater-rb/clearwater)
57
16
  - [paggio](https://github.com/opal/paggio)
17
+ - [Inesita](https://github.com/inesita-rb/inesita)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @api private
3
4
  module Phlex::BlackHole
4
5
  extend self
5
6
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @api private
3
4
  module Phlex::Callable
4
5
  def to_proc
5
6
  method(:call).to_proc
data/lib/phlex/context.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @api private
3
4
  class Phlex::Context
4
5
  def initialize
5
6
  @target = +""
@@ -1,5 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Include this module into an {HTML} or {SVG} component to make it yield the content block before calling {#template}.
4
+ # @example
5
+ # class Tabs < Phlex::HTML
6
+ # include DeferredRender
7
+ #
8
+ # Tab = Data.define(:name, :content)
9
+ #
10
+ # def initialize
11
+ # @tabs = []
12
+ # end
13
+ #
14
+ # def template
15
+ # @tabs.each { |t| a { t.name } }
16
+ # @tabs.each { |t| article(&t.content) }
17
+ # end
18
+ #
19
+ # def tab(name, &content)
20
+ # @tabs << Tab.new(name, content)
21
+ # end
22
+ # end
3
23
  module Phlex::DeferredRender
4
24
  # This module doesn't do anything. Phlex::HTML#call checks for its inclusion in the ancestry instead.
25
+
26
+ # @!method template
27
+ # @abstract Override to define your own template.
28
+ # @note {DeferredRender} templates do not receive the content block. Instead, it is yielded in advance.
5
29
  end
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Phlex
4
- module ElementClobberingGuard
5
- def method_added(method_name)
6
- if method_name[0] == "_" && private_instance_methods.include?(:"__phlex#{method_name}__")
7
- raise NameError, "πŸ‘‹ Redefining the method `#{name}##{method_name}` is not a good idea."
8
- end
9
-
3
+ # @api private
4
+ module Phlex::ElementClobberingGuard
5
+ def method_added(method_name)
6
+ if method_name[0] == "_" && element_method?(method_name[1..].to_sym)
7
+ raise Phlex::NameError, "πŸ‘‹ Redefining the method `#{name}##{method_name}` is not a good idea."
8
+ else
10
9
  super
11
10
  end
12
11
  end
@@ -4,68 +4,96 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
4
4
  using Phlex::Overrides::Symbol::Name
5
5
  end
6
6
 
7
+ # Extending this module provides the {register_element} macro for registering your own custom elements. It's already extended by {HTML} and {SVG}.
8
+ # @example
9
+ # module MyCustomElements
10
+ # extend Phlex::Elements
11
+ #
12
+ # register_element :trix_editor
13
+ # end
14
+ #
15
+ # class MyComponent < Phlex::HTML
16
+ # include MyCustomElements
17
+ #
18
+ # def template
19
+ # trix_editor
20
+ # end
21
+ # end
7
22
  module Phlex::Elements
8
- private def slow_registered_elements
9
- private_instance_methods
10
- .lazy
11
- .map(&:to_s)
12
- .select { |m| m.start_with?("__phlex_") }
13
- .map { |m| m[8...-2].to_sym }
23
+ # @api private
24
+ def registered_elements
25
+ @registered_elements ||= Concurrent::Map.new
14
26
  end
15
27
 
16
- def register_element(element, tag: element.name.tr("_", "-"))
28
+ # Register a custom element. This macro defines an element method for the current class and descendents only. There is no global element registry.
29
+ # @param method_name [Symbol]
30
+ # @param tag [String] the name of the tag, otherwise this will be the method name with underscores replaced with dashes.
31
+ # @return [Symbol] the name of the method created
32
+ # @note The methods defined by this macro depend on other methods from {SGML} so they should always be mixed into an {HTML} or {SVG} component.
33
+ # @example Register the custom element `<trix-editor>`
34
+ # register_element :trix_editor
35
+ def register_element(method_name, tag: nil)
36
+ tag ||= method_name.name.tr("_", "-")
37
+
17
38
  class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
18
39
  # frozen_string_literal: true
19
40
 
20
- def __phlex_#{element}__(**attributes, &block)
41
+ def #{method_name}(**attributes, &block)
42
+ target = @_context.target
43
+
21
44
  if attributes.length > 0 # with attributes
22
45
  if block_given? # with content block
23
- @_context.target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
46
+ target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
24
47
  yield_content(&block)
25
- @_context.target << "</#{tag}>"
48
+ target << "</#{tag}>"
26
49
  else # without content block
27
- @_context.target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << "></#{tag}>"
50
+ target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << "></#{tag}>"
28
51
  end
29
52
  else # without attributes
30
53
  if block_given? # with content block
31
- @_context.target << "<#{tag}>"
54
+ target << "<#{tag}>"
32
55
  yield_content(&block)
33
- @_context.target << "</#{tag}>"
56
+ target << "</#{tag}>"
34
57
  else # without content block
35
- @_context.target << "<#{tag}></#{tag}>"
58
+ target << "<#{tag}></#{tag}>"
36
59
  end
37
60
  end
38
61
 
62
+ #{'flush' if tag == 'head'}
63
+
39
64
  nil
40
65
  end
41
66
 
42
- alias_method :_#{element}, :__phlex_#{element}__
43
- alias_method :#{element}, :__phlex_#{element}__
44
- private :__phlex_#{element}__
67
+ alias_method :_#{method_name}, :#{method_name}
45
68
  RUBY
46
69
 
47
- element
70
+ registered_elements[method_name] = tag
71
+
72
+ method_name
48
73
  end
49
74
 
50
- def register_void_element(element, tag: element.name.tr("_", "-"))
75
+ # @api private
76
+ def register_void_element(method_name, tag: method_name.name.tr("_", "-"))
51
77
  class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
52
78
  # frozen_string_literal: true
53
79
 
54
- def __phlex_#{element}__(**attributes)
80
+ def #{method_name}(**attributes)
81
+ target = @_context.target
82
+
55
83
  if attributes.length > 0 # with attributes
56
- @_context.target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
84
+ target << "<#{tag}" << (Phlex::ATTRIBUTE_CACHE[respond_to?(:process_attributes) ? (attributes.hash + self.class.hash) : attributes.hash] || __attributes__(**attributes)) << ">"
57
85
  else # without attributes
58
- @_context.target << "<#{tag}>"
86
+ target << "<#{tag}>"
59
87
  end
60
88
 
61
89
  nil
62
90
  end
63
91
 
64
- alias_method :_#{element}, :__phlex_#{element}__
65
- alias_method :#{element}, :__phlex_#{element}__
66
- private :__phlex_#{element}__
92
+ alias_method :_#{method_name}, :#{method_name}
67
93
  RUBY
68
94
 
69
- element
95
+ registered_elements[method_name] = tag
96
+
97
+ method_name
70
98
  end
71
99
  end
data/lib/phlex/helpers.rb CHANGED
@@ -5,8 +5,24 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0")
5
5
  end
6
6
 
7
7
  module Phlex::Helpers
8
+ private
9
+
10
+ # Tokens
8
11
  # @return [String]
9
- private def tokens(*tokens, **conditional_tokens)
12
+ # @example With Proc conditions
13
+ # tokens(
14
+ # -> { true } => "a",
15
+ # -> { false } => "b"
16
+ # )
17
+ # @example With method conditions
18
+ # tokens(
19
+ # active?: "active"
20
+ # )
21
+ # @example With else condition
22
+ # tokens(
23
+ # active?: { then: "active", else: "inactive" }
24
+ # )
25
+ def tokens(*tokens, **conditional_tokens)
10
26
  conditional_tokens.each do |condition, token|
11
27
  truthy = case condition
12
28
  when Symbol then send(condition)
@@ -33,7 +49,7 @@ module Phlex::Helpers
33
49
  end
34
50
 
35
51
  # @api private
36
- private def __append_token__(tokens, token)
52
+ def __append_token__(tokens, token)
37
53
  case token
38
54
  when nil then nil
39
55
  when String then tokens << token
@@ -44,8 +60,9 @@ module Phlex::Helpers
44
60
  end
45
61
  end
46
62
 
63
+ # Like {#tokens} but returns a {Hash} where the tokens are the value for `:class`.
47
64
  # @return [Hash]
48
- private def classes(*tokens, **conditional_tokens)
65
+ def classes(*tokens, **conditional_tokens)
49
66
  tokens = self.tokens(*tokens, **conditional_tokens)
50
67
 
51
68
  if tokens.empty?
@@ -56,7 +73,7 @@ module Phlex::Helpers
56
73
  end
57
74
 
58
75
  # @return [Hash]
59
- private def mix(*args)
76
+ def mix(*args)
60
77
  args.each_with_object({}) do |object, result|
61
78
  result.merge!(object) do |_key, old, new|
62
79
  case new