hot_module 1.0.0.alpha9 → 1.0.0.alpha11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/Gemfile.lock +8 -7
- data/README.md +3 -3
- data/hot_module.gemspec +5 -4
- data/lib/hot_module/component_renderer.rb +9 -13
- data/lib/hot_module/fragment.rb +10 -7
- data/lib/hot_module/petite.rb +1 -1
- data/lib/hot_module/query_selection.rb +3 -3
- data/lib/hot_module/version.rb +1 -1
- data/lib/hot_module.rb +116 -51
- metadata +23 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d90f5f3aee3f096c2b0dc962592cef3ff02563a5a8b5bef47cab9adc9eabf309
|
4
|
+
data.tar.gz: cdda20661fa3aab05d14f793a4b6ef3cf6d9c0bfc116a28a49a1118ab1286d2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff109253d98e063cfcf6a79481a3cde7934afca492dcca0edd865266cc1401918ba858f04f1cd7ae125d424332f9cdbfd1e562fe4e9914c55313a08070aa61cc
|
7
|
+
data.tar.gz: bb1864cc03b42c1612bd53aa29ef7278d38ad46b8d3362ab31b6093aa8abe907a7a2d1587b04338b2e2b74b868136235181a6871ef27eecb2690e59765d9e3c7
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.0.0.alpha10] - 2023-04-04
|
4
|
+
|
5
|
+
- Update debugging features based on Nokolexbor fixes
|
6
|
+
|
3
7
|
## [1.0.0.alpha9] - 2023-04-02
|
4
8
|
|
5
|
-
- Add support for [@crystallized/shadow-effects](https://github.com/
|
9
|
+
- Add support for [@crystallized/shadow-effects](https://github.com/hotmodule/crystallized/tree/main/packages/shadow-effects) template syntax
|
6
10
|
- Let `camelcased` handle symbol arrays, so it works with `attr_reader`
|
7
11
|
|
8
12
|
## [1.0.0.alpha8] - 2023-03-23
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hot_module (1.0.0.
|
5
|
-
|
4
|
+
hot_module (1.0.0.alpha11)
|
5
|
+
concurrent-ruby (~> 1.2)
|
6
|
+
nokolexbor (>= 0.4.2)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
@@ -33,9 +34,9 @@ GEM
|
|
33
34
|
racc (~> 1.4)
|
34
35
|
nokogiri (1.14.2-x86_64-linux)
|
35
36
|
racc (~> 1.4)
|
36
|
-
nokolexbor (0.4.
|
37
|
+
nokolexbor (0.4.2-arm64-darwin)
|
37
38
|
parallel (1.22.1)
|
38
|
-
parser (3.2.
|
39
|
+
parser (3.2.2.0)
|
39
40
|
ast (~> 2.4.1)
|
40
41
|
racc (1.6.2)
|
41
42
|
rainbow (3.1.1)
|
@@ -44,17 +45,17 @@ GEM
|
|
44
45
|
reverse_markdown (2.1.1)
|
45
46
|
nokogiri
|
46
47
|
rexml (3.2.5)
|
47
|
-
rubocop (1.
|
48
|
+
rubocop (1.49.0)
|
48
49
|
json (~> 2.3)
|
49
50
|
parallel (~> 1.10)
|
50
51
|
parser (>= 3.2.0.0)
|
51
52
|
rainbow (>= 2.2.2, < 4.0)
|
52
53
|
regexp_parser (>= 1.8, < 3.0)
|
53
54
|
rexml (>= 3.2.5, < 4.0)
|
54
|
-
rubocop-ast (>= 1.
|
55
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
55
56
|
ruby-progressbar (~> 1.7)
|
56
57
|
unicode-display_width (>= 2.4.0, < 3.0)
|
57
|
-
rubocop-ast (1.
|
58
|
+
rubocop-ast (1.28.0)
|
58
59
|
parser (>= 3.2.1.0)
|
59
60
|
rubocop-minitest (0.22.2)
|
60
61
|
rubocop (>= 0.90, < 2.0)
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Parse, mutate, and render custom elements in Ruby using [HTML Modules](https://github.com/WICG/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md).
|
4
4
|
|
5
|
-
Great for pairing with [esbuild-plugin-html-modules](https://github.com/
|
5
|
+
Great for pairing with [esbuild-plugin-html-modules](https://github.com/hotmodule/esbuild-plugin-html-modules) for a full-stack component rendering pipeline.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -26,7 +26,7 @@ To install this gem onto your local machine, run `bin/rake install`. To release
|
|
26
26
|
|
27
27
|
## Contributing
|
28
28
|
|
29
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
29
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/hotmodule/hot_module. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/hotmodule/hot_module/blob/main/CODE_OF_CONDUCT.md).
|
30
30
|
|
31
31
|
## License
|
32
32
|
|
@@ -34,4 +34,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
34
34
|
|
35
35
|
## Code of Conduct
|
36
36
|
|
37
|
-
Everyone interacting in the HoTModuLe project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
37
|
+
Everyone interacting in the HoTModuLe project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/hotmodule/hot_module/blob/main/CODE_OF_CONDUCT.md).
|
data/hot_module.gemspec
CHANGED
@@ -9,13 +9,13 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ["jared@whitefusion.studio"]
|
10
10
|
|
11
11
|
spec.summary = "Parse, mutate, and render HTML Modules in Ruby."
|
12
|
-
spec.homepage = "https://github.com/
|
12
|
+
spec.homepage = "https://github.com/hotmodule/hot_module#readme"
|
13
13
|
spec.license = "MIT"
|
14
14
|
spec.required_ruby_version = ">= 3.0"
|
15
15
|
|
16
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
-
spec.metadata["source_code_uri"] = "https://github.com/
|
18
|
-
spec.metadata["changelog_uri"] = "https://github.com/
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/hotmodule/hot_module"
|
18
|
+
spec.metadata["changelog_uri"] = "https://github.com/hotmodule/hot_module/blob/main/CHANGELOG.md"
|
19
19
|
spec.metadata["rubygems_mfa_required"] = "true"
|
20
20
|
|
21
21
|
# Specify which files should be added to the gem when it is released.
|
@@ -27,7 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
end
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
spec.add_dependency "
|
30
|
+
spec.add_dependency "concurrent-ruby", "~> 1.2"
|
31
|
+
spec.add_dependency "nokolexbor", ">= 0.4.2"
|
31
32
|
|
32
33
|
spec.add_development_dependency "hash_with_dot_access", "~> 1.2"
|
33
34
|
end
|
@@ -7,21 +7,16 @@ module HoTModuLe
|
|
7
7
|
|
8
8
|
class ComponentRenderer < Bridgetown::Builder
|
9
9
|
def build
|
10
|
-
|
11
|
-
Bridgetown::Component.subclasses.each do |component|
|
12
|
-
next unless component.respond_to?(:tag_name)
|
13
|
-
|
14
|
-
registered_tags[component.tag_name] = component
|
15
|
-
end
|
16
|
-
|
17
|
-
render_html_modules(registered_tags)
|
10
|
+
render_html_modules
|
18
11
|
end
|
19
12
|
|
20
|
-
|
21
|
-
|
13
|
+
# rubocop:todo Metrics
|
14
|
+
def render_html_modules
|
15
|
+
inspect_html do |doc, resource|
|
22
16
|
view_context = HoTModuLe::View.new(resource)
|
23
17
|
|
24
|
-
|
18
|
+
HoTModuLe.registered_elements.each do |component|
|
19
|
+
tag_name = component.tag_name
|
25
20
|
doc.xpath("//#{tag_name}").reverse.each do |node|
|
26
21
|
if node["hmod:ignore"]
|
27
22
|
node.attribute("hmod:ignore").remove
|
@@ -33,9 +28,9 @@ module HoTModuLe
|
|
33
28
|
|
34
29
|
new_attrs = {}
|
35
30
|
attrs.each do |k, v|
|
36
|
-
next unless k.start_with?("
|
31
|
+
next unless k.start_with?("arg:")
|
37
32
|
|
38
|
-
new_key = k.delete_prefix("
|
33
|
+
new_key = k.delete_prefix("arg:")
|
39
34
|
attrs.delete(k)
|
40
35
|
new_attrs[new_key] = resource.instance_eval(v)
|
41
36
|
end
|
@@ -54,5 +49,6 @@ module HoTModuLe
|
|
54
49
|
end
|
55
50
|
end
|
56
51
|
end
|
52
|
+
# rubocop:enable Metrics
|
57
53
|
end
|
58
54
|
end
|
data/lib/hot_module/fragment.rb
CHANGED
@@ -2,15 +2,17 @@
|
|
2
2
|
|
3
3
|
module HoTModuLe
|
4
4
|
class Fragment
|
5
|
-
def initialize(fragment,
|
5
|
+
def initialize(fragment, component)
|
6
6
|
@fragment = fragment
|
7
|
-
@
|
8
|
-
@
|
7
|
+
@component = component
|
8
|
+
@attribute_bindings = component.class.attribute_bindings.each do |attr_def|
|
9
|
+
attr_def.method = component.method(attr_def.method_name)
|
10
|
+
end
|
9
11
|
end
|
10
12
|
|
11
|
-
# NOTE: for some reason, the
|
12
|
-
# parent node. That doesn't work for our case. We want to go strictly in source order.
|
13
|
-
# is our own implementation of that.
|
13
|
+
# NOTE: for some reason, the traverse method yields node children first, then the
|
14
|
+
# parent node. That doesn't work for our case. We want to go strictly in source order.
|
15
|
+
# So this is our own implementation of that.
|
14
16
|
def traverse(node, &block)
|
15
17
|
yield(node)
|
16
18
|
node.children.each { |child| traverse(child, &block) }
|
@@ -32,7 +34,8 @@ module HoTModuLe
|
|
32
34
|
break unless attribute_binding.method.(attribute: attr_node, node: node)
|
33
35
|
end
|
34
36
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
35
|
-
|
37
|
+
line_segments = [@component.class.html_module, @component.class.line_number_of_node(attr_node)]
|
38
|
+
raise e.class, e.message.lines.first, [line_segments.join(":"), *e.backtrace]
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
data/lib/hot_module/petite.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HoTModuLe
|
4
|
-
# Add a couple familar DOM API features to
|
4
|
+
# Add a couple familar DOM API features to Nokolexbor
|
5
5
|
module QuerySelection
|
6
6
|
# @param selector [String]
|
7
|
-
# @return [
|
7
|
+
# @return [Nokolexbor::Element]
|
8
8
|
def query_selector(selector) = at_css(selector)
|
9
9
|
|
10
10
|
# @param selector [String]
|
11
|
-
# @return [
|
11
|
+
# @return [Nokolexbor::Element]
|
12
12
|
def query_selector_all(selector) = css(selector)
|
13
13
|
end
|
14
14
|
|
data/lib/hot_module/version.rb
CHANGED
data/lib/hot_module.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative "hot_module/version"
|
4
4
|
|
5
5
|
require "nokolexbor"
|
6
|
+
require "concurrent"
|
6
7
|
|
7
8
|
# Include this module into your own component class
|
8
9
|
module HoTModuLe
|
@@ -23,10 +24,30 @@ module HoTModuLe
|
|
23
24
|
require_relative "hot_module/fragment"
|
24
25
|
require_relative "hot_module/query_selection"
|
25
26
|
|
27
|
+
def self.registered_elements
|
28
|
+
@registered_elements ||= Concurrent::Set.new
|
29
|
+
|
30
|
+
@registered_elements.each do |component|
|
31
|
+
begin
|
32
|
+
next if Kernel.const_get(component.to_s) == component # thin out unloaded consts
|
33
|
+
rescue NameError; end # rubocop:disable Lint/SuppressedException
|
34
|
+
|
35
|
+
@registered_elements.delete component
|
36
|
+
end
|
37
|
+
|
38
|
+
@registered_elements
|
39
|
+
end
|
40
|
+
|
26
41
|
# @param klass [Class]
|
27
42
|
# @return [void]
|
28
43
|
def self.included(klass)
|
29
44
|
klass.extend ClassMethods
|
45
|
+
|
46
|
+
klass.attribute_binding "hmod:children", :_hmod_children_binding, only: :template
|
47
|
+
klass.attribute_binding "hmod:replace", :_hmod_replace_binding
|
48
|
+
klass.attribute_binding "hmod:text", :_hmod_expr_binding
|
49
|
+
klass.attribute_binding "hmod:html", :_hmod_expr_binding
|
50
|
+
|
30
51
|
# Don't stomp on a superclass's `content` method
|
31
52
|
return if klass.instance_methods.include?(:content)
|
32
53
|
|
@@ -41,7 +62,8 @@ module HoTModuLe
|
|
41
62
|
end
|
42
63
|
end
|
43
64
|
|
44
|
-
def html_file_extensions = %w[module.html
|
65
|
+
def html_file_extensions = %w[module.html mod.html html].freeze
|
66
|
+
|
45
67
|
def processed_css_extension = "css-local"
|
46
68
|
|
47
69
|
# @param tag_name [String]
|
@@ -54,53 +76,56 @@ module HoTModuLe
|
|
54
76
|
raise HoTModuLe::Error, "You must either supply a file path argument or respond to `source_location'"
|
55
77
|
end
|
56
78
|
|
57
|
-
|
79
|
+
self.tag_name tag_name
|
58
80
|
|
59
81
|
if html_module
|
60
|
-
|
82
|
+
self.html_module html_module
|
61
83
|
else
|
62
84
|
basepath = File.join(File.dirname(source_location), File.basename(source_location, ".*"))
|
63
85
|
|
64
|
-
|
86
|
+
self.html_module(html_file_extensions.lazy.filter_map do |ext|
|
65
87
|
path = "#{basepath}.#{ext}"
|
66
88
|
File.exist?(path) ? path : nil
|
67
|
-
end.first
|
89
|
+
end.first)
|
68
90
|
|
69
91
|
raise HoTModuLe::Error, "Cannot find sidecar HTML module for `#{self}'" unless @html_module
|
70
92
|
end
|
71
93
|
|
72
|
-
|
94
|
+
self.shadow_root shadow_root
|
73
95
|
end
|
74
96
|
|
75
97
|
# @param value [String]
|
76
98
|
# @return [String]
|
77
99
|
def tag_name(value = nil)
|
78
|
-
@tag_name ||=
|
100
|
+
@tag_name ||= begin
|
101
|
+
HoTModuLe.registered_elements << self
|
102
|
+
value
|
103
|
+
end
|
79
104
|
end
|
80
105
|
|
81
106
|
# @param value [String]
|
82
107
|
# @return [String]
|
83
|
-
def html_module(value = nil)
|
84
|
-
@html_module ||= value
|
85
|
-
end
|
108
|
+
def html_module(value = nil) = @html_module ||= value
|
86
109
|
|
87
110
|
# @param value [Boolean]
|
88
111
|
# @return [Boolean]
|
89
|
-
def shadow_root(value = nil)
|
90
|
-
@shadow_root ||= value
|
91
|
-
end
|
112
|
+
def shadow_root(value = nil) = @shadow_root ||= value
|
92
113
|
|
93
|
-
# @return [
|
114
|
+
# @return [Nokolexbor::Element]
|
94
115
|
def doc
|
95
|
-
@doc ||=
|
96
|
-
"<#{tag_name}>#{File.read(html_module).strip}</#{tag_name}>"
|
97
|
-
|
116
|
+
@doc ||= begin
|
117
|
+
@doc_html = "<#{tag_name}>#{File.read(html_module).strip}</#{tag_name}>"
|
118
|
+
Nokolexbor::DocumentFragment.parse(@doc_html).first_element_child
|
119
|
+
end
|
98
120
|
end
|
99
121
|
|
100
|
-
def
|
101
|
-
|
122
|
+
def line_number_of_node(node)
|
123
|
+
loc = node.source_location
|
124
|
+
instance_variable_get(:@doc_html)[0..loc].count("\n") + 1
|
102
125
|
end
|
103
126
|
|
127
|
+
def attribute_bindings = @attribute_bindings ||= []
|
128
|
+
|
104
129
|
def attribute_binding(matcher, method_name, only: nil)
|
105
130
|
attribute_bindings << AttributeBinding.new(
|
106
131
|
matcher: Regexp.new(matcher),
|
@@ -111,22 +136,21 @@ module HoTModuLe
|
|
111
136
|
end
|
112
137
|
|
113
138
|
module ContentMethod
|
114
|
-
# @return [String,
|
115
|
-
def content
|
139
|
+
# @return [String, Nokolexbor::Element]
|
140
|
+
def content = @_content
|
116
141
|
end
|
117
142
|
|
118
143
|
# Override in component
|
119
144
|
#
|
120
145
|
# @return [Hash]
|
121
|
-
def attributes
|
122
|
-
{}
|
123
|
-
end
|
146
|
+
def attributes = {}
|
124
147
|
|
125
148
|
# @param attributes [Hash]
|
126
|
-
# @param content [String,
|
149
|
+
# @param content [String, Nokolexbor::Element]
|
127
150
|
# @param return_node [Boolean]
|
128
151
|
def render_element(attributes: self.attributes, content: self.content, return_node: false) # rubocop:disable Metrics
|
129
152
|
doc = self.class.doc.clone
|
153
|
+
@_content = content
|
130
154
|
|
131
155
|
tmpl_el = doc.css("> template").find { _1.attributes.empty? }
|
132
156
|
|
@@ -140,6 +164,33 @@ module HoTModuLe
|
|
140
164
|
# Process all the template bits
|
141
165
|
process_fragment(tmpl_el)
|
142
166
|
|
167
|
+
HoTModuLe.registered_elements.each do |component|
|
168
|
+
tmpl_el.children[0].css(component.tag_name).reverse.each do |node|
|
169
|
+
if node["hmod:ignore"]
|
170
|
+
node.attribute("hmod:ignore").remove
|
171
|
+
next
|
172
|
+
end
|
173
|
+
|
174
|
+
attrs = node.attributes.transform_values(&:value)
|
175
|
+
attrs.reject! { |k| k.start_with?("hmod:") }
|
176
|
+
new_attrs = {}
|
177
|
+
attrs.each do |k, v|
|
178
|
+
next unless k.start_with?("arg:")
|
179
|
+
|
180
|
+
new_key = k.delete_prefix("arg:")
|
181
|
+
attrs.delete(k)
|
182
|
+
new_attrs[new_key] = instance_eval(v, self.class.html_module, self.class.line_number_of_node(node))
|
183
|
+
end
|
184
|
+
attrs.merge!(new_attrs)
|
185
|
+
attrs.transform_keys!(&:to_sym)
|
186
|
+
|
187
|
+
new_node = node.replace(
|
188
|
+
component.new(**attrs).render_element(content: node.children)
|
189
|
+
)
|
190
|
+
new_node.first.attribute("hmod:ignore")&.remove
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
143
194
|
# Set attributes on the custom element
|
144
195
|
attributes.each { |k, v| doc[k.to_s.tr("_", "-")] = value_to_attribute(v) if v }
|
145
196
|
|
@@ -176,14 +227,15 @@ module HoTModuLe
|
|
176
227
|
style_tag.content = output_styles
|
177
228
|
end
|
178
229
|
|
230
|
+
child_content = @_replaced_children || content
|
179
231
|
if self.class.shadow_root
|
180
232
|
# Guess what? We can reuse the same template tag! =)
|
181
233
|
tmpl_el["shadowrootmode"] = "open"
|
182
234
|
tmpl_el.children[0] << style_tag if style_tag
|
183
|
-
doc <<
|
235
|
+
doc << child_content if child_content
|
184
236
|
else
|
185
237
|
tmpl_el.children[0] << style_tag if style_tag
|
186
|
-
tmpl_el.children[0].at_css("slot:not([name])")&.swap(
|
238
|
+
tmpl_el.children[0].at_css("slot:not([name])")&.swap(child_content) if child_content
|
187
239
|
tmpl_el.children[0].children.each do |node|
|
188
240
|
doc << node
|
189
241
|
end
|
@@ -194,13 +246,9 @@ module HoTModuLe
|
|
194
246
|
return_node ? doc : doc.to_html
|
195
247
|
end
|
196
248
|
|
197
|
-
def call(...)
|
198
|
-
render_element(...)
|
199
|
-
end
|
249
|
+
def call(...) = render_element(...)
|
200
250
|
|
201
|
-
def inspect
|
202
|
-
"#<#{self.class.name} #{attributes}>"
|
203
|
-
end
|
251
|
+
def inspect = "#<#{self.class.name} #{attributes}>"
|
204
252
|
|
205
253
|
def value_to_attribute(val)
|
206
254
|
case val
|
@@ -213,16 +261,15 @@ module HoTModuLe
|
|
213
261
|
end
|
214
262
|
end
|
215
263
|
|
264
|
+
def node_or_string(val)
|
265
|
+
val.is_a?(Nokolexbor::Node) ? val : val.to_s
|
266
|
+
end
|
267
|
+
|
216
268
|
# Override in component if need be, otherwise we'll use the node walker/binding pipeline
|
217
269
|
#
|
218
|
-
# @param fragment [
|
270
|
+
# @param fragment [Nokolexbor::Element]
|
219
271
|
# @return [void]
|
220
|
-
def process_fragment(fragment)
|
221
|
-
Fragment.new(
|
222
|
-
fragment, self.class.attribute_bindings.each { _1.method = method(_1.method_name) },
|
223
|
-
html_module: self.class.html_module
|
224
|
-
).process
|
225
|
-
end
|
272
|
+
def process_fragment(fragment) = Fragment.new(fragment, self).process
|
226
273
|
|
227
274
|
def process_list(attribute:, node:, item_node:, for_in:) # rubocop:disable Metrics
|
228
275
|
_context_nodes.push(node)
|
@@ -247,10 +294,7 @@ module HoTModuLe
|
|
247
294
|
_context_locals[lh[0]] = list_item
|
248
295
|
_context_locals[lh[1]] = index if lh[1]
|
249
296
|
|
250
|
-
Fragment.new(
|
251
|
-
new_node, self.class.attribute_bindings,
|
252
|
-
html_module: self.class.html_module
|
253
|
-
).process
|
297
|
+
Fragment.new(new_node, self).process
|
254
298
|
end
|
255
299
|
end
|
256
300
|
end
|
@@ -260,7 +304,7 @@ module HoTModuLe
|
|
260
304
|
_context_locals.keys.reverse_each do |name|
|
261
305
|
eval_code = "#{name} = _context_locals[\"#{name}\"];" + eval_code
|
262
306
|
end
|
263
|
-
instance_eval(eval_code, self.class.html_module
|
307
|
+
instance_eval(eval_code, self.class.html_module, self.class.line_number_of_node(attribute))
|
264
308
|
end
|
265
309
|
|
266
310
|
def class_list_for(obj)
|
@@ -275,13 +319,9 @@ module HoTModuLe
|
|
275
319
|
end.join(" ")
|
276
320
|
end
|
277
321
|
|
278
|
-
def _context_nodes
|
279
|
-
@_context_nodes ||= []
|
280
|
-
end
|
322
|
+
def _context_nodes = @_context_nodes ||= []
|
281
323
|
|
282
|
-
def _context_locals
|
283
|
-
@_context_locals ||= {}
|
284
|
-
end
|
324
|
+
def _context_locals = @_context_locals ||= {}
|
285
325
|
|
286
326
|
def _check_stack(node)
|
287
327
|
node_and_ancestors = [node, *node.ancestors.to_a]
|
@@ -303,6 +343,31 @@ module HoTModuLe
|
|
303
343
|
yield previous_context
|
304
344
|
@_context_locals = previous_context
|
305
345
|
end
|
346
|
+
|
347
|
+
def _hmod_children_binding(attribute:, node:) # rubocop:disable Lint/UnusedMethodArgument
|
348
|
+
@_replaced_children = node.children[0]
|
349
|
+
node.remove
|
350
|
+
end
|
351
|
+
|
352
|
+
def _hmod_replace_binding(attribute:, node:)
|
353
|
+
if node.name == "template"
|
354
|
+
node.children[0].inner_html = node_or_string(evaluate_attribute_expression(attribute))
|
355
|
+
node.replace(node.children[0].children)
|
356
|
+
else
|
357
|
+
node.inner_html = node_or_string(evaluate_attribute_expression(attribute))
|
358
|
+
node.replace(node.children)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def _hmod_expr_binding(attribute:, node:)
|
363
|
+
if attribute.name.end_with?(":text")
|
364
|
+
node.content = node_or_string(evaluate_attribute_expression(attribute))
|
365
|
+
attribute.parent.delete(attribute.name)
|
366
|
+
elsif attribute.name.end_with?(":html")
|
367
|
+
node.inner_html = node_or_string(evaluate_attribute_expression(attribute))
|
368
|
+
attribute.parent.delete(attribute.name)
|
369
|
+
end
|
370
|
+
end
|
306
371
|
end
|
307
372
|
|
308
373
|
if defined?(Bridgetown)
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hot_module
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.alpha11
|
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-04-
|
11
|
+
date: 2023-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: concurrent-ruby
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokolexbor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.4.2
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: hash_with_dot_access
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -62,13 +76,13 @@ files:
|
|
62
76
|
- lib/hot_module/query_selection.rb
|
63
77
|
- lib/hot_module/shadow_effects.rb
|
64
78
|
- lib/hot_module/version.rb
|
65
|
-
homepage: https://github.com/
|
79
|
+
homepage: https://github.com/hotmodule/hot_module#readme
|
66
80
|
licenses:
|
67
81
|
- MIT
|
68
82
|
metadata:
|
69
|
-
homepage_uri: https://github.com/
|
70
|
-
source_code_uri: https://github.com/
|
71
|
-
changelog_uri: https://github.com/
|
83
|
+
homepage_uri: https://github.com/hotmodule/hot_module#readme
|
84
|
+
source_code_uri: https://github.com/hotmodule/hot_module
|
85
|
+
changelog_uri: https://github.com/hotmodule/hot_module/blob/main/CHANGELOG.md
|
72
86
|
rubygems_mfa_required: 'true'
|
73
87
|
post_install_message:
|
74
88
|
rdoc_options: []
|