Enable Ruby classes the ability to generate reusable pieces of html
class MyController < ApplicationController
include HtmlSlice
def index
html_slice :say_hello do
h1 "hello #{pizza}"
end
end
def pizza
"🍕"
end
end
# index.html.erb
<%= raw @html_slice[:say_hello] %>
- Generate HTML dynamically in instance scope: unlike Markaby, HtmlSlice
self
points to the class instance that are using it, make easier to reuse code and make abstractions (see https://github.com/markaby/markaby?tab=readme-ov-file#label-A+Note+About+instance_eval). - HtmlSlice uses
include
instead of inheritance. This means we can "plug" it in anywhere—Rails controllers, services, Sinatra apps, Roda apps—or create specific view classes if needed. - Can be used to generate all application html or only html partials (slices 🍕).
- Lightweight, use HtmlSlice without performance penalties.
- Escapes HTML content to prevent XSS vulnerabilities.
Install the gem and add to the application's Gemfile by executing:
$ bundle add html_slice
If bundler is not being used to manage dependencies, install the gem by executing:
$ gem install html_slice
Include HtmlSlice in any Ruby class to generate HTML dynamically.
require 'html_slice'
class HelloView
include HtmlSlice
def to_html
html_slice do
h1 'hello world'
text
div do
_ '<b> some raw html </b>'
end
end
end
def text
tag :p, %q(
Lorem ipsum dolor sit amet
)
end
end
puts HelloView.new.to_html
# <h1>hello world</h1><p>Lorem ipsum dolor sit amet</p><div><b> some raw html </b></div>
- The
html_slice
method starts the HTML generation process creating an @html_slice instance variable and returning its content. - Each time we call the html tag methods, the method append the generated html in @html_slice.
- Tags like div, h1, and ul are dynamically defined as methods, enabling you to structure HTML seamlessly.
- Tags that are not defined as methods can be generated using the
tag
method (*only the most common tags are dinamically defined as methods, except "p", "head" and "body") - Use the
_
method to append raw content to the @html_slice.
HTML attributes can be added to tags as a hash:
div id: "main", class: "highlighted" do
span "Hello world"
end
"_" in html attributes is converted to "-"
div x_data: "{ hello: 'world' }" do # x-data="{ hello: 'world' }"
span "Hello world"
end
The @html_slice holds a hash where every key maps to a html string generated calling the "tag methods", html slice default key is :default
require 'html_slice'
class HelloView
include HtmlSlice
def to_html
html_slice do # @html_slice[:default] = ''
h1 'hello world' # @html_slice[:default] << '<h1>hello world</h1>'
text # @html_slice[:default] << '<p>Lorem ipsum dolor sit amet</p>'
div do
_ '<b> some raw html </b>'
end
end
html_slice :some_key do # @html_slice[:some_key] = ''
h1 'hello world' # @html_slice[:some_key] << '<h1>hello world</h1>'
text # @html_slice[:some_key] << '<p>Lorem ipsum dolor sit amet</p>'
div do
_ '<b> some raw html </b>'
end
end
end
def text
tag :p, %q(
Lorem ipsum dolor sit amet
)
end
end
HelloView.new.to_html
html_slice
block
class App < Roda
include HtmlSlice
def layout
html_layout do
yield
end
end
plugin :autoload_hash_branches
autoload_hash_branch_dir('./app/routes')
route(&:hash_branches)
end
# app/routes/foods
class App
hash_branch('foods') do |r|
r.is do
r.get do
@foods = Food.order(:name).all
layout do
ul do
@foods.each do |food|
li food.inspect
end
end
end
end
end
end
end
class ApplicationController
include HtmlSlice
def html(&block)
html_slice(&block).html_safe
end
end
# Imagine a Rails controller
class MyController < ApplicationController
before_action :set_items
def index
render html: (html do
h1 'hello world'
div class: 'to-do' do
to_do_list
end
end)
end
# "<h1>hello world</h1><div class='to-do'><ul><li>Clean the house</li><li>Study Ruby</li><li>Play sports</li></ul></div>"
private
def to_do_list
ul do
@items.each do |item|
li item
end
end
end
def set_items
@items ||= ['Clean the house', 'Study Ruby', 'Play sports']
end
end
class MyController < ApplicationController
include HtmlSlice
def index
html_slice :say_hello do
h1 "hello #{pizza}"
end
end
def pizza
"🍕"
end
end
# index.html.erb
<%= raw @html_slice[:say_hello] %>
class ApplicationController
include HtmlSlice
def layout
html_layout { # Same as html_slice but wrap the content in a <!DOCTYPE html><html>...</html> structure
tag :head do
meta charset: 'utf-8'
custom_head
end
tag :body do
yield
end
}.html_safe
end
end
# Imagine a Rails controller
class MyController < ApplicationController
before_action :set_items
def index
render html: (layout do
h1 'hello world'
div class: 'to-do' do
to_do_list
end
end)
end
# "<!DOCTYPE html><html><head><meta charset='utf-8'/><title>Hello HtmlSlice</title></head><body><h1>hello world</h1><div class='to-do'><ul><li>Clean the house</li><li>Study Ruby</li><li>Play sports</li></ul></div></body></html>"
def custom_head
title 'Hello HtmlSlice'
end
private
def to_do_list
ul do
@items.each do |item|
li item
end
end
end
def set_items
@items ||= ['Clean the house', 'Study Ruby', 'Play sports']
end
end
We must use the _
method that render raw content
class HelloController < ApplicationController
def index
render html: (html do
h1 'Hello#h_slice'
tag :p, 'Find me in app/controllers/hello_controller.rb'
_ helpers.link_to('oi')
_ (helpers.form_for 'user' do |f|
f.text_field('name')
end)
end)
end
end
Rendering a div
with h1
and a unique value 100,000 times (cpu time):
user system total real
erubi 0.865151 0.005151 0.870302 ( 0.870701)
markaby 0.785023 0.004450 0.789473 ( 0.789531)
papercraft 0.215119 0.001360 0.216479 ( 0.216479)
phlex 0.146289 0.002243 0.148532 ( 0.148719)
html_slice 0.186992 0.000697 0.187689 ( 0.187692)
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/henrique-ft/html_slice. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
Everyone interacting in the HtmlSlice project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.