Glimmer DSL for Web 0.0.2 (Early Alpha)

Ruby in the Browser Web GUI Library

Gem Version Join the chat at https://gitter.im/AndyObtiva/glimmer

This project is inspired-by Glimmer DSL for Opal and is similar in enabling frontend GUI development with Ruby, but it mainly differs from Glimmer DSL for Opal by adopting a DSL that follows web-like HTML syntax in Ruby (enabling transfer of HTML/CSS/JS skills) instead of adopting a desktop GUI DSL that is webified. Also, it will begin by supporting Opal Ruby, but it might grow to support Ruby WASM as an alternative to Opal Ruby that could be switched to with a simple configuration change.

Note that the library is an Early Alpha and its APIs might change frequently until hitting a minor release at least.

You can finally live in pure Rubyland on the web!

Glimmer DSL for Web is an upcoming pre-alpha gem that enables building web GUI in pure Ruby via Opal on Rails (and potentially Ruby WASM in the future).

Sample

Initial HTML Markup:

...
<div id="app-container">
</div>
...

Glimmer GUI code:

require 'glimmer-dsl-web'

include Glimmer

# This will hook into element #app-container and then build HTML inside it using Ruby DSL code
div(parent: '#app-container') {
  label(class: 'greeting') {
    'Hello, World!'
  }
}

That produces:

...
<div id="app-container">
  <div parent="#app-container" class="element element-1">
    <label class="greeting element element-2">
      Hello, World!
    </label>
  </div>
</div>
...

Hello, World! Sample

Glimmer GUI code:

require 'glimmer-dsl-web'

include Glimmer

Document.ready? do
  div {
    'Hello, World!'
  }.render
end

That produces the following under <body></body>:

<div parent="body" class="element element-1">
  Hello, World!
</div>

Hello, Button! Sample

UPCOMING (NOT RELEASED OR SUPPORTED YET)

Glimmer GUI code demonstrating MVC + Glimmer Web Components (Views) + Data-Binding:

require 'glimmer-dsl-web'

class Counter
  attr_accessor :count

  def initialize
    self.count = 0
  end

  def increment!
    self.count += 1
  end
end

class HelloButton
  include Glimmer::Web::Component

  before_render do
    @counter = Counter.new
  end

  markup {
    # This will hook into element #app-container and then build HTML inside it using Ruby DSL code
    div(root_css_selector) {
      text 'Hello, Button!'

      button {
        # Unidirectional Data-Binding indicating that on every change to @counter.count, the value
        # is read and converted to "Click To Increment: #{value}  ", and then automatically
        # copied to button innerText (content) to display to the user
        inner_text <= [@counter, :count, on_read: ->(value) { "Click To Increment: #{value}  " }]

        on_click {
          @counter.increment!
        }
      }
    }
  }
end

HelloButton.render('#app-container')

That produces:

<div id="application">
  <button>
    Click To Increment: 0
  </button>
</div>

When clicked:

<div id="application">
  <button>
    Click To Increment: 1
  </button>
</div>

When clicked 7 times:

<div id="application">
  <button>
    Click To Increment: 7
  </button>
</div>

NOTE: Glimmer DSL for Web is a pre-alpha project. If you want it developed faster, please open an issue report. I have completed some GitHub project features much faster before due to issue reports and pull requests. Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.

Learn more about the differences between various Glimmer DSLs by looking at:

Glimmer DSL Comparison Table.

Table of Contents

Prerequisites

Setup

(NOTE: Keep in mind this is a very early experimental and incomplete alpha. If you run into issues, try to go back to a previous revision. Also, there is a slight chance any issues you encounter are fixed in master or some other branch that you could check out instead)

The glimmer-dsl-web gem is a Rails Engine gem that includes assets.

Rails 7

Please follow the following steps to setup.

Install a Rails 7 gem:

gem install rails -v7.0.1

Start a new Rails 7 app:

rails new glimmer_app_server

Add the following to Gemfile:

gem 'opal', '1.4.1'
gem 'opal-rails', '2.0.2'
gem 'opal-async', '~> 1.4.0'
gem 'opal-jquery', '~> 0.4.6'
gem 'glimmer-dsl-web', '~> 0.0.2'
gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
gem 'glimmer-dsl-css', '~> 1.2.1', require: false

Run:

bundle

Follow opal-rails instructions, basically running:

bin/rails g opal:install

Edit config/initializers/assets.rb and add the following at the bottom:

Opal.use_gem 'glimmer-dsl-web'

Run:

rails g scaffold welcome

Run:

rails db:migrate

Add the following to config/routes.rb inside the Rails.application.routes.draw block:

mount Glimmer::Engine => "/glimmer" # add on top
root to: 'welcomes#index'

Edit app/views/layouts/application.html.erb and add the following below other stylesheet_link_tag declarations:

<%= stylesheet_link_tag    'glimmer/glimmer', media: 'all', 'data-turbolinks-track': 'reload' %>

Clear the file app/views/welcomes/index.html.erb completely from all content.

Delete app/javascript/application.js

Edit and replace app/assets/javascript/application.js.rb content with code below (optionally including a require statement for one of the samples below):

require 'glimmer-dsl-web' # brings opal and other dependencies automatically

# Add more require-statements or Glimmer GUI DSL code

Example to confirm setup is working:

Initial HTML Markup:

...
<div id="app-container">
</div>
...

Glimmer GUI code:

require 'glimmer-dsl-web'

include Glimmer

# This will hook into element #app-container and then build HTML inside it using Ruby DSL code
div(parent: '#app-container') {
  label(class: 'greeting') {
    'Hello, World!'
  }
}

That produces:

...
<div id="app-container">
  <div parent="#app-container" class="element element-1">
    <label class="greeting element element-2">
      Hello, World!
    </label>
  </div>
</div>
...

Start the Rails server:

rails s

Visit http://localhost:3000

You should see:

setup is working

If you run into any issues in setup, refer to the Sample Glimmer DSL for Web Rails 7 App project (in case I forgot to include some setup steps by mistake).

Otherwise, if you still cannot setup successfully (even with the help of the sample project, or if the sample project stops working), please do not hesitate to report an Issue request or fix and submit a Pull Request.

Rails 6

Please follow the following steps to setup.

Install a Rails 6 gem:

gem install rails -v6.1.4.6

Start a new Rails 6 app (skipping webpack):

rails new glimmer_app_server --skip-webpack-install

Disable the webpacker gem line in Gemfile:

# gem 'webpacker', '~> 5.0'

Add the following to Gemfile:

gem 'opal', '1.4.1'
gem 'opal-rails', '2.0.2'
gem 'opal-async', '~> 1.4.0'
gem 'opal-jquery', '~> 0.4.6'
gem 'glimmer-dsl-web', '~> 0.0.2'
gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
gem 'glimmer-dsl-css', '~> 1.2.1', require: false

Run:

bundle

Follow opal-rails instructions, basically running:

bin/rails g opal:install

Edit config/initializers/assets.rb and add the following at the bottom:

Opal.use_gem 'glimmer-dsl-web'

Run:

rails g scaffold welcome

Run:

rails db:migrate

Add the following to config/routes.rb inside the Rails.application.routes.draw block:

mount Glimmer::Engine => "/glimmer" # add on top
root to: 'welcomes#index'

Edit app/views/layouts/application.html.erb and add the following below other stylesheet_link_tag declarations:

<%= stylesheet_link_tag 'glimmer/glimmer', media: 'all', 'data-turbolinks-track': 'reload' %>

Also, delete the following line:

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

Clear the file app/views/welcomes/index.html.erb completely from all content.

Edit and replace app/assets/javascript/application.js.rb content with code below (optionally including a require statement for one of the samples below):

require 'glimmer-dsl-web' # brings opal and other dependencies automatically

# Add more require-statements or Glimmer GUI DSL code

Example to confirm setup is working:

Initial HTML Markup:

...
<div id="app-container">
</div>
...

Glimmer GUI code:

require 'glimmer-dsl-web'

include Glimmer

# This will hook into element #app-container and then build HTML inside it using Ruby DSL code
div(parent: '#app-container') {
  label(class: 'greeting') {
    'Hello, World!'
  }
}

That produces:

...
<div id="app-container">
  <div parent="#app-container" class="element element-1">
    <label class="greeting element element-2">
      Hello, World!
    </label>
  </div>
</div>
...

Start the Rails server:

rails s

Visit http://localhost:3000

You should see:

setup is working

NOT RELEASED OR SUPPORTED YET

If you run into any issues in setup, refer to the Sample Glimmer DSL for Web Rails 6 App project (in case I forgot to include some setup steps by mistake).

Otherwise, if you still cannot setup successfully (even with the help of the sample project, or if the sample project stops working), please do not hesitate to report an Issue request or fix and submit a Pull Request.

Supported Glimmer DSL Keywords

All HTML elements.

All HTML attributes.

Samples

This external sample app contains all the samples mentioned below configured inside a Rails Opal app with all the prerequisites ready to go for convenience:

https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app

[NOT RELEASED OR SUPPORTED YET] https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails-app

Hello Samples

Hello, World!

Glimmer GUI code:

require 'glimmer-dsl-web'

include Glimmer

Document.ready? do
  div {
    'Hello, World!'
  }.render
end

That produces the following under <body></body>:

<div parent="body" class="element element-1">
  Hello, World!
</div>

Hello, Button!

UPCOMING (NOT RELEASED OR SUPPORTED YET)

Glimmer GUI code demonstrating MVC + Glimmer Web Components (Views) + Data-Binding:

require 'glimmer-dsl-web'

class Counter
  attr_accessor :count

  def initialize
    self.count = 0
  end

  def increment!
    self.count += 1
  end
end

class HelloButton
  include Glimmer::Web::Component

  before_render do
    @counter = Counter.new
  end

  markup {
    # This will hook into element #app-container and then build HTML inside it using Ruby DSL code
    div(root_css_selector) {
      text 'Hello, Button!'

      button {
        # Unidirectional Data-Binding indicating that on every change to @counter.count, the value
        # is read and converted to "Click To Increment: #{value}  ", and then automatically
        # copied to button innerText (content) to display to the user
        inner_text <= [@counter, :count, on_read: ->(value) { "Click To Increment: #{value}  " }]

        on_click {
          @counter.increment!
        }
      }
    }
  }
end

HelloButton.render('#app-container')

That produces:

<div id="application">
  <button>
    Click To Increment: 0
  </button>
</div>

When clicked:

<div id="application">
  <button>
    Click To Increment: 1
  </button>
</div>

When clicked 7 times:

<div id="application">
  <button>
    Click To Increment: 7
  </button>
</div>

Glimmer Supporting Libraries

Here is a list of notable 3rd party gems used by Glimmer DSL for Web:

  • glimmer-dsl-xml: Glimmer DSL for XML & HTML in pure Ruby.
  • glimmer-dsl-css: Glimmer DSL for CSS (Cascading Style Sheets) in pure Ruby.
  • opal-async: Non-blocking tasks and enumerators for Web.
  • to_collection: Treat an array of objects and a singular object uniformly as a collection of objects.

Glimmer Process

Glimmer Process 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 is simply made up of 7 guidelines to pick and choose as necessary until software development needs are satisfied.

Learn more by reading the GPG (Glimmer Process Guidelines)

Help

Issues

You may submit issues on GitHub.

Click here to submit an issue.

Chat

If you need live help, try to Join the chat at https://gitter.im/AndyObtiva/glimmer

Feature Suggestions

These features have been suggested. You might see them in a future version of Glimmer. You are welcome to contribute more feature suggestions.

TODO.md

Change Log

CHANGELOG.md

Contributing

CONTRIBUTING.md

Contributors

Click here to view contributor commits.

License

MIT

Copyright (c) 2023 - Andy Maleh. See LICENSE.txt for further details.

--

Built for Glimmer (DSL Framework).