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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a248314a1dcc33c038a9d2f542dce35d31d7d5702435a1c8db5b13b75068470
4
- data.tar.gz: 8d83a134edc023c5ec2debe421a7f45e11887671b918ba75532574bf3019525a
3
+ metadata.gz: 757705f381e25fbeb5666fd26b544cece14ed84cb335f6b1f7e6a4c273bac53f
4
+ data.tar.gz: 6a5b9416eb62f2b823f1357c813ee18e417df6e769ae57dcb8704bb8079a31bd
5
5
  SHA512:
6
- metadata.gz: 64e47e6380713ca42182644f9b20b0f4137deaf951707413d49f3909346be470e66426f09aa5f3a67656808b3bfb3e07bc00ee27a8c54167ec3cbb80f254972e
7
- data.tar.gz: d55f560a40cb259fa0b28ee82be1cb066efe26aa4d44f749ec05bcb97ba1f5ff735a44a252100fa8565a8338aa9b53bab0f77c6719e12061f40d40e18b1abb04
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 (Beta)
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
- def todo_mvc_styles
1261
- rule('body, button, html') {
1262
- margin '0'
1263
- padding '0'
1256
+ style {
1257
+ r('body, button, html') {
1258
+ margin 0
1259
+ padding 0
1264
1260
  }
1265
1261
 
1266
- rule('button') {
1267
- _webkit_font_smoothing 'antialiased'
1268
- _webkit_appearance 'none'
1269
- appearance 'none'
1270
- background 'none'
1271
- border '0'
1272
- color 'inherit'
1273
- font_family 'inherit'
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 'inherit'
1276
- vertical_align 'baseline'
1271
+ font_weight :inherit
1272
+ vertical_align :baseline
1277
1273
  }
1278
1274
 
1279
- rule('.todoapp') {
1275
+ r('.todoapp') {
1280
1276
  background '#fff'
1281
1277
  margin '130px 0 40px 0'
1282
- position 'relative'
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
- rule('body') {
1283
+ r('body') {
1288
1284
  font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
1289
- line_height '1.4em'
1285
+ line_height 1.4.em
1290
1286
  background '#f5f5f5'
1291
1287
  color '#111111'
1292
- min_width '230px'
1293
- max_width '550px'
1288
+ min_width 230
1289
+ max_width 550
1294
1290
  margin '0 auto'
1295
- _webkit_font_smoothing 'antialiased'
1291
+ _webkit_font_smoothing :antialiased
1296
1292
  font_weight '300'
1297
1293
  }
1298
1294
  }
1299
- end
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.1'
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.1'
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
- def todo_mvc_styles
3383
- rule('body, button, html') {
3384
- margin '0'
3385
- padding '0'
3610
+ style {
3611
+ r('body, button, html') {
3612
+ margin 0
3613
+ padding 0
3386
3614
  }
3387
3615
 
3388
- rule('button') {
3389
- _webkit_font_smoothing 'antialiased'
3390
- _webkit_appearance 'none'
3391
- appearance 'none'
3392
- background 'none'
3393
- border '0'
3394
- color 'inherit'
3395
- font_family 'inherit'
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 'inherit'
3398
- vertical_align 'baseline'
3625
+ font_weight :inherit
3626
+ vertical_align :baseline
3399
3627
  }
3400
3628
 
3401
- rule('.todoapp') {
3629
+ r('.todoapp') {
3402
3630
  background '#fff'
3403
3631
  margin '130px 0 40px 0'
3404
- position 'relative'
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
- rule('body') {
3637
+ r('body') {
3410
3638
  font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
3411
- line_height '1.4em'
3639
+ line_height 1.4.em
3412
3640
  background '#f5f5f5'
3413
3641
  color '#111111'
3414
- min_width '230px'
3415
- max_width '550px'
3642
+ min_width 230
3643
+ max_width 550
3416
3644
  margin '0 auto'
3417
- _webkit_font_smoothing 'antialiased'
3645
+ _webkit_font_smoothing :antialiased
3418
3646
  font_weight '300'
3419
3647
  }
3420
3648
  }
3421
- end
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
1
+ 0.4.3
@@ -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.1 ruby lib
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.1"
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-27"
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/style_expression.rb",
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.0"])
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 = nil)
9
+
10
+ attr_reader :element, :property, :translator, :sub_property
11
+ def initialize(element, property, translator: nil)
12
12
  @element = element
13
- @property = property
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
- # TODO implement automatic cleanup upon calling element.remove
17
- # Alternatively, have this be built into ElementProxy and remove this code
18
- # if @element.respond_to?(:dispose)
19
- # @element.on_widget_disposed do |dispose_event|
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
- @element.send("#{@property}=", converted_value) unless converted_value == evaluated_property_value
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
- @element.send(@property)
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