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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33b3883d286639fd0120ce59444d69f5a69a77fff208d5fcc057338210bcde4d
4
- data.tar.gz: a385e62cf6d4232ba5ede351c4a0c6e885bd7260ea35afff78ee35eaf7449fee
3
+ metadata.gz: 6b5bbe4c65f744b46c84b6fb6949994e9ebe78301f6e73fcb0ce91590d37a128
4
+ data.tar.gz: acfe3bf54d39db1737d5a46a86c9aabfd06437c2287b13bbe1b59634049acdae
5
5
  SHA512:
6
- metadata.gz: 4da9a2ac04771a7f7024caf8f2db678f6459a54f7090513a2a00402e6ec65626ed61a90abdf314219ace4a310d6d87eaafb65f97a6c1994b0fdf5861897bb051
7
- data.tar.gz: d19f2e2285950719c5456087e6eff9f27577da175257ec8ec58cecd0188ee57690934d0e3f06c2156f1dc5e4828857284d0fdf0b0ab051c2af9441c89cbc6de0
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- heartml (1.0.0.beta16)
4
+ heartml (1.0.0.beta18)
5
5
  concurrent-ruby (~> 1.2)
6
6
  nokolexbor (>= 0.4.2)
7
7
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Heartml: Ruby (WIP)
1
+ # Heartml: Ruby Web Components (WIP)
2
2
 
3
- Server-rendered web components 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 web component library written in JavaScript.
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/hotmodule/esbuild-plugin-html-modules) for a full-stack component rendering pipeline.
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)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Heartml
4
4
  # @return [String]
5
- VERSION = "1.0.0.beta16"
5
+ VERSION = "1.0.0.beta18"
6
6
  end
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 "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
+ 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].start_with?("data-") })
193
+ (node.attributes.count == 1 && node.attributes.any? { |k| k[0] == "data-ssr-only" })
198
194
  end
199
195
 
200
- unless tmpl_el
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 external and internal styles
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:not([name])")&.swap(child_content) if child_content
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 _server_children(attribute:, node:) # rubocop:disable Lint/UnusedMethodArgument
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.beta16
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-10-26 00:00:00.000000000 Z
11
+ date: 2024-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby