glimmer-dsl-web 0.2.6 → 0.2.7

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: 45ca1b698d2d53da63a133041ac83c77888d42b1e504bc2fa3b81b54c610ff32
4
- data.tar.gz: 91268134dcba4d5d04435d8ee517f7a1e39e277ff0be9487aa7dd99eb1899ee2
3
+ metadata.gz: ebc8e783bfbc67d9366e1887368e89bb7a75db102e56ca966268a2091c5a8e90
4
+ data.tar.gz: a44da8782e6ca10c5183f4f7377eac39bb2b7af4d7e03f088d885a2fce34b219
5
5
  SHA512:
6
- metadata.gz: 68b47d95332b4156d5c04643078cf95bf9d51098b5219836bb1a25eb440d2db25fca55ade3179c64b6587b887b890d4188eb8a91b2f9a32c78ba88027c114774
7
- data.tar.gz: efdb2f8bfb640b0fe1ce052cf867c2d0b58f4ceae6284e23178f51d42b296e53dda009794cd08cb7a46ec2cc0894f0a9054c1a903d40bc7c62dae0570eec16e9
6
+ metadata.gz: 577aea1ffced7cb27937958583c877416921d3f784fd4a2a9589ed3a3b95f39037b1a22f596ab03ed2c336abdab080fce67533b4120e800cb81d3cef144954a8
7
+ data.tar.gz: 05726c636474ad543649bb3200a51c2a238e79248f89207698b229a09fc3e3c6cb9b19489142d71c973505098c1809c8d2978c17ab8628ef9c339666f6fae2f5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.2.7
4
+
5
+ - Unidirectional Data-Binding of element `style` property
6
+ - Support `a` as a formatting element under `p`
7
+ - Todo MVC Sample: `require 'glimmer-dsl-web/samples/regular/todo_mvc'`
8
+
3
9
  ## 0.2.6
4
10
 
5
11
  - Upgrade to `glimmer-dsl-xml` 1.4.0 to provide access to `html_to_glimmer` converter command (converts legacy HTML to Glimmer DSL syntax)
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.2.6 (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.2.7 (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)
@@ -8,9 +8,11 @@
8
8
 
9
9
  **(Talk Videos: [Intro to Ruby in the Browser](https://youtu.be/4AdcfbI6A4c?si=MmxOrkhIXTDHQoYi) & [Frontend Ruby with Glimmer DSL for Web](https://youtu.be/rIZ-ILUv9ME?si=raygUXVPd_7ypWuE))**
10
10
 
11
- 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. [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c) finally fulfills every 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.
11
+ [![Todo MVC](/images/glimmer-dsl-web-samples-regular-todo-mvc.gif)](/lib/glimmer-dsl-web/samples/regular/todo_mvc.rb)
12
12
 
13
- [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). 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)!
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, companies can cut their hiring budget in half by having Backend Ruby Software Engineers do Frontend Development with Ruby! [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c) finally fulfills every 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
+
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)!
14
16
 
15
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 Ajax HTTP 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 Ajax HTTP calls](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector/models/sample_selector_presenter.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).
16
18
 
@@ -1148,6 +1150,100 @@ Screenshot:
1148
1150
 
1149
1151
  ![Hello, Observer!](/images/glimmer-dsl-web-samples-hello-hello-observer.gif)
1150
1152
 
1153
+ **Todo MVC**
1154
+
1155
+ ```ruby
1156
+ require 'glimmer-dsl-web'
1157
+
1158
+ require_relative 'todo_mvc/presenters/todo_presenter'
1159
+
1160
+ require_relative 'todo_mvc/views/new_todo_form'
1161
+ require_relative 'todo_mvc/views/todo_list'
1162
+ require_relative 'todo_mvc/views/todo_filters'
1163
+ require_relative 'todo_mvc/views/todo_mvc_footer'
1164
+
1165
+ class TodoMvc
1166
+ include Glimmer::Web::Component
1167
+
1168
+ before_render do
1169
+ @presenter = TodoPresenter.new
1170
+ end
1171
+
1172
+ after_render do
1173
+ @presenter.setup_filter_routes
1174
+ end
1175
+
1176
+ markup {
1177
+ div(class: 'todomvc') {
1178
+ section(class: 'todoapp') {
1179
+ new_todo_form(presenter: @presenter)
1180
+
1181
+ todo_list(presenter: @presenter)
1182
+
1183
+ todo_filters(presenter: @presenter)
1184
+
1185
+ style {
1186
+ todo_mvc_styles
1187
+ }
1188
+ }
1189
+
1190
+ todo_mvc_footer
1191
+
1192
+ on_remove do
1193
+ @presenter.unsetup_filter_routes
1194
+ end
1195
+ }
1196
+ }
1197
+
1198
+ def todo_mvc_styles
1199
+ rule('body, button, html') {
1200
+ margin '0'
1201
+ padding '0'
1202
+ }
1203
+
1204
+ rule('button') {
1205
+ _webkit_font_smoothing 'antialiased'
1206
+ _webkit_appearance 'none'
1207
+ appearance 'none'
1208
+ background 'none'
1209
+ border '0'
1210
+ color 'inherit'
1211
+ font_family 'inherit'
1212
+ font_size '100%'
1213
+ font_weight 'inherit'
1214
+ vertical_align 'baseline'
1215
+ }
1216
+
1217
+ rule('.todoapp') {
1218
+ background '#fff'
1219
+ margin '130px 0 40px 0'
1220
+ position 'relative'
1221
+ box_shadow '0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1)'
1222
+ }
1223
+
1224
+ media('screen and (-webkit-min-device-pixel-ratio:0)') {
1225
+ rule('body') {
1226
+ font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
1227
+ line_height '1.4em'
1228
+ background '#f5f5f5'
1229
+ color '#111111'
1230
+ min_width '230px'
1231
+ max_width '550px'
1232
+ margin '0 auto'
1233
+ _webkit_font_smoothing 'antialiased'
1234
+ font_weight '300'
1235
+ }
1236
+ }
1237
+ end
1238
+ end
1239
+
1240
+ Document.ready? do
1241
+ TodoMvc.render
1242
+ end
1243
+ ```
1244
+
1245
+ ![Todo MVC](/images/glimmer-dsl-web-samples-regular-todo-mvc.gif)
1246
+
1151
1247
  To get started, [Setup](#setup) Ruby gem, read [Usage](#usage) instructions, and check out more [Samples](#samples) (including playing around with a [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app)).
1152
1248
 
1153
1249
  --
@@ -1230,7 +1326,7 @@ rails new glimmer_app_server
1230
1326
  Add the following to `Gemfile`:
1231
1327
 
1232
1328
  ```
1233
- gem 'glimmer-dsl-web', '~> 0.2.6'
1329
+ gem 'glimmer-dsl-web', '~> 0.2.7'
1234
1330
  ```
1235
1331
 
1236
1332
  Run:
@@ -1457,7 +1553,7 @@ Disable the `webpacker` gem line in `Gemfile`:
1457
1553
  Add the following to `Gemfile`:
1458
1554
 
1459
1555
  ```ruby
1460
- gem 'glimmer-dsl-web', '~> 0.2.6'
1556
+ gem 'glimmer-dsl-web', '~> 0.2.7'
1461
1557
  ```
1462
1558
 
1463
1559
  Run:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.6
1
+ 0.2.7
@@ -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.2.6 ruby lib
5
+ # stub: glimmer-dsl-web 0.2.7 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-dsl-web".freeze
9
- s.version = "0.2.6".freeze
9
+ s.version = "0.2.7"
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-05-26"
14
+ s.date = "2024-06-15"
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 = [
@@ -48,9 +48,21 @@ Gem::Specification.new do |s|
48
48
  "lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb",
49
49
  "lib/glimmer-dsl-web/samples/hello/hello_world.rb",
50
50
  "lib/glimmer-dsl-web/samples/regular/button_counter.rb",
51
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc.rb",
52
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/models/todo.rb",
53
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/presenters/todo_presenter.rb",
54
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/edit_todo_input.rb",
55
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_form.rb",
56
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_input.rb",
57
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_filters.rb",
58
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_input.rb",
59
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list.rb",
60
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list_item.rb",
61
+ "lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_mvc_footer.rb",
51
62
  "lib/glimmer-dsl-web/vendor/jquery.js",
52
63
  "lib/glimmer/config/opal_logger.rb",
53
64
  "lib/glimmer/data_binding/element_binding.rb",
65
+ "lib/glimmer/dsl/web/a_expression.rb",
54
66
  "lib/glimmer/dsl/web/bind_expression.rb",
55
67
  "lib/glimmer/dsl/web/component_expression.rb",
56
68
  "lib/glimmer/dsl/web/content_data_binding_expression.rb",
@@ -76,24 +88,24 @@ Gem::Specification.new do |s|
76
88
  ]
77
89
  s.homepage = "http://github.com/AndyObtiva/glimmer-dsl-web".freeze
78
90
  s.licenses = ["MIT".freeze]
79
- s.rubygems_version = "3.5.3".freeze
91
+ s.rubygems_version = "3.4.10".freeze
80
92
  s.summary = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework)".freeze
81
93
 
82
94
  s.specification_version = 4
83
95
 
84
- s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6".freeze])
85
- s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0".freeze])
86
- s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.4.0".freeze])
87
- s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2".freeze])
88
- s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3".freeze])
89
- s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1".freeze])
90
- s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1".freeze])
91
- s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1".freeze, "< 3.0.0".freeze])
92
- s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 0".freeze])
93
- s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0".freeze, "< 14.0.0".freeze])
94
- s.add_development_dependency(%q<rake-tui>.freeze, [">= 0".freeze])
95
- s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9".freeze, "< 3.0.0".freeze])
96
- s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1".freeze, "< 7.0.0".freeze])
97
- s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2".freeze])
96
+ s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.6"])
97
+ s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0"])
98
+ s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.4.0"])
99
+ s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2"])
100
+ s.add_runtime_dependency(%q<opal-rails>.freeze, ["= 2.0.3"])
101
+ s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1"])
102
+ s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1"])
103
+ s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1", "< 3.0.0"])
104
+ s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 1.0.0"])
105
+ s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
106
+ s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
107
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9", "< 3.0.0"])
108
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 6.2.1", "< 7.0.0"])
109
+ s.add_development_dependency(%q<opal-rspec>.freeze, ["~> 0.8.0.alpha2"])
98
110
  end
