glimmer-dsl-web 0.0.11 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c16186f1613018ccbaaf2b6bc4214b2e0ad5ce8a96354639febd256616f18a1f
4
- data.tar.gz: 26b8cb6ac6b64c912e39294b32cc21f29f053aa62000991970846dd95f127d57
3
+ metadata.gz: 5c9bd6a7f085751de551a8eada611f25b6462c32f31019ebc31e296a98a7dbe7
4
+ data.tar.gz: cde631c346fddf15d48c52b85643f4f436761b059ccca0a8909cca56fdc7676e
5
5
  SHA512:
6
- metadata.gz: 0dc717529f81c4aa66e6ed6c31c32bef68e71a152ec04f3b619515339d29d5f71de076d2e4fd2622b2f7ca173e15a426588a8e46127e1f78139f403722341f6d
7
- data.tar.gz: 5901cf78e56fac1cb786955bc1d84777968d3f881d00c06d1e2b9b46a0e52c83c79674560a71103b6685b4bbe1a04d45ebd858e8039404a6f713817c1e72817c
6
+ metadata.gz: 036cbe077a6378e6fb18cf10060074b4a071b20f4293960ded842458069c4dfb5bc041eb909f0b7b3cfbb809f73a41605f2b97f101b338f1ee616e52f00445c3
7
+ data.tar.gz: 4441339edfaf2724324e4aa30c19b2afc7e0e9d673add6130882e1c3220e278a1be1d21be126bf9b8aaa7568c62a0c59ecbce9ca2d1103183263ae17deb2d15e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.1.0
4
+
5
+ - Update rendering system to render HTML elements immediately instead of waiting for complete components to be rendered all at once.
6
+ - Support `render: false` option in any element or component to avoid rendering when building the elements/components (including a Component#create alternative to Component#render that defers rendering if needed).
7
+ - Fix `Glimmer::Web::Component` `after_render` hook by ensuring it only fires after the component markup has been rendered
8
+
9
+ ## 0.0.12
10
+
11
+ - Treat HTML text formatting elements differently (e.g. `b`, `i`, `strong`, `em`, `sub`, `sup`, `del`, `ins`, `small`, `mark`) by not appending to their parent content, yet having them generate a String with `to_s` that can be embedded in a `String` that is the text content of another normal element like `p` or `div`.
12
+ - Treat `span` as a special text formatting element if included inside a `p` and as a normal element outside a `p`.
13
+ - Hello, Paragraph! Sample: `require 'glimmer-dsl-web/samples/hello/hello_paragraph'`
14
+
3
15
  ## 0.0.11
4
16
 
5
17
  - Support element custom event listener: `on_remove`
data/README.md CHANGED
@@ -1,4 +1,4 @@
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.0.11 (Early Alpha)
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.1.0 (Beta)
2
2
  ## Ruby in the Browser Web GUI Frontend Library
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)
@@ -17,7 +17,7 @@ include Glimmer
17
17
  Document.ready? do
18
18
  div {
19
19
  'Hello, World!'
20
- }.render
20
+ }
21
21
  end
22
22
  ```
23
23
 
@@ -49,7 +49,7 @@ Document.ready? do
49
49
  $$.alert('Hello, Button!')
50
50
  end
51
51
  }
52
- }.render
52
+ }
53
53
  end
54
54
  ```
55
55
 
@@ -150,7 +150,7 @@ Document.ready? do
150
150
  }
151
151
  CSS
152
152
  }
153
- }.render
153
+ }
154
154
  end
155
155
  ```
156
156
 
@@ -245,7 +245,11 @@ class HelloObserver
245
245
  end
246
246
 
247
247
  after_render do
248
- # observe Model attribute @number_holder.number for changes and update View
248
+ @number_input.value = @number_holder.number
249
+ @range_input.value = @number_holder.number
250
+ # Observe Model attribute @number_holder.number for changes and update View
251
+ # Observer is automatically cleaned up if remove method is called on rendered HelloObserver
252
+ # or its top-level element
249
253
  observe(@number_holder, :number) do
250
254
  number_string = @number_holder.number.to_s
251
255
  @number_input.value = number_string unless @number_input.value == number_string
@@ -260,7 +264,7 @@ class HelloObserver
260
264
  markup {
261
265
  div {
262
266
  div {
263
- @number_input = input(type: 'number', value: @number_holder.number, min: 0, max: 100) {
267
+ @number_input = input(type: 'number', min: 0, max: 100) {
264
268
  # oninput listener updates Model attribute @number_holder.number
265
269
  oninput do
266
270
  @number_holder.number = @number_input.value.to_i
@@ -274,7 +278,7 @@ class HelloObserver
274
278
  }
275
279
  }
276
280
  div {
277
- @range_input = input(type: 'range', value: @number_holder.number, min: 0, max: 100) {
281
+ @range_input = input(type: 'range', min: 0, max: 100) {
278
282
  # oninput listener updates Model attribute @number_holder.number
279
283
  oninput do
280
284
  @number_holder.number = @range_input.value.to_i
@@ -409,7 +413,7 @@ Document.ready? do
409
413
  computed_by: @address.members + ['state_code'],
410
414
  ]
411
415
  }
412
- }.render
416
+ }
413
417
  end
414
418
  ```
415
419
 
