heartml 1.0.0.beta7 → 1.0.0.beta8

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: b691744cecebf95f2fb8f13f06a78eee6329bc9a2d254c164ee40dd3f02dadf2
4
- data.tar.gz: f414b9bea17b174e3b0da67b4bad5cbe8e16e27e88f171cd6282e2932ea2ab27
3
+ metadata.gz: 9af36d404ea8e79e505dd4ae52f7154d697bccf0722bec8b35a34172a7620d2f
4
+ data.tar.gz: 7870f15ce64e811f91ccb07c5b20fe5a010af2d2c4eac355b2583ac8e859730c
5
5
  SHA512:
6
- metadata.gz: 38a1ea44179bc544eecccdce6dcb8a7628f6c203f49bfbf27674eab0a358b9f943d9e52482a6f42be890a81caf2a95a4904416280f5c56c8b67c5b0ae372671f
7
- data.tar.gz: cb6ee9fa4cabf62994186774b1ab93ba36136ed2a945797c98fad82f35e51ae00e5d4356ba4a40625fae95026e8b1fc6d4b076b9d7e2ae8740cfa2d250a44877
6
+ metadata.gz: df9a6f3028cccad882c443af444734f969a3be9fce3aad110114c5728692db08a7678645aecac64858ab0454041c7142387b86fe02813a264dafcd77828579e3
7
+ data.tar.gz: 152c74f825813fe9183fe37f6cb491670804b3ecc53ec5277a0f4a5161ddbb199d4f332333be417d19e59ca99b8d69353dad9270f4370c9814a6c54720fe879c
data/.rubocop.yml CHANGED
@@ -3,7 +3,7 @@ require:
3
3
  - rubocop-rake
4
4
 
5
5
  AllCops:
6
- TargetRubyVersion: 3.0
6
+ TargetRubyVersion: 3.1
7
7
  NewCops: enable
8
8
 
9
9
  Metrics/MethodLength:
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.0.0.beta8] - 2023-09-25
6
+
7
+ - Simplify modules structure, add tag swap feature, other refactors
8
+ - Bump min Ruby version to 3.1
9
+
5
10
  ## [1.0.0.beta7] - 2023-09-25
6
11
 
7
12
  - Add Railtie for Heartml component support in Rails
data/Gemfile CHANGED
@@ -14,4 +14,5 @@ gem "rubocop", "~> 1.21"
14
14
  gem "rubocop-minitest", "~> 0.22.1"
15
15
  gem "rubocop-rake", "~> 0.6.0"
16
16
 
17
+ gem "hash_with_dot_access", "~> 1.2"
17
18
  gem "solargraph", "~> 0.47.2", group: :development
data/Gemfile.lock CHANGED
@@ -1,71 +1,86 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- heartml (1.0.0.beta7)
4
+ heartml (1.0.0.beta8)
5
5
  concurrent-ruby (~> 1.2)
