heartml 1.0.0.beta3 → 1.0.0.beta5
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/lib/heartml/bridgetown_renderer.rb +40 -0
- data/lib/heartml/fragment.rb +8 -4
- data/lib/heartml/version.rb +1 -1
- data/lib/heartml.rb +32 -88
- metadata +3 -3
- data/lib/heartml/component_renderer.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 053e789d42574715a2f4269205a6dfe549a3d4af6970a6f6446b51735a9be340
|
4
|
+
data.tar.gz: cfe795359ca2e951218853f336057d4751bac7e04564bc857808573c3f2e045a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36c6248a2b135f2d11b20b054d2a6bf8334460d56fe184a6c4d646e92561c2210e1e3a707975930613ed86091812708888b14d1fbd46f5efefe3befe3aeb3558
|
7
|
+
data.tar.gz: a4241d8e092361148f6ce228c0023007c7e97e650ab4c4336ea12b1f61287f1c1b034eff06f97f6718ae1c400fb82f252197de9205bdd7057058ad382cb56ce6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.0.0.beta5] - 2023-09-04
|
4
|
+
|
5
|
+
- Fix issue with ViewComponent in Rails apps
|
6
|
+
- Add fragment error handling
|
7
|
+
|
8
|
+
## [1.0.0.beta4] - 2023-08-27
|
9
|
+
|
10
|
+
- Refactor and improve Bridgetown plugin and simplify context handling for template rendering
|
11
|
+
|
3
12
|
## [1.0.0.beta3] - 2023-08-12
|
4
13
|
|
5
14
|
- Ensure attributes are processed on component node before it's rendered as component
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Heartml
|
4
|
+
class BridgetownRenderer < Bridgetown::Builder
|
5
|
+
def build
|
6
|
+
render_heart_modules
|
7
|
+
end
|
8
|
+
|
9
|
+
def render_heart_modules
|
10
|
+
inspect_html do |doc, resource|
|
11
|
+
view_context = Bridgetown::ERBView.new(resource)
|
12
|
+
|
13
|
+
rdr = Heartml::TemplateRenderer.new(body: doc.at_css("body"), context: view_context)
|
14
|
+
# rdr.define_singleton_method(:view_context) { view_context }
|
15
|
+
rdr.call
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Bridgetown.initializer :heartml do |config|
|
22
|
+
Bridgetown::Component.extend ActiveSupport::DescendantsTracker
|
23
|
+
|
24
|
+
Heartml.module_eval do
|
25
|
+
def render_in(view_context, rendering_mode: :string, &block)
|
26
|
+
self.rendering_mode = rendering_mode
|
27
|
+
super(view_context, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Eager load all components
|
32
|
+
config.hook :site, :after_reset do |site|
|
33
|
+
unless site.config.eager_load_paths.find { _1.end_with?(site.config.components_dir) }
|
34
|
+
site.config.eager_load_paths << site.config.autoload_paths.find { _1.end_with?(site.config.components_dir) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
config.html_inspector_parser "nokolexbor"
|
39
|
+
config.builder Heartml::BridgetownRenderer
|
40
|
+
end
|
data/lib/heartml/fragment.rb
CHANGED
@@ -38,21 +38,25 @@ module Heartml
|
|
38
38
|
|
39
39
|
params.each do |param|
|
40
40
|
new_key, v2 = param.split(":").map(&:strip)
|
41
|
+
v2 ||= new_key
|
42
|
+
|
41
43
|
new_attrs[new_key] = @component.evaluate_attribute_expression(attr, v2)
|
42
44
|
end
|
43
45
|
attrs.delete(k)
|
44
46
|
end
|
45
47
|
attrs.merge!(new_attrs)
|
46
48
|
attrs.reject! { |k| k.start_with?("server-") || k.start_with?("iso-") || k.start_with?("host-") }
|
47
|
-
attrs.transform_keys!(
|
49
|
+
attrs.transform_keys! { _1.tr("-", "_").to_sym }
|
48
50
|
|
49
51
|
obj = component.new(**attrs)
|
50
52
|
render_output = if obj.respond_to?(:render_in)
|
51
|
-
obj.render_in(@component.
|
53
|
+
obj.render_in(@component.context, rendering_mode: :node) do
|
52
54
|
process(fragamatize(node.children))
|
53
55
|
end
|
54
56
|
else
|
55
|
-
obj.render_element(
|
57
|
+
obj.render_element(
|
58
|
+
content: process(fragamatize(node.children)), context: @component.context
|
59
|
+
)
|
56
60
|
end
|
57
61
|
|
58
62
|
node.replace(render_output)
|
@@ -78,7 +82,7 @@ module Heartml
|
|
78
82
|
break unless attribute_binding.method.(attribute: attr_node, node: node)
|
79
83
|
end
|
80
84
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
81
|
-
line_segments = [@component.class.heart_module, @component.
|
85
|
+
line_segments = [@component.class.heart_module, @component._line_number_of_node(attr_node)]
|
82
86
|
raise e.class, e.message.lines.first, [line_segments.join(":"), *e.backtrace]
|
83
87
|
end
|
84
88
|
end
|
data/lib/heartml/version.rb
CHANGED
data/lib/heartml.rb
CHANGED
@@ -54,9 +54,13 @@ module Heartml
|
|
54
54
|
klass.attribute_binding "server-unsafe-eval", :_server_replace_binding
|
55
55
|
|
56
56
|
# Don't stomp on a superclass's `content` method
|
57
|
-
|
57
|
+
has_content_method = begin
|
58
|
+
klass.instance_method(:content)
|
59
|
+
rescue NameError
|
60
|
+
false
|
61
|
+
end
|
58
62
|
|
59
|
-
klass.include ContentMethod
|
63
|
+
klass.include ContentMethod unless has_content_method
|
60
64
|
end
|
61
65
|
|
62
66
|
# Extends the component class
|
@@ -124,10 +128,8 @@ module Heartml
|
|
124
128
|
end
|
125
129
|
end
|
126
130
|
|
127
|
-
|
128
|
-
|
129
|
-
instance_variable_get(:@doc_html)[0..loc].count("\n") + 1
|
130
|
-
end
|
131
|
+
# @return [String]
|
132
|
+
def doc_html = @doc_html
|
131
133
|
|
132
134
|
def attribute_bindings = @attribute_bindings ||= []
|
133
135
|
|
@@ -149,6 +151,14 @@ module Heartml
|
|
149
151
|
@_replaced_content = new_content
|
150
152
|
end
|
151
153
|
|
154
|
+
def context
|
155
|
+
return @context if @context
|
156
|
+
|
157
|
+
return unless respond_to?(:view_context)
|
158
|
+
|
159
|
+
view_context # compatibility with other Ruby component systems
|
160
|
+
end
|
161
|
+
|
152
162
|
# Override in component
|
153
163
|
#
|
154
164
|
# @return [Hash]
|
@@ -165,9 +175,11 @@ module Heartml
|
|
165
175
|
|
166
176
|
# @param attributes [Hash]
|
167
177
|
# @param content [String, Nokolexbor::Element]
|
168
|
-
def render_element(attributes: self.attributes, content: self.content) # rubocop:disable Metrics
|
178
|
+
def render_element(attributes: self.attributes, content: self.content, context: self.context) # rubocop:disable Metrics
|
169
179
|
doc = self.class.doc.clone
|
180
|
+
@doc_html ||= self.class.doc_html # keep a spare copy for determining error line number
|
170
181
|
@_content = content
|
182
|
+
@context = context
|
171
183
|
|
172
184
|
tmpl_el = doc.css("> template").find do |node|
|
173
185
|
node.attributes.empty? ||
|
@@ -184,33 +196,6 @@ module Heartml
|
|
184
196
|
# Process all the template bits
|
185
197
|
process_fragment(tmpl_el)
|
186
198
|
|
187
|
-
# Heartml.registered_elements.each do |component|
|
188
|
-
# tmpl_el.children[0].css(component.tag_name).reverse.each do |node|
|
189
|
-
# if node["server-ignore"]
|
190
|
-
# node.remove_attribute("server-ignore")
|
191
|
-
# next
|
192
|
-
# end
|
193
|
-
|
194
|
-
# attrs = node.attributes.transform_values(&:value)
|
195
|
-
# attrs.reject! { |k| k.start_with?("server-") }
|
196
|
-
# new_attrs = {}
|
197
|
-
# attrs.each do |k, v|
|
198
|
-
# next unless k.start_with?("arg:")
|
199
|
-
|
200
|
-
# new_key = k.delete_prefix("arg:")
|
201
|
-
# attrs.delete(k)
|
202
|
-
# new_attrs[new_key] = instance_eval(v, self.class.heart_module, self.class.line_number_of_node(node))
|
203
|
-
# end
|
204
|
-
# attrs.merge!(new_attrs)
|
205
|
-
# attrs.transform_keys!(&:to_sym)
|
206
|
-
|
207
|
-
# new_node = node.replace(
|
208
|
-
# component.new(**attrs).render_element(content: node.children)
|
209
|
-
# )
|
210
|
-
# new_node.remove_attribute("server-ignore")
|
211
|
-
# end
|
212
|
-
# end
|
213
|
-
|
214
199
|
# Set attributes on the custom element
|
215
200
|
attributes.each { |k, v| doc[k.to_s.tr("_", "-")] = value_to_attribute(v) if v }
|
216
201
|
|
@@ -323,7 +308,7 @@ module Heartml
|
|
323
308
|
_context_locals.keys.reverse_each do |name|
|
324
309
|
eval_code = "#{name} = _context_locals[\"#{name}\"];" + eval_code
|
325
310
|
end
|
326
|
-
instance_eval(eval_code, self.class.heart_module,
|
311
|
+
instance_eval(eval_code, self.class.heart_module, _line_number_of_node(attribute))
|
327
312
|
end
|
328
313
|
|
329
314
|
def class_list_for(obj)
|
@@ -338,6 +323,11 @@ module Heartml
|
|
338
323
|
end.join(" ")
|
339
324
|
end
|
340
325
|
|
326
|
+
def _line_number_of_node(node)
|
327
|
+
loc = node.source_location
|
328
|
+
instance_variable_get(:@doc_html)[0..loc].count("\n") + 1
|
329
|
+
end
|
330
|
+
|
341
331
|
def _context_nodes = @_context_nodes ||= []
|
342
332
|
|
343
333
|
def _context_locals = @_context_locals ||= {}
|
@@ -381,26 +371,6 @@ module Heartml
|
|
381
371
|
end
|
382
372
|
end
|
383
373
|
|
384
|
-
# def _server_replace_binding(attribute:, node:)
|
385
|
-
# if node.name == "template"
|
386
|
-
# node.children[0].inner_html = node_or_string(evaluate_attribute_expression(attribute))
|
387
|
-
# node.replace(node.children[0].children)
|
388
|
-
# else
|
389
|
-
# node.inner_html = node_or_string(evaluate_attribute_expression(attribute))
|
390
|
-
# node.replace(node.children)
|
391
|
-
# end
|
392
|
-
# end
|
393
|
-
|
394
|
-
# def _server_expr_binding(attribute:, node:)
|
395
|
-
# if attribute.name.end_with?(":text")
|
396
|
-
# node.content = node_or_string(evaluate_attribute_expression(attribute))
|
397
|
-
# attribute.parent.delete(attribute.name)
|
398
|
-
# elsif attribute.name.end_with?(":html")
|
399
|
-
# node.inner_html = node_or_string(evaluate_attribute_expression(attribute))
|
400
|
-
# attribute.parent.delete(attribute.name)
|
401
|
-
# end
|
402
|
-
# end
|
403
|
-
|
404
374
|
class ServerComponent
|
405
375
|
def self.inherited(klass)
|
406
376
|
super
|
@@ -409,19 +379,15 @@ module Heartml
|
|
409
379
|
end
|
410
380
|
end
|
411
381
|
|
412
|
-
class
|
382
|
+
class TemplateRenderer < ServerComponent
|
413
383
|
def self.heart_module
|
414
384
|
"eval"
|
415
385
|
end
|
416
386
|
|
417
|
-
def
|
418
|
-
|
419
|
-
0
|
420
|
-
end
|
421
|
-
|
422
|
-
def initialize(body:, scope:) # rubocop:disable Lint/MissingSuper
|
387
|
+
def initialize(body:, context:) # rubocop:disable Lint/MissingSuper
|
388
|
+
@doc_html = body.is_a?(String) ? body : body.to_html
|
423
389
|
@body = body.is_a?(String) ? Nokolexbor::DocumentFragment.parse(body) : body
|
424
|
-
@
|
390
|
+
@context = context
|
425
391
|
end
|
426
392
|
|
427
393
|
def call
|
@@ -430,36 +396,14 @@ module Heartml
|
|
430
396
|
end
|
431
397
|
|
432
398
|
def respond_to_missing?(key)
|
433
|
-
|
399
|
+
context.respond_to?(key)
|
434
400
|
end
|
435
401
|
|
436
402
|
# TODO: delegate instead?
|
437
403
|
def method_missing(key, *args, **kwargs)
|
438
|
-
|
404
|
+
context.send(key, *args, **kwargs)
|
439
405
|
end
|
440
406
|
end
|
441
407
|
end
|
442
408
|
|
443
|
-
if defined?(Bridgetown)
|
444
|
-
Bridgetown.initializer :heartml do |config|
|
445
|
-
Bridgetown::Component.extend ActiveSupport::DescendantsTracker
|
446
|
-
|
447
|
-
Heartml.module_eval do
|
448
|
-
def render_in(view_context, rendering_mode = :string, &block)
|
449
|
-
self.rendering_mode = rendering_mode
|
450
|
-
super(view_context, &block)
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
# Eager load all components
|
455
|
-
config.hook :site, :after_reset do |site|
|
456
|
-
unless site.config.eager_load_paths.find { _1.end_with?(site.config.components_dir) }
|
457
|
-
site.config.eager_load_paths << site.config.autoload_paths.find { _1.end_with?(site.config.components_dir) }
|
458
|
-
end
|
459
|
-
end
|
460
|
-
|
461
|
-
config.html_inspector_parser "nokolexbor"
|
462
|
-
require_relative "heartml/component_renderer"
|
463
|
-
config.builder Heartml::ComponentRenderer
|
464
|
-
end
|
465
|
-
end
|
409
|
+
require_relative "heartml/bridgetown_renderer" if defined?(Bridgetown)
|
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.
|
4
|
+
version: 1.0.0.beta5
|
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-
|
11
|
+
date: 2023-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -70,7 +70,7 @@ files:
|
|
70
70
|
- benchmark.rb
|
71
71
|
- heartml.gemspec
|
72
72
|
- lib/heartml.rb
|
73
|
-
- lib/heartml/
|
73
|
+
- lib/heartml/bridgetown_renderer.rb
|
74
74
|
- lib/heartml/fragment.rb
|
75
75
|
- lib/heartml/petite.rb
|
76
76
|
- lib/heartml/query_selection.rb
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Heartml
|
4
|
-
class ComponentRenderer < Bridgetown::Builder
|
5
|
-
def build
|
6
|
-
render_heart_modules
|
7
|
-
end
|
8
|
-
|
9
|
-
# TODO: rework this using new server effects and component context!
|
10
|
-
def render_heart_modules
|
11
|
-
inspect_html do |doc, resource|
|
12
|
-
view_context = Bridgetown::ERBView.new(resource)
|
13
|
-
|
14
|
-
rdr = FragmentRenderComponent.new(body: doc.at_css("body"), scope: view_context)
|
15
|
-
rdr.define_singleton_method(:view_context) { view_context }
|
16
|
-
rdr.call
|
17
|
-
|
18
|
-
# Heartml.registered_elements.each do |component|
|
19
|
-
# tag_name = component.tag_name
|
20
|
-
# doc.xpath("//#{tag_name}").reverse.each do |node|
|
21
|
-
# if node["server-ignore"]
|
22
|
-
# node.remove_attribute("server-ignore")
|
23
|
-
# next
|
24
|
-
# end
|
25
|
-
|
26
|
-
# attrs = node.attributes.transform_values(&:value)
|
27
|
-
# attrs.reject! { |k| k.start_with?("server-") }
|
28
|
-
|
29
|
-
# new_attrs = {}
|
30
|
-
# attrs.each do |k, v|
|
31
|
-
# next unless k.start_with?("arg:")
|
32
|
-
|
33
|
-
# new_key = k.delete_prefix("arg:")
|
34
|
-
# attrs.delete(k)
|
35
|
-
# new_attrs[new_key] = resource.instance_eval(v)
|
36
|
-
# end
|
37
|
-
# attrs.merge!(new_attrs)
|
38
|
-
# attrs.transform_keys!(&:to_sym)
|
39
|
-
|
40
|
-
# new_node = node.replace(
|
41
|
-
# component.new(**attrs).render_in(view_context, rendering_mode: :node) { node.children }
|
42
|
-
# )
|
43
|
-
# new_node.remove_attribute("server-ignore")
|
44
|
-
# end
|
45
|
-
# rescue StandardError => e
|
46
|
-
# Bridgetown.logger.error "Unable to render <#{tag_name}> (#{component}) in #{resource.path}"
|
47
|
-
# raise e
|
48
|
-
# end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|