heartml 1.0.0.beta16 → 1.0.0.beta18
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 +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +3 -3
- data/lib/heartml/server_effects.rb +15 -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
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [1.0.0.beta18] — 2024-11-27
|
6
|
+
|
7
|
+
- Simplifications and improvements to server directive syntax and CSS handling [#1]
|
8
|
+
|
9
|
+
## [1.0.0.beta17] — 2024-10-27
|
10
|
+
|
11
|
+
- Add `.` effect shortcut for `@textContent = .`
|
12
|
+
|
5
13
|
## [1.0.0.beta16] — 2024-10-26
|
6
14
|
|
7
15
|
- Fix rendering logic in Bridgetown 2.0 beta
|
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
|
|
@@ -71,6 +81,11 @@ module Heartml
|
|
71
81
|
statements = syntax.split(";").map(&:strip)
|
72
82
|
|
73
83
|
statements.each do |statement| # rubocop:disable Metrics
|
84
|
+
if statement.start_with?(".")
|
85
|
+
# shortcut for text content
|
86
|
+
statement = "@textContent=#{statement}"
|
87
|
+
end
|
88
|
+
|
74
89
|
if statement.start_with?("@")
|
75
90
|
# property assignment
|
76
91
|
expression = statement.split("=").map(&:strip)
|
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
|