6
6
  nokolexbor (>= 0.4.2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (7.0.4.3)
11
+ activesupport (7.1.3)
12
+ base64
13
+ bigdecimal
12
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ connection_pool (>= 2.2.5)
16
+ drb
13
17
  i18n (>= 1.6, < 2)
14
18
  minitest (>= 5.1)
19
+ mutex_m
15
20
  tzinfo (~> 2.0)
16
21
  ast (2.4.2)
17
22
  backport (1.2.0)
18
- benchmark (0.2.1)
19
- concurrent-ruby (1.2.2)
20
- diff-lcs (1.5.0)
23
+ base64 (0.2.0)
24
+ benchmark (0.3.0)
25
+ bigdecimal (3.1.6)
26
+ concurrent-ruby (1.2.3)
27
+ connection_pool (2.4.1)
28
+ diff-lcs (1.5.1)
29
+ drb (2.2.0)
30
+ ruby2_keywords
21
31
  e2mmap (0.1.0)
22
32
  hash_with_dot_access (1.2.0)
23
33
  activesupport (>= 5.0.0, < 8.0)
24
- i18n (1.12.0)
34
+ i18n (1.14.1)
25
35
  concurrent-ruby (~> 1.0)
26
- jaro_winkler (1.5.4)
27
- json (2.6.3)
36
+ jaro_winkler (1.5.6)
37
+ json (2.7.1)
28
38
  kramdown (2.4.0)
29
39
  rexml
30
40
  kramdown-parser-gfm (1.1.0)
31
41
  kramdown (~> 2.0)
32
- mini_portile2 (2.8.4)
33
- minitest (5.18.0)
34
- nokogiri (1.14.2)
35
- mini_portile2 (~> 2.8.0)
42
+ language_server-protocol (3.17.0.3)
43
+ mini_portile2 (2.8.5)
44
+ minitest (5.22.2)
45
+ mutex_m (0.2.0)
46
+ nokogiri (1.16.2)
47
+ mini_portile2 (~> 2.8.2)
36
48
  racc (~> 1.4)
37
- nokogiri (1.14.2-arm64-darwin)
49
+ nokogiri (1.16.2-arm64-darwin)
38
50
  racc (~> 1.4)
39
- nokogiri (1.14.2-x86_64-linux)
51
+ nokogiri (1.16.2-x86_64-linux)
40
52
  racc (~> 1.4)
41
- nokolexbor (0.5.0-arm64-darwin)
42
- parallel (1.22.1)
43
- parser (3.2.2.0)
53
+ nokolexbor (0.5.2)
54
+ parallel (1.24.0)
55
+ parser (3.3.0.5)
44
56
  ast (~> 2.4.1)
45
- racc (1.6.2)
57
+ racc
58
+ racc (1.7.3)
46
59
  rainbow (3.1.1)
47
- rake (13.0.6)
48
- regexp_parser (2.7.0)
60
+ rake (13.1.0)
61
+ regexp_parser (2.9.0)
49
62
  reverse_markdown (2.1.1)
50
63
  nokogiri
51
- rexml (3.2.5)
52
- rubocop (1.49.0)
64
+ rexml (3.2.6)
65
+ rubocop (1.60.2)
53
66
  json (~> 2.3)
67
+ language_server-protocol (>= 3.17.0)
54
68
  parallel (~> 1.10)
55
- parser (>= 3.2.0.0)
69
+ parser (>= 3.3.0.2)
56
70
  rainbow (>= 2.2.2, < 4.0)
57
71
  regexp_parser (>= 1.8, < 3.0)
58
72
  rexml (>= 3.2.5, < 4.0)
59
- rubocop-ast (>= 1.28.0, < 2.0)
73
+ rubocop-ast (>= 1.30.0, < 2.0)
60
74
  ruby-progressbar (~> 1.7)
61
75
  unicode-display_width (>= 2.4.0, < 3.0)
62
- rubocop-ast (1.28.0)
76
+ rubocop-ast (1.30.0)
63
77
  parser (>= 3.2.1.0)
64
78
  rubocop-minitest (0.22.2)
65
79
  rubocop (>= 0.90, < 2.0)
66
80
  rubocop-rake (0.6.0)
67
81
  rubocop (~> 1.0)
68
82
  ruby-progressbar (1.13.0)
83
+ ruby2_keywords (0.0.5)
69
84
  solargraph (0.47.2)
70
85
  backport (~> 1.2)
71
86
  benchmark
@@ -81,14 +96,12 @@ GEM
81
96
  thor (~> 1.0)
82
97
  tilt (~> 2.0)
83
98
  yard (~> 0.9, >= 0.9.24)
84
- thor (1.2.1)
85
- tilt (2.1.0)
99
+ thor (1.3.0)
100
+ tilt (2.3.0)
86
101
  tzinfo (2.0.6)
87
102
  concurrent-ruby (~> 1.0)
88
- unicode-display_width (2.4.2)
89
- webrick (1.7.0)
90
- yard (0.9.28)
91
- webrick (~> 1.7.0)
103
+ unicode-display_width (2.5.0)
104
+ yard (0.9.34)
92
105
 
93
106
  PLATFORMS
94
107
  arm64-darwin-21
data/heartml.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = "Server-rendered web components"
12
12
  spec.homepage = "https://github.com/heartml/heartml-ruby#readme"
13
13
  spec.license = "MIT"
14
- spec.required_ruby_version = ">= 3.0"
14
+ spec.required_ruby_version = ">= 3.1"
15
15
 
16
16
  spec.metadata["homepage_uri"] = spec.homepage
17
17
  spec.metadata["source_code_uri"] = "https://github.com/heartml/heartml-ruby"
@@ -29,6 +29,4 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_dependency "concurrent-ruby", "~> 1.2"
31
31
  spec.add_dependency "nokolexbor", ">= 0.4.2"
32
-
33
- spec.add_development_dependency "hash_with_dot_access", "~> 1.2"
34
32
  end
@@ -11,7 +11,6 @@ module Heartml
11
11
  view_context = Bridgetown::ERBView.new(resource)
12
12
 
13
13
  rdr = Heartml::TemplateRenderer.new(body: doc.at_css("body"), context: view_context)
14
- # rdr.define_singleton_method(:view_context) { view_context }
15
14
  rdr.call
16
15
  end
17
16
  end
@@ -19,6 +18,7 @@ module Heartml
19
18
  end
20
19
 
21
20
  Bridgetown.initializer :heartml do |config|
21
+ # TODO: maybe we can ditch this once we're off ActiveSupport in Bridgetown
22
22
  Bridgetown::Component.extend ActiveSupport::DescendantsTracker
23
23
 
24
24
  Heartml.module_eval do
@@ -13,9 +13,9 @@ module Heartml
13
13
  # NOTE: for some reason, the traverse method yields node children first, then the
14
14
  # parent node. That doesn't work for our case. We want to go strictly in source order.
15
15
  # So this is our own implementation of that.
16
- def traverse(node, &block)
16
+ def traverse(node, &block) # rubocop:disable Style/ArgumentsForwarding
17
17
  yield(node)
18
- node.children.each { |child| traverse(child, &block) }
18
+ node.children.each { |child| traverse(child, &block) } # rubocop:disable Style/ArgumentsForwarding
19
19
  end
20
20
 
21
21
  def process(fragment = @fragment) # rubocop:disable Metrics
@@ -79,7 +79,7 @@ module Heartml
79
79
  next unless attribute_binding.matcher.match?(name)
80
80
  next if attribute_binding.method.receiver._check_stack(node)
81
81
 
82
- break unless attribute_binding.method.(attribute: attr_node, node: node)
82
+ break unless attribute_binding.method.(attribute: attr_node, node:)
83
83
  end
84
84
  rescue Exception => e # rubocop:disable Lint/RescueException
85
85
  line_segments = [@component.class.heart_module, @component._line_number_of_node(attr_node)]
@@ -36,7 +36,7 @@ module Heartml
36
36
 
37
37
  # @param klass [Class]
38
38
  # @return [void]
39
- def self.included(klass) # rubocop:disable Metrics
39
+ def self.included_extras(klass) # rubocop:disable Metrics
40
40
  klass.attribute_binding "server-effect", :_server_effect_binding
41
41
  klass.attribute_binding "iso-effect", :_iso_effect_binding
42
42
 
@@ -58,7 +58,7 @@ module Heartml
58
58
  end
59
59
 
60
60
  def _server_effect_binding(attribute:, node:)
61
- _iso_effect_binding(attribute: attribute, node: node)
61
+ _iso_effect_binding(attribute:, node:)
62
62
  node.remove_attribute "host-effect"
63
63
  end
64
64
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Heartml
4
+ class ServerComponent
5
+ def self.source_location
6
+ caller_locations(1, 10).reject do |l|
7
+ l.label == "inherited"
8
+ end[1].absolute_path
9
+ end
10
+
11
+ def self.inherited(klass)
12
+ super
13
+ klass.include Heartml
14
+ end
15
+ end
16
+
17
+ class TemplateRenderer < ServerComponent
18
+ def self.heart_module
19
+ "eval"
20
+ end
21
+
22
+ def initialize(body:, context:) # rubocop:disable Lint/MissingSuper
23
+ @doc_html = body.is_a?(String) ? body : body.to_html
24
+ @body = body.is_a?(String) ? Nokolexbor::DocumentFragment.parse(body) : body
25
+ @context = context
26
+ end
27
+
28
+ def call
29
+ Fragment.new(@body, self).process
30
+ @body
31
+ end
32
+
33
+ def respond_to_missing?(key)
34
+ context.respond_to?(key)
35
+ end
36
+
37
+ # TODO: delegate instead?
38
+ def method_missing(key, *args, **kwargs)
39
+ context.send(key, *args, **kwargs)
40
+ end
41
+ end
42
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Heartml
4
4
  # @return [String]
5
- VERSION = "1.0.0.beta7"
5
+ VERSION = "1.0.0.beta8"
6
6
  end
data/lib/heartml.rb CHANGED
@@ -26,6 +26,8 @@ module Heartml
26
26
  require_relative "heartml/query_selection"
27
27
  require "heartml/server_effects"
28
28
 
29
+ include ServerEffects
30
+
29
31
  def self.registered_elements
30
32
  @registered_elements ||= Concurrent::Set.new
31
33
 
@@ -50,8 +52,9 @@ module Heartml
50
52
  def self.included(klass)
51
53
  klass.extend ClassMethods
52
54
 
53
- klass.attribute_binding "server-children", :_server_children_binding, only: :template
54
- klass.attribute_binding "server-unsafe-eval", :_server_replace_binding
55
+ klass.attribute_binding "server-children", :_server_children, only: :template
56
+ klass.attribute_binding "server-content", :_server_content, only: :template
57
+ klass.attribute_binding "server-unsafe-eval", :_server_unsafe_eval
55
58
 
56
59
  # Don't stomp on a superclass's `content` method
57
60
  has_content_method = begin
@@ -61,6 +64,8 @@ module Heartml
61
64
  end
62
65
 
63
66
  klass.include ContentMethod unless has_content_method
67
+
68
+ ServerEffects.included_extras(klass)
64
69
  end
65
70
 
66
71
  # Extends the component class
@@ -112,6 +117,8 @@ module Heartml
112
117
  end
113
118
  end
114
119
 
120
+ def output_tag_name(value = nil) = @output_tag_name ||= value
121
+
115
122
  # @param value [String]
116
123
  # @return [String]
117
124
  def heart_module(value = nil) = @heart_module ||= value
@@ -136,7 +143,7 @@ module Heartml
136
143
  def attribute_binding(matcher, method_name, only: nil)
137
144
  attribute_bindings << AttributeBinding.new(
138
145
  matcher: Regexp.new(matcher),
139
- method_name: method_name,
146
+ method_name:,
140
147
  only_for_tag: only
141
148
  )
142
149
  end
@@ -247,7 +254,17 @@ module Heartml
247
254
  tmpl_el.remove
248
255
  end
249
256
 
250
- rendering_mode == :node ? doc : doc.to_html
257
+ if self.class.output_tag_name
258
+ swap_doc = doc.document.create_element(self.class.output_tag_name)
259
+ doc.attrs.each do |attr, value|
260
+ swap_doc[attr] = value
261
+ end
262
+ swap_doc << doc.children
263
+
264
+ rendering_mode == :node ? swap_doc : swap_doc.to_html
265
+ else
266
+ rendering_mode == :node ? doc : doc.to_html
267
+ end
251
268
  end
252
269
 
253
270
  def call(...) = render_element(...)
@@ -319,7 +336,7 @@ module Heartml
319
336
  # TODO: handle objects inside of an array?
320
337
  obj
321
338
  else
322
- Array[obj]
339
+ [obj]
323
340
  end.join(" ")
324
341
  end
325
342
 
@@ -353,12 +370,12 @@ module Heartml
353
370
  @_context_locals = previous_context
354
371
  end
355
372
 
356
- def _server_children_binding(attribute:, node:) # rubocop:disable Lint/UnusedMethodArgument
373
+ def _server_children(attribute:, node:) # rubocop:disable Lint/UnusedMethodArgument
357
374
  self.replaced_content = node.children[0]
358
375
  node.remove
359
376
  end
360
377
 
361
- def _server_replace_binding(attribute:, node:)
378
+ def _server_unsafe_eval(attribute:, node:)
362
379
  node_name = node.name
363
380
  correct_node = node_name == "template" ? node.children[0] : node
364
381
  result = node_or_string(evaluate_attribute_expression(attribute, correct_node.inner_html))
@@ -371,40 +388,12 @@ module Heartml
371
388
  end
372
389
  end
373
390
 
374
- class ServerComponent
375
- def self.inherited(klass)
376
- super
377
- klass.include Heartml
378
- klass.include Heartml::ServerEffects
379
- end
380
- end
381
-
382
- class TemplateRenderer < ServerComponent
383
- def self.heart_module
384
- "eval"
385
- end
386
-
387
- def initialize(body:, context:) # rubocop:disable Lint/MissingSuper
388
- @doc_html = body.is_a?(String) ? body : body.to_html
389
- @body = body.is_a?(String) ? Nokolexbor::DocumentFragment.parse(body) : body
390
- @context = context
391
- end
392
-
393
- def call
394
- Fragment.new(@body, self).process
395
- @body
396
- end
397
-
398
- def respond_to_missing?(key)
399
- context.respond_to?(key)
400
- end
401
-
402
- # TODO: delegate instead?
403
- def method_missing(key, *args, **kwargs)
404
- context.send(key, *args, **kwargs)
405
- end
391
+ def _server_content(attribute:, node:)
392
+ result = evaluate_attribute_expression(attribute, "content")
393
+ node.swap(result)
406
394
  end
407
395
  end
408
396
 
397
+ require_relative "heartml/template_renderer"
409
398
  require_relative "heartml/bridgetown_renderer" if defined?(Bridgetown)
410
399
  require_relative "heartml/railtie" if defined?(Rails::Railtie)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heartml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta7
4
+ version: 1.0.0.beta8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared White
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-26 00:00:00.000000000 Z
11
+ date: 2024-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.4.2
41
- - !ruby/object:Gem::Dependency
42
- name: hash_with_dot_access
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.2'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.2'
55
41
  description:
56
42
  email:
57
43
  - jared@whitefusion.studio
@@ -72,10 +58,10 @@ files:
72
58
  - lib/heartml.rb
73
59
  - lib/heartml/bridgetown_renderer.rb
74
60
  - lib/heartml/fragment.rb
75
- - lib/heartml/petite.rb
76
61
  - lib/heartml/query_selection.rb
77
62
  - lib/heartml/railtie.rb
78
63
  - lib/heartml/server_effects.rb
64
+ - lib/heartml/template_renderer.rb
79
65
  - lib/heartml/version.rb
80
66
  homepage: https://github.com/heartml/heartml-ruby#readme
81
67
  licenses:
@@ -93,14 +79,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - ">="
95
81
  - !ruby/object:Gem::Version
96
- version: '3.0'
82
+ version: '3.1'
97
83
  required_rubygems_version: !ruby/object:Gem::Requirement
98
84
  requirements:
99
- - - ">"
85
+ - - ">="
100
86
  - !ruby/object:Gem::Version
101
- version: 1.3.1
87
+ version: '0'
102
88
  requirements: []
103
- rubygems_version: 3.3.3
89
+ rubygems_version: 3.5.3
104
90
  signing_key:
105
91
  specification_version: 4
106
92
  summary: Server-rendered web components
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "heartml"
4
-
5
- module Heartml
6
- module Petite
7
- # @param klass [Class]
8
- # @return [void]
9
- def self.included(klass)
10
- klass.attribute_binding "v-for", :_petite_for_binding, only: :template
11
- klass.attribute_binding "v-text", :_petite_text_binding
12
- klass.attribute_binding "v-html", :_petite_html_binding
13
- klass.attribute_binding "v-bind", :_petite_bound_attribute
14
- klass.attribute_binding %r{^:}, :_petite_bound_attribute
15
- end
16
-
17
- protected
18
-
19
- def _petite_for_binding(attribute:, node:)
20
- delimiter = node["v-for"].include?(" of ") ? " of " : " in "
21
- expression = node["v-for"].split(delimiter)
22
-
23
- process_list(
24
- attribute: attribute,
25
- node: node,
26
- item_node: node.children[0].first_element_child,
27
- for_in: expression
28
- )
29
- end
30
-
31
- def _petite_text_binding(attribute:, node:)
32
- node.content = evaluate_attribute_expression(attribute).to_s
33
- end
34
-
35
- def _petite_html_binding(attribute:, node:)
36
- node.inner_html = evaluate_attribute_expression(attribute).to_s
37
- end
38
-
39
- def _petite_bound_attribute(attribute:, node:) # rubocop:disable Metrics
40
- return if attribute.name == ":key"
41
-
42
- real_attribute = if attribute.name.start_with?(":")
43
- attribute.name.delete_prefix(":")
44
- elsif attribute.name.start_with?("v-bind:")
45
- attribute.name.delete_prefix("v-bind:")
46
- end
47
-
48
- obj = evaluate_attribute_expression(attribute)
49
-
50
- if real_attribute == "class"
51
- node[real_attribute] = class_list_for(obj)
52
- elsif real_attribute != "style" # style bindings aren't SSRed
53
- node[real_attribute] = obj if obj
54
- end
55
- end
56
- end
57
- end