glimmer-dsl-web 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +265 -16
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +9 -6
- data/lib/glimmer/dsl/web/content_data_binding_expression.rb +41 -0
- data/lib/glimmer/dsl/web/dsl.rb +2 -9
- data/lib/glimmer/dsl/web/element_expression.rb +3 -3
- data/lib/glimmer/web/element_proxy.rb +70 -3
- data/lib/glimmer/web/listener_proxy.rb +0 -1
- data/lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb +137 -0
- data/lib/glimmer-dsl-web.rb +6 -2
- metadata +48 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '028be0c05ee74f8e639b3b43adbdd52e7b90e7e5b52a0e7026fbf74e0d017300'
|
4
|
+
data.tar.gz: d2b8e3fc639dfa55655f05faf740fd36fcf518bc143eb8f08a874be3e34f72ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9a0add34e7db5cd7d0816e0006ed0426f9bc739402e4951f672195f6dcce472943b5f5c501213269b0ec84fb636aaea701fe35326639827bd580b94db370a5a
|
7
|
+
data.tar.gz: 19ccf1280735e472c6f643a21e105f0b1020fdacc53a66f63588be6f7b8faddb1e8391667094687a204c3d1363ee760c6b752c84866b86323437c17b8fdbe7d6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.0.8
|
4
|
+
|
5
|
+
- Validate that element keywords belong to the valid list of HTML element tag names to prevent rendering fake elements the keyword does not match a real HTML element tag
|
6
|
+
- Support inner_html/outer_html properties (it seems they did not convert to innerHTML/outerHTML correctly because of the all caps HTML)
|
7
|
+
- Support element properties via original JS names (e.g. innerHTML) to prevent logic from breaking if some do not convert correctly from underscored versions
|
8
|
+
- Package dependencies properly in the gem to avoid instructing users to add in Rails Gemfile manually
|
9
|
+
- Content Data-Binding support to regenerate element content based on changes to an observed model attribute.
|
10
|
+
Content Data-Binding Example:
|
11
|
+
content(*data_binding_options) { |data_binding_value|
|
12
|
+
li {
|
13
|
+
data_binding_value
|
14
|
+
}
|
15
|
+
}
|
16
|
+
- Ensuring removing data-binding model listeners when calling `element#remove` in addition to already removing standard HTML event listeners
|
17
|
+
- New Hello, Content Data-Binding! Sample: `require 'glimmer-dsl-web/samples/hello/hello_content_data_binding'`
|
18
|
+
|
3
19
|
## 0.0.7
|
4
20
|
|
5
21
|
- Support input[type=number] value data-binding as a Ruby Numeric object (Integer or Float)
|
data/README.md
CHANGED
@@ -1,9 +1,11 @@
|
|
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.
|
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.8 (Early Alpha)
|
2
2
|
## Ruby in the Browser Web GUI Frontend Library
|
3
3
|
[](http://badge.fury.io/rb/glimmer-dsl-web)
|
4
4
|
[](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
5
5
|
|
6
|
-
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web GUI frontends using [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), as per [Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby](https://youtu.be/knutsgHTrfQ?t=789). It aims at providing the simplest, most intuitive,
|
6
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web GUI frontends using [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), as per [Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby](https://youtu.be/knutsgHTrfQ?t=789). It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend library in existence. The library 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)) 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. You can finally live in pure Rubyland on the Web in both the frontend and backend with [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web)!
|
7
|
+
|
8
|
+
(the project plans to add component support very soon, albeit components are already supported by creating your own Ruby classes and having them render part of the GUI hierarchy)
|
7
9
|
|
8
10
|
**Hello, World! Sample**
|
9
11
|
|
@@ -337,6 +339,137 @@ Screenshot:
|
|
337
339
|
|
338
340
|

|
339
341
|
|
342
|
+
**Hello, Content Data-Binding!**
|
343
|
+
|
344
|
+
If you need to regenerate HTML element content dynamically, you can use Content Data-Binding to effortlessly
|
345
|
+
rebuild HTML elements based on changes in a Model attribute that provides the source data.
|
346
|
+
In this example, we generate multiple address forms based on the number of addresses the user has.
|
347
|
+
|
348
|
+
Glimmer GUI code:
|
349
|
+
|
350
|
+
```ruby
|
351
|
+
require 'glimmer-dsl-web'
|
352
|
+
|
353
|
+
class Address
|
354
|
+
attr_accessor :text
|
355
|
+
attr_reader :name, :street, :city, :state, :zip
|
356
|
+
|
357
|
+
def name=(value)
|
358
|
+
@name = value
|
359
|
+
update_text
|
360
|
+
end
|
361
|
+
|
362
|
+
def street=(value)
|
363
|
+
@street = value
|
364
|
+
update_text
|
365
|
+
end
|
366
|
+
|
367
|
+
def city=(value)
|
368
|
+
@city = value
|
369
|
+
update_text
|
370
|
+
end
|
371
|
+
|
372
|
+
def state=(value)
|
373
|
+
@state = value
|
374
|
+
update_text
|
375
|
+
end
|
376
|
+
|
377
|
+
def zip=(value)
|
378
|
+
@zip = value
|
379
|
+
update_text
|
380
|
+
end
|
381
|
+
|
382
|
+
private
|
383
|
+
|
384
|
+
def update_text
|
385
|
+
self.text = [name, street, city, state, zip].compact.reject(&:empty?).join(', ')
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
class User
|
390
|
+
attr_accessor :addresses
|
391
|
+
attr_reader :address_count
|
392
|
+
|
393
|
+
def initialize
|
394
|
+
@address_count = 1
|
395
|
+
@addresses = []
|
396
|
+
update_addresses
|
397
|
+
end
|
398
|
+
|
399
|
+
def address_count=(value)
|
400
|
+
value = [[1, value.to_i].max, 3].min
|
401
|
+
@address_count = value
|
402
|
+
update_addresses
|
403
|
+
end
|
404
|
+
|
405
|
+
private
|
406
|
+
|
407
|
+
def update_addresses
|
408
|
+
address_count_change = address_count - addresses.size
|
409
|
+
if address_count_change > 0
|
410
|
+
address_count_change.times { addresses << Address.new }
|
411
|
+
else
|
412
|
+
address_count_change.abs.times { addresses.pop }
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
@user = User.new
|
418
|
+
|
419
|
+
div {
|
420
|
+
div {
|
421
|
+
label('Number of addresses: ', for: 'address-count-field')
|
422
|
+
input(id: 'address-count-field', type: 'number', min: 1, max: 3) {
|
423
|
+
value <=> [@user, :address_count]
|
424
|
+
}
|
425
|
+
}
|
426
|
+
|
427
|
+
div {
|
428
|
+
# Content Data-Binding is used to dynamically (re)generate content of div
|
429
|
+
# based on changes to @user.addresses, replacing older content on every change
|
430
|
+
content(@user, :addresses) do
|
431
|
+
@user.addresses.each do |address|
|
432
|
+
div {
|
433
|
+
div(style: 'display: grid; grid-auto-columns: 80px 280px;') { |address_div|
|
434
|
+
[:name, :street, :city, :state, :zip].each do |attribute|
|
435
|
+
label(attribute.to_s.capitalize, for: "#{attribute}-field")
|
436
|
+
input(id: "#{attribute}-field", type: 'text') {
|
437
|
+
value <=> [address, attribute]
|
438
|
+
}
|
439
|
+
end
|
440
|
+
|
441
|
+
div(style: 'grid-column: 1 / span 2;') {
|
442
|
+
inner_text <= [address, :text]
|
443
|
+
}
|
444
|
+
|
445
|
+
style {
|
446
|
+
<<~CSS
|
447
|
+
#{address_div.selector} {
|
448
|
+
margin: 10px 0;
|
449
|
+
}
|
450
|
+
#{address_div.selector} * {
|
451
|
+
margin: 5px;
|
452
|
+
}
|
453
|
+
#{address_div.selector} label {
|
454
|
+
grid-column: 1;
|
455
|
+
}
|
456
|
+
#{address_div.selector} input, #{address_div.selector} select {
|
457
|
+
grid-column: 2;
|
458
|
+
}
|
459
|
+
CSS
|
460
|
+
}
|
461
|
+
}
|
462
|
+
}
|
463
|
+
end
|
464
|
+
end
|
465
|
+
}
|
466
|
+
}.render
|
467
|
+
```
|
468
|
+
|
469
|
+
Screenshot:
|
470
|
+
|
471
|
+

|
472
|
+
|
340
473
|
**Button Counter Sample**
|
341
474
|
|
342
475
|
**UPCOMING (NOT RELEASED OR SUPPORTED YET)**
|
@@ -441,6 +574,7 @@ Learn more about the differences between various [Glimmer](https://github.com/An
|
|
441
574
|
- [Hello, Button!](#hello-button)
|
442
575
|
- [Hello, Form!](#hello-form)
|
443
576
|
- [Hello, Data-Binding!](#hello-data-binding)
|
577
|
+
- [Hello, Content Data-Binding!](#hello-content-data-binding)
|
444
578
|
- [Hello, Input (Date/Time)!](#hello-input-datetime)
|
445
579
|
- [Button Counter](#button-counter)
|
446
580
|
- [Glimmer Process](#glimmer-process)
|
@@ -487,13 +621,7 @@ rails new glimmer_app_server
|
|
487
621
|
Add the following to `Gemfile`:
|
488
622
|
|
489
623
|
```
|
490
|
-
gem '
|
491
|
-
gem 'opal-rails', '2.0.2'
|
492
|
-
gem 'opal-async', '~> 1.4.0'
|
493
|
-
gem 'opal-jquery', '~> 0.4.6'
|
494
|
-
gem 'glimmer-dsl-web', '~> 0.0.7'
|
495
|
-
gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
|
496
|
-
gem 'glimmer-dsl-css', '~> 1.2.1', require: false
|
624
|
+
gem 'glimmer-dsl-web', '~> 0.0.8'
|
497
625
|
```
|
498
626
|
|
499
627
|
Run:
|
@@ -632,13 +760,7 @@ Disable the `webpacker` gem line in `Gemfile`:
|
|
632
760
|
Add the following to `Gemfile`:
|
633
761
|
|
634
762
|
```ruby
|
635
|
-
gem '
|
636
|
-
gem 'opal-rails', '2.0.2'
|
637
|
-
gem 'opal-async', '~> 1.4.0'
|
638
|
-
gem 'opal-jquery', '~> 0.4.6'
|
639
|
-
gem 'glimmer-dsl-web', '~> 0.0.7'
|
640
|
-
gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
|
641
|
-
gem 'glimmer-dsl-css', '~> 1.2.1', require: false
|
763
|
+
gem 'glimmer-dsl-web', '~> 0.0.8'
|
642
764
|
```
|
643
765
|
|
644
766
|
Run:
|
@@ -1254,6 +1376,133 @@ Screenshot:
|
|
1254
1376
|
|
1255
1377
|

|
1256
1378
|
|
1379
|
+
#### Hello, Content Data-Binding!
|
1380
|
+
|
1381
|
+
Glimmer GUI code:
|
1382
|
+
|
1383
|
+
```ruby
|
1384
|
+
require 'glimmer-dsl-web'
|
1385
|
+
|
1386
|
+
class Address
|
1387
|
+
attr_accessor :text
|
1388
|
+
attr_reader :name, :street, :city, :state, :zip
|
1389
|
+
|
1390
|
+
def name=(value)
|
1391
|
+
@name = value
|
1392
|
+
update_text
|
1393
|
+
end
|
1394
|
+
|
1395
|
+
def street=(value)
|
1396
|
+
@street = value
|
1397
|
+
update_text
|
1398
|
+
end
|
1399
|
+
|
1400
|
+
def city=(value)
|
1401
|
+
@city = value
|
1402
|
+
update_text
|
1403
|
+
end
|
1404
|
+
|
1405
|
+
def state=(value)
|
1406
|
+
@state = value
|
1407
|
+
update_text
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def zip=(value)
|
1411
|
+
@zip = value
|
1412
|
+
update_text
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
private
|
1416
|
+
|
1417
|
+
def update_text
|
1418
|
+
self.text = [name, street, city, state, zip].compact.reject(&:empty?).join(', ')
|
1419
|
+
end
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
class User
|
1423
|
+
attr_accessor :addresses
|
1424
|
+
attr_reader :address_count
|
1425
|
+
|
1426
|
+
def initialize
|
1427
|
+
@address_count = 1
|
1428
|
+
@addresses = []
|
1429
|
+
update_addresses
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
def address_count=(value)
|
1433
|
+
value = [[1, value.to_i].max, 3].min
|
1434
|
+
@address_count = value
|
1435
|
+
update_addresses
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
private
|
1439
|
+
|
1440
|
+
def update_addresses
|
1441
|
+
address_count_change = address_count - addresses.size
|
1442
|
+
if address_count_change > 0
|
1443
|
+
address_count_change.times { addresses << Address.new }
|
1444
|
+
else
|
1445
|
+
address_count_change.abs.times { addresses.pop }
|
1446
|
+
end
|
1447
|
+
end
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
@user = User.new
|
1451
|
+
|
1452
|
+
div {
|
1453
|
+
div {
|
1454
|
+
label('Number of addresses: ', for: 'address-count-field')
|
1455
|
+
input(id: 'address-count-field', type: 'number', min: 1, max: 3) {
|
1456
|
+
value <=> [@user, :address_count]
|
1457
|
+
}
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
div {
|
1461
|
+
# Content Data-Binding is used to dynamically (re)generate content of div
|
1462
|
+
# based on changes to @user.addresses, replacing older content on every change
|
1463
|
+
content(@user, :addresses) do
|
1464
|
+
@user.addresses.each do |address|
|
1465
|
+
div {
|
1466
|
+
div(style: 'display: grid; grid-auto-columns: 80px 280px;') { |address_div|
|
1467
|
+
[:name, :street, :city, :state, :zip].each do |attribute|
|
1468
|
+
label(attribute.to_s.capitalize, for: "#{attribute}-field")
|
1469
|
+
input(id: "#{attribute}-field", type: 'text') {
|
1470
|
+
value <=> [address, attribute]
|
1471
|
+
}
|
1472
|
+
end
|
1473
|
+
|
1474
|
+
div(style: 'grid-column: 1 / span 2;') {
|
1475
|
+
inner_text <= [address, :text]
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
style {
|
1479
|
+
<<~CSS
|
1480
|
+
#{address_div.selector} {
|
1481
|
+
margin: 10px 0;
|
1482
|
+
}
|
1483
|
+
#{address_div.selector} * {
|
1484
|
+
margin: 5px;
|
1485
|
+
}
|
1486
|
+
#{address_div.selector} label {
|
1487
|
+
grid-column: 1;
|
1488
|
+
}
|
1489
|
+
#{address_div.selector} input, #{address_div.selector} select {
|
1490
|
+
grid-column: 2;
|
1491
|
+
}
|
1492
|
+
CSS
|
1493
|
+
}
|
1494
|
+
}
|
1495
|
+
}
|
1496
|
+
end
|
1497
|
+
end
|
1498
|
+
}
|
1499
|
+
}.render
|
1500
|
+
```
|
1501
|
+
|
1502
|
+
Screenshot:
|
1503
|
+
|
1504
|
+

|
1505
|
+
|
1257
1506
|
#### Hello, Input (Date/Time)!
|
1258
1507
|
|
1259
1508
|
Glimmer GUI code:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
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.0.
|
5
|
+
# stub: glimmer-dsl-web 0.0.8 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-web".freeze
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.8".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-
|
14
|
+
s.date = "2024-01-03"
|
15
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
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.extra_rdoc_files = [
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/glimmer-dsl-web/ext/date.rb",
|
32
32
|
"lib/glimmer-dsl-web/ext/exception.rb",
|
33
33
|
"lib/glimmer-dsl-web/samples/hello/hello_button.rb",
|
34
|
+
"lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb",
|
34
35
|
"lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb",
|
35
36
|
"lib/glimmer-dsl-web/samples/hello/hello_form.rb",
|
36
37
|
"lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb",
|
@@ -39,6 +40,7 @@ Gem::Specification.new do |s|
|
|
39
40
|
"lib/glimmer/config/opal_logger.rb",
|
40
41
|
"lib/glimmer/data_binding/element_binding.rb",
|
41
42
|
"lib/glimmer/dsl/web/bind_expression.rb",
|
43
|
+
"lib/glimmer/dsl/web/content_data_binding_expression.rb",
|
42
44
|
"lib/glimmer/dsl/web/data_binding_expression.rb",
|
43
45
|
"lib/glimmer/dsl/web/dsl.rb",
|
44
46
|
"lib/glimmer/dsl/web/element_expression.rb",
|
@@ -61,10 +63,13 @@ Gem::Specification.new do |s|
|
|
61
63
|
|
62
64
|
s.specification_version = 4
|
63
65
|
|
64
|
-
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.
|
66
|
+
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6".freeze])
|
65
67
|
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.3.2".freeze])
|
66
68
|
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.2.2".freeze])
|
69
|
+
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.4.1".freeze])
|
70
|
+
s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.2".freeze])
|
67
71
|
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.0".freeze])
|
72
|
+
s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.4.6".freeze])
|
68
73
|
s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1".freeze, "< 3.0.0".freeze])
|
69
74
|
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 0".freeze])
|
70
75
|
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0".freeze, "< 14.0.0".freeze])
|
@@ -72,7 +77,5 @@ Gem::Specification.new do |s|
|
|
72
77
|
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9".freeze, "< 3.0.0".freeze])
|
73
78
|
s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1".freeze, "< 7.0.0".freeze])
|
74
79
|
s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2".freeze])
|
75
|
-
s.add_development_dependency(%q<opal-rails>.freeze, ["~> 1.1.2".freeze])
|
76
|
-
s.add_development_dependency(%q<opal-jquery>.freeze, ["~> 0.4.4".freeze])
|
77
80
|
end
|
78
81
|
|
@@ -0,0 +1,41 @@
|
|
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/expression'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module DSL
|
26
|
+
module Web
|
27
|
+
class ContentDataBindingExpression < Expression
|
28
|
+
def can_interpret?(parent, keyword, *args, &block)
|
29
|
+
keyword == 'content' &&
|
30
|
+
block_given? &&
|
31
|
+
args.size > 0 &&
|
32
|
+
parent&.respond_to?(:bind_content)
|
33
|
+
end
|
34
|
+
|
35
|
+
def interpret(parent, keyword, *args, &block)
|
36
|
+
parent.bind_content(*args, &block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/glimmer/dsl/web/dsl.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'glimmer/dsl/engine'
|
2
|
-
# Dir[File.expand_path('../*_expression.rb', __FILE__)].each {|f| require f}
|
3
2
|
require 'glimmer/dsl/web/element_expression'
|
4
3
|
require 'glimmer/dsl/web/listener_expression'
|
5
4
|
require 'glimmer/dsl/web/property_expression'
|
@@ -7,25 +6,19 @@ require 'glimmer/dsl/web/p_expression'
|
|
7
6
|
require 'glimmer/dsl/web/select_expression'
|
8
7
|
require 'glimmer/dsl/web/bind_expression'
|
9
8
|
require 'glimmer/dsl/web/data_binding_expression'
|
9
|
+
require 'glimmer/dsl/web/content_data_binding_expression'
|
10
10
|
require 'glimmer/dsl/web/shine_data_binding_expression'
|
11
11
|
|
12
12
|
module Glimmer
|
13
13
|
module DSL
|
14
14
|
module Web
|
15
|
-
# TODO implement all those expressions
|
16
|
-
# %w[
|
17
|
-
# listener
|
18
|
-
# data_binding
|
19
|
-
# property
|
20
|
-
# shine_data_binding
|
21
|
-
# element
|
22
|
-
# ]
|
23
15
|
Engine.add_dynamic_expressions(
|
24
16
|
Web,
|
25
17
|
%w[
|
26
18
|
listener
|
27
19
|
data_binding
|
28
20
|
property
|
21
|
+
content_data_binding
|
29
22
|
shine_data_binding
|
30
23
|
element
|
31
24
|
]
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'glimmer/dsl/expression'
|
2
2
|
require 'glimmer/dsl/web/general_element_expression'
|
3
3
|
|
4
|
+
require 'glimmer/web/element_proxy'
|
5
|
+
|
4
6
|
module Glimmer
|
5
7
|
module DSL
|
6
8
|
module Web
|
@@ -8,9 +10,7 @@ module Glimmer
|
|
8
10
|
include GeneralElementExpression
|
9
11
|
|
10
12
|
def can_interpret?(parent, keyword, *args, &block)
|
11
|
-
|
12
|
-
# TODO raise a proper error if root is an element that is not found (maybe do this in model)
|
13
|
-
!keyword.to_s.start_with?('on')
|
13
|
+
Glimmer::Web::ElementProxy.keyword_supported?(keyword)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -25,6 +25,10 @@ module Glimmer
|
|
25
25
|
module Web
|
26
26
|
class ElementProxy
|
27
27
|
class << self
|
28
|
+
def keyword_supported?(keyword)
|
29
|
+
ELEMENT_KEYWORDS.include?(keyword.to_s)
|
30
|
+
end
|
31
|
+
|
28
32
|
# Factory Method that translates a Glimmer DSL keyword into a ElementProxy object
|
29
33
|
def for(keyword, parent, args, block)
|
30
34
|
element_type(keyword).new(keyword, parent, args, block)
|
@@ -67,7 +71,28 @@ module Glimmer
|
|
67
71
|
|
68
72
|
Event = Struct.new(:widget, keyword_init: true)
|
69
73
|
|
74
|
+
ELEMENT_KEYWORDS = [
|
75
|
+
"a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b",
|
76
|
+
"base", "basefont", "bdi", "bdo", "bgsound", "big", "blink", "blockquote", "body", "br",
|
77
|
+
"button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data",
|
78
|
+
"datalist", "dd", "decorator", "del", "details", "dfn", "dir", "div", "dl", "dt",
|
79
|
+
"element", "em", "embed", "fieldset", "figcaption", "figure", "font", "footer", "form", "frame",
|
80
|
+
"frameset", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup",
|
81
|
+
"hr", "html", "i", "iframe", "img", "input", "ins", "isindex", "kbd", "keygen",
|
82
|
+
"label", "legend", "li", "link", "listing", "main", "map", "mark", "marquee", "menu",
|
83
|
+
"menuitem", "meta", "meter", "nav", "nobr", "noframes", "noscript", "object", "ol", "optgroup",
|
84
|
+
"option", "output", "p", "param", "plaintext", "pre", "progress", "q", "rp", "rt",
|
85
|
+
"ruby", "s", "samp", "script", "section", "select", "shadow", "small", "source", "spacer",
|
86
|
+
"span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td",
|
87
|
+
"template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "tt",
|
88
|
+
"u", "ul", "var", "video", "wbr", "xmp",
|
89
|
+
]
|
90
|
+
|
70
91
|
GLIMMER_ATTRIBUTES = [:parent]
|
92
|
+
PROPERTY_ALIASES = {
|
93
|
+
'inner_html' => 'innerHTML',
|
94
|
+
'outer_html' => 'outerHTML',
|
95
|
+
}
|
71
96
|
FORMAT_DATETIME = '%Y-%m-%dT%H:%M'
|
72
97
|
FORMAT_DATE = '%Y-%m-%d'
|
73
98
|
FORMAT_TIME = '%H:%M'
|
@@ -123,6 +148,11 @@ module Glimmer
|
|
123
148
|
listeners.each do |event, event_listeners|
|
124
149
|
event_listeners.dup.each(&:unregister)
|
125
150
|
end
|
151
|
+
listeners.clear
|
152
|
+
data_bindings.each do |element_binding, model_binding|
|
153
|
+
element_binding.unregister_all_observables
|
154
|
+
end
|
155
|
+
data_bindings.clear
|
126
156
|
end
|
127
157
|
|
128
158
|
# Subclasses can override with their own selector
|
@@ -423,6 +453,10 @@ module Glimmer
|
|
423
453
|
event_listener_proxies.clear
|
424
454
|
end
|
425
455
|
|
456
|
+
def data_bindings
|
457
|
+
@data_bindings ||= {}
|
458
|
+
end
|
459
|
+
|
426
460
|
def data_bind(property, model_binding)
|
427
461
|
element_binding_translator = value_converters_for_input_type(type)[:model_to_view]
|
428
462
|
element_binding_parameters = [self, property, element_binding_translator]
|
@@ -430,6 +464,7 @@ module Glimmer
|
|
430
464
|
element_binding.call(model_binding.evaluate_property)
|
431
465
|
#TODO make this options observer dependent and all similar observers in element specific data binding handlers
|
432
466
|
element_binding.observe(model_binding)
|
467
|
+
data_bindings[element_binding] = model_binding
|
433
468
|
unless model_binding.binding_options[:read_only]
|
434
469
|
# TODO add guards against nil cases for hash below
|
435
470
|
listener_keyword = data_binding_listener_for_element_and_property(keyword, property)
|
@@ -444,19 +479,36 @@ module Glimmer
|
|
444
479
|
end
|
445
480
|
end
|
446
481
|
|
482
|
+
# Data-binds the generation of nested content to a model/property (in binding args)
|
483
|
+
# consider providing an option to avoid initial rendering without any changes happening
|
484
|
+
def bind_content(*binding_args, &content_block)
|
485
|
+
# TODO in the future, consider optimizing code by diffing content if that makes sense
|
486
|
+
content_binding_work = proc do |*values|
|
487
|
+
children.dup.each { |child| child.remove }
|
488
|
+
content(&content_block)
|
489
|
+
end
|
490
|
+
content_binding_observer = Glimmer::DataBinding::Observer.proc(&content_binding_work)
|
491
|
+
content_binding_observer.observe(*binding_args)
|
492
|
+
content_binding_work.call # TODO inspect if we need to pass args here (from observed attributes) [but it's simpler not to pass anything at first]
|
493
|
+
end
|
494
|
+
|
447
495
|
def respond_to_missing?(method_name, include_private = false)
|
448
496
|
# TODO consider doing more correct checking of availability of properties/methods using native `` ticks
|
449
497
|
property_name = property_name_for(method_name)
|
498
|
+
unnormalized_property_name = unnormalized_property_name_for(method_name)
|
450
499
|
super(method_name, include_private) ||
|
451
500
|
(dom_element && dom_element.length > 0 && Native.call(dom_element, '0').respond_to?(method_name.to_s.camelcase, include_private)) ||
|
501
|
+
(dom_element && dom_element.length > 0 && Native.call(dom_element, '0').respond_to?(method_name.to_s, include_private)) ||
|
452
502
|
dom_element.respond_to?(method_name, include_private) ||
|
453
503
|
(!dom_element.prop(property_name).nil? && !dom_element.prop(property_name).is_a?(Proc)) ||
|
504
|
+
(!dom_element.prop(unnormalized_property_name).nil? && !dom_element.prop(unnormalized_property_name).is_a?(Proc)) ||
|
454
505
|
method_name.to_s.start_with?('on_')
|
455
506
|
end
|
456
507
|
|
457
508
|
def method_missing(method_name, *args, &block)
|
458
509
|
# TODO consider doing more correct checking of availability of properties/methods using native `` ticks
|
459
510
|
property_name = property_name_for(method_name)
|
511
|
+
unnormalized_property_name = unnormalized_property_name_for(method_name)
|
460
512
|
if method_name.to_s.start_with?('on_')
|
461
513
|
handle_observation_request(method_name, block)
|
462
514
|
elsif dom_element.respond_to?(method_name)
|
@@ -467,12 +519,22 @@ module Glimmer
|
|
467
519
|
else
|
468
520
|
dom_element.prop(property_name)
|
469
521
|
end
|
522
|
+
elsif !dom_element.prop(unnormalized_property_name).nil? && !dom_element.prop(unnormalized_property_name).is_a?(Proc)
|
523
|
+
if method_name.end_with?('=')
|
524
|
+
dom_element.prop(unnormalized_property_name, *args)
|
525
|
+
else
|
526
|
+
dom_element.prop(unnormalized_property_name)
|
527
|
+
end
|
470
528
|
elsif dom_element && dom_element.length > 0
|
529
|
+
js_args = block.nil? ? args : (args + [block])
|
471
530
|
begin
|
472
|
-
js_args = block.nil? ? args : (args + [block])
|
473
531
|
Native.call(dom_element, '0').method_missing(method_name.to_s.camelcase, *js_args)
|
474
532
|
rescue Exception => e
|
475
|
-
|
533
|
+
begin
|
534
|
+
Native.call(dom_element, '0').method_missing(method_name.to_s, *js_args)
|
535
|
+
rescue Exception => e
|
536
|
+
super(method_name, *args, &block)
|
537
|
+
end
|
476
538
|
end
|
477
539
|
else
|
478
540
|
super(method_name, *args, &block)
|
@@ -480,7 +542,12 @@ module Glimmer
|
|
480
542
|
end
|
481
543
|
|
482
544
|
def property_name_for(method_name)
|
483
|
-
method_name.end_with?('=') ? method_name.to_s[0...-1]
|
545
|
+
attribute_name = method_name.end_with?('=') ? method_name.to_s[0...-1] : method_name.to_s
|
546
|
+
PROPERTY_ALIASES[attribute_name] || attribute_name.camelcase
|
547
|
+
end
|
548
|
+
|
549
|
+
def unnormalized_property_name_for(method_name)
|
550
|
+
method_name.end_with?('=') ? method_name.to_s[0...-1] : method_name.to_s
|
484
551
|
end
|
485
552
|
|
486
553
|
def swt_widget
|
@@ -34,7 +34,6 @@ module Glimmer
|
|
34
34
|
@selector = selector
|
35
35
|
@listener = listener
|
36
36
|
@js_listener = lambda do |js_event|
|
37
|
-
# TODO wrap event with a Ruby Event object before passing to listener
|
38
37
|
event = EventProxy.new(js_event: js_event, listener: self)
|
39
38
|
result = listener.call(event)
|
40
39
|
result = true if result.nil?
|
@@ -0,0 +1,137 @@
|
|
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 Address
|
25
|
+
attr_accessor :text
|
26
|
+
attr_reader :name, :street, :city, :state, :zip
|
27
|
+
|
28
|
+
def name=(value)
|
29
|
+
@name = value
|
30
|
+
update_text
|
31
|
+
end
|
32
|
+
|
33
|
+
def street=(value)
|
34
|
+
@street = value
|
35
|
+
update_text
|
36
|
+
end
|
37
|
+
|
38
|
+
def city=(value)
|
39
|
+
@city = value
|
40
|
+
update_text
|
41
|
+
end
|
42
|
+
|
43
|
+
def state=(value)
|
44
|
+
@state = value
|
45
|
+
update_text
|
46
|
+
end
|
47
|
+
|
48
|
+
def zip=(value)
|
49
|
+
@zip = value
|
50
|
+
update_text
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def update_text
|
56
|
+
self.text = [name, street, city, state, zip].compact.reject(&:empty?).join(', ')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class User
|
61
|
+
attr_accessor :addresses
|
62
|
+
attr_reader :address_count
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
@address_count = 1
|
66
|
+
@addresses = []
|
67
|
+
update_addresses
|
68
|
+
end
|
69
|
+
|
70
|
+
def address_count=(value)
|
71
|
+
value = [[1, value.to_i].max, 3].min
|
72
|
+
@address_count = value
|
73
|
+
update_addresses
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def update_addresses
|
79
|
+
address_count_change = address_count - addresses.size
|
80
|
+
if address_count_change > 0
|
81
|
+
address_count_change.times { addresses << Address.new }
|
82
|
+
else
|
83
|
+
address_count_change.abs.times { addresses.pop }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
@user = User.new
|
89
|
+
|
90
|
+
div {
|
91
|
+
div {
|
92
|
+
label('Number of addresses: ', for: 'address-count-field')
|
93
|
+
input(id: 'address-count-field', type: 'number', min: 1, max: 3) {
|
94
|
+
value <=> [@user, :address_count]
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
div {
|
99
|
+
# Content Data-Binding is used to dynamically (re)generate content of div
|
100
|
+
# based on changes to @user.addresses, replacing older content on every change
|
101
|
+
content(@user, :addresses) do
|
102
|
+
@user.addresses.each do |address|
|
103
|
+
div {
|
104
|
+
div(style: 'display: grid; grid-auto-columns: 80px 280px;') { |address_div|
|
105
|
+
[:name, :street, :city, :state, :zip].each do |attribute|
|
106
|
+
label(attribute.to_s.capitalize, for: "#{attribute}-field")
|
107
|
+
input(id: "#{attribute}-field", type: 'text') {
|
108
|
+
value <=> [address, attribute]
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
div(style: 'grid-column: 1 / span 2;') {
|
113
|
+
inner_text <= [address, :text]
|
114
|
+
}
|
115
|
+
|
116
|
+
style {
|
117
|
+
<<~CSS
|
118
|
+
#{address_div.selector} {
|
119
|
+
margin: 10px 0;
|
120
|
+
}
|
121
|
+
#{address_div.selector} * {
|
122
|
+
margin: 5px;
|
123
|
+
}
|
124
|
+
#{address_div.selector} label {
|
125
|
+
grid-column: 1;
|
126
|
+
}
|
127
|
+
#{address_div.selector} input, #{address_div.selector} select {
|
128
|
+
grid-column: 2;
|
129
|
+
}
|
130
|
+
CSS
|
131
|
+
}
|
132
|
+
}
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
}
|
137
|
+
}.render
|
data/lib/glimmer-dsl-web.rb
CHANGED
@@ -26,7 +26,11 @@ GLIMMER_DSL_OPAL_LIB = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib')
|
|
26
26
|
|
27
27
|
$LOAD_PATH.unshift(GLIMMER_DSL_OPAL_LIB)
|
28
28
|
|
29
|
-
if RUBY_ENGINE
|
29
|
+
if RUBY_ENGINE != 'opal'
|
30
|
+
require 'opal-rails'
|
31
|
+
require 'opal-async'
|
32
|
+
require 'opal-jquery'
|
33
|
+
else
|
30
34
|
# GLIMMER_DSL_OPAL_MISSING = File.join(GLIMMER_DSL_OPAL_ROOT, 'lib', 'glimmer-dsl-opal', 'missing')
|
31
35
|
|
32
36
|
# $LOAD_PATH.unshift(GLIMMER_DSL_OPAL_MISSING) # missing Ruby classes/methods
|
@@ -75,7 +79,7 @@ if RUBY_ENGINE == 'opal'
|
|
75
79
|
require 'glimmer-dsl-xml'
|
76
80
|
require 'glimmer-dsl-css'
|
77
81
|
|
78
|
-
Glimmer::Config.loop_max_count =
|
82
|
+
Glimmer::Config.loop_max_count = 50 # TODO consider disabling if preferred
|
79
83
|
|
80
84
|
original_logger_level = Glimmer::Config.logger.level
|
81
85
|
Glimmer::Config.logger = Glimmer::Config::OpalLogger.new(STDOUT)
|
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.
|
4
|
+
version: 0.0.8
|
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-
|
11
|
+
date: 2024-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: 2.7.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.
|
26
|
+
version: 2.7.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: glimmer-dsl-xml
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.2.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: opal
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.4.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.4.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: opal-rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.0.2
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.0.2
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: opal-async
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +94,20 @@ dependencies:
|
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
96
|
version: 1.4.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: opal-jquery
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.4.6
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.4.6
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: to_collection
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,34 +230,6 @@ dependencies:
|
|
188
230
|
- - "~>"
|
189
231
|
- !ruby/object:Gem::Version
|
190
232
|
version: 0.8.0.alpha2
|
191
|
-
- !ruby/object:Gem::Dependency
|
192
|
-
name: opal-rails
|
193
|
-
requirement: !ruby/object:Gem::Requirement
|
194
|
-
requirements:
|
195
|
-
- - "~>"
|
196
|
-
- !ruby/object:Gem::Version
|
197
|
-
version: 1.1.2
|
198
|
-
type: :development
|
199
|
-
prerelease: false
|
200
|
-
version_requirements: !ruby/object:Gem::Requirement
|
201
|
-
requirements:
|
202
|
-
- - "~>"
|
203
|
-
- !ruby/object:Gem::Version
|
204
|
-
version: 1.1.2
|
205
|
-
- !ruby/object:Gem::Dependency
|
206
|
-
name: opal-jquery
|
207
|
-
requirement: !ruby/object:Gem::Requirement
|
208
|
-
requirements:
|
209
|
-
- - "~>"
|
210
|
-
- !ruby/object:Gem::Version
|
211
|
-
version: 0.4.4
|
212
|
-
type: :development
|
213
|
-
prerelease: false
|
214
|
-
version_requirements: !ruby/object:Gem::Requirement
|
215
|
-
requirements:
|
216
|
-
- - "~>"
|
217
|
-
- !ruby/object:Gem::Version
|
218
|
-
version: 0.4.4
|
219
233
|
description: Glimmer DSL for Web (Ruby in the Browser Web GUI Frontend Library) -
|
220
234
|
Enables frontend GUI development with Ruby by adopting a DSL that follows web-like
|
221
235
|
HTML syntax, enabling the transfer of HTML/CSS/JS skills to Ruby frontend development.
|
@@ -239,6 +253,7 @@ files:
|
|
239
253
|
- lib/glimmer-dsl-web/ext/date.rb
|
240
254
|
- lib/glimmer-dsl-web/ext/exception.rb
|
241
255
|
- lib/glimmer-dsl-web/samples/hello/hello_button.rb
|
256
|
+
- lib/glimmer-dsl-web/samples/hello/hello_content_data_binding.rb
|
242
257
|
- lib/glimmer-dsl-web/samples/hello/hello_data_binding.rb
|
243
258
|
- lib/glimmer-dsl-web/samples/hello/hello_form.rb
|
244
259
|
- lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb
|
@@ -247,6 +262,7 @@ files:
|
|
247
262
|
- lib/glimmer/config/opal_logger.rb
|
248
263
|
- lib/glimmer/data_binding/element_binding.rb
|
249
264
|
- lib/glimmer/dsl/web/bind_expression.rb
|
265
|
+
- lib/glimmer/dsl/web/content_data_binding_expression.rb
|
250
266
|
- lib/glimmer/dsl/web/data_binding_expression.rb
|
251
267
|
- lib/glimmer/dsl/web/dsl.rb
|
252
268
|
- lib/glimmer/dsl/web/element_expression.rb
|