99
111
 
@@ -0,0 +1,17 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/web/general_element_expression'
3
+
4
+ module Glimmer
5
+ module DSL
6
+ module Web
7
+ class AExpression < StaticExpression
8
+ include GeneralElementExpression
9
+
10
+ def can_interpret?(parent, keyword, *args, &block)
11
+ (parent.nil? ||
12
+ (parent.respond_to?(:keyword) && parent.keyword != 'p'))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -24,6 +24,7 @@ require 'glimmer/dsl/web/element_expression'
24
24
  require 'glimmer/dsl/web/formatting_element_expression'
25
25
  require 'glimmer/dsl/web/listener_expression'
26
26
  require 'glimmer/dsl/web/property_expression'
27
+ require 'glimmer/dsl/web/a_expression'
27
28
  require 'glimmer/dsl/web/span_expression'
28
29
  require 'glimmer/dsl/web/style_expression'
29
30
  require 'glimmer/dsl/web/bind_expression'
@@ -45,6 +46,7 @@ module Glimmer
45
46
  property
46
47
  content_data_binding
47
48
  shine_data_binding
49
+ style
48
50
  formatting_element
49
51
  ]
50
52
  )
@@ -24,7 +24,7 @@ end
24
24
  module Glimmer
25
25
  # Optimize performance through shortcut methods for all HTML elements that circumvent the DSL chain of responsibility
26
26
  element_expression = Glimmer::DSL::Web::ElementExpression.new
27
- (Glimmer::Web::ElementProxy::ELEMENT_KEYWORDS - ['span', 'style']).each do |keyword|
27
+ (Glimmer::Web::ElementProxy::ELEMENT_KEYWORDS - ['a', 'span', 'style']).each do |keyword|
28
28
  Glimmer::DSL::Engine.static_expressions[keyword] ||= Concurrent::Hash.new
29
29
  element_expression_dsl = element_expression.class.dsl
30
30
  Glimmer::DSL::Engine.static_expressions[keyword][element_expression_dsl] = element_expression
@@ -1,13 +1,18 @@
1
- require 'glimmer/dsl/static_expression'
1
+ require 'glimmer/dsl/expression'
2
2
  require 'glimmer/dsl/web/general_element_expression'
3
3
 
4
4
  module Glimmer
5
5
  module DSL
6
6
  module Web
7
- class StyleExpression < StaticExpression
7
+ class StyleExpression < Expression
8
8
  include GeneralElementExpression
9
9
  include Glimmer
10
10
 
11
+ def can_interpret?(parent, keyword, *args, &block)
12
+ keyword == 'style' &&
13
+ !block.nil?
14
+ end
15
+
11
16
  def add_content(parent, keyword, *args, &block)
12
17
  if parent.rendered? || parent.skip_content_on_render_blocks?
13
18
  return_value = css(&block).to_s
@@ -33,7 +33,8 @@ module Glimmer
33
33
  keyword = keyword.to_s
34
34
  (
35
35
  FORMATTING_ELEMENT_KEYWORDS.include?(keyword) ||
36
- (keyword == 'span' && parent&.keyword == 'p')
36
+ (keyword == 'span' && parent&.keyword == 'p') ||
37
+ (keyword == 'a' && parent&.keyword == 'p')
37
38
  )
38
39
  end
39
40
 