@@ -544,7 +548,7 @@ Document.ready? do
544
548
  end
545
549
  end
546
550
  }
547
- }.render
551
+ }
548
552
  end
549
553
  ```
550
554
 
@@ -978,7 +982,100 @@ Screenshot:
978
982
 
979
983
  ![Hello, glimmer_component Rails Helper!](/images/glimmer-dsl-web-samples-hello-hello-component.png)
980
984
 
981
- NOTE: Glimmer DSL for Web is an Early Alpha 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 an early alpha, so the more feedback and issues you report the better.
985
+ **Hello, Paragraph!**
986
+
987
+ To facilitate building formatted textual paragraphs in Ruby, the Glimmer GUI DSL is advanced enough to behave differently when using HTML formatting elements: `<br>`, `<strong>`, `<em>`, `<br>`, `<i>`, `<sub>`, `<sup>`, `<del>`, `<ins>`, `<small>`, `<mark>`
988
+
989
+ Instead of returning Ruby objects that are nested as children within their parent, the Glimmer GUI DSL returns `String` objects directly that can be concatenated to or embedded within other `String` objects via interpolation.
990
+
991
+ This enables writing code like:
992
+
993
+ `p {"#{strong('Yesterday, ')}Robert suggested adding a new #{em('feature')} to our software product.#{br}}`
994
+
995
+ That is close to how it is written in HTML, albeit briefer in Ruby:
996
+
997
+ `<p><strong>Yesterday, </strong>Robert suggested adding a new <em>feature</em> to our software product.<br></p>`
998
+
999
+ Formatting elements just like regular elements can accept text content as their first argument or as their block return value. So, the code above could equally be written as follows:
1000
+
1001
+ `p {"#{strong{'Yesterday, '}}Robert suggested adding a new #{em{'feature'}} to our software product.#{br}}`
1002
+
1003
+ This enables seggregating formatting element attributes if desired, as in this example:
1004
+
1005
+ `p {"#{strong(class: 'very-string'){'Yesterday, '}}Robert suggested adding a new #{em(class: 'very-emphasized'){'feature'}} to our software product.#{br}}`
1006
+
1007
+ Another way of writing the same code is to pass the text content as the first argument, before attributes:
1008
+
1009
+
1010
+ `p {"#{strong('Yesterday, ', class: 'very-string')}Robert suggested adding a new #{em('feature', class: 'very-emphasized')} to our software product.#{br}}`
1011
+
1012
+ One last bit of info to keep in mind is that `<span>` generally generates a normal element, except when used inside a `<p>`'s content block, in which case it is assumed to be used for formatting, so
1013
+ it returns a `String` to enable code like this:
1014
+
1015
+ `p {"#{span('Yesterday, ', style: 'text-decoration: underline;')}Robert suggested adding a new #{em('feature', class: 'very-emphasized')} to our software product.#{br}}`
1016
+
1017
+ In any case, below is a full example leveraging the Glimmer GUI DSL alternative approach when utilizing formatting elements underneath a paragraph.
1018
+
1019
+ Glimmer GUI code:
1020
+
1021
+ ```ruby
1022
+ require 'glimmer-dsl-web'
1023
+
1024
+ class HelloParagraph
1025
+ include Glimmer::Web::Component
1026
+
1027
+ markup {
1028
+ div {
1029
+ h1(class: 'title') {
1030
+ 'Flying Cars Become 100% Safe with AI Powered Balance!'
1031
+ }
1032
+
1033
+ p(class: 'intro') {"
1034
+ In the early 2030's, #{em('flying cars')} became affordable after their prices dropped
1035
+ below #{small(del('$100,000'))}#{ins('$80,000')} as a result of the innovations of #{strong('Travel-X')}. Still, that did not
1036
+ make #{em('flying cars')} any popular due to the extreme difficulty in piloting such flying vehicles for the average
1037
+ person, making it very tough to pass the tests for getting a piloting license given the learning curve.
1038
+ "}
1039
+
1040
+ p {"
1041
+ That said, #{b('Travel-X')} has recently come up with a new feature for their flagship #{i('flying car')},
1042
+ the Ptero#{sub(1)}#{sup('TM')}, which relies on AI#{sub(2)} to automatically balance the flying cars in mid-air,
1043
+ thus significantly facilitating their piloting by the average consumer.
1044
+ "}
1045
+
1046
+ p(class: 'conclusion') {"
1047
+ That Ptero#{sup('TM')} will be so stable and well balanced while flying that the consumer will be able to drive
1048
+ as if it is a plain old car, with the only difference being vertical elevation, the control of which will be handled
1049
+ automatically by AI. The Ptero#{sup('TM')} will debut for #{span(style: 'text-decoration: underline dashed;'){'$79,000'}}.
1050
+ "}
1051
+
1052
+ h2(class: 'legend-title') {
1053
+ mark('Legend:')
1054
+ }
1055
+
1056
+ p(class: 'legend') {"
1057
+ #{strong("1- Ptero:")} Pterosaur is flying dinosaur species#{br}
1058
+ #{strong("2- AI:")} Artificial Intelligence#{br}
1059
+ "}
1060
+
1061
+ }
1062
+ }
1063
+ end
1064
+
1065
+ Document.ready? do
1066
+ HelloParagraph.render
1067
+ end
1068
+ ```
1069
+
1070
+ Screenshot:
1071
+
1072
+ --
1073
+
1074
+ ![Hello, Paragraph!](/images/glimmer-dsl-web-samples-hello-hello-paragraph.png)
1075
+
1076
+ --
1077
+
1078
+ 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.
982
1079
 
983
1080
  Learn more about the differences between various [Glimmer](https://github.com/AndyObtiva/glimmer) DSLs by looking at:
984
1081
 
@@ -986,9 +1083,7 @@ Learn more about the differences between various [Glimmer](https://github.com/An
986
1083
 
987
1084
  ## Table of Contents
988
1085
 
989
- - [Glimmer DSL for Web](#-glimmer-dsl-for-opal-alpha-pure-ruby-web-gui)
990
- - [Principles](#principles)
991
- - [Background](#background)
1086
+ - [Glimmer DSL for Web](#)
992
1087
  - [Prerequisites](#prerequisites)
993
1088
  - [Setup](#setup)
994
1089
  - [Usage](#usage)
@@ -1004,8 +1099,11 @@ Learn more about the differences between various [Glimmer](https://github.com/An
1004
1099
  - [Hello, Content Data-Binding!](#hello-content-data-binding)
1005
1100
  - [Hello, Component!](#hello-content-data-binding)
1006
1101
  - [Hello, glimmer_component Rails Helper!](#hello-glimmer_component-rails-helper)
1102
+ - [Hello, Paragraph!](#hello-paragraph)
1007
1103
  - [Hello, Input (Date/Time)!](#hello-input-datetime)
1008
1104
  - [Button Counter](#button-counter)
1105
+ - [Design Principles](#design-principles)
1106
+ - [Supporting Libraries](#supporting-libraries)
1009
1107
  - [Glimmer Process](#glimmer-process)
1010
1108
  - [Help](#help)
1011
1109
  - [Issues](#issues)
@@ -1025,7 +1123,7 @@ Learn more about the differences between various [Glimmer](https://github.com/An
1025
1123
 
1026
1124
  ## Setup
1027
1125
 
1028
- (NOTE: Keep in mind this is an Early Alpha. 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)
1126
+ (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)
1029
1127
 
1030
1128
  The [glimmer-dsl-web](https://rubygems.org/gems/glimmer-dsl-web) gem is a [Rails Engine](https://guides.rubyonrails.org/engines.html) gem that includes assets.
1031
1129
 
@@ -1048,7 +1146,7 @@ rails new glimmer_app_server
1048
1146
  Add the following to `Gemfile`:
1049
1147
 
1050
1148
  ```
1051
- gem 'glimmer-dsl-web', '~> 0.0.11'
1149
+ gem 'glimmer-dsl-web', '~> 0.1.0'
1052
1150
  ```
1053
1151
 
1054
1152
  Run:
@@ -1151,7 +1249,7 @@ Document.ready? do
1151
1249
  label(class: 'greeting') {
1152
1250
  'Hello, World!'
1153
1251
  }
1154
- }.render
1252
+ }
1155
1253
  end
1156
1254
  ```
1157
1255
 
@@ -1202,7 +1300,7 @@ Document.ready? do
1202
1300
  label(class: 'greeting') {
1203
1301
  'Hello, World!'
1204
1302
  }
1205
- }.render
1303
+ }
1206
1304
  end
1207
1305
  ```
1208
1306
 
@@ -1264,7 +1362,7 @@ Disable the `webpacker` gem line in `Gemfile`:
1264
1362
  Add the following to `Gemfile`:
1265
1363
 
1266
1364
  ```ruby
1267
- gem 'glimmer-dsl-web', '~> 0.0.11'
1365
+ gem 'glimmer-dsl-web', '~> 0.1.0'
1268
1366
  ```
1269
1367
 
1270
1368
  Run:
@@ -1365,7 +1463,7 @@ Document.ready? do
1365
1463
  label(class: 'greeting') {
1366
1464
  'Hello, World!'
1367
1465
  }
1368
- }.render
1466
+ }
1369
1467
  end
1370
1468
  ```
1371
1469
 
@@ -1520,7 +1618,7 @@ include Glimmer
1520
1618
  Document.ready? do
1521
1619
  div {
1522
1620
  'Hello, World!'
1523
- }.render
1621
+ }
1524
1622
  end
1525
1623
  ```
1526
1624
 
@@ -1542,7 +1640,7 @@ require 'glimmer-dsl-web'
1542
1640
  include Glimmer
1543
1641
 
1544
1642
  Document.ready? do
1545
- div('Hello, World!').render
1643
+ div('Hello, World!')
1546
1644
  end
1547
1645
  ```
1548
1646
 
@@ -1574,7 +1672,7 @@ Document.ready? do
1574
1672
  $$.alert('Hello, Button!')
1575
1673
  end
1576
1674
  }
1577
- }.render
1675
+ }
1578
1676
  end
1579
1677
  ```
1580
1678
 
@@ -1675,7 +1773,7 @@ Document.ready? do
1675
1773
  }
1676
1774
  CSS
1677
1775
  }
1678
- }.render
1776
+ }
1679
1777
  end
1680
1778
  ```
1681
1779
 
@@ -1770,7 +1868,11 @@ class HelloObserver
1770
1868
  end
1771
1869
 
1772
1870
  after_render do
1773
- # observe Model attribute @number_holder.number for changes and update View
1871
+ @number_input.value = @number_holder.number
1872
+ @range_input.value = @number_holder.number
1873
+ # Observe Model attribute @number_holder.number for changes and update View
1874
+ # Observer is automatically cleaned up if remove method is called on rendered HelloObserver
1875
+ # or its top-level element
1774
1876
  observe(@number_holder, :number) do
1775
1877
  number_string = @number_holder.number.to_s
1776
1878
  @number_input.value = number_string unless @number_input.value == number_string
@@ -1785,7 +1887,7 @@ class HelloObserver
1785
1887
  markup {
1786
1888
  div {
1787
1889
  div {
1788
- @number_input = input(type: 'number', value: @number_holder.number, min: 0, max: 100) {
1890
+ @number_input = input(type: 'number', min: 0, max: 100) {
1789
1891
  # oninput listener updates Model attribute @number_holder.number
1790
1892
  oninput do
1791
1893
  @number_holder.number = @number_input.value.to_i
@@ -1799,7 +1901,7 @@ class HelloObserver
1799
1901
  }
1800
1902
  }
1801
1903
  div {
1802
- @range_input = input(type: 'range', value: @number_holder.number, min: 0, max: 100) {
1904
+ @range_input = input(type: 'range', min: 0, max: 100) {
1803
1905
  # oninput listener updates Model attribute @number_holder.number
1804
1906
  oninput do
1805
1907
  @number_holder.number = @range_input.value.to_i
@@ -1990,7 +2092,7 @@ Document.ready? do
1990
2092
  computed_by: @address.members + ['state_code'],
1991
2093
  ]
1992
2094
  }
1993
- }.render
2095
+ }
1994
2096
  end
1995
2097
  ```
1996
2098
 
@@ -2125,7 +2227,7 @@ Document.ready? do
2125
2227
  end
2126
2228
  end
2127
2229
  }
2128
- }.render
2230
+ }
2129
2231
  end
2130
2232
  ```
2131
2233
 
@@ -2559,6 +2661,98 @@ Screenshot:
2559
2661
 
2560
2662
  ![Hello, glimmer_component Rails Helper!](/images/glimmer-dsl-web-samples-hello-hello-component.png)
2561
2663
 
2664
+ #### Hello, Paragraph!
2665
+
2666
+ To facilitate building formatted textual paragraphs in Ruby, the Glimmer GUI DSL is advanced enough to behave differently when using HTML formatting elements: `<br>`, `<strong>`, `<em>`, `<br>`, `<i>`, `<sub>`, `<sup>`, `<del>`, `<ins>`, `<small>`, `<mark>`
2667
+
2668
+ Instead of returning Ruby objects that are nested as children within their parent, the Glimmer GUI DSL returns `String` objects directly that can be concatenated to or embedded within other `String` objects via interpolation.
2669
+
2670
+ This enables writing code like:
2671
+
2672
+ `p {"#{strong('Yesterday, ')}Robert suggested adding a new #{em('feature')} to our software product.#{br}}`
2673
+
2674
+ That is close to how it is written in HTML, albeit briefer in Ruby:
2675
+
2676
+ `<p><strong>Yesterday, </strong>Robert suggested adding a new <em>feature</em> to our software product.<br></p>`
2677
+
2678
+ Formatting elements just like regular elements can accept text content as their first argument or as their block return value. So, the code above could equally be written as follows:
2679
+
2680
+ `p {"#{strong{'Yesterday, '}}Robert suggested adding a new #{em{'feature'}} to our software product.#{br}}`
2681
+
2682
+ This enables seggregating formatting element attributes if desired, as in this example:
2683
+
2684
+ `p {"#{strong(class: 'very-string'){'Yesterday, '}}Robert suggested adding a new #{em(class: 'very-emphasized'){'feature'}} to our software product.#{br}}`
2685
+
2686
+ Another way of writing the same code is to pass the text content as the first argument, before attributes:
2687
+
2688
+
2689
+ `p {"#{strong('Yesterday, ', class: 'very-string')}Robert suggested adding a new #{em('feature', class: 'very-emphasized')} to our software product.#{br}}`
2690
+
2691
+ One last bit of info to keep in mind is that `<span>` generally generates a normal element, except when used inside a `<p>`'s content block, in which case it is assumed to be used for formatting, so
2692
+ it returns a `String` to enable code like this:
2693
+
2694
+ `p {"#{span('Yesterday, ', style: 'text-decoration: underline;')}Robert suggested adding a new #{em('feature', class: 'very-emphasized')} to our software product.#{br}}`
2695
+
2696
+ In any case, below is a full example leveraging the Glimmer GUI DSL alternative approach when utilizing formatting elements underneath a paragraph.
2697
+
2698
+ Glimmer GUI code:
2699
+
2700
+ ```ruby
2701
+ require 'glimmer-dsl-web'
2702
+
2703
+ class HelloParagraph
2704
+ include Glimmer::Web::Component
2705
+
2706
+ markup {
2707
+ div {
2708
+ h1(class: 'title') {
2709
+ 'Flying Cars Become 100% Safe with AI Powered Balance!'
2710
+ }
2711
+
2712
+ p(class: 'intro') {"
2713
+ In the early 2030's, #{em('flying cars')} became affordable after their prices dropped
2714
+ below #{small(del('$100,000'))}#{ins('$80,000')} as a result of the innovations of #{strong('Travel-X')}. Still, that did not
2715
+ make #{em('flying cars')} any popular due to the extreme difficulty in piloting such flying vehicles for the average
2716
+ person, making it very tough to pass the tests for getting a piloting license given the learning curve.
2717
+ "}
2718
+
2719
+ p {"
2720
+ That said, #{b('Travel-X')} has recently come up with a new feature for their flagship #{i('flying car')},
2721
+ the Ptero#{sub(1)}#{sup('TM')}, which relies on AI#{sub(2)} to automatically balance the flying cars in mid-air,
2722
+ thus significantly facilitating their piloting by the average consumer.
2723
+ "}
2724
+
2725
+ p(class: 'conclusion') {"
2726
+ That Ptero#{sup('TM')} will be so stable and well balanced while flying that the consumer will be able to drive
2727
+ as if it is a plain old car, with the only difference being vertical elevation, the control of which will be handled
2728
+ automatically by AI. The Ptero#{sup('TM')} will debut for #{span(style: 'text-decoration: underline dashed;'){'$79,000'}}.
2729
+ "}
2730
+
2731
+ h2(class: 'legend-title') {
2732
+ mark('Legend:')
2733
+ }
2734
+
2735
+ p(class: 'legend') {"
2736
+ #{strong("1- Ptero:")} Pterosaur is flying dinosaur species#{br}
2737
+ #{strong("2- AI:")} Artificial Intelligence#{br}
2738
+ "}
2739
+
2740
+ }
2741
+ }
2742
+ end
2743
+
2744
+ Document.ready? do
2745
+ HelloParagraph.render
2746
+ end
2747
+ ```
2748
+
2749
+ Screenshot:
2750
+
2751
+ --
2752
+
2753
+ ![Hello, Paragraph!](/images/glimmer-dsl-web-samples-hello-hello-paragraph.png)
2754
+
2755
+ --
2562
2756
 
2563
2757
  #### Hello, Input (Date/Time)!
2564
2758
 
@@ -2659,7 +2853,7 @@ Document.ready? do
2659
2853
  CSS
2660
2854
  }
2661
2855
  }
2662
- }.render
2856
+ }
2663
2857
  end
2664
2858
  ```
2665
2859
 
@@ -2744,7 +2938,18 @@ Screenshot:
2744
2938
 
2745
2939
  ![Button Counter](/images/glimmer-dsl-web-samples-regular-button-counter.gif)
2746
2940
 
2747
- ## Glimmer Supporting Libraries
2941
+ ## Design Principles
2942
+
2943
+ - The Ruby Way (including TIMTOWTDI: There Is More Than One Way To Do It)
2944
+ - The Rails Way Convention over Configuration via smart defaults and automation of low-level details
2945
+ - Requiring the least amount of syntax possible to build highly interactive web pages
2946
+ - Declarative syntax that visually maps to the DOM (Document Object Model) hierarchy
2947
+ - Ability to mix declarative and imperative code conveniently in one language
2948
+ - Computers serve Software Engineers (not Software Engineers serve Computers)
2949
+ - Think only about real world concepts directly relevant to web page interaction
2950
+ - Modular Software Design (e.g. support for Components)
2951
+
2952
+ ## Supporting Libraries
2748
2953
 
2749
2954
  Here is a list of notable 3rd party gems used by Glimmer DSL for Web:
2750
2955
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML & HTML in pure Ruby.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.11
1
+ 0.1.0
@@ -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.0.11 ruby lib
5
+ # stub: glimmer-dsl-web 0.1.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-dsl-web".freeze
9
- s.version = "0.0.11".freeze
9
+ s.version = "0.1.0".freeze
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-01-06"
15
- s.description = "Glimmer DSL for Web (Ruby in the Browser Web GUI Frontend Library) - Enables frontend GUI development with Ruby by adopting a DSL that follows web-like HTML syntax, enabling the transfer of HTML/CSS/JS skills to Ruby frontend development. This library relies on Opal Ruby.".freeze
14
+ s.date = "2024-01-08"
15
+ s.description = "Glimmer DSL for Web (Ruby in the Browser Web GUI Frontend Library) enables building Web GUI 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 library in existence. The library follows the Ruby way (with DSLs and TIMTOWTDI) and the Rails way (Convention over Configuration) while supporting 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. You can finally live in pure Rubyland on the Web in both the frontend and backend with Glimmer DSL for Web! This library relies on Opal Ruby.".freeze
16
16
  s.email = "andy.am@gmail.com".freeze
17
17
  s.extra_rdoc_files = [
18
18
  "CHANGELOG.md",
@@ -38,6 +38,7 @@ Gem::Specification.new do |s|
38
38
  "lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb",
39
39
  "lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb",
40
40
  "lib/glimmer-dsl-web/samples/hello/hello_observer.rb",
41
+ "lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb",
41
42
  "lib/glimmer-dsl-web/samples/hello/hello_world.rb",
42
43
  "lib/glimmer-dsl-web/samples/regular/button_counter.rb",
43
44
  "lib/glimmer-dsl-web/vendor/jquery.js",
@@ -49,6 +50,7 @@ Gem::Specification.new do |s|
49
50
  "lib/glimmer/dsl/web/data_binding_expression.rb",
50
51
  "lib/glimmer/dsl/web/dsl.rb",
51
52
  "lib/glimmer/dsl/web/element_expression.rb",
53
+ "lib/glimmer/dsl/web/formatting_element_expression.rb",
52
54
  "lib/glimmer/dsl/web/general_element_expression.rb",
53
55
  "lib/glimmer/dsl/web/listener_expression.rb",
54
56
  "lib/glimmer/dsl/web/observe_expression.rb",
@@ -62,6 +64,7 @@ Gem::Specification.new do |s|
62
64
  "lib/glimmer/web/component.rb",
63
65
  "lib/glimmer/web/element_proxy.rb",
64
66
  "lib/glimmer/web/event_proxy.rb",
67
+ "lib/glimmer/web/formatting_element_proxy.rb",
65
68
  "lib/glimmer/web/listener_proxy.rb"
66
69
  ]
67
70
  s.homepage = "http://github.com/AndyObtiva/glimmer-dsl-web".freeze
@@ -21,6 +21,7 @@
21
21
 
22
22
  require 'glimmer/dsl/engine'
23
23
  require 'glimmer/dsl/web/element_expression'
24
+ require 'glimmer/dsl/web/formatting_element_expression'
24
25
  require 'glimmer/dsl/web/listener_expression'
25
26
  require 'glimmer/dsl/web/property_expression'
26
27
  require 'glimmer/dsl/web/p_expression'
@@ -44,6 +45,7 @@ module Glimmer
44
45
  property
45
46
  content_data_binding
46
47
  shine_data_binding
48
+ formatting_element
47
49
  element
48
50
  ]
49
51
  )
@@ -0,0 +1,19 @@
1
+ require 'glimmer/dsl/expression'
2
+
3
+ require 'glimmer/web/formatting_element_proxy'
4
+
5
+ module Glimmer
6
+ module DSL
7
+ module Web
8
+ class FormattingElementExpression < Expression
9
+ def can_interpret?(parent, keyword, *args, &block)
10
+ Glimmer::Web::FormattingElementProxy.keyword_supported?(keyword, parent: parent)
11
+ end
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ Glimmer::Web::FormattingElementProxy.format(keyword, *args, &block)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -93,10 +93,17 @@ module Glimmer
93
93
  self.name.underscore.gsub('::', '__').split('__').last
94
94
  end
95
95
 
96
+ # Creates component without rendering
97
+ def create(*args)
98
+ args << {} unless args.last.is_a?(Hash)
99
+ args.last[:render] = false
100
+ rendered_component = send(keyword, *args)
101
+ rendered_component
102
+ end
103
+
104
+ # Creates and renders component
96
105
  def render(*args)
97
106
  rendered_component = send(keyword, *args)
98
- options = args.last.is_a?(Hash) ? args.last.slice(:parent, :custom_parent_dom_element, :brand_new) : {}
99
- rendered_component.render(**options)
100
107
  rendered_component
101
108
  end
102
109
  end
@@ -204,10 +211,15 @@ module Glimmer
204
211
  markup_block = self.class.instance_variable_get("@markup_block")
205
212
  raise Glimmer::Error, 'Invalid Glimmer web component for having no markup! Please define markup block!' if markup_block.nil?
206
213
  @markup_root = instance_exec(&markup_block)
207
- @markup_root.options[:parent] = options[:parent] if options[:parent]
214
+ @markup_root.options[:parent] = options[:parent] if !options[:parent].nil?
208
215
  @parent ||= @markup_root.parent
209
216
  raise Glimmer::Error, 'Invalid Glimmer web component for having an empty markup! Please fill markup block!' if @markup_root.nil?
210
- execute_hooks('after_render')
217
+ if options[:render] != false
218
+ execute_hooks('after_render')
219
+ else
220
+ on_render_listener = proc { execute_hooks('after_render') }
221
+ @markup_root.handle_observation_request('on_render', on_render_listener)
222
+ end
211
223
 
212
224
  # TODO adapt for web
213
225
  observer_registration_cleanup_listener = proc do
@@ -109,16 +109,25 @@ module Glimmer
109
109
  @keyword = keyword
110
110
  @parent = parent
111
111
  @options = args.last.is_a?(Hash) ? args.last.symbolize_keys : {}
112
+ if parent.nil?
113
+ options[:parent] ||= Component.interpretation_stack.last&.options&.[](:parent)
114
+ options[:render] ||= Component.interpretation_stack.last&.options&.[](:render)
115
+ end
112
116
  @args = args
113
117
  @block = block
114
118
  @children = []
115
119
  @parent&.post_initialize_child(self)
120
+ render if !@rendered && render_after_create?
121
+ end
122
+
123
+ def render_after_create?
124
+ options[:render] != false && (@parent.nil? || @parent.render_after_create?)
116
125
  end
117
126
 
118
127
  # Executes for the parent of a child that just got added
119
128
  def post_initialize_child(child)
120
129
  @children << child
121
- child.render
130
+ child.render if !render_after_create?
122
131
  end
123
132
 
124
133
  # Executes for the parent of a child that just got removed
@@ -128,6 +137,7 @@ module Glimmer
128
137
 
129
138
  # Executes at the closing of a parent widget curly braces after all children/properties have been added/set
130
139
  def post_add_content
140
+ # TODO double check every place we should call this method
131
141
  # No Op
132
142
  end
133
143
 
@@ -215,7 +225,7 @@ module Glimmer
215
225
  def parent_selector
216
226
  @parent&.selector
217
227
  end
218
-
228
+
219
229
  def parent_dom_element
220
230
  if parent_selector
221
231
  Document.find(parent_selector)
@@ -253,8 +263,10 @@ module Glimmer
253
263
  handle_observation_request(keyword, event_listener)
254
264
  end
255
265
  end
256
- children.each do |child|
257
- child.render
266
+ unless render_after_create?
267
+ children.each do |child|
268
+ child.render
269
+ end
258
270
  end
259
271
  @rendered = true
260
272
  unless skip_content_on_render_blocks?
@@ -262,6 +274,10 @@ module Glimmer
262
274
  content(&content_block)
263
275
  end
264
276
  end
277
+ # TODO replace following line with a method call like (`notify_listeners('on_render')`)
278
+ listeners_for('on_render').each do |listener|
279
+ listener.original_event_listener.call(EventProxy.new(listener: listener))
280
+ end
265
281
  end
266
282
  alias rerender render
267
283
 
@@ -302,6 +318,7 @@ module Glimmer
302
318
 
303
319
  def dom
304
320
  # TODO auto-convert known glimmer attributes like parent to data attributes like data-parent
321
+ # TODO check if we need to avoid rendering content block if no content is available
305
322
  @dom ||= html {
306
323
  send(keyword, html_options) {
307
324
  args.first if args.first.is_a?(String)
@@ -1,3 +1,5 @@
1
+ # backtick_javascript: true
2
+
1
3
  # Copyright (c) 2023-2024 Andy Maleh
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining
@@ -0,0 +1,56 @@
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 Glimmer
25
+ module Web
26
+ class FormattingElementProxy
27
+ class << self
28
+ include Glimmer
29
+
30
+ def keyword_supported?(keyword, parent: nil)
31
+ keyword = keyword.to_s
32
+ (
33
+ FORMATTING_ELEMENT_KEYWORDS.include?(keyword) ||
34
+ (parent&.keyword == 'p' && keyword == 'span')
35
+ )
36
+ end
37
+
38
+ def format(keyword, *args, &block)
39
+ content = nil
40
+ if block_given?
41
+ content = block.call.to_s
42
+ elsif args.any? && !args.first.is_a?(Hash)
43
+ content = args.first.to_s
44
+ end
45
+ attribute_hash = args.last.is_a?(Hash) ? args.last : {}
46
+ content_block = proc { content } unless content.nil?
47
+ html {
48
+ send(keyword, attribute_hash, &content_block)
49
+ }.to_s
50
+ end
51
+ end
52
+
53
+ FORMATTING_ELEMENT_KEYWORDS = %w[b i strong em sub sup del ins small mark br]
54
+ end
55
+ end
56
+ end
@@ -30,5 +30,5 @@ Document.ready? do
30
30
  $$.alert('Hello, Button!')
31
31
  end
32
32
  }
33
- }.render
33
+ }
34
34
  end
@@ -137,5 +137,5 @@ Document.ready? do
137
137
  end
138
138
  end
139
139
  }
140
- }.render
140
+ }
141
141
  end
@@ -177,5 +177,5 @@ Document.ready? do
177
177
  computed_by: @address.members + ['state_code'],
178
178
  ]
179
179
  }
180
- }.render
180
+ }
181
181
  end
@@ -98,5 +98,5 @@ Document.ready? do
98
98
  }
99
99
  CSS
100
100
  }
101
- }.render
101
+ }
102
102
  end
@@ -113,5 +113,5 @@ Document.ready? do
113
113
  CSS
114
114
  }
115
115
  }
116
- }.render
116
+ }
117
117
  end
@@ -37,7 +37,11 @@ class HelloObserver
37
37
  end
38
38
 
39
39
  after_render do
40
- # observe Model attribute @number_holder.number for changes and update View
40
+ @number_input.value = @number_holder.number
41
+ @range_input.value = @number_holder.number
42
+ # Observe Model attribute @number_holder.number for changes and update View
43
+ # Observer is automatically cleaned up if remove method is called on rendered HelloObserver
44
+ # or its top-level element
41
45
  observe(@number_holder, :number) do
42
46
  number_string = @number_holder.number.to_s
43
47
  @number_input.value = number_string unless @number_input.value == number_string
@@ -52,7 +56,7 @@ class HelloObserver
52
56
  markup {
53
57
  div {
54
58
  div {
55
- @number_input = input(type: 'number', value: @number_holder.number, min: 0, max: 100) {
59
+ @number_input = input(type: 'number', min: 0, max: 100) {
56
60
  # oninput listener updates Model attribute @number_holder.number
57
61
  oninput do
58
62
  @number_holder.number = @number_input.value.to_i
@@ -66,7 +70,7 @@ class HelloObserver
66
70
  }
67
71
  }
68
72
  div {
69
- @range_input = input(type: 'range', value: @number_holder.number, min: 0, max: 100) {
73
+ @range_input = input(type: 'range', min: 0, max: 100) {
70
74
  # oninput listener updates Model attribute @number_holder.number
71
75
  oninput do
72
76
  @number_holder.number = @range_input.value.to_i
@@ -0,0 +1,67 @@
1
+ # Copyright (c) 2023-2024 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer-dsl-web'
23
+
24
+ class HelloParagraph
25
+ include Glimmer::Web::Component
26
+
27
+ markup {
28
+ div {
29
+ h1(class: 'title') {
30
+ 'Flying Cars Become 100% Safe with AI Powered Balance!'
31
+ }
32
+
33
+ p(class: 'intro') {"
34
+ In the early 2030's, #{em('flying cars')} became affordable after their prices dropped
35
+ below #{small(del('$100,000'))}#{ins('$80,000')} as a result of the innovations of #{strong('Travel-X')}. Still, that did not
36
+ make #{em('flying cars')} any popular due to the extreme difficulty in piloting such flying vehicles for the average
37
+ person, making it very tough to pass the tests for getting a piloting license given the learning curve.
38
+ "}
39
+
40
+ p {"
41
+ That said, #{b('Travel-X')} has recently come up with a new feature for their flagship #{i('flying car')},
42
+ the Ptero#{sub(1)}#{sup('TM')}, which relies on AI#{sub(2)} to automatically balance the flying cars in mid-air,
43
+ thus significantly facilitating their piloting by the average consumer.
44
+ "}
45
+
46
+ p(class: 'conclusion') {"
47
+ That Ptero#{sup('TM')} will be so stable and well balanced while flying that the consumer will be able to drive
48
+ as if it is a plain old car, with the only difference being vertical elevation, the control of which will be handled
49
+ automatically by AI. The Ptero#{sup('TM')} will debut for #{span(style: 'text-decoration: underline dashed;'){'$79,000'}}.
50
+ "}
51
+
52
+ h2(class: 'legend-title') {
53
+ mark('Legend:')
54
+ }
55
+
56
+ p(class: 'legend') {"
57
+ #{strong("1- Ptero:")} Pterosaur is flying dinosaur species#{br}
58
+ #{strong("2- AI:")} Artificial Intelligence#{br}
59
+ "}
60
+
61
+ }
62
+ }
63
+ end
64
+
65
+ Document.ready? do
66
+ HelloParagraph.render
67
+ end
@@ -26,5 +26,5 @@ include Glimmer
26
26
  Document.ready? do
27
27
  div {
28
28
  'Hello, World!'
29
- }.render
29
+ }
30
30
  end
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.0.11
4
+ version: 0.1.0
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-01-06 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -230,10 +230,17 @@ 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 GUI Frontend Library) -
234
- Enables frontend GUI development with Ruby by adopting a DSL that follows web-like
235
- HTML syntax, enabling the transfer of HTML/CSS/JS skills to Ruby frontend development.
236
- This library relies on Opal Ruby.
233
+ description: Glimmer DSL for Web (Ruby in the Browser Web GUI Frontend Library) enables
234
+ building Web GUI frontends using Ruby in the Browser, as per Matz's recommendation
235
+ in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. It aims at
236
+ providing the simplest, most intuitive, most straight-forward, and most productive
237
+ frontend library in existence. The library follows the Ruby way (with DSLs and TIMTOWTDI)
238
+ and the Rails way (Convention over Configuration) while supporting both Unidirectional
239
+ (One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using
240
+ <=>). Dynamic rendering (and re-rendering) of HTML content is also supported via
241
+ Content Data-Binding. And, modular design is supported with Glimmer Web Components.
242
+ You can finally live in pure Rubyland on the Web in both the frontend and backend
243
+ with Glimmer DSL for Web! This library relies on Opal Ruby.
237
244
  email: andy.am@gmail.com
238
245
  executables: []
239
246
  extensions: []
@@ -260,6 +267,7 @@ files:
260
267
  - lib/glimmer-dsl-web/samples/hello/hello_glimmer_component_helper/address_form.rb
261
268
  - lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb
262
269
  - lib/glimmer-dsl-web/samples/hello/hello_observer.rb
270
+ - lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb
263
271
  - lib/glimmer-dsl-web/samples/hello/hello_world.rb
264
272
  - lib/glimmer-dsl-web/samples/regular/button_counter.rb
265
273
  - lib/glimmer-dsl-web/vendor/jquery.js
@@ -271,6 +279,7 @@ files:
271
279
  - lib/glimmer/dsl/web/data_binding_expression.rb
272
280
  - lib/glimmer/dsl/web/dsl.rb
273
281
  - lib/glimmer/dsl/web/element_expression.rb
282
+ - lib/glimmer/dsl/web/formatting_element_expression.rb
274
283
  - lib/glimmer/dsl/web/general_element_expression.rb
275
284
  - lib/glimmer/dsl/web/listener_expression.rb
276
285
  - lib/glimmer/dsl/web/observe_expression.rb
@@ -284,6 +293,7 @@ files:
284
293
  - lib/glimmer/web/component.rb
285
294
  - lib/glimmer/web/element_proxy.rb
286
295
  - lib/glimmer/web/event_proxy.rb
296
+ - lib/glimmer/web/formatting_element_proxy.rb
287
297
  - lib/glimmer/web/listener_proxy.rb
288
298
  homepage: http://github.com/AndyObtiva/glimmer-dsl-web
289
299
  licenses: