glimmer-dsl-web 0.2.2 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +182 -151
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +22 -22
- data/lib/glimmer/dsl/web/dsl.rb +1 -3
- data/lib/glimmer/dsl/web/element_expression.rb +5 -1
- data/lib/glimmer/dsl/web/span_expression.rb +17 -0
- data/lib/glimmer/web/component.rb +9 -4
- data/lib/glimmer/web/element_proxy.rb +6 -0
- data/lib/glimmer/web/formatting_element_proxy.rb +1 -1
- data/lib/glimmer-dsl-web/ext/kernel.rb +42 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_component.rb +2 -2
- data/lib/glimmer-dsl-web.rb +1 -0
- metadata +18 -14
- data/lib/glimmer/dsl/web/p_expression.rb +0 -12
- data/lib/glimmer/dsl/web/select_expression.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 212cee9f2c87b145cca85b47395f541a749d0a472560a946c1f3b0061ec7b801
|
4
|
+
data.tar.gz: f7cccb64081e75018c6e043e021b071d70c7b2696057a32e25b191fb2c3dd4f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e590b30b6f3d54f859e168bd7220cfa51e8d3f2354836fb851ab20c21114518ddd2a502a74a262b704148561e64b65a07cbd2ed61593914a274fa7542da8e1c9
|
7
|
+
data.tar.gz: 1a334ce05e730c2eef25005d5a1a9d16683b639fac910e83ba0ceff88c380230df884486f994140bce11a68e10210ff1a28266604560ecaa134859b621402cf2
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.2.4
|
4
|
+
|
5
|
+
- Enhance `Kernel#puts` & `Kernel#p` to enable printing any native JS object with `console.log` (without having to manually wrap with `Native`)
|
6
|
+
- Support Content Data-Binding from inside a `Glimmer::Web::Component`
|
7
|
+
|
8
|
+
## 0.2.3
|
9
|
+
|
10
|
+
- Ensure that setting `element.class_name=classnameval` does not override its Glimmer built-in CSS classes
|
11
|
+
- Alias `Kernel#p` as `Kernel#pi` (puts inspect) to allow using `pi` in place of `p` for printing inspected objects given that `p` is used up by the HTML DSL.
|
12
|
+
- Remove `element` from dynamic part of Glimmer DSL to allow it to fail faster if an invalid HTML element name was used
|
13
|
+
- Fix use of `span` keyword under `p`, fixing Hello, Paragraph! sample.
|
14
|
+
|
3
15
|
## 0.2.2
|
4
16
|
|
5
17
|
- Fix bug in content data-binding that was caused by recent performance optimizations (+ fix Hello, Content Data-Binding! sample)
|
data/README.md
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.2.
|
2
|
-
## Ruby in the Browser Web
|
1
|
+
# [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.2.4 (Beta)
|
2
|
+
## Ruby in the Browser Web Frontend Framework
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-web.svg)](http://badge.fury.io/rb/glimmer-dsl-web)
|
4
4
|
[![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
5
|
|
6
|
-
[Glimmer](https://github.com/AndyObtiva/glimmer)
|
6
|
+
**(Based on Original [Glimmer](https://github.com/AndyObtiva/glimmer) Library Handling World’s Ruby GUI Needs Since 2007. Beware of Imitators!)**
|
7
|
+
|
8
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web Frontends using [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), as per [Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby](https://youtu.be/knutsgHTrfQ?t=789). It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with [DSLs](https://martinfowler.com/books/dsl.html) and [TIMTOWTDI](https://en.wiktionary.org/wiki/TMTOWTDI#English)) and the Rails way ([Convention over Configuration](https://rubyonrails.org/doctrine)) in building Isomorphic Ruby on Rails Applications. It provides a Ruby [HTML DSL](#usage), which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) [Data-Binding](#hello-data-binding) (using `<=`) and Bidirectional (Two-Way) [Data-Binding](#hello-data-binding) (using `<=>`). Dynamic rendering (and re-rendering) of HTML content is also supported via [Content Data-Binding](#hello-content-data-binding). And, modular design is supported with [Glimmer Web Components](#hello-component). Many [samples](#samples) are demonstrated in the [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) (there is a very minimal [Standalone [No Rails] sample app](https://github.com/Largo/glimmer-dsl-web-standalone-demo) too). You can finally live in pure Rubyland on the Web in both the frontend and backend with [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web)!
|
7
9
|
|
8
10
|
**Hello, World! Sample**
|
9
11
|
|
10
|
-
Glimmer
|
12
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
11
13
|
|
12
14
|
```ruby
|
13
15
|
require 'glimmer-dsl-web'
|
@@ -31,11 +33,13 @@ That produces the following under `<body></body>`:
|
|
31
33
|
|
32
34
|
![setup is working](/images/glimmer-dsl-web-setup-example-working.png)
|
33
35
|
|
36
|
+
You can also mount the `div` elsewhere by passing the `parent: parent_css_selector` option (e.g. `div(parent: 'div#app-container') { 'Hello, World!' }`).
|
37
|
+
|
34
38
|
**Hello, Button!**
|
35
39
|
|
36
|
-
Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to
|
40
|
+
Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to JS global scope from Ruby to invoke functions like `alert`.
|
37
41
|
|
38
|
-
Glimmer
|
42
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
39
43
|
|
40
44
|
```ruby
|
41
45
|
require 'glimmer-dsl-web'
|
@@ -67,9 +71,9 @@ Screenshot:
|
|
67
71
|
|
68
72
|
**Hello, Form!**
|
69
73
|
|
70
|
-
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby
|
74
|
+
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby HTML DSL. Also, you can apply CSS styles by including directly in Ruby code as a string, using [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css), or managing CSS completely separately using something like [SCSS](https://sass-lang.com/). The CSS techniques could be combined as well, like by managing common reusable CSS styles separately in SCSS, but adding component specific CSS styles in Ruby when it is more convenient.
|
71
75
|
|
72
|
-
Glimmer
|
76
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
73
77
|
|
74
78
|
```ruby
|
75
79
|
require 'glimmer-dsl-web'
|
@@ -221,95 +225,11 @@ Screenshot:
|
|
221
225
|
|
222
226
|
![Hello, Form!](/images/glimmer-dsl-web-samples-hello-hello-form.gif)
|
223
227
|
|
224
|
-
**Hello, Observer!**
|
225
|
-
|
226
|
-
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) provides the `observe(model, attribute) { ... }` keyword to employ the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) as per [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (Model View Controller), enabling Views to observe Models and update themselves in response to changes. If the `observe` keyword is used from inside a [Component](#hello-component) (covered later), when the Component is removed or its top-level element is removed, the observer is automatically cleaned up. The need for such explicit observers is significantly diminished by the availablility of the more advanced Unidirectional [Data-Binding](#hello-data-binding) Support and Bidirectional [Data-Binding](#hello-data-binding) Support (covered later).
|
227
|
-
|
228
|
-
Glimmer GUI code:
|
229
|
-
|
230
|
-
```ruby
|
231
|
-
require 'glimmer-dsl-web'
|
232
|
-
|
233
|
-
class NumberHolder
|
234
|
-
attr_accessor :number
|
235
|
-
|
236
|
-
def initialize
|
237
|
-
self.number = 50
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
class HelloObserver
|
242
|
-
include Glimmer::Web::Component
|
243
|
-
|
244
|
-
before_render do
|
245
|
-
@number_holder = NumberHolder.new
|
246
|
-
end
|
247
|
-
|
248
|
-
after_render do
|
249
|
-
@number_input.value = @number_holder.number
|
250
|
-
@range_input.value = @number_holder.number
|
251
|
-
# Observe Model attribute @number_holder.number for changes and update View
|
252
|
-
# Observer is automatically cleaned up if remove method is called on rendered HelloObserver
|
253
|
-
# or its top-level element
|
254
|
-
observe(@number_holder, :number) do
|
255
|
-
number_string = @number_holder.number.to_s
|
256
|
-
@number_input.value = number_string unless @number_input.value == number_string
|
257
|
-
@range_input.value = number_string unless @range_input.value == number_string
|
258
|
-
end
|
259
|
-
# Bidirectional Data-Binding does the same thing automatically
|
260
|
-
# Just disable the observe block above as well as the oninput listeners below
|
261
|
-
# and enable the `value <=> [@number_holder, :number]` lines to try the data-binding version
|
262
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
263
|
-
end
|
264
|
-
|
265
|
-
markup {
|
266
|
-
div {
|
267
|
-
div {
|
268
|
-
@number_input = input(type: 'number', min: 0, max: 100) {
|
269
|
-
# oninput listener updates Model attribute @number_holder.number
|
270
|
-
oninput do
|
271
|
-
@number_holder.number = @number_input.value.to_i
|
272
|
-
end
|
273
|
-
|
274
|
-
# Bidirectional Data-Binding simplifies the implementation significantly
|
275
|
-
# by enabling the following line and disabling oninput listeners as well
|
276
|
-
# as the after_body observe block observer
|
277
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
278
|
-
# value <=> [@number_holder, :number]
|
279
|
-
}
|
280
|
-
}
|
281
|
-
div {
|
282
|
-
@range_input = input(type: 'range', min: 0, max: 100) {
|
283
|
-
# oninput listener updates Model attribute @number_holder.number
|
284
|
-
oninput do
|
285
|
-
@number_holder.number = @range_input.value.to_i
|
286
|
-
end
|
287
|
-
|
288
|
-
# Bidirectional Data-Binding simplifies the implementation significantly
|
289
|
-
# by enabling the following line and disabling oninput listeners as well
|
290
|
-
# as the after_body observe block observer
|
291
|
-
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
292
|
-
# value <=> [@number_holder, :number]
|
293
|
-
}
|
294
|
-
}
|
295
|
-
}
|
296
|
-
}
|
297
|
-
end
|
298
|
-
|
299
|
-
Document.ready? do
|
300
|
-
HelloObserver.render
|
301
|
-
end
|
302
|
-
```
|
303
|
-
|
304
|
-
Screenshot:
|
305
|
-
|
306
|
-
![Hello, Observer!](/images/glimmer-dsl-web-samples-hello-hello-observer.gif)
|
307
|
-
|
308
228
|
**Hello, Data-Binding!**
|
309
229
|
|
310
230
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) intuitively supports both Unidirectional (One-Way) Data-Binding via the `<=` operator and Bidirectional (Two-Way) Data-Binding via the `<=>` operator, incredibly simplifying how to sync View properties with Model attributes with the simplest code to reason about.
|
311
231
|
|
312
|
-
Glimmer
|
232
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
313
233
|
|
314
234
|
```ruby
|
315
235
|
require 'glimmer-dsl-web'
|
@@ -428,7 +348,7 @@ If you need to regenerate HTML element content dynamically, you can use Content
|
|
428
348
|
rebuild HTML elements based on changes in a Model attribute that provides the source data.
|
429
349
|
In this example, we generate multiple address forms based on the number of addresses the user has.
|
430
350
|
|
431
|
-
Glimmer
|
351
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
432
352
|
|
433
353
|
```ruby
|
434
354
|
require 'glimmer-dsl-web'
|
@@ -559,13 +479,15 @@ Screenshot:
|
|
559
479
|
|
560
480
|
You can define Glimmer web components (View components) to reuse visual concepts to your heart's content,
|
561
481
|
by simply defining a class with `include Glimmer::Web::Component` and encasing the reusable markup inside
|
562
|
-
a `markup {...}` block. Glimmer web components automatically extend the Glimmer
|
563
|
-
that match the underscored versions of the component class names (e.g.
|
564
|
-
the `order_summary` keyword for reusing that component within the Glimmer
|
565
|
-
|
482
|
+
a `markup {...}` block. Glimmer web components automatically extend the Glimmer HTML DSL with new keywords
|
483
|
+
that match the underscored versions of the component class names (e.g. an `OrderSummary` class yields
|
484
|
+
the `order_summary` keyword for reusing that component within the Glimmer HTML DSL).
|
485
|
+
You may insert a Glimmer component anywhere into a Rails View using `glimmer_component(component_path, *args)`
|
486
|
+
Rails helper (more about it in [Hello, glimmer_component Rails Helper!](#hello-glimmer_component-rails-helper)).
|
487
|
+
Below, we define an `AddressForm` component that generates an `address_form` keyword, and then we
|
566
488
|
reuse it twice inside an `AddressPage` component displaying a Shipping Address and a Billing Address.
|
567
489
|
|
568
|
-
Glimmer
|
490
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
569
491
|
|
570
492
|
```ruby
|
571
493
|
require 'glimmer-dsl-web'
|
@@ -645,9 +567,9 @@ end
|
|
645
567
|
# AddressForm Glimmer Web Component (View component)
|
646
568
|
#
|
647
569
|
# Including Glimmer::Web::Component makes this class a View component and automatically
|
648
|
-
# generates a new Glimmer
|
570
|
+
# generates a new Glimmer HTML DSL keyword that matches the lowercase underscored version
|
649
571
|
# of the name of the class. AddressForm generates address_form keyword, which can be used
|
650
|
-
# elsewhere in Glimmer
|
572
|
+
# elsewhere in Glimmer HTML DSL code as done inside AddressPage below.
|
651
573
|
class AddressForm
|
652
574
|
include Glimmer::Web::Component
|
653
575
|
|
@@ -814,7 +736,7 @@ Rails View code:
|
|
814
736
|
</div>
|
815
737
|
```
|
816
738
|
|
817
|
-
Glimmer
|
739
|
+
Glimmer HTML DSL Ruby code in the frontend (`app/assets/opal/address_form.rb`):
|
818
740
|
|
819
741
|
```ruby
|
820
742
|
require 'glimmer-dsl-web'
|
@@ -979,9 +901,9 @@ Screenshot:
|
|
979
901
|
|
980
902
|
**Hello, Paragraph!**
|
981
903
|
|
982
|
-
To facilitate building formatted textual paragraphs in Ruby, the Glimmer
|
904
|
+
To facilitate building formatted textual paragraphs in Ruby, thanks to [Glimmer](https://github.com/AndyObtiva/glimmer#dsl-engine), the most advanced DSL engine in Ruby, the Glimmer HTML DSL is advanced enough to intelligently behave differently under different situations, like when using HTML formatting elements: `<br>`, `<strong>`, `<em>`, `<br>`, `<i>`, `<sub>`, `<sup>`, `<del>`, `<ins>`, `<small>`, `<mark>`
|
983
905
|
|
984
|
-
Instead of returning Ruby objects that are nested as children within their parent, the Glimmer
|
906
|
+
Instead of returning Ruby objects that are nested as children within their parent, the Glimmer HTML DSL returns `String` objects directly that can be concatenated to or embedded within other `String` objects via interpolation.
|
985
907
|
|
986
908
|
This enables writing code like:
|
987
909
|
|
@@ -1009,9 +931,9 @@ it returns a `String` to enable code like this:
|
|
1009
931
|
|
1010
932
|
`p {"#{span('Yesterday, ', style: 'text-decoration: underline;')}Robert suggested adding a new #{em('feature', class: 'very-emphasized')} to our software product.#{br}}`
|
1011
933
|
|
1012
|
-
In any case, below is a full example leveraging the Glimmer
|
934
|
+
In any case, below is a full example leveraging the Glimmer HTML DSL alternative approach when utilizing formatting elements underneath a paragraph.
|
1013
935
|
|
1014
|
-
Glimmer
|
936
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1015
937
|
|
1016
938
|
```ruby
|
1017
939
|
require 'glimmer-dsl-web'
|
@@ -1068,6 +990,92 @@ Screenshot:
|
|
1068
990
|
|
1069
991
|
![Hello, Paragraph!](/images/glimmer-dsl-web-samples-hello-hello-paragraph.png)
|
1070
992
|
|
993
|
+
**Hello, Observer!**
|
994
|
+
|
995
|
+
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) provides the `observe(model, attribute) { ... }` keyword to employ the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) as per [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (Model View Controller), enabling Views to observe Models and update themselves in response to changes. If the `observe` keyword is used from inside a [Component](#hello-component), when the Component is removed or its top-level element is removed, the observer is automatically cleaned up. The need for such explicit observers is significantly diminished by the availablility of the more advanced Unidirectional [Data-Binding](#hello-data-binding) Support and Bidirectional [Data-Binding](#hello-data-binding) Support.
|
996
|
+
|
997
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
998
|
+
|
999
|
+
```ruby
|
1000
|
+
require 'glimmer-dsl-web'
|
1001
|
+
|
1002
|
+
class NumberHolder
|
1003
|
+
attr_accessor :number
|
1004
|
+
|
1005
|
+
def initialize
|
1006
|
+
self.number = 50
|
1007
|
+
end
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
class HelloObserver
|
1011
|
+
include Glimmer::Web::Component
|
1012
|
+
|
1013
|
+
before_render do
|
1014
|
+
@number_holder = NumberHolder.new
|
1015
|
+
end
|
1016
|
+
|
1017
|
+
after_render do
|
1018
|
+
@number_input.value = @number_holder.number
|
1019
|
+
@range_input.value = @number_holder.number
|
1020
|
+
# Observe Model attribute @number_holder.number for changes and update View
|
1021
|
+
# Observer is automatically cleaned up if remove method is called on rendered HelloObserver
|
1022
|
+
# or its top-level element
|
1023
|
+
observe(@number_holder, :number) do
|
1024
|
+
number_string = @number_holder.number.to_s
|
1025
|
+
@number_input.value = number_string unless @number_input.value == number_string
|
1026
|
+
@range_input.value = number_string unless @range_input.value == number_string
|
1027
|
+
end
|
1028
|
+
# Bidirectional Data-Binding does the same thing automatically
|
1029
|
+
# Just disable the observe block above as well as the oninput listeners below
|
1030
|
+
# and enable the `value <=> [@number_holder, :number]` lines to try the data-binding version
|
1031
|
+
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
markup {
|
1035
|
+
div {
|
1036
|
+
div {
|
1037
|
+
@number_input = input(type: 'number', min: 0, max: 100) {
|
1038
|
+
# oninput listener updates Model attribute @number_holder.number
|
1039
|
+
oninput do
|
1040
|
+
@number_holder.number = @number_input.value.to_i
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
# Bidirectional Data-Binding simplifies the implementation significantly
|
1044
|
+
# by enabling the following line and disabling oninput listeners as well
|
1045
|
+
# as the after_body observe block observer
|
1046
|
+
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
1047
|
+
# value <=> [@number_holder, :number]
|
1048
|
+
}
|
1049
|
+
}
|
1050
|
+
div {
|
1051
|
+
@range_input = input(type: 'range', min: 0, max: 100) {
|
1052
|
+
# oninput listener updates Model attribute @number_holder.number
|
1053
|
+
oninput do
|
1054
|
+
@number_holder.number = @range_input.value.to_i
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
# Bidirectional Data-Binding simplifies the implementation significantly
|
1058
|
+
# by enabling the following line and disabling oninput listeners as well
|
1059
|
+
# as the after_body observe block observer
|
1060
|
+
# Learn more about Bidirectional and Unidirectional Data-Binding in hello_data_binding.rb
|
1061
|
+
# value <=> [@number_holder, :number]
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
Document.ready? do
|
1069
|
+
HelloObserver.render
|
1070
|
+
end
|
1071
|
+
```
|
1072
|
+
|
1073
|
+
Screenshot:
|
1074
|
+
|
1075
|
+
![Hello, Observer!](/images/glimmer-dsl-web-samples-hello-hello-observer.gif)
|
1076
|
+
|
1077
|
+
To get started, [Setup](#setup) Ruby gem, read [Usage](#usage) instructions, and check out more [Samples](#samples) (including playing around with a [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app)).
|
1078
|
+
|
1071
1079
|
--
|
1072
1080
|
|
1073
1081
|
NOTE: Glimmer DSL for Web is a Beta project. If you want it developed faster, please [open an issue report](https://github.com/AndyObtiva/glimmer-dsl-web/issues/new). I have completed some GitHub project features much faster before due to [issue reports](https://github.com/AndyObtiva/glimmer-dsl-web/issues) and [pull requests](https://github.com/AndyObtiva/glimmer-dsl-web/pulls). Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still a Beta, so the more feedback and issues you report the better.
|
@@ -1081,6 +1089,9 @@ Learn more about the differences between various [Glimmer](https://github.com/An
|
|
1081
1089
|
- [Glimmer DSL for Web](#)
|
1082
1090
|
- [Prerequisites](#prerequisites)
|
1083
1091
|
- [Setup](#setup)
|
1092
|
+
- [Rails 7](#rails-7)
|
1093
|
+
- [Rails 6](#rails-6)
|
1094
|
+
- [Standalone (No Rails)](#standalone-no-rails)
|
1084
1095
|
- [Usage](#usage)
|
1085
1096
|
- [Supported Glimmer DSL Keywords](#supported-glimmer-dsl-keywords)
|
1086
1097
|
- [Coming from Glimmer DSL for Opal](#coming-from-glimmer-dsl-for-opal)
|
@@ -1114,17 +1125,17 @@ Learn more about the differences between various [Glimmer](https://github.com/An
|
|
1114
1125
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) will begin by supporting [Opal Ruby](https://opalrb.com/) on [Rails](https://rubyonrails.org/). [Opal](https://opalrb.com/) is a lightweight Ruby to JavaScript transpiler that results in small downloadables compared to WASM. In the future, the project might grow to support [Ruby WASM](https://github.com/ruby/ruby.wasm) as an alternative to [Opal Ruby](https://opalrb.com/) that could be switched to with a simple configuration change.
|
1115
1126
|
|
1116
1127
|
- Ruby 3.0+
|
1117
|
-
- Rails
|
1128
|
+
- Rails 7: [https://github.com/rails/rails](https://github.com/rails/rails)
|
1118
1129
|
|
1119
1130
|
## Setup
|
1120
1131
|
|
1121
|
-
|
1132
|
+
You can setup Glimmer DSL for Web in [Rails 7](#rails-7), [Rails 6](#rails-6), or [Standalone (No Rails)](#standalone-no-rails).
|
1122
1133
|
|
1123
|
-
|
1134
|
+
(NOTE: Keep in mind this is a Beta. If you run into issues, try to go back to a [previous revision](https://rubygems.org/gems/glimmer-dsl-web/versions). Also, there is a slight chance any issues you encounter are fixed in master or some other branch that you could check out instead)
|
1124
1135
|
|
1125
1136
|
### Rails 7
|
1126
1137
|
|
1127
|
-
Please follow
|
1138
|
+
Please follow these steps to setup.
|
1128
1139
|
|
1129
1140
|
Install a Rails 7 gem:
|
1130
1141
|
|
@@ -1141,7 +1152,7 @@ rails new glimmer_app_server
|
|
1141
1152
|
Add the following to `Gemfile`:
|
1142
1153
|
|
1143
1154
|
```
|
1144
|
-
gem 'glimmer-dsl-web', '~> 0.2.
|
1155
|
+
gem 'glimmer-dsl-web', '~> 0.2.4'
|
1145
1156
|
```
|
1146
1157
|
|
1147
1158
|
Run:
|
@@ -1158,7 +1169,7 @@ Follow [opal-rails](https://github.com/opal/opal-rails) instructions, basically
|
|
1158
1169
|
bin/rails g opal:install
|
1159
1170
|
```
|
1160
1171
|
|
1161
|
-
To enable the `glimmer-dsl-web`
|
1172
|
+
To enable the `glimmer-dsl-web` gem in the frontend, edit `config/initializers/assets.rb` and add the following at the bottom:
|
1162
1173
|
|
1163
1174
|
```ruby
|
1164
1175
|
Opal.use_gem 'glimmer-dsl-web'
|
@@ -1168,9 +1179,11 @@ Opal.append_path Rails.root.join('app', 'assets', 'opal')
|
|
1168
1179
|
To enable Opal Browser Debugging in Ruby with the [Source Maps](https://opalrb.com/docs/guides/v1.4.1/source_maps.html) feature, edit `config/initializers/opal.rb` and add the following inside the `Rails.application.configure do; end` block at the bottom of it:
|
1169
1180
|
|
1170
1181
|
```ruby
|
1171
|
-
config.assets.debug = true
|
1182
|
+
config.assets.debug = true if Rails.env.development?
|
1172
1183
|
```
|
1173
1184
|
|
1185
|
+
Assuming this is a brand new Rails application and you do not have any Rails resources, you can scaffold the welcome resource just for testing purposes.
|
1186
|
+
|
1174
1187
|
Run:
|
1175
1188
|
|
1176
1189
|
```
|
@@ -1212,7 +1225,7 @@ Edit and replace `app/assets/opal/opal_application.rb` content with code below (
|
|
1212
1225
|
```ruby
|
1213
1226
|
require 'glimmer-dsl-web' # brings opal and other dependencies automatically
|
1214
1227
|
|
1215
|
-
# Add more require-statements or Glimmer
|
1228
|
+
# Add more require-statements or Glimmer HTML DSL code
|
1216
1229
|
```
|
1217
1230
|
|
1218
1231
|
```ruby
|
@@ -1221,7 +1234,7 @@ require 'glimmer-dsl-web'
|
|
1221
1234
|
require 'glimmer-dsl-web/samples/hello/hello_world.rb'
|
1222
1235
|
```
|
1223
1236
|
|
1224
|
-
If the `<body></body>` element (where the Glimmer
|
1237
|
+
If the `<body></body>` element (where the Glimmer HTML DSL adds elements by default) is not available when the JS file is loading, you need to put the code inside a `Document.ready? do; end` (but, it is recommended that you load the JS file after the parent element like `<body></body>` is in the page already for faster performance, which is guaranteed automatically by using `glimmer_component`, mentioned in details below):
|
1225
1238
|
|
1226
1239
|
```ruby
|
1227
1240
|
require 'glimmer-dsl-web'
|
@@ -1233,7 +1246,7 @@ end
|
|
1233
1246
|
|
1234
1247
|
Example to confirm setup is working:
|
1235
1248
|
|
1236
|
-
Glimmer
|
1249
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1237
1250
|
|
1238
1251
|
```ruby
|
1239
1252
|
require 'glimmer-dsl-web'
|
@@ -1284,7 +1297,7 @@ HTML:
|
|
1284
1297
|
...
|
1285
1298
|
```
|
1286
1299
|
|
1287
|
-
Glimmer
|
1300
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1288
1301
|
|
1289
1302
|
```ruby
|
1290
1303
|
require 'glimmer-dsl-web'
|
@@ -1337,9 +1350,11 @@ If you run into any issues in setup, refer to the [Sample Glimmer DSL for Web Ra
|
|
1337
1350
|
|
1338
1351
|
Otherwise, if you still cannot setup successfully (even with the help of the sample project, or if the sample project stops working), please do not hesitate to report an [Issue request](https://github.com/AndyObtiva/glimmer-dsl-web/issues) or fix and submit a [Pull Request](https://github.com/AndyObtiva/glimmer-dsl-web/pulls).
|
1339
1352
|
|
1353
|
+
Next, read [Usage](#usage) instructions, and check out [Samples](#samples).
|
1354
|
+
|
1340
1355
|
### Rails 6
|
1341
1356
|
|
1342
|
-
Please follow
|
1357
|
+
Please follow these steps to setup.
|
1343
1358
|
|
1344
1359
|
Install a Rails 6 gem:
|
1345
1360
|
|
@@ -1362,7 +1377,7 @@ Disable the `webpacker` gem line in `Gemfile`:
|
|
1362
1377
|
Add the following to `Gemfile`:
|
1363
1378
|
|
1364
1379
|
```ruby
|
1365
|
-
gem 'glimmer-dsl-web', '~> 0.2.
|
1380
|
+
gem 'glimmer-dsl-web', '~> 0.2.4'
|
1366
1381
|
```
|
1367
1382
|
|
1368
1383
|
Run:
|
@@ -1379,7 +1394,7 @@ Follow [opal-rails](https://github.com/opal/opal-rails) instructions, basically
|
|
1379
1394
|
bin/rails g opal:install
|
1380
1395
|
```
|
1381
1396
|
|
1382
|
-
To enable the `glimmer-dsl-web`
|
1397
|
+
To enable the `glimmer-dsl-web` gem in the frontend, edit `config/initializers/assets.rb` and add the following at the bottom:
|
1383
1398
|
|
1384
1399
|
```ruby
|
1385
1400
|
Opal.use_gem 'glimmer-dsl-web'
|
@@ -1389,9 +1404,11 @@ Opal.append_path Rails.root.join('app', 'assets', 'opal')
|
|
1389
1404
|
To enable Opal Browser Debugging in Ruby with the [Source Maps](https://opalrb.com/docs/guides/v1.4.1/source_maps.html) feature, edit `config/initializers/opal.rb` and add the following inside the `Rails.application.configure do; end` block at the bottom of it:
|
1390
1405
|
|
1391
1406
|
```ruby
|
1392
|
-
config.assets.debug = true
|
1407
|
+
config.assets.debug = true if Rails.env.development?
|
1393
1408
|
```
|
1394
1409
|
|
1410
|
+
Assuming this is a brand new Rails application and you do not have any Rails resources, you can scaffold the welcome resource just for testing purposes.
|
1411
|
+
|
1395
1412
|
Run:
|
1396
1413
|
|
1397
1414
|
```
|
@@ -1439,7 +1456,7 @@ Edit and replace `app/assets/opal/opal_application.rb` content with code below (
|
|
1439
1456
|
```ruby
|
1440
1457
|
require 'glimmer-dsl-web' # brings opal and other dependencies automatically
|
1441
1458
|
|
1442
|
-
# Add more require-statements or Glimmer
|
1459
|
+
# Add more require-statements or Glimmer HTML DSL code
|
1443
1460
|
```
|
1444
1461
|
|
1445
1462
|
Example to confirm setup is working:
|
@@ -1453,7 +1470,7 @@ Initial HTML Markup:
|
|
1453
1470
|
...
|
1454
1471
|
```
|
1455
1472
|
|
1456
|
-
Glimmer
|
1473
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1457
1474
|
|
1458
1475
|
```ruby
|
1459
1476
|
require 'glimmer-dsl-web'
|
@@ -1519,9 +1536,17 @@ If you run into any issues in setup, refer to the [Sample Glimmer DSL for Web Ra
|
|
1519
1536
|
|
1520
1537
|
Otherwise, if you still cannot setup successfully (even with the help of the sample project, or if the sample project stops working), please do not hesitate to report an [Issue request](https://github.com/AndyObtiva/glimmer-dsl-web/issues) or fix and submit a [Pull Request](https://github.com/AndyObtiva/glimmer-dsl-web/pulls).
|
1521
1538
|
|
1539
|
+
Next, read [Usage](#usage) instructions, and check out [Samples](#samples).
|
1540
|
+
|
1541
|
+
### Standalone (No Rails)
|
1542
|
+
|
1543
|
+
Andreas Idogawa-Wildi ([@Largo](https://github.com/Largo)) created a project that demonstrates how to use Glimmer DSL for Web standalone (without Rails):
|
1544
|
+
|
1545
|
+
[https://github.com/Largo/glimmer-dsl-web-standalone-demo](https://github.com/Largo/glimmer-dsl-web-standalone-demo)
|
1546
|
+
|
1522
1547
|
## Usage
|
1523
1548
|
|
1524
|
-
Glimmer DSL for Web offers a
|
1549
|
+
Glimmer DSL for Web offers a HTML DSL ([Graphical User Interface](https://en.wikipedia.org/wiki/Graphical_user_interface) [Domain Specific Language](https://en.wikipedia.org/wiki/Domain-specific_language)) for building HTML Web User Interfaces declaratively in Ruby.
|
1525
1550
|
|
1526
1551
|
1- **Keywords (HTML Elements)**
|
1527
1552
|
|
@@ -1537,7 +1562,7 @@ Also, if the element has a little bit of text content that can fit in one line,
|
|
1537
1562
|
|
1538
1563
|
3- **Content Block (Properties + Listeners + Nested Elements + Text Content)**
|
1539
1564
|
|
1540
|
-
Element methods can accept a Ruby content block. It intentionally has a `{...}` style even as a multi-line block to indicate that the code is declarative
|
1565
|
+
Element methods can accept a Ruby content block. It intentionally has a `{...}` style even as a multi-line block to indicate that the code is declarative HTML DSL structure code (intentionally breaking away from Ruby imperative code conventions given this is a declarative HTML DSL ([Domain Specific Language](https://en.wikipedia.org/wiki/Domain-specific_language)), meaning a different language that has its own conventions, embedded within Ruby).
|
1541
1566
|
|
1542
1567
|
You can nest HTML element properties under an element like:
|
1543
1568
|
|
@@ -1557,7 +1582,7 @@ button('Add') {
|
|
1557
1582
|
}
|
1558
1583
|
```
|
1559
1584
|
|
1560
|
-
Given that listener code is imperative, it uses a `do; end` style for Ruby blocks to separate it from declarative
|
1585
|
+
Given that listener code is imperative, it uses a `do; end` style for Ruby blocks to separate it from declarative HTML DSL structure code and enable quicker readability of the code.
|
1561
1586
|
|
1562
1587
|
You can nest other HTML elements under an HTML element the same way you do so in HTML, like:
|
1563
1588
|
|
@@ -1591,6 +1616,8 @@ p(class: 'summary') {
|
|
1591
1616
|
|
1592
1617
|
You can get/set any element property or invoke any element function by simply calling the lowercase underscored version of their name in Ruby like `input.check_validity`, `input.value`, and `input.id`.
|
1593
1618
|
|
1619
|
+
Next, check out [Samples](#samples).
|
1620
|
+
|
1594
1621
|
## Supported Glimmer DSL Keywords
|
1595
1622
|
|
1596
1623
|
[All HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), following the Ruby method name standard of lowercase and underscored names.
|
@@ -1601,7 +1628,7 @@ You can get/set any element property or invoke any element function by simply ca
|
|
1601
1628
|
|
1602
1629
|
## Coming from Glimmer DSL for Opal
|
1603
1630
|
|
1604
|
-
This project is inspired by [Glimmer DSL for Opal](https://github.com/AndyObtiva/glimmer-dsl-opal) and is similar in enabling
|
1631
|
+
This project is inspired by [Glimmer DSL for Opal](https://github.com/AndyObtiva/glimmer-dsl-opal) and is similar in enabling Web Frontend development with Ruby. [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) mainly differs from Glimmer DSL for Opal by adopting a DSL that follows web-like HTML syntax in Ruby to facilitate leveraging existing HTML/CSS/JS skills instead of adopting a desktop HTML DSL that is webified. As a result, applications written in Glimmer DSL for Opal are not compatible with Glimmer DSL for Web.
|
1605
1632
|
|
1606
1633
|
## Samples
|
1607
1634
|
|
@@ -1613,7 +1640,7 @@ https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app
|
|
1613
1640
|
|
1614
1641
|
#### Hello, World!
|
1615
1642
|
|
1616
|
-
Glimmer
|
1643
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1617
1644
|
|
1618
1645
|
```ruby
|
1619
1646
|
require 'glimmer-dsl-web'
|
@@ -1659,11 +1686,13 @@ That produces the following under `<body></body>`:
|
|
1659
1686
|
|
1660
1687
|
![setup is working](/images/glimmer-dsl-web-setup-example-working.png)
|
1661
1688
|
|
1689
|
+
You can also mount the `div` elsewhere by passing the `parent: parent_css_selector` option (e.g. `div(parent: 'div#app-container') { 'Hello, World!' }`).
|
1690
|
+
|
1662
1691
|
#### Hello, Button!
|
1663
1692
|
|
1664
|
-
Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to
|
1693
|
+
Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to JS global scope from Ruby to invoke functions like `alert`.
|
1665
1694
|
|
1666
|
-
Glimmer
|
1695
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1667
1696
|
|
1668
1697
|
```ruby
|
1669
1698
|
require 'glimmer-dsl-web'
|
@@ -1695,9 +1724,9 @@ Screenshot:
|
|
1695
1724
|
|
1696
1725
|
#### Hello, Form!
|
1697
1726
|
|
1698
|
-
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby
|
1727
|
+
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby HTML DSL. Also, you can apply CSS styles by including directly in Ruby code as a string, using [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css), or managing CSS completely separately using something like [SCSS](https://sass-lang.com/). The CSS techniques could be combined as well, like by managing common reusable CSS styles separately in SCSS, but adding component specific CSS styles in Ruby when it is more convenient.
|
1699
1728
|
|
1700
|
-
Glimmer
|
1729
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1701
1730
|
|
1702
1731
|
```ruby
|
1703
1732
|
require 'glimmer-dsl-web'
|
@@ -1851,9 +1880,9 @@ Screenshot:
|
|
1851
1880
|
|
1852
1881
|
#### Hello, Observer!
|
1853
1882
|
|
1854
|
-
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) provides the `observe(model, attribute) { ... }` keyword to employ the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) as per [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (Model View Controller), enabling Views to observe Models and update themselves in response to changes. If the `observe` keyword is used from inside a [Component](#hello-component)
|
1883
|
+
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) provides the `observe(model, attribute) { ... }` keyword to employ the [Observer Design Pattern](https://en.wikipedia.org/wiki/Observer_pattern) as per [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (Model View Controller), enabling Views to observe Models and update themselves in response to changes. If the `observe` keyword is used from inside a [Component](#hello-component), when the Component is removed or its top-level element is removed, the observer is automatically cleaned up. The need for such explicit observers is significantly diminished by the availablility of the more advanced Unidirectional [Data-Binding](#hello-data-binding) Support and Bidirectional [Data-Binding](#hello-data-binding) Support.
|
1855
1884
|
|
1856
|
-
Glimmer
|
1885
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1857
1886
|
|
1858
1887
|
```ruby
|
1859
1888
|
require 'glimmer-dsl-web'
|
@@ -1937,7 +1966,7 @@ Screenshot:
|
|
1937
1966
|
|
1938
1967
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) intuitively supports both Unidirectional (One-Way) Data-Binding via the `<=` operator and Bidirectional (Two-Way) Data-Binding via the `<=>` operator, incredibly simplifying how to sync View properties with Model attributes with the simplest code to reason about.
|
1939
1968
|
|
1940
|
-
Glimmer
|
1969
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
1941
1970
|
|
1942
1971
|
```ruby
|
1943
1972
|
require 'glimmer-dsl-web'
|
@@ -2110,7 +2139,7 @@ If you need to regenerate HTML element content dynamically, you can use Content
|
|
2110
2139
|
rebuild HTML elements based on changes in a Model attribute that provides the source data.
|
2111
2140
|
In this example, we generate multiple address forms based on the number of addresses the user has.
|
2112
2141
|
|
2113
|
-
Glimmer
|
2142
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
2114
2143
|
|
2115
2144
|
```ruby
|
2116
2145
|
require 'glimmer-dsl-web'
|
@@ -2241,13 +2270,15 @@ Screenshot:
|
|
2241
2270
|
|
2242
2271
|
You can define Glimmer web components (View components) to reuse visual concepts to your heart's content,
|
2243
2272
|
by simply defining a class with `include Glimmer::Web::Component` and encasing the reusable markup inside
|
2244
|
-
a `markup {...}` block. Glimmer web components automatically extend the Glimmer
|
2245
|
-
that match the underscored versions of the component class names (e.g.
|
2246
|
-
the `order_summary` keyword for reusing that component within the Glimmer
|
2247
|
-
|
2273
|
+
a `markup {...}` block. Glimmer web components automatically extend the Glimmer HTML DSL with new keywords
|
2274
|
+
that match the underscored versions of the component class names (e.g. an `OrderSummary` class yields
|
2275
|
+
the `order_summary` keyword for reusing that component within the Glimmer HTML DSL).
|
2276
|
+
You may insert a Glimmer component anywhere into a Rails View using `glimmer_component(component_path, *args)`
|
2277
|
+
Rails helper (more about it in [Hello, glimmer_component Rails Helper!](#hello-glimmer_component-rails-helper)).
|
2278
|
+
Below, we define an `AddressForm` component that generates an `address_form` keyword, and then we
|
2248
2279
|
reuse it twice inside an `AddressPage` component displaying a Shipping Address and a Billing Address.
|
2249
2280
|
|
2250
|
-
Glimmer
|
2281
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
2251
2282
|
|
2252
2283
|
```ruby
|
2253
2284
|
require 'glimmer-dsl-web'
|
@@ -2327,9 +2358,9 @@ end
|
|
2327
2358
|
# AddressForm Glimmer Web Component (View component)
|
2328
2359
|
#
|
2329
2360
|
# Including Glimmer::Web::Component makes this class a View component and automatically
|
2330
|
-
# generates a new Glimmer
|
2361
|
+
# generates a new Glimmer HTML DSL keyword that matches the lowercase underscored version
|
2331
2362
|
# of the name of the class. AddressForm generates address_form keyword, which can be used
|
2332
|
-
# elsewhere in Glimmer
|
2363
|
+
# elsewhere in Glimmer HTML DSL code as done inside AddressPage below.
|
2333
2364
|
class AddressForm
|
2334
2365
|
include Glimmer::Web::Component
|
2335
2366
|
|
@@ -2496,7 +2527,7 @@ Rails View code:
|
|
2496
2527
|
</div>
|
2497
2528
|
```
|
2498
2529
|
|
2499
|
-
Glimmer
|
2530
|
+
Glimmer HTML DSL Ruby code in the frontend (`app/assets/opal/address_form.rb`):
|
2500
2531
|
|
2501
2532
|
```ruby
|
2502
2533
|
require 'glimmer-dsl-web'
|
@@ -2661,9 +2692,9 @@ Screenshot:
|
|
2661
2692
|
|
2662
2693
|
#### Hello, Paragraph!
|
2663
2694
|
|
2664
|
-
To facilitate building formatted textual paragraphs in Ruby, the Glimmer
|
2695
|
+
To facilitate building formatted textual paragraphs in Ruby, thanks to [Glimmer](https://github.com/AndyObtiva/glimmer#dsl-engine), the most advanced DSL engine in Ruby, the Glimmer HTML DSL is advanced enough to intelligently behave differently under different situations, like when using HTML formatting elements: `<br>`, `<strong>`, `<em>`, `<br>`, `<i>`, `<sub>`, `<sup>`, `<del>`, `<ins>`, `<small>`, `<mark>`
|
2665
2696
|
|
2666
|
-
Instead of returning Ruby objects that are nested as children within their parent, the Glimmer
|
2697
|
+
Instead of returning Ruby objects that are nested as children within their parent, the Glimmer HTML DSL returns `String` objects directly that can be concatenated to or embedded within other `String` objects via interpolation.
|
2667
2698
|
|
2668
2699
|
This enables writing code like:
|
2669
2700
|
|
@@ -2691,9 +2722,9 @@ it returns a `String` to enable code like this:
|
|
2691
2722
|
|
2692
2723
|
`p {"#{span('Yesterday, ', style: 'text-decoration: underline;')}Robert suggested adding a new #{em('feature', class: 'very-emphasized')} to our software product.#{br}}`
|
2693
2724
|
|
2694
|
-
In any case, below is a full example leveraging the Glimmer
|
2725
|
+
In any case, below is a full example leveraging the Glimmer HTML DSL alternative approach when utilizing formatting elements underneath a paragraph.
|
2695
2726
|
|
2696
|
-
Glimmer
|
2727
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
2697
2728
|
|
2698
2729
|
```ruby
|
2699
2730
|
require 'glimmer-dsl-web'
|
@@ -2754,7 +2785,7 @@ Screenshot:
|
|
2754
2785
|
|
2755
2786
|
#### Hello, Input (Date/Time)!
|
2756
2787
|
|
2757
|
-
Glimmer
|
2788
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
2758
2789
|
|
2759
2790
|
```ruby
|
2760
2791
|
require 'glimmer-dsl-web'
|
@@ -2859,7 +2890,7 @@ Screenshot:
|
|
2859
2890
|
|
2860
2891
|
#### Button Counter
|
2861
2892
|
|
2862
|
-
Glimmer
|
2893
|
+
Glimmer HTML DSL Ruby code in the frontend demonstrating MVC + Glimmer Web Components (Views) + Data-Binding:
|
2863
2894
|
|
2864
2895
|
```ruby
|
2865
2896
|
require 'glimmer-dsl-web'
|
@@ -2938,7 +2969,7 @@ Screenshot:
|
|
2938
2969
|
|
2939
2970
|
- The Ruby Way (including TIMTOWTDI: There Is More Than One Way To Do It)
|
2940
2971
|
- The Rails Way Convention over Configuration via smart defaults and automation of low-level details
|
2941
|
-
- Requiring the least amount of
|
2972
|
+
- Requiring the least amount of code possible to build highly interactive web pages
|
2942
2973
|
- Declarative syntax that visually maps to the DOM (Document Object Model) hierarchy
|
2943
2974
|
- Ability to mix declarative and imperative code conveniently in one language
|
2944
2975
|
- Computers serve Software Engineers (not Software Engineers serve Computers)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.4
|
data/glimmer-dsl-web.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer-dsl-web 0.2.
|
5
|
+
# stub: glimmer-dsl-web 0.2.4 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-web".freeze
|
9
|
-
s.version = "0.2.
|
9
|
+
s.version = "0.2.4"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Andy Maleh".freeze]
|
14
|
-
s.date = "2024-
|
15
|
-
s.description = "Glimmer DSL for Web (Ruby in the Browser Web
|
14
|
+
s.date = "2024-02-04"
|
15
|
+
s.description = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) enables building Web Frontends using Ruby in the Browser, as per Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with DSLs and TIMTOWTDI) and the Rails way (Convention over Configuration) in building Isomorphic Ruby on Rails Applications. It provides a Ruby HTML DSL, which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using <=>). Dynamic rendering (and re-rendering) of HTML content is also supported via Content Data-Binding. And, modular design is supported with Glimmer Web Components. Many samples are demonstrated in the Rails sample app (there is a very minimal Standalone [No Rails] sample app too). You can finally live in pure Rubyland on the Web in both the frontend and backend with Glimmer DSL for Web! This gem relies on Opal Ruby.".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.extra_rdoc_files = [
|
18
18
|
"CHANGELOG.md",
|
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
"lib/glimmer-dsl-web/ext/class.rb",
|
31
31
|
"lib/glimmer-dsl-web/ext/date.rb",
|
32
32
|
"lib/glimmer-dsl-web/ext/exception.rb",
|
33
|
+
"lib/glimmer-dsl-web/ext/kernel.rb",
|
33
34
|
"lib/glimmer-dsl-web/samples/hello/hello_button.rb",
|
34
35
|
"lib/glimmer-dsl-web/samples/hello/hello_component.rb",
|
35
36
|
"lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb",
|
@@ -54,10 +55,9 @@ Gem::Specification.new do |s|
|
|
54
55
|
"lib/glimmer/dsl/web/general_element_expression.rb",
|
55
56
|
"lib/glimmer/dsl/web/listener_expression.rb",
|
56
57
|
"lib/glimmer/dsl/web/observe_expression.rb",
|
57
|
-
"lib/glimmer/dsl/web/p_expression.rb",
|
58
58
|
"lib/glimmer/dsl/web/property_expression.rb",
|
59
|
-
"lib/glimmer/dsl/web/select_expression.rb",
|
60
59
|
"lib/glimmer/dsl/web/shine_data_binding_expression.rb",
|
60
|
+
"lib/glimmer/dsl/web/span_expression.rb",
|
61
61
|
"lib/glimmer/dsl/web/style_expression.rb",
|
62
62
|
"lib/glimmer/helpers/glimmer_helper.rb",
|
63
63
|
"lib/glimmer/util/proc_tracker.rb",
|
@@ -70,24 +70,24 @@ Gem::Specification.new do |s|
|
|
70
70
|
]
|
71
71
|
s.homepage = "http://github.com/AndyObtiva/glimmer-dsl-web".freeze
|
72
72
|
s.licenses = ["MIT".freeze]
|
73
|
-
s.rubygems_version = "3.
|
74
|
-
s.summary = "Glimmer DSL for Web (Ruby in the Browser Web
|
73
|
+
s.rubygems_version = "3.4.10".freeze
|
74
|
+
s.summary = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework)".freeze
|
75
75
|
|
76
76
|
s.specification_version = 4
|
77
77
|
|
78
|
-
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6"
|
79
|
-
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.3.2"
|
80
|
-
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.2.3"
|
81
|
-
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2"
|
82
|
-
s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3"
|
83
|
-
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1"
|
84
|
-
s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1"
|
85
|
-
s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1"
|
86
|
-
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 0"
|
87
|
-
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0"
|
88
|
-
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"
|
89
|
-
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9"
|
90
|
-
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1"
|
91
|
-
s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2"
|
78
|
+
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6"])
|
79
|
+
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.3.2"])
|
80
|
+
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.2.3"])
|
81
|
+
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2"])
|
82
|
+
s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3"])
|
83
|
+
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1"])
|
84
|
+
s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1"])
|
85
|
+
s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1", "< 3.0.0"])
|
86
|
+
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 0"])
|
87
|
+
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
|
88
|
+
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
|
89
|
+
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9", "< 3.0.0"])
|
90
|
+
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
|
91
|
+
s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2"])
|
92
92
|
end
|
93
93
|
|
data/lib/glimmer/dsl/web/dsl.rb
CHANGED
@@ -24,8 +24,7 @@ require 'glimmer/dsl/web/element_expression'
|
|
24
24
|
require 'glimmer/dsl/web/formatting_element_expression'
|
25
25
|
require 'glimmer/dsl/web/listener_expression'
|
26
26
|
require 'glimmer/dsl/web/property_expression'
|
27
|
-
|
28
|
-
# require 'glimmer/dsl/web/select_expression'
|
27
|
+
require 'glimmer/dsl/web/span_expression'
|
29
28
|
require 'glimmer/dsl/web/style_expression'
|
30
29
|
require 'glimmer/dsl/web/bind_expression'
|
31
30
|
require 'glimmer/dsl/web/data_binding_expression'
|
@@ -47,7 +46,6 @@ module Glimmer
|
|
47
46
|
content_data_binding
|
48
47
|
shine_data_binding
|
49
48
|
formatting_element
|
50
|
-
element
|
51
49
|
]
|
52
50
|
)
|
53
51
|
end
|
@@ -17,10 +17,14 @@ module Glimmer
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
module Kernel
|
21
|
+
alias pi p
|
22
|
+
end
|
23
|
+
|
20
24
|
module Glimmer
|
21
25
|
# Optimize performance through shortcut methods for all HTML elements that circumvent the DSL chain of responsibility
|
22
26
|
element_expression = Glimmer::DSL::Web::ElementExpression.new
|
23
|
-
(Glimmer::Web::ElementProxy::ELEMENT_KEYWORDS - ['style']).each do |keyword|
|
27
|
+
(Glimmer::Web::ElementProxy::ELEMENT_KEYWORDS - ['span', 'style']).each do |keyword|
|
24
28
|
Glimmer::DSL::Engine.static_expressions[keyword] ||= Concurrent::Hash.new
|
25
29
|
element_expression_dsl = element_expression.class.dsl
|
26
30
|
Glimmer::DSL::Engine.static_expressions[keyword][element_expression_dsl] = element_expression
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'glimmer/dsl/static_expression'
|
2
|
+
require 'glimmer/dsl/web/general_element_expression'
|
3
|
+
|
4
|
+
module Glimmer
|
5
|
+
module DSL
|
6
|
+
module Web
|
7
|
+
class SpanExpression < StaticExpression
|
8
|
+
include GeneralElementExpression
|
9
|
+
|
10
|
+
def can_interpret?(parent, keyword, *args, &block)
|
11
|
+
(parent.nil? ||
|
12
|
+
(parent.respond_to?(:keyword) && parent.keyword != 'p'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -316,11 +316,16 @@ module Glimmer
|
|
316
316
|
|
317
317
|
# Returns content block if used as an attribute reader (no args)
|
318
318
|
# Otherwise, if a block is passed, it adds it as content to this Glimmer web component
|
319
|
-
def content(&block)
|
320
|
-
if
|
321
|
-
|
319
|
+
def content(*args, &block)
|
320
|
+
if args.empty?
|
321
|
+
if block_given?
|
322
|
+
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Web::ComponentExpression.new, self.class.keyword, &block)
|
323
|
+
else
|
324
|
+
@content
|
325
|
+
end
|
322
326
|
else
|
323
|
-
|
327
|
+
# delegate to GUI DSL ContentExpression
|
328
|
+
super
|
324
329
|
end
|
325
330
|
end
|
326
331
|
|
@@ -371,6 +371,12 @@ module Glimmer
|
|
371
371
|
@element_id ||= "element-#{ElementProxy.next_id_number_for(name)}"
|
372
372
|
end
|
373
373
|
|
374
|
+
def class_name=(value)
|
375
|
+
value = value.is_a?(Array) ? value.join(' ') : value.to_s
|
376
|
+
new_class_name = "#{name} #{element_id} #{value}"
|
377
|
+
dom_element.prop('className', new_class_name)
|
378
|
+
end
|
379
|
+
|
374
380
|
def add_css_class(css_class)
|
375
381
|
dom_element.add_class(css_class)
|
376
382
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# backtick_javascript: true
|
2
|
+
|
3
|
+
# Copyright (c) 2023-2024 Andy Maleh
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module ::Kernel
|
25
|
+
alias puts_without_glimmer puts
|
26
|
+
def puts(*strs)
|
27
|
+
puts_without_glimmer(*strs)
|
28
|
+
rescue Exception
|
29
|
+
strs.each do |str|
|
30
|
+
`console.log(#{str})`
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
alias p_without_glimmer p
|
35
|
+
def p(*args)
|
36
|
+
p_without_glimmer(*args)
|
37
|
+
rescue Exception
|
38
|
+
args.each do |arg|
|
39
|
+
`console.log(#{arg})`
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -96,9 +96,9 @@ end
|
|
96
96
|
# AddressForm Glimmer Web Component (View component)
|
97
97
|
#
|
98
98
|
# Including Glimmer::Web::Component makes this class a View component and automatically
|
99
|
-
# generates a new Glimmer
|
99
|
+
# generates a new Glimmer HTML DSL keyword that matches the lowercase underscored version
|
100
100
|
# of the name of the class. AddressForm generates address_form keyword, which can be used
|
101
|
-
# elsewhere in Glimmer
|
101
|
+
# elsewhere in Glimmer HTML DSL code as done inside AddressPage below.
|
102
102
|
class AddressForm
|
103
103
|
include Glimmer::Web::Component
|
104
104
|
|
data/lib/glimmer-dsl-web.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -230,17 +230,21 @@ dependencies:
|
|
230
230
|
- - "~>"
|
231
231
|
- !ruby/object:Gem::Version
|
232
232
|
version: 0.8.0.alpha2
|
233
|
-
description: Glimmer DSL for Web (Ruby in the Browser Web
|
234
|
-
building Web
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
and the Rails way (Convention over Configuration)
|
233
|
+
description: Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) enables
|
234
|
+
building Web Frontends using Ruby in the Browser, as per Matz's recommendation in
|
235
|
+
his RubyConf 2022 keynote speech to replace JavaScript with Ruby. It aims at providing
|
236
|
+
the simplest, most intuitive, most straight-forward, and most productive frontend
|
237
|
+
framework in existence. The framework follows the Ruby way (with DSLs and TIMTOWTDI)
|
238
|
+
and the Rails way (Convention over Configuration) in building Isomorphic Ruby on
|
239
|
+
Rails Applications. It provides a Ruby HTML DSL, which uniquely enables writing
|
240
|
+
both structure code and logic code in one language. It supports both Unidirectional
|
239
241
|
(One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using
|
240
242
|
<=>). Dynamic rendering (and re-rendering) of HTML content is also supported via
|
241
243
|
Content Data-Binding. And, modular design is supported with Glimmer Web Components.
|
242
|
-
|
243
|
-
|
244
|
+
Many samples are demonstrated in the Rails sample app (there is a very minimal Standalone
|
245
|
+
[No Rails] sample app too). You can finally live in pure Rubyland on the Web in
|
246
|
+
both the frontend and backend with Glimmer DSL for Web! This gem relies on Opal
|
247
|
+
Ruby.
|
244
248
|
email: andy.am@gmail.com
|
245
249
|
executables: []
|
246
250
|
extensions: []
|
@@ -259,6 +263,7 @@ files:
|
|
259
263
|
- lib/glimmer-dsl-web/ext/class.rb
|
260
264
|
- lib/glimmer-dsl-web/ext/date.rb
|
261
265
|
- lib/glimmer-dsl-web/ext/exception.rb
|
266
|
+
- lib/glimmer-dsl-web/ext/kernel.rb
|
262
267
|
- lib/glimmer-dsl-web/samples/hello/hello_button.rb
|
263
268
|
- lib/glimmer-dsl-web/samples/hello/hello_component.rb
|
264
269
|
- lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb
|
@@ -283,10 +288,9 @@ files:
|
|
283
288
|
- lib/glimmer/dsl/web/general_element_expression.rb
|
284
289
|
- lib/glimmer/dsl/web/listener_expression.rb
|
285
290
|
- lib/glimmer/dsl/web/observe_expression.rb
|
286
|
-
- lib/glimmer/dsl/web/p_expression.rb
|
287
291
|
- lib/glimmer/dsl/web/property_expression.rb
|
288
|
-
- lib/glimmer/dsl/web/select_expression.rb
|
289
292
|
- lib/glimmer/dsl/web/shine_data_binding_expression.rb
|
293
|
+
- lib/glimmer/dsl/web/span_expression.rb
|
290
294
|
- lib/glimmer/dsl/web/style_expression.rb
|
291
295
|
- lib/glimmer/helpers/glimmer_helper.rb
|
292
296
|
- lib/glimmer/util/proc_tracker.rb
|
@@ -315,8 +319,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
315
319
|
- !ruby/object:Gem::Version
|
316
320
|
version: '0'
|
317
321
|
requirements: []
|
318
|
-
rubygems_version: 3.
|
322
|
+
rubygems_version: 3.4.10
|
319
323
|
signing_key:
|
320
324
|
specification_version: 4
|
321
|
-
summary: Glimmer DSL for Web (Ruby in the Browser Web
|
325
|
+
summary: Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework)
|
322
326
|
test_files: []
|