@@ -0,0 +1,44 @@
1
+ Todo = Struct.new(:task, :completed, :editing, keyword_init: true) do
2
+ class << self
3
+ attr_writer :all
4
+
5
+ def all
6
+ @all ||= []
7
+ end
8
+
9
+ def active
10
+ all.select(&:active?)
11
+ end
12
+
13
+ def completed
14
+ all.select(&:completed?)
15
+ end
16
+ end
17
+
18
+ FILTERS = [:all, :active, :completed]
19
+
20
+ alias completed? completed
21
+ alias editing? editing
22
+
23
+ def active
24
+ !completed
25
+ end
26
+ alias active? active
27
+
28
+ def start_editing
29
+ return if editing?
30
+ @original_task = task
31
+ self.editing = true
32
+ end
33
+
34
+ def cancel_editing
35
+ return unless editing?
36
+ self.task = @original_task
37
+ self.editing = false
38
+ end
39
+
40
+ def save_editing
41
+ return unless editing?
42
+ self.editing = false
43
+ end
44
+ end
@@ -0,0 +1,102 @@
1
+ require 'glimmer/data_binding/observer'
2
+
3
+ require_relative '../models/todo'
4
+
5
+ class TodoPresenter
6
+ FILTER_ROUTE_REGEXP = /\#\/([^\/]*)$/
7
+
8
+ attr_accessor :todos, :can_clear_completed, :active_todo_count
9
+ attr_reader :new_todo, :filter
10
+
11
+ def initialize
12
+ @todos = Todo.all.clone
13
+ @new_todo = Todo.new(task: '')
14
+ @filter = :all
15
+ refresh_todo_stats
16
+ end
17
+
18
+ def create_todo(todo = nil)
19
+ todo ||= new_todo.clone
20
+ Todo.all.prepend(todo)
21
+ observers_for_todo_stats[todo.object_id] = todo_stat_observer.observe(todo, :completed) unless observers_for_todo_stats.has_key?(todo.object_id)
22
+ refresh_todos_with_filter
23
+ refresh_todo_stats
24
+ new_todo.task = ''
25
+ end
26
+
27
+ def refresh_todos_with_filter
28
+ self.todos = Todo.send(filter).clone
29
+ end
30
+
31
+ def filter=(filter)
32
+ return if filter == @filter
33
+ @filter = filter
34
+ refresh_todos_with_filter
35
+ end
36
+
37
+ def destroy(todo)
38
+ delete(todo)
39
+ refresh_todos_with_filter
40
+ refresh_todo_stats
41
+ end
42
+
43
+ def clear_completed
44
+ Todo.completed.each { |todo| delete(todo) }
45
+ refresh_todos_with_filter
46
+ refresh_todo_stats
47
+ end
48
+
49
+ def toggle_all_completed
50
+ target_completed_value = Todo.active.any?
51
+ todos_to_update = target_completed_value ? Todo.active : Todo.completed
52
+ todos_to_update.each { |todo| todo.completed = target_completed_value }
53
+ end
54
+
55
+ def setup_filter_routes
56
+ @filter_router_function = -> (event) { apply_route_filter }
57
+ $$.addEventListener('popstate', &@filter_router_function)
58
+ apply_route_filter
59
+ end
60
+
61
+ def apply_route_filter
62
+ route_filter_match = $$.document.location.href.to_s.match(FILTER_ROUTE_REGEXP)
63
+ return if route_filter_match.nil?
64
+ route_filter = route_filter_match[1]
65
+ route_filter = 'all' if route_filter == ''
66
+ self.filter = route_filter
67
+ end
68
+
69
+ def unsetup_filter_routes
70
+ $$.removeEventListener('popstate', &@filter_router_function)
71
+ @filter_router_function = nil
72
+ end
73
+
74
+ private
75
+
76
+ def delete(todo)
77
+ Todo.all.delete(todo)
78
+ observer_registration = observers_for_todo_stats.delete(todo.object_id)
79
+ observer_registration&.deregister
80
+ end
81
+
82
+ def observers_for_todo_stats
83
+ @observers_for_todo_stats = {}
84
+ end
85
+
86
+ def todo_stat_observer
87
+ @todo_stat_observer ||= Glimmer::DataBinding::Observer.proc { refresh_todo_stats }
88
+ end
89
+
90
+ def refresh_todo_stats
91
+ refresh_can_clear_completed
92
+ refresh_active_todo_count
93
+ end
94
+
95
+ def refresh_can_clear_completed
96
+ self.can_clear_completed = Todo.completed.any?
97
+ end
98
+
99
+ def refresh_active_todo_count
100
+ self.active_todo_count = Todo.active.count
101
+ end
102
+ end
@@ -0,0 +1,55 @@
1
+ require_relative 'todo_input'
2
+
3
+ class EditTodoInput < TodoInput
4
+ option :presenter
5
+ option :todo
6
+
7
+ markup {
8
+ input(class: todo_input_class) { |edit_input|
9
+ style <= [ todo, :editing,
10
+ on_read: ->(editing) { editing ? '' : 'display: none;' },
11
+ after_read: ->(_) { edit_input.focus if todo.editing? }
12
+ ]
13
+
14
+ value <=> [todo, :task]
15
+
16
+ onkeyup do |event|
17
+ if event.key == 'Enter' || event.keyCode == "\r"
18
+ todo.save_editing
19
+ presenter.destroy(todo) if todo.task.strip.empty?
20
+ elsif event.key == 'Escape' || event.keyCode == 27
21
+ todo.cancel_editing
22
+ end
23
+ end
24
+
25
+ onblur do |event|
26
+ todo.save_editing
27
+ end
28
+
29
+ style {
30
+ todo_input_styles
31
+ }
32
+ }
33
+ }
34
+
35
+ def todo_input_class
36
+ 'edit-todo'
37
+ end
38
+
39
+ def todo_input_styles
40
+ super
41
+
42
+ rule("*:has(> .#{todo_input_class})") {
43
+ position 'relative'
44
+ }
45
+
46
+ rule(".#{todo_input_class}") {
47
+ position 'absolute'
48
+ display 'block'
49
+ width 'calc(100% - 43px)'
50
+ padding '12px 16px'
51
+ margin '0 0 0 43px'
52
+ top '0'
53
+ }
54
+ end
55
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'new_todo_input'
2
+
3
+ class NewTodoForm
4
+ include Glimmer::Web::Component
5
+
6
+ option :presenter
7
+
8
+ markup {
9
+ header(class: 'header') {
10
+ h1('todos')
11
+
12
+ new_todo_input(presenter: presenter)
13
+
14
+ style {
15
+ rule('.header h1') {
16
+ color '#b83f45'
17
+ font_size '80px'
18
+ font_weight '200'
19
+ position 'absolute'
20
+ text_align 'center'
21
+ _webkit_text_rendering 'optimizeLegibility'
22
+ _moz_text_rendering 'optimizeLegibility'
23
+ text_rendering 'optimizeLegibility'
24
+ top '-140px'
25
+ width '100%'
26
+ }
27
+ }
28
+ }
29
+ }
30
+ end
@@ -0,0 +1,41 @@
1
+ require_relative 'todo_input'
2
+
3
+ class NewTodoInput < TodoInput
4
+ option :presenter
5
+
6
+ markup {
7
+ input(class: todo_input_class, placeholder: "What needs to be done?", autofocus: "") {
8
+ value <=> [presenter.new_todo, :task]
9
+
10
+ onkeyup do |event|
11
+ presenter.create_todo if event.key == 'Enter' || event.keyCode == "\r"
12
+ end
13
+
14
+ style {
15
+ todo_input_styles
16
+ }
17
+ }
18
+ }
19
+
20
+ def todo_input_class
21
+ 'new-todo'
22
+ end
23
+
24
+ def todo_input_styles
25
+ super
26
+
27
+ rule(".#{todo_input_class}") {
28
+ padding '16px 16px 16px 60px'
29
+ height '65px'
30
+ border 'none'
31
+ background 'rgba(0, 0, 0, 0.003)'
32
+ box_shadow 'inset 0 -2px 1px rgba(0,0,0,0.03)'
33
+ }
34
+
35
+ rule(".#{todo_input_class}::placeholder") {
36
+ font_style 'italic'
37
+ font_weight '400'
38
+ color 'rgba(0, 0, 0, 0.4)'
39
+ }
40
+ end
41
+ end
@@ -0,0 +1,123 @@
1
+ class TodoFilters
2
+ include Glimmer::Web::Component
3
+
4
+ option :presenter
5
+
6
+ markup {
7
+ footer(class: 'todo-filters') {
8
+ style <= [ Todo, :all,
9
+ on_read: ->(todos) { todos.empty? ? 'display: none;' : '' }
10
+ ]
11
+
12
+ span(class: 'todo-count') {
13
+ span('.strong') {
14
+ inner_text <= [presenter, :active_todo_count]
15
+ }
16
+ span {
17
+ " items left"
18
+ }
19
+ }
20
+
21
+ ul(class: 'filters') {
22
+ Todo::FILTERS.each do |filter|
23
+ li {
24
+ a(filter.to_s.capitalize, href: "#/#{filter unless filter == :all}") {
25
+ class_name <= [ presenter, :filter,
26
+ on_read: -> (presenter_filter) { presenter_filter == filter ? 'selected' : '' }
27
+ ]
28
+
29
+ onclick do |event|
30
+ presenter.filter = filter
31
+ end
32
+ }
33
+ }
34
+ end
35
+ }
36
+
37
+ button('Clear completed', class: 'clear-completed') {
38
+ style <= [ presenter, :can_clear_completed,
39
+ on_read: -> (can_clear_completed) { can_clear_completed ? '' : 'display: none;' },
40
+ ]
41
+
42
+ onclick do |event|
43
+ presenter.clear_completed
44
+ end
45
+ }
46
+
47
+ style {
48
+ rule('.todo-filters') {
49
+ border_top '1px solid #e6e6e6'
50
+ font_size '15px'
51
+ height '20px'
52
+ padding '10px 15px'
53
+ text_align 'center'
54
+ }
55
+
56
+ rule('.todo-filters:before') {
57
+ bottom '0'
58
+ box_shadow '0 1px 1px rgba(0,0,0,.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0,0,0,.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0,0,0,.2)'
59
+ content '""'
60
+ height '50px'
61
+ left '0'
62
+ overflow 'hidden'
63
+ position 'absolute'
64
+ right '0'
65
+ }
66
+
67
+ rule('.todo-count') {
68
+ float 'left'
69
+ text_align 'left'
70
+ }
71
+
72
+ rule('.todo-count .strong') {
73
+ font_weight '300'
74
+ }
75
+
76
+ rule('.filters') {
77
+ left '0'
78
+ list_style 'none'
79
+ margin '0'
80
+ padding '0'
81
+ position 'absolute'
82
+ right '0'
83
+ }
84
+
85
+ rule('.filters li') {
86
+ display 'inline'
87
+ }
88
+
89
+ rule('.filters li a') {
90
+ border '1px solid transparent'
91
+ border_radius '3px'
92
+ color 'inherit'
93
+ margin '3px'
94
+ padding '3px 7px'
95
+ text_decoration 'none'
96
+ cursor 'pointer'
97
+ }
98
+
99
+ rule('.filters li a.selected') {
100
+ border_color '#ce4646'
101
+ }
102
+
103
+ rule('.clear-completed, html .clear-completed:active') {
104
+ cursor 'pointer'
105
+ float 'right'
106
+ line_height '19px'
107
+ position 'relative'
108
+ text_decoration 'none'
109
+ }
110
+
111
+ media('(max-width: 430px)') {
112
+ rule('.todo-filters') {
113
+ height '50px'
114
+ }
115
+
116
+ rule('.filters') {
117
+ bottom '10px'
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ end
@@ -0,0 +1,30 @@
1
+ # Superclass for NewTodoInput and EditTodoInput with common styles
2
+ class TodoInput
3
+ include Glimmer::Web::Component
4
+
5
+ def todo_input_class
6
+ 'todo-input'
7
+ end
8
+
9
+ def todo_input_styles
10
+ rule(".#{todo_input_class}") {
11
+ position 'relative'
12
+ margin '0'
13
+ width '100%'
14
+ font_size '24px'
15
+ font_family 'inherit'
16
+ font_weight 'inherit'
17
+ line_height '1.4em'
18
+ color 'inherit'
19
+ padding '6px'
20
+ border '1px solid #999'
21
+ box_shadow 'inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2)'
22
+ box_sizing 'border-box'
23
+ _webkit_font_smoothing 'antialiased'
24
+ }
25
+
26
+ rule(".#{todo_input_class}::selection") {
27
+ background 'red'
28
+ }
29
+ end
30
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'todo_list_item'
2
+
3
+ class TodoList
4
+ include Glimmer::Web::Component
5
+
6
+ option :presenter
7
+
8
+ markup {
9
+ main(class: 'main') {
10
+ style <= [ Todo, :all,
11
+ on_read: ->(todos) { todos.empty? ? 'display: none;' : '' }
12
+ ]
13
+
14
+ div(class: 'toggle-all-container') {
15
+ input(class: 'toggle-all', type: 'checkbox')
16
+
17
+ label('Mark all as complete', class: 'toggle-all-label', for: 'toggle-all') {
18
+ onclick do |event|
19
+ presenter.toggle_all_completed
20
+ end
21
+ }
22
+ }
23
+
24
+ ul(class: 'todo-list') {
25
+ content(presenter, :todos) {
26
+ presenter.todos.each do |todo|
27
+ todo_list_item(presenter:, todo:)
28
+ end
29
+ }
30
+ }
31
+
32
+ style {
33
+ todo_list_styles
34
+ }
35
+ }
36
+ }
37
+
38
+ def todo_list_styles
39
+ rule('.main') {
40
+ border_top '1px solid #e6e6e6'
41
+ position 'relative'
42
+ z_index '2'
43
+ }
44
+
45
+ rule('.toggle-all') {
46
+ border 'none'
47
+ bottom '100%'
48
+ height '1px'
49
+ opacity '0'
50
+ position 'absolute'
51
+ right '100%'
52
+ width '1px'
53
+ }
54
+
55
+ rule('.toggle-all+label') {
56
+ align_items 'center'
57
+ display 'flex'
58
+ font_size '0'
59
+ height '65px'
60
+ justify_content 'center'
61
+ left '0'
62
+ position 'absolute'
63
+ top '-65px'
64
+ width '45px'
65
+ }
66
+
67
+ rule('.toggle-all+label:before') {
68
+ color '#949494'
69
+ content '"❯"'
70
+ display 'inline-block'
71
+ font_size '22px'
72
+ padding '10px 27px'
73
+ _webkit_transform 'rotate(90deg)'
74
+ transform 'rotate(90deg)'
75
+ }
76
+
77
+ rule('.toggle-all:focus+label, .toggle:focus+label, :focus') {
78
+ box_shadow '0 0 2px 2px #cf7d7d'
79
+ outline '0'
80
+ }
81
+
82
+ rule('.todo-list') {
83
+ list_style 'none'
84
+ margin '0'
85
+ padding '0'
86
+ }
87
+ end
88
+ end
@@ -0,0 +1,158 @@
1
+ require_relative 'edit_todo_input'
2
+
3
+ class TodoListItem
4
+ include Glimmer::Web::Component
5
+
6
+ option :presenter
7
+ option :todo
8
+
9
+ markup {
10
+ li {
11
+ class_name <= [ todo, :completed,
12
+ on_read: -> (completed) { li_class_name(todo) }
13
+ ]
14
+ class_name <= [ todo, :editing,
15
+ on_read: -> (editing) { li_class_name(todo) }
16
+ ]
17
+
18
+ div(class: 'view') {
19
+ input(class: 'toggle', type: 'checkbox') {
20
+ checked <=> [ todo, :completed,
21
+ after_write: -> (_) { presenter.refresh_todos_with_filter if presenter.filter != :all }
22
+ ]
23
+ }
24
+
25
+ label {
26
+ inner_html <= [todo, :task]
27
+
28
+ ondblclick do |event|
29
+ todo.start_editing
30
+ end
31
+ }
32
+
33
+ button(class: 'destroy') {
34
+ onclick do |event|
35
+ presenter.destroy(todo)
36
+ end
37
+ }
38
+ }
39
+
40
+ edit_todo_input(presenter:, todo:)
41
+
42
+ if todo == presenter.todos.first
43
+ style {
44
+ todo_list_item_styles
45
+ }
46
+ end
47
+ }
48
+ }
49
+
50
+ def li_class_name(todo)
51
+ classes = []
52
+ classes << 'completed' if todo.completed?
53
+ classes << 'editing' if todo.editing?
54
+ classes.join(' ')
55
+ end
56
+
57
+ def todo_list_item_styles
58
+ rule('.todo-list li.completed label') {
59
+ color '#949494'
60
+ text_decoration 'line-through'
61
+ }
62
+
63
+ rule('.todo-list li') {
64
+ border_bottom '1px solid #ededed'
65
+ font_size '24px'
66
+ position 'relative'
67
+ }
68
+
69
+ rule('.todo-list li .toggle') {
70
+ _webkit_appearance 'none'
71
+ appearance 'none'
72
+ border 'none'
73
+ bottom '0'
74
+ height 'auto'
75
+ margin 'auto 0'
76
+ opacity '0'
77
+ position 'absolute'
78
+ text_align 'center'
79
+ top '0'
80
+ width '40px'
81
+ }
82
+
83
+ rule('.todo-list li label') {
84
+ color '#484848'
85
+ display 'block'
86
+ font_weight '400'
87
+ line_height '1.2'
88
+ min_height '40px'
89
+ padding '15px 15px 15px 60px'
90
+ transition 'color .4s'
91
+ word_break 'break-all'
92
+ }
93
+
94
+ rule('.todo-list li .toggle+label') {
95
+ background_image 'url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23949494%22%20stroke-width%3D%223%22/%3E%3C/svg%3E)'
96
+ background_position '0'
97
+ background_repeat 'no-repeat'
98
+ }
99
+
100
+ rule('.todo-list li.completed label') {
101
+ color '#949494'
102
+ text_decoration 'line-through'
103
+ }
104
+
105
+ rule('.todo-list li .toggle:checked+label') {
106
+ background_image 'url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%2359A193%22%20stroke-width%3D%223%22%2F%3E%3Cpath%20fill%3D%22%233EA390%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22%2F%3E%3C%2Fsvg%3E)'
107
+ }
108
+
109
+ rule('.todo-list li.editing') {
110
+ border_bottom 'none'
111
+ padding '0'
112
+ }
113
+
114
+ rule('.todo-list li.editing input[type=checkbox], .todo-list li.editing label') {
115
+ opacity '0'
116
+ }
117
+
118
+ rule('.todo-list li .destroy') {
119
+ bottom '0'
120
+ color '#949494'
121
+ display 'none'
122
+ font_size '30px'
123
+ height '40px'
124
+ margin 'auto 0'
125
+ position 'absolute'
126
+ right '10px'
127
+ top '0'
128
+ transition 'color .2s ease-out'
129
+ width '40px'
130
+ }
131
+
132
+ rule('.todo-list li:focus .destroy, .todo-list li:hover .destroy') {
133
+ display 'block'
134
+ }
135
+
136
+ rule('.todo-list li .destroy:focus, .todo-list li .destroy:hover') {
137
+ color '#c18585'
138
+ }
139
+
140
+ rule('.todo-list li .destroy:after') {
141
+ content '"×"'
142
+ display 'block'
143
+ height '100%'
144
+ line_height '1.1'
145
+ }
146
+
147
+ media ('screen and (-webkit-min-device-pixel-ratio: 0)') {
148
+ rule('.todo-list li .toggle, .toggle-all') {
149
+ background 'none'
150
+ }
151
+
152
+ rule('.todo-list li .toggle') {
153
+ height '40px'
154
+ }
155
+ }
156
+ end
157
+ end
158
+
@@ -0,0 +1,45 @@
1
+ class TodoMvcFooter
2
+ include Glimmer::Web::Component
3
+
4
+ markup {
5
+ footer(class: 'info') {
6
+ p {
7
+ "Double-click to edit a todo"
8
+ }
9
+ p {
10
+ "Created by #{a('Andy Maleh', href: 'https://github.com/AndyObtiva')}"
11
+ }
12
+ p {
13
+ "Part of #{a('TodoMVC', href: 'http://todomvc.com')}"
14
+ }
15
+
16
+ style {
17
+ todo_mvc_styles
18
+ }
19
+ }
20
+ }
21
+
22
+ def todo_mvc_styles
23
+ rule('footer.info') {
24
+ margin '65px auto 0'
25
+ color '#4d4d4d'
26
+ font_size '11px'
27
+ text_shadow '0 1px 0 rgba(255, 255, 255, 0.5)'
28
+ text_align 'center'
29
+ }
30
+
31
+ rule('footer.info p') {
32
+ line_height '1'
33
+ }
34
+
35
+ rule('footer.info a') {
36
+ color 'inherit'
37
+ text_decoration 'none'
38
+ font_weight '400'
39
+ }
40
+
41
+ rule('footer.info a:hover') {
42
+ text_decoration 'underline'
43
+ }
44
+ end
45
+ end
@@ -0,0 +1,87 @@
1
+ require 'glimmer-dsl-web'
2
+
3
+ require_relative 'todo_mvc/presenters/todo_presenter'
4
+
5
+ require_relative 'todo_mvc/views/new_todo_form'
6
+ require_relative 'todo_mvc/views/todo_list'
7
+ require_relative 'todo_mvc/views/todo_filters'
8
+ require_relative 'todo_mvc/views/todo_mvc_footer'
9
+
10
+ class TodoMvc
11
+ include Glimmer::Web::Component
12
+
13
+ before_render do
14
+ @presenter = TodoPresenter.new
15
+ end
16
+
17
+ after_render do
18
+ @presenter.setup_filter_routes
19
+ end
20
+
21
+ markup {
22
+ div(class: 'todomvc') {
23
+ section(class: 'todoapp') {
24
+ new_todo_form(presenter: @presenter)
25
+
26
+ todo_list(presenter: @presenter)
27
+
28
+ todo_filters(presenter: @presenter)
29
+
30
+ style {
31
+ todo_mvc_styles
32
+ }
33
+ }
34
+
35
+ todo_mvc_footer
36
+
37
+ on_remove do
38
+ @presenter.unsetup_filter_routes
39
+ end
40
+ }
41
+ }
42
+
43
+ def todo_mvc_styles
44
+ rule('body, button, html') {
45
+ margin '0'
46
+ padding '0'
47
+ }
48
+
49
+ rule('button') {
50
+ _webkit_font_smoothing 'antialiased'
51
+ _webkit_appearance 'none'
52
+ appearance 'none'
53
+ background 'none'
54
+ border '0'
55
+ color 'inherit'
56
+ font_family 'inherit'
57
+ font_size '100%'
58
+ font_weight 'inherit'
59
+ vertical_align 'baseline'
60
+ }
61
+
62
+ rule('.todoapp') {
63
+ background '#fff'
64
+ margin '130px 0 40px 0'
65
+ position 'relative'
66
+ box_shadow '0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1)'
67
+ }
68
+
69
+ media('screen and (-webkit-min-device-pixel-ratio:0)') {
70
+ rule('body') {
71
+ font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
72
+ line_height '1.4em'
73
+ background '#f5f5f5'
74
+ color '#111111'
75
+ min_width '230px'
76
+ max_width '550px'
77
+ margin '0 auto'
78
+ _webkit_font_smoothing 'antialiased'
79
+ font_weight '300'
80
+ }
81
+ }
82
+ end
83
+ end
84
+
85
+ Document.ready? do
86
+ TodoMvc.render
87
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
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-05-26 00:00:00.000000000 Z
11
+ date: 2024-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - ">="
136
136
  - !ruby/object:Gem::Version
137
- version: '0'
137
+ version: 1.0.0
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - ">="
143
143
  - !ruby/object:Gem::Version
144
- version: '0'
144
+ version: 1.0.0
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: rake
147
147
  requirement: !ruby/object:Gem::Requirement
@@ -281,9 +281,21 @@ files:
281
281
  - lib/glimmer-dsl-web/samples/hello/hello_paragraph.rb
282
282
  - lib/glimmer-dsl-web/samples/hello/hello_world.rb
283
283
  - lib/glimmer-dsl-web/samples/regular/button_counter.rb
284
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc.rb
285
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/models/todo.rb
286
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/presenters/todo_presenter.rb
287
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/edit_todo_input.rb
288
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_form.rb
289
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_input.rb
290
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_filters.rb
291
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_input.rb
292
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list.rb
293
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list_item.rb
294
+ - lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_mvc_footer.rb
284
295
  - lib/glimmer-dsl-web/vendor/jquery.js
285
296
  - lib/glimmer/config/opal_logger.rb
286
297
  - lib/glimmer/data_binding/element_binding.rb
298
+ - lib/glimmer/dsl/web/a_expression.rb
287
299
  - lib/glimmer/dsl/web/bind_expression.rb
288
300
  - lib/glimmer/dsl/web/component_expression.rb
289
301
  - lib/glimmer/dsl/web/content_data_binding_expression.rb
@@ -325,7 +337,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
325
337
  - !ruby/object:Gem::Version
326
338
  version: '0'
327
339
  requirements: []
328
- rubygems_version: 3.5.3
340
+ rubygems_version: 3.4.10
329
341
  signing_key:
330
342
  specification_version: 4
331
343
  summary: Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework)