glimmer-dsl-web 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +293 -56
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +8 -5
- data/lib/glimmer/data_binding/element_binding.rb +35 -13
- data/lib/glimmer/dsl/web/class_name_inclusion_data_binding.rb +21 -0
- data/lib/glimmer/dsl/web/dsl.rb +6 -2
- data/lib/glimmer/dsl/web/element_expression.rb +12 -1
- data/lib/glimmer/dsl/web/inline_style_data_binding_expression.rb +21 -0
- data/lib/glimmer/dsl/web/{style_expression.rb → style_element_expression.rb} +1 -1
- data/lib/glimmer/web/component.rb +8 -2
- data/lib/glimmer/web/element_proxy.rb +95 -8
- data/lib/glimmer-dsl-web/samples/hello/hello_style.rb +30 -42
- data/lib/glimmer-dsl-web/samples/hello/hello_svg.rb +45 -0
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/edit_todo_input.rb +19 -10
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_form.rb +8 -8
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_input.rb +8 -5
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_filters.rb +64 -51
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_input.rb +14 -14
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list.rb +33 -37
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list_item.rb +62 -59
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_mvc_footer.rb +9 -9
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc.rb +20 -20
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 757705f381e25fbeb5666fd26b544cece14ed84cb335f6b1f7e6a4c273bac53f
|
4
|
+
data.tar.gz: 6a5b9416eb62f2b823f1357c813ee18e417df6e769ae57dcb8704bb8079a31bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d1c13a1b7199085718ccb37158232874a0599eee6bac22036ee86aa0d29ae2cdaf404a1ab701b5a9060cedbb4b846f00750a97a17760430a0731cb2a53e4e65
|
7
|
+
data.tar.gz: 0cd1b2ab98e2abab219c9d5dcbbb49dbf9c5c5f8bfa9b6f8a764589aa3d65dac991a77bd1b865d1f616db5ca82c2eb05b239a60a27b8f6f17a81cdd03365937e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.4.3
|
4
|
+
|
5
|
+
- Support element class name inclusion data-binding (e.g. `class_name('pushed') <= [@button_model, :pushed]`)
|
6
|
+
- Refactor Todo MVC sample to simplify and utilize new element inline style data-binding and element class name inclusion data-binding features
|
7
|
+
- Fix issue with component removal removing its style element even if other instances of the same component still exist (this was breaking TodoMVC when clearly Todo items)
|
8
|
+
|
9
|
+
## 0.4.2
|
10
|
+
|
11
|
+
- Support element inline style data-binding (e.g. `style(:background_color) <= [@button_model, :background_color]`)
|
12
|
+
- Support SVG element keywords
|
13
|
+
- Hello, SVG! Sample: `require 'glimmer-dsl-web/samples/hello/hello_svg'`
|
14
|
+
- Upgrade to glimmer-dsl-css 1.5.1 to get support for `px`, `in`, `pt`, `cm`, `mm`, `em` methods on `Numeric` (e.g. `14.px` => `"14px"` / `2.em` => `"2em"`) and support for `%` method on `Integer`/`Float` to allow producing `%` CSS values (e.g. `90.%` => `"90%"`)
|
15
|
+
|
3
16
|
## 0.4.1
|
4
17
|
|
5
18
|
- Enhance Hello, Style! sample to allow setting styled button background color
|
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.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.4.3 (Beta)
|
2
2
|
## Ruby-in-the-Browser Web Frontend Framework
|
3
3
|
### Finally, Ruby Developer Productivity, Happiness, and Fun in the Frontend!!!
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-web.svg)](http://badge.fury.io/rb/glimmer-dsl-web)
|
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
You can finally have Ruby developer happiness and productivity in the Frontend! No more wasting time splitting your resources across multiple languages, using badly engineered, over-engineered, or premature-optimization-obsessed JavaScript libraries, fighting JavaScript build issues (e.g. webpack), or rewriting Ruby Backend code in Frontend JavaScript. With [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), you can have an exponential jump in development productivity (2x or higher), time-to-release (1/2 or less time), cost (1/2 or cheaper), and maintainability (~50% the code that is simpler and more readable) over JavaScript libraries like React, Angular, Ember, Vue, and Svelte, while being able to reuse Backend Ruby code as is in the Frontend for faster interactions when needed. Also, with Frontend Ruby, companies can cut their hiring budget in half by having Backend Ruby Software Engineers do Frontend Development in Ruby! [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c) finally fulfills every smart highly-productive Rubyist's dream by bringing Ruby productivity fun to Frontend Development, the same productivity fun you had for years and decades in Backend Development.
|
14
14
|
|
15
|
-
[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 supports Rails' principle of the One Person Framework by not requiring any extra developers with JavaScript expertise, yet enabling Ruby (Backend) Software Engineers to develop the Frontend with Ruby code that is better than any JavaScript code produced by JS developers. 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). Modular design is supported with [Glimmer Web Components](#hello-component). And, a Ruby CSS DSL is supported with the included [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css). To automatically convert legacy HTML & CSS code to Glimmer DSL Ruby code, Software Engineers could use the included [`html_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-xml#html-to-glimmer-converter) and [`css_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-css#css-to-glimmer-converter) commands. 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] static site 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)!
|
15
|
+
[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 supports Rails' principle of the One Person Framework by not requiring any extra developers with JavaScript expertise, yet enabling Ruby (Backend) Software Engineers to develop the Frontend with Ruby code that is better than any JavaScript code produced by JS developers. 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) (including full support for [SVG](#hello-svg)), 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). Modular design is supported with [Glimmer Web Components](#hello-component). And, a Ruby CSS DSL is supported with the included [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css). To automatically convert legacy HTML & CSS code to Glimmer DSL Ruby code, Software Engineers could use the included [`html_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-xml#html-to-glimmer-converter) and [`css_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-css#css-to-glimmer-converter) commands. 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] static site 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)!
|
16
16
|
|
17
17
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) aims to be a very simple Ruby-based drop-in replacement for your existing JavaScript Frontend library (e.g. React, Angular, Vue, Ember, Svelte) or your JavaScript Frontend layer in general. It does not change how your Frontend interacts with the Backend, meaning you can continue to write Rails Backend API endpoints as needed and make HTTP/Ajax requests or read data embedded in elements, but from [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c). Whatever is possible in JavaScript is possible when using Glimmer DSL for Web as it integrates with any existing JavaScript library. The [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) demonstrates how to [make HTTP calls](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector/models/sample_api.rb) and how to [integrate with a JavaScript library](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/layouts/application.html.erb) (highlightjs) that performs [code syntax highlighting](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector.rb).
|
18
18
|
|
@@ -1243,10 +1243,6 @@ class TodoMvc
|
|
1243
1243
|
todo_list(presenter: @presenter)
|
1244
1244
|
|
1245
1245
|
todo_filters(presenter: @presenter)
|
1246
|
-
|
1247
|
-
style {
|
1248
|
-
todo_mvc_styles
|
1249
|
-
}
|
1250
1246
|
}
|
1251
1247
|
|
1252
1248
|
todo_mvc_footer
|
@@ -1257,46 +1253,46 @@ class TodoMvc
|
|
1257
1253
|
}
|
1258
1254
|
}
|
1259
1255
|
|
1260
|
-
|
1261
|
-
|
1262
|
-
margin
|
1263
|
-
padding
|
1256
|
+
style {
|
1257
|
+
r('body, button, html') {
|
1258
|
+
margin 0
|
1259
|
+
padding 0
|
1264
1260
|
}
|
1265
1261
|
|
1266
|
-
|
1267
|
-
_webkit_font_smoothing
|
1268
|
-
_webkit_appearance
|
1269
|
-
appearance
|
1270
|
-
background
|
1271
|
-
border
|
1272
|
-
color
|
1273
|
-
font_family
|
1262
|
+
r('button') {
|
1263
|
+
_webkit_font_smoothing :antialiased
|
1264
|
+
_webkit_appearance :none
|
1265
|
+
appearance :none
|
1266
|
+
background :none
|
1267
|
+
border 0
|
1268
|
+
color :inherit
|
1269
|
+
font_family :inherit
|
1274
1270
|
font_size '100%'
|
1275
|
-
font_weight
|
1276
|
-
vertical_align
|
1271
|
+
font_weight :inherit
|
1272
|
+
vertical_align :baseline
|
1277
1273
|
}
|
1278
1274
|
|
1279
|
-
|
1275
|
+
r('.todoapp') {
|
1280
1276
|
background '#fff'
|
1281
1277
|
margin '130px 0 40px 0'
|
1282
|
-
position
|
1278
|
+
position :relative
|
1283
1279
|
box_shadow '0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1)'
|
1284
1280
|
}
|
1285
1281
|
|
1286
1282
|
media('screen and (-webkit-min-device-pixel-ratio:0)') {
|
1287
|
-
|
1283
|
+
r('body') {
|
1288
1284
|
font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
|
1289
|
-
line_height
|
1285
|
+
line_height 1.4.em
|
1290
1286
|
background '#f5f5f5'
|
1291
1287
|
color '#111111'
|
1292
|
-
min_width
|
1293
|
-
max_width
|
1288
|
+
min_width 230
|
1289
|
+
max_width 550
|
1294
1290
|
margin '0 auto'
|
1295
|
-
_webkit_font_smoothing
|
1291
|
+
_webkit_font_smoothing :antialiased
|
1296
1292
|
font_weight '300'
|
1297
1293
|
}
|
1298
1294
|
}
|
1299
|
-
|
1295
|
+
}
|
1300
1296
|
end
|
1301
1297
|
|
1302
1298
|
Document.ready? do
|
@@ -1340,11 +1336,14 @@ Learn more about the differences between various [Glimmer](https://github.com/An
|
|
1340
1336
|
- [Hello, Component!](#hello-content-data-binding)
|
1341
1337
|
- [Hello, glimmer_component Rails Helper!](#hello-glimmer_component-rails-helper)
|
1342
1338
|
- [Hello, Paragraph!](#hello-paragraph)
|
1339
|
+
- [Hello, Style!](#hello-style)
|
1340
|
+
- [Hello, SVG!](#hello-svg)
|
1343
1341
|
- [Hello, Input (Date/Time)!](#hello-input-datetime)
|
1344
1342
|
- [Button Counter](#button-counter)
|
1345
1343
|
- [Todo MVC](#todo-mvc)
|
1346
1344
|
- [Design Principles](#design-principles)
|
1347
1345
|
- [Supporting Libraries](#supporting-libraries)
|
1346
|
+
- [Influences and Inspiration](#influences-and-inspiration)
|
1348
1347
|
- [Glimmer Process](#glimmer-process)
|
1349
1348
|
- [Help](#help)
|
1350
1349
|
- [Issues](#issues)
|
@@ -1391,7 +1390,7 @@ rails new glimmer_app_server
|
|
1391
1390
|
Add the following to `Gemfile`:
|
1392
1391
|
|
1393
1392
|
```
|
1394
|
-
gem 'glimmer-dsl-web', '~> 0.4.
|
1393
|
+
gem 'glimmer-dsl-web', '~> 0.4.3'
|
1395
1394
|
```
|
1396
1395
|
|
1397
1396
|
Run:
|
@@ -1620,7 +1619,7 @@ Disable the `webpacker` gem line in `Gemfile`:
|
|
1620
1619
|
Add the following to `Gemfile`:
|
1621
1620
|
|
1622
1621
|
```ruby
|
1623
|
-
gem 'glimmer-dsl-web', '~> 0.4.
|
1622
|
+
gem 'glimmer-dsl-web', '~> 0.4.3'
|
1624
1623
|
```
|
1625
1624
|
|
1626
1625
|
Run:
|
@@ -3140,6 +3139,239 @@ Screenshot:
|
|
3140
3139
|
|
3141
3140
|
![Hello, Paragraph!](/images/glimmer-dsl-web-samples-hello-hello-paragraph.png)
|
3142
3141
|
|
3142
|
+
#### Hello, Style!
|
3143
|
+
|
3144
|
+
Every Glimmer Web Component can have a `style {}` block that contains CSS styles common to all instances of that element. That block is evaluated against the component class as such.
|
3145
|
+
|
3146
|
+
Also, within every element, you can add `style(:property) <= [model, attribute]` element inline style data-binding statements to dynamically alter a CSS style property based on some changes to a model attribute.
|
3147
|
+
|
3148
|
+
[lib/glimmer-dsl-web/samples/hello/hello_style.rb](/lib/glimmer-dsl-web/samples/hello/hello_style.rb)
|
3149
|
+
|
3150
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
3151
|
+
|
3152
|
+
```ruby
|
3153
|
+
require 'glimmer-dsl-web'
|
3154
|
+
|
3155
|
+
class ButtonModel
|
3156
|
+
WIDTH_MIN = 160
|
3157
|
+
WIDTH_MAX = 960
|
3158
|
+
HEIGHT_MIN = 100
|
3159
|
+
HEIGHT_MAX = 600
|
3160
|
+
FONT_SIZE_MIN = 40
|
3161
|
+
FONT_SIZE_MAX = 200
|
3162
|
+
|
3163
|
+
attr_accessor :text, :pushed, :background_color, :width, :height, :font_size
|
3164
|
+
|
3165
|
+
def initialize
|
3166
|
+
@text = 'Push'
|
3167
|
+
@width = WIDTH_MIN
|
3168
|
+
@height = HEIGHT_MIN
|
3169
|
+
@font_size = FONT_SIZE_MIN
|
3170
|
+
@background_color = '#add8e6'
|
3171
|
+
end
|
3172
|
+
|
3173
|
+
def push
|
3174
|
+
self.pushed = !pushed
|
3175
|
+
end
|
3176
|
+
|
3177
|
+
def text
|
3178
|
+
pushed ? 'Pull' : 'Push'
|
3179
|
+
end
|
3180
|
+
|
3181
|
+
def width=(value)
|
3182
|
+
@width = value
|
3183
|
+
self.font_size = @width/4 if @font_size > @width/4
|
3184
|
+
end
|
3185
|
+
|
3186
|
+
def height=(value)
|
3187
|
+
@height = value
|
3188
|
+
self.font_size = @height/2.5 if @font_size > @height/2.5
|
3189
|
+
end
|
3190
|
+
|
3191
|
+
def font_size=(value)
|
3192
|
+
@font_size = value
|
3193
|
+
self.width = @font_size*4 if @height < @font_size*4
|
3194
|
+
self.height = @font_size*2.5 if @height < @font_size*2.5
|
3195
|
+
end
|
3196
|
+
|
3197
|
+
def border_color
|
3198
|
+
red = background_color[1..2].hex
|
3199
|
+
green = background_color[3..4].hex
|
3200
|
+
blue = background_color[5..6].hex
|
3201
|
+
new_red = red - 10
|
3202
|
+
new_green = green - 10
|
3203
|
+
new_blue = blue - 10
|
3204
|
+
"##{new_red.to_s(16)}#{new_green.to_s(16)}#{new_blue.to_s(16)}"
|
3205
|
+
end
|
3206
|
+
end
|
3207
|
+
|
3208
|
+
class StyledButton
|
3209
|
+
include Glimmer::Web::Component
|
3210
|
+
|
3211
|
+
option :button_model
|
3212
|
+
|
3213
|
+
markup {
|
3214
|
+
button {
|
3215
|
+
inner_text <= [button_model, :text, computed_by: :pushed]
|
3216
|
+
|
3217
|
+
class_name(:pushed) <= [button_model, :pushed]
|
3218
|
+
class_name(:pulled) <= [button_model, :pushed, on_read: :!]
|
3219
|
+
|
3220
|
+
style(:width) <= [button_model, :width, on_read: :px]
|
3221
|
+
style(:height) <= [button_model, :height, on_read: :px]
|
3222
|
+
style(:font_size) <= [button_model, :font_size, on_read: :px]
|
3223
|
+
style(:background_color) <= [button_model, :background_color]
|
3224
|
+
style(:border_color) <= [button_model, :border_color, computed_by: :background_color]
|
3225
|
+
|
3226
|
+
onclick do
|
3227
|
+
button_model.push
|
3228
|
+
end
|
3229
|
+
}
|
3230
|
+
}
|
3231
|
+
|
3232
|
+
style {
|
3233
|
+
r(component_element_selector) {
|
3234
|
+
font_family 'Courrier New, Courrier'
|
3235
|
+
border_radius 5
|
3236
|
+
border_width 17
|
3237
|
+
margin 5
|
3238
|
+
}
|
3239
|
+
|
3240
|
+
r("#{component_element_selector}.pulled") {
|
3241
|
+
border_style :outset
|
3242
|
+
}
|
3243
|
+
|
3244
|
+
r("#{component_element_selector}.pushed") {
|
3245
|
+
border_style :inset
|
3246
|
+
}
|
3247
|
+
}
|
3248
|
+
end
|
3249
|
+
|
3250
|
+
class StyledButtonRangeInput
|
3251
|
+
include Glimmer::Web::Component
|
3252
|
+
|
3253
|
+
option :button_model
|
3254
|
+
option :property
|
3255
|
+
option :property_min
|
3256
|
+
option :property_max
|
3257
|
+
|
3258
|
+
markup {
|
3259
|
+
input(type: 'range', min: property_min, max: property_max) {
|
3260
|
+
value <=> [button_model, property]
|
3261
|
+
}
|
3262
|
+
}
|
3263
|
+
end
|
3264
|
+
|
3265
|
+
class StyledButtonColorInput
|
3266
|
+
include Glimmer::Web::Component
|
3267
|
+
|
3268
|
+
option :button_model
|
3269
|
+
option :property
|
3270
|
+
|
3271
|
+
markup {
|
3272
|
+
input(type: 'color') {
|
3273
|
+
value <=> [button_model, property]
|
3274
|
+
}
|
3275
|
+
}
|
3276
|
+
end
|
3277
|
+
|
3278
|
+
class HelloStyle
|
3279
|
+
include Glimmer::Web::Component
|
3280
|
+
|
3281
|
+
before_render do
|
3282
|
+
@button_model = ButtonModel.new
|
3283
|
+
end
|
3284
|
+
|
3285
|
+
markup {
|
3286
|
+
div {
|
3287
|
+
div(class: 'styled-button-form') {
|
3288
|
+
label('Styled Button Width:', class: 'property-label', for: 'styled-button-width-input')
|
3289
|
+
styled_button_range_input(button_model: @button_model, property: :width, property_min: ButtonModel::WIDTH_MIN, property_max: ButtonModel::WIDTH_MAX, id: 'styled-button-width-input')
|
3290
|
+
|
3291
|
+
label('Styled Button Height:', class: 'property-label', for: 'styled-button-height-input')
|
3292
|
+
styled_button_range_input(button_model: @button_model, property: :height, property_min: ButtonModel::HEIGHT_MIN, property_max: ButtonModel::HEIGHT_MAX, id: 'styled-button-height-input')
|
3293
|
+
|
3294
|
+
label('Styled Button Font Size:', class: 'property-label', for: 'styled-button-font-size-input')
|
3295
|
+
styled_button_range_input(button_model: @button_model, property: :font_size, property_min: ButtonModel::FONT_SIZE_MIN, property_max: ButtonModel::FONT_SIZE_MAX, id: 'styled-button-font-size-input')
|
3296
|
+
|
3297
|
+
label('Styled Button Background Color:', for: 'styled-button-background-color-input')
|
3298
|
+
styled_button_color_input(button_model: @button_model, property: :background_color, id: 'styled-button-background-color-input')
|
3299
|
+
}
|
3300
|
+
|
3301
|
+
styled_button(button_model: @button_model)
|
3302
|
+
}
|
3303
|
+
}
|
3304
|
+
|
3305
|
+
style {
|
3306
|
+
r('.styled-button-form') {
|
3307
|
+
padding 20
|
3308
|
+
display 'inline-grid'
|
3309
|
+
grid_template_columns 'auto auto'
|
3310
|
+
}
|
3311
|
+
|
3312
|
+
r('.styled-button-form label, input') {
|
3313
|
+
display :block
|
3314
|
+
margin '5px 5px 5px 0'
|
3315
|
+
}
|
3316
|
+
|
3317
|
+
r("#{component_element_selector} .styled-button") {
|
3318
|
+
display :block
|
3319
|
+
}
|
3320
|
+
}
|
3321
|
+
end
|
3322
|
+
|
3323
|
+
Document.ready? do
|
3324
|
+
HelloStyle.render
|
3325
|
+
end
|
3326
|
+
```
|
3327
|
+
|
3328
|
+
Screenshot:
|
3329
|
+
|
3330
|
+
--
|
3331
|
+
|
3332
|
+
![Hello, Style!](/images/glimmer-dsl-web-samples-hello-hello-style.gif)
|
3333
|
+
|
3334
|
+
#### Hello, SVG!
|
3335
|
+
|
3336
|
+
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG) (Scalable Vector Graphics) is fully supported and can be utilized by simply embedding [SVG elements](https://developer.mozilla.org/en-US/docs/Web/SVG/Element) (all lower-case in Ruby) via the Glimmer HTML DSL syntax, just like any other HTML elements.
|
3337
|
+
|
3338
|
+
[lib/glimmer-dsl-web/samples/hello/hello_svg.rb](/lib/glimmer-dsl-web/samples/hello/hello_svg.rb)
|
3339
|
+
|
3340
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
3341
|
+
|
3342
|
+
```ruby
|
3343
|
+
require 'glimmer-dsl-web'
|
3344
|
+
|
3345
|
+
class HelloSvg
|
3346
|
+
include Glimmer::Web::Component
|
3347
|
+
|
3348
|
+
markup {
|
3349
|
+
div {
|
3350
|
+
svg(width: '100%', height: '100') {
|
3351
|
+
circle(cx: '50', cy: '50', r: '50', style: 'fill:blue;') {
|
3352
|
+
animate(attributename: 'cx', begin: '0s', dur: '8s', from: '50', to: '90%', repeatcount: 'indefinite')
|
3353
|
+
}
|
3354
|
+
}
|
3355
|
+
svg(width: '200', height: '180') {
|
3356
|
+
rect(x: '30', y: '30', height: '110', width: '110', style: 'stroke:green;fill:red') {
|
3357
|
+
animatetransform(attributename: 'transform', begin: '0.1s', dur: '10s', type: 'rotate', from: '0 85 85', to: '360 85 85', repeatcount: 'indefinite')
|
3358
|
+
}
|
3359
|
+
}
|
3360
|
+
}
|
3361
|
+
}
|
3362
|
+
end
|
3363
|
+
|
3364
|
+
Document.ready? do
|
3365
|
+
HelloSvg.render
|
3366
|
+
end
|
3367
|
+
```
|
3368
|
+
|
3369
|
+
Screenshot:
|
3370
|
+
|
3371
|
+
--
|
3372
|
+
|
3373
|
+
![Hello, SVG!](/images/glimmer-dsl-web-samples-hello-hello-svg.gif)
|
3374
|
+
|
3143
3375
|
--
|
3144
3376
|
|
3145
3377
|
#### Hello, Input (Date/Time)!
|
@@ -3365,10 +3597,6 @@ class TodoMvc
|
|
3365
3597
|
todo_list(presenter: @presenter)
|
3366
3598
|
|
3367
3599
|
todo_filters(presenter: @presenter)
|
3368
|
-
|
3369
|
-
style {
|
3370
|
-
todo_mvc_styles
|
3371
|
-
}
|
3372
3600
|
}
|
3373
3601
|
|
3374
3602
|
todo_mvc_footer
|
@@ -3379,46 +3607,46 @@ class TodoMvc
|
|
3379
3607
|
}
|
3380
3608
|
}
|
3381
3609
|
|
3382
|
-
|
3383
|
-
|
3384
|
-
margin
|
3385
|
-
padding
|
3610
|
+
style {
|
3611
|
+
r('body, button, html') {
|
3612
|
+
margin 0
|
3613
|
+
padding 0
|
3386
3614
|
}
|
3387
3615
|
|
3388
|
-
|
3389
|
-
_webkit_font_smoothing
|
3390
|
-
_webkit_appearance
|
3391
|
-
appearance
|
3392
|
-
background
|
3393
|
-
border
|
3394
|
-
color
|
3395
|
-
font_family
|
3616
|
+
r('button') {
|
3617
|
+
_webkit_font_smoothing :antialiased
|
3618
|
+
_webkit_appearance :none
|
3619
|
+
appearance :none
|
3620
|
+
background :none
|
3621
|
+
border 0
|
3622
|
+
color :inherit
|
3623
|
+
font_family :inherit
|
3396
3624
|
font_size '100%'
|
3397
|
-
font_weight
|
3398
|
-
vertical_align
|
3625
|
+
font_weight :inherit
|
3626
|
+
vertical_align :baseline
|
3399
3627
|
}
|
3400
3628
|
|
3401
|
-
|
3629
|
+
r('.todoapp') {
|
3402
3630
|
background '#fff'
|
3403
3631
|
margin '130px 0 40px 0'
|
3404
|
-
position
|
3632
|
+
position :relative
|
3405
3633
|
box_shadow '0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1)'
|
3406
3634
|
}
|
3407
3635
|
|
3408
3636
|
media('screen and (-webkit-min-device-pixel-ratio:0)') {
|
3409
|
-
|
3637
|
+
r('body') {
|
3410
3638
|
font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
|
3411
|
-
line_height
|
3639
|
+
line_height 1.4.em
|
3412
3640
|
background '#f5f5f5'
|
3413
3641
|
color '#111111'
|
3414
|
-
min_width
|
3415
|
-
max_width
|
3642
|
+
min_width 230
|
3643
|
+
max_width 550
|
3416
3644
|
margin '0 auto'
|
3417
|
-
_webkit_font_smoothing
|
3645
|
+
_webkit_font_smoothing :antialiased
|
3418
3646
|
font_weight '300'
|
3419
3647
|
}
|
3420
3648
|
}
|
3421
|
-
|
3649
|
+
}
|
3422
3650
|
end
|
3423
3651
|
|
3424
3652
|
Document.ready? do
|
@@ -3448,6 +3676,15 @@ Here is a list of notable 3rd party gems used by Glimmer DSL for Web:
|
|
3448
3676
|
- [opal-async](https://github.com/AndyObtiva/opal-async): Non-blocking tasks and enumerators for Web.
|
3449
3677
|
- [to_collection](https://github.com/AndyObtiva/to_collection): Treat an array of objects and a singular object uniformly as a collection of objects.
|
3450
3678
|
|
3679
|
+
## Influences and Inspiration
|
3680
|
+
|
3681
|
+
- https://github.com/inesita-rb/inesita
|
3682
|
+
- https://github.com/opal/paggio
|
3683
|
+
- https://github.com/ruby-hyperloop/hyperloop
|
3684
|
+
- https://docs.hyperstack.org/
|
3685
|
+
- https://github.com/AndyObtiva/glimmer-dsl-opal
|
3686
|
+
- https://github.com/AndyObtiva/glimmer
|
3687
|
+
|
3451
3688
|
## Glimmer Process
|
3452
3689
|
|
3453
3690
|
[Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md) is the lightweight software development process used for building Glimmer libraries and Glimmer apps, which goes beyond Agile, rendering all Agile processes obsolete. [Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md) is simply made up of 7 guidelines to pick and choose as necessary until software development needs are satisfied.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.3
|
data/glimmer-dsl-web.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
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.4.
|
5
|
+
# stub: glimmer-dsl-web 0.4.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-web".freeze
|
9
|
-
s.version = "0.4.
|
9
|
+
s.version = "0.4.3"
|
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-07-
|
14
|
+
s.date = "2024-07-28"
|
15
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. Modular design is supported with Glimmer Web Components. And, a Ruby CSS DSL is supported with the included Glimmer DSL for CSS. 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 = [
|
@@ -47,6 +47,7 @@ Gem::Specification.new do |s|
|
|
47
47
|
"lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb",
|
48
48
|
"lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb",
|
49
49
|
"lib/glimmer-dsl-web/samples/hello/hello_style.rb",
|
50
|
+
"lib/glimmer-dsl-web/samples/hello/hello_svg.rb",
|
50
51
|
"lib/glimmer-dsl-web/samples/hello/hello_world.rb",
|
51
52
|
"lib/glimmer-dsl-web/samples/regular/button_counter.rb",
|
52
53
|
"lib/glimmer-dsl-web/samples/regular/todo_mvc.rb",
|
@@ -65,6 +66,7 @@ Gem::Specification.new do |s|
|
|
65
66
|
"lib/glimmer/data_binding/element_binding.rb",
|
66
67
|
"lib/glimmer/dsl/web/a_expression.rb",
|
67
68
|
"lib/glimmer/dsl/web/bind_expression.rb",
|
69
|
+
"lib/glimmer/dsl/web/class_name_inclusion_data_binding.rb",
|
68
70
|
"lib/glimmer/dsl/web/component_expression.rb",
|
69
71
|
"lib/glimmer/dsl/web/content_data_binding_expression.rb",
|
70
72
|
"lib/glimmer/dsl/web/data_binding_expression.rb",
|
@@ -72,12 +74,13 @@ Gem::Specification.new do |s|
|
|
72
74
|
"lib/glimmer/dsl/web/element_expression.rb",
|
73
75
|
"lib/glimmer/dsl/web/formatting_element_expression.rb",
|
74
76
|
"lib/glimmer/dsl/web/general_element_expression.rb",
|
77
|
+
"lib/glimmer/dsl/web/inline_style_data_binding_expression.rb",
|
75
78
|
"lib/glimmer/dsl/web/listener_expression.rb",
|
76
79
|
"lib/glimmer/dsl/web/observe_expression.rb",
|
77
80
|
"lib/glimmer/dsl/web/property_expression.rb",
|
78
81
|
"lib/glimmer/dsl/web/shine_data_binding_expression.rb",
|
79
82
|
"lib/glimmer/dsl/web/span_expression.rb",
|
80
|
-
"lib/glimmer/dsl/web/
|
83
|
+
"lib/glimmer/dsl/web/style_element_expression.rb",
|
81
84
|
"lib/glimmer/helpers/glimmer_helper.rb",
|
82
85
|
"lib/glimmer/util/proc_tracker.rb",
|
83
86
|
"lib/glimmer/web.rb",
|
@@ -97,7 +100,7 @@ Gem::Specification.new do |s|
|
|
97
100
|
|
98
101
|
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.8.0"])
|
99
102
|
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0"])
|
100
|
-
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.5.
|
103
|
+
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.5.1"])
|
101
104
|
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2"])
|
102
105
|
s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3"])
|
103
106
|
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1"])
|
@@ -6,30 +6,52 @@ module Glimmer
|
|
6
6
|
class ElementBinding
|
7
7
|
include Observable
|
8
8
|
include Observer
|
9
|
-
|
10
|
-
attr_reader :element, :property
|
11
|
-
def initialize(element, property, translator
|
9
|
+
|
10
|
+
attr_reader :element, :property, :translator, :sub_property
|
11
|
+
def initialize(element, property, translator: nil)
|
12
12
|
@element = element
|
13
|
-
|
13
|
+
if (property_parts = property.to_s.match(Glimmer::Web::ElementProxy::REGEX_CLASS_NAME_SUB_PROPERTY))
|
14
|
+
@property, @sub_property = property_parts.to_a.drop(1)
|
15
|
+
elsif (property_parts = property.to_s.match(Glimmer::Web::ElementProxy::REGEX_STYLE_SUB_PROPERTY))
|
16
|
+
@property, @sub_property = property_parts.to_a.drop(1)
|
17
|
+
@sub_property = @sub_property.gsub('_', '-')
|
18
|
+
else
|
19
|
+
@property = property
|
20
|
+
end
|
14
21
|
@translator = translator
|
15
22
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# unregister_all_observables
|
21
|
-
# end
|
22
|
-
# end
|
23
|
+
if @element.respond_to?(:remove)
|
24
|
+
unregister_handler = lambda { |dispose_event| unregister_all_observables }
|
25
|
+
@element.handle_observation_request('on_remove', unregister_handler)
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
def call(value)
|
26
30
|
evaluated_property_value = evaluate_property
|
27
31
|
converted_value = @translator&.call(value, evaluated_property_value) || value
|
28
|
-
|
32
|
+
if converted_value != evaluated_property_value
|
33
|
+
if @sub_property
|
34
|
+
if @property.to_s == 'class_name'
|
35
|
+
@element.class_name_included(@sub_property, converted_value)
|
36
|
+
elsif @property.to_s == 'style'
|
37
|
+
@element.style_property(@sub_property, converted_value)
|
38
|
+
end
|
39
|
+
else
|
40
|
+
@element.send("#{@property}=", converted_value)
|
41
|
+
end
|
42
|
+
end
|
29
43
|
end
|
30
44
|
|
31
45
|
def evaluate_property
|
32
|
-
@
|
46
|
+
if @sub_property
|
47
|
+
if @property.to_s == 'class_name'
|
48
|
+
@element.class_name_included(@sub_property)
|
49
|
+
elsif @property.to_s == 'style'
|
50
|
+
@element.style_property(@sub_property)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
@element.send(@property)
|
54
|
+
end
|
33
55
|
end
|
34
56
|
end
|
35
57
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'glimmer/dsl/expression'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module DSL
|
5
|
+
module Web
|
6
|
+
class ClassNameInclusionDataBindingExpression < Expression
|
7
|
+
def can_interpret?(parent, keyword, *args, &block)
|
8
|
+
keyword == 'class_name' &&
|
9
|
+
block.nil? &&
|
10
|
+
args.size == 1 &&
|
11
|
+
textual?(args.first)
|
12
|
+
end
|
13
|
+
|
14
|
+
def interpret(parent, keyword, *args, &block)
|
15
|
+
parent_attribute = "#{keyword}_#{args.first.to_s}"
|
16
|
+
Glimmer::DataBinding::Shine.new(parent, parent_attribute)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|