heartml 1.0.0.beta17 → 1.0.0.beta18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +3 -3
- data/lib/heartml/server_effects.rb +10 -0
- data/lib/heartml/version.rb +1 -1
- data/lib/heartml.rb +15 -47
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b5bbe4c65f744b46c84b6fb6949994e9ebe78301f6e73fcb0ce91590d37a128
|
4
|
+
data.tar.gz: acfe3bf54d39db1737d5a46a86c9aabfd06437c2287b13bbe1b59634049acdae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddca7cfd38b3ddb634a3791cfbf4fb0425a24f222f58139a5d5f67388503f0afb0654a1c663f600b1fe1eeb64affe71a9d60f9ea047001486baf580e38cdedc3
|
7
|
+
data.tar.gz: 0ae6a4dd6e06c6e3bf6fb4ec9eafe482d76fea77b346a6493f96a7f6b39cad06a7e2774b8c8457cca438c58914bf1ce86d91f53bf17fbb0e9aea225fc7895edc
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# Heartml: Ruby (WIP)
|
1
|
+
# Heartml: Ruby Web Components (WIP)
|
2
2
|
|
3
|
-
Server-rendered
|
3
|
+
Server-rendered custom elements in Ruby using a SFC (Single-File Component) format loosely based on [HTML Modules](https://github.com/WICG/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md). Logic on the server-side is analogous to client-side logic provided by the [Heartml JavaScript library](https://github.com/heartml/heartml).
|
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/whitefusionhq/esbuild-plugin-html-modules) for a full-stack component rendering pipeline.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -58,6 +58,16 @@ module Heartml
|
|
58
58
|
directive :attribute, ->(_, node, name, value) {
|
59
59
|
node[name] = value if name.match?(%r{^aria[A-Z-]}) || value
|
60
60
|
}
|
61
|
+
|
62
|
+
directive :appendUnsafe, ->(_, node, value) {
|
63
|
+
node.swap(value.is_a?(Nokolexbor::Node) ? value : value.to_s)
|
64
|
+
}
|
65
|
+
|
66
|
+
directive :append, ->(_, node, value) {
|
67
|
+
span = node.document.create_element("span")
|
68
|
+
span.content = value.to_s
|
69
|
+
node.swap(span.inner_html)
|
70
|
+
}
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
data/lib/heartml/version.rb
CHANGED
data/lib/heartml.rb
CHANGED
@@ -52,9 +52,7 @@ module Heartml
|
|
52
52
|
def self.included(klass)
|
53
53
|
klass.extend ClassMethods
|
54
54
|
|
55
|
-
klass.attribute_binding "
|
56
|
-
klass.attribute_binding "server-content", :_server_content, only: :template
|
57
|
-
klass.attribute_binding "server-unsafe-eval", :_server_unsafe_eval
|
55
|
+
klass.attribute_binding "hl-content", :_server_content, only: :template
|
58
56
|
|
59
57
|
# Don't stomp on a superclass's `content` method
|
60
58
|
has_content_method = begin
|
@@ -82,8 +80,6 @@ module Heartml
|
|
82
80
|
|
83
81
|
def html_file_extensions = %w[module.html mod.html heartml].freeze
|
84
82
|
|
85
|
-
def processed_css_extension = "css-local"
|
86
|
-
|
87
83
|
# @param tag_name [String]
|
88
84
|
# @param heart_module [String] if not provided, a class method called `source_location` must be
|
89
85
|
# available with the absolute path of the Ruby file
|
@@ -194,13 +190,20 @@ module Heartml
|
|
194
190
|
|
195
191
|
tmpl_el = doc.css("> template").find do |node|
|
196
192
|
node.attributes.empty? ||
|
197
|
-
(node.attributes.count == 1 && node.attributes.any? { |k| k[0]
|
193
|
+
(node.attributes.count == 1 && node.attributes.any? { |k| k[0] == "data-ssr-only" })
|
198
194
|
end
|
199
195
|
|
200
|
-
|
196
|
+
if tmpl_el
|
197
|
+
# Hoist light DOM children templates, if need be
|
198
|
+
doc.css("> template[hl-content]").each do |node|
|
199
|
+
tmpl_el.children[0] << node
|
200
|
+
end
|
201
|
+
else
|
202
|
+
# No top-level template, so we create one
|
201
203
|
tmpl_el = doc.document.create_element("template")
|
202
204
|
immediate_children = doc.css("> :not(style):not(script)")
|
203
205
|
tmpl_el.children[0] << immediate_children
|
206
|
+
tmpl_el.children[0] << doc.css("> style[server-effect]")
|
204
207
|
doc.prepend_child(tmpl_el)
|
205
208
|
end
|
206
209
|
|
@@ -210,26 +213,8 @@ module Heartml
|
|
210
213
|
# Set attributes on the custom element
|
211
214
|
attributes.each { |k, v| doc[k.to_s.tr("_", "-")] = value_to_attribute(v) if v }
|
212
215
|
|
213
|
-
# Look for
|
214
|
-
output_styles = ""
|
215
|
-
external_styles = doc.css("link[rel=stylesheet]")
|
216
|
-
external_styles.each do |external_style|
|
217
|
-
next unless external_style["server-process"]
|
218
|
-
|
219
|
-
output_styles += File.read(File.expand_path(external_style["href"], File.dirname(self.class.heart_module)))
|
220
|
-
external_style.remove
|
221
|
-
rescue StandardError => e
|
222
|
-
raise e.class, e.message.lines.first,
|
223
|
-
["#{self.class.heart_module}:#{external_style.line}", *e.backtrace]
|
224
|
-
end
|
225
|
-
sidecar_file = "#{File.join(
|
226
|
-
File.dirname(self.class.heart_module), File.basename(self.class.heart_module, ".*")
|
227
|
-
)}.#{self.class.processed_css_extension}"
|
228
|
-
output_styles += if File.exist?(sidecar_file)
|
229
|
-
File.read(sidecar_file)
|
230
|
-
else
|
231
|
-
doc.css("> style:not([scope])").map(&:content).join
|
232
|
-
end
|
216
|
+
# Look for internal styles
|
217
|
+
output_styles = doc.css("> style:not([scope])").map(&:content).join
|
233
218
|
|
234
219
|
# Now remove all nodes *except* the template
|
235
220
|
doc.children.each do |node|
|
@@ -248,10 +233,11 @@ module Heartml
|
|
248
233
|
# Guess what? We can reuse the same template tag! =)
|
249
234
|
tmpl_el["shadowrootmode"] = "open"
|
250
235
|
tmpl_el.children[0] << style_tag if style_tag
|
236
|
+
child_content.at_css("hl-slot")&.swap(content) if @_replaced_content.is_a?(Nokolexbor::Node) && content
|
251
237
|
doc << child_content if child_content
|
252
238
|
else
|
253
239
|
tmpl_el.children[0] << style_tag if style_tag
|
254
|
-
tmpl_el.children[0].at_css("slot
|
240
|
+
tmpl_el.children[0].at_css("hl-slot")&.swap(child_content) if child_content
|
255
241
|
tmpl_el.children[0].children.each do |node|
|
256
242
|
doc << node
|
257
243
|
end
|
@@ -376,28 +362,10 @@ module Heartml
|
|
376
362
|
@_context_locals = previous_context
|
377
363
|
end
|
378
364
|
|
379
|
-
def
|
365
|
+
def _server_content(attribute:, node:) # rubocop:disable Lint/UnusedMethodArgument
|
380
366
|
self.replaced_content = node.children[0]
|
381
367
|
node.remove
|
382
368
|
end
|
383
|
-
|
384
|
-
def _server_unsafe_eval(attribute:, node:)
|
385
|
-
node_name = node.name
|
386
|
-
correct_node = node_name == "template" ? node.children[0] : node
|
387
|
-
result = node_or_string(evaluate_attribute_expression(attribute, correct_node.inner_html))
|
388
|
-
|
389
|
-
if node_name == "template"
|
390
|
-
node.swap(result)
|
391
|
-
else
|
392
|
-
node.inner_html = result
|
393
|
-
attribute.parent.delete(attribute.name)
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
def _server_content(attribute:, node:)
|
398
|
-
result = evaluate_attribute_expression(attribute, "content")
|
399
|
-
node.swap(result)
|
400
|
-
end
|
401
369
|
end
|
402
370
|
|
403
371
|
require_relative "heartml/template_renderer"
|
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.beta18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jared White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|