Roda::Tags
Coverage: 100%
A Roda plugin providing easy creation of flexible HTML tags within Roda apps or Roda plugins.
Extensively tested and with 100% code test coverage.
Installation
Add this line to your application's Gemfile:
gem 'roda-tags'
And then execute:
bundle
Or install it yourself as:
gem install roda-tags
Getting Started
To use Roda::Tags just ensure the gem is included in the Gemfile and then...
...add the plugin to your app...
class MyApp < Roda
plugin :tags # see Configurations below for options
# or
plugin :tag_helpers # , options
# <snip...>
end
...or include the plugin in your own Roda plugin.
class Roda
module RodaPlugins
module YourPlugin
def self.load_dependencies(app, opts={})
app.plugin :tags, opts
# or
app.plugin :tag_helpers, opts
end
# <snip...>
end
end
end
Usage
TODO: add usage notes here...
Key Methods / Functionality
Roda::Tags contains two plugins - [:tags
, :tag_helpers
] - that can be
used independently or together.
Note! The :tags
plugin is loaded by the :tag_helpers
plugin.
1. :tags
Plugin
This plugin have one key public method - tag()
, which supports this
dynamic syntax:
-- tag(*args, &block)
tag(name)
tag(name, &block)
tag(name, content)
tag(name, content, attributes)
tag(name, content, attributes, &block)
tag(name, attributes)
tag(name, attributes, &block)
This makes the method very flexible as can be seen below.
Self closing tags
tag(:br) #=> <br> or <br/> if XHTML
tag(:hr, class: :divider) #=> <hr class="divider">
Multi line tags
tag(:div) #=> <div></div>
tag(:div, 'content')
# <div>
# content
# </div>
tag(:div, 'content', id: 'comment')
# <div id="comment">
# content
# </div>
# NB! no content
tag(:div, id: :comment)
#=> <div id="comment"></div>
Single line tags
tag(:h1,'Header') #=> <h1>Header</h1>
tag(:abbr, 'UN', title: "United Nations") #=> <abbr title="United Nations">UN</abbr>
Working with blocks
tag(:div) do
tag(:p, 'Hello World')
end
# <div>
# <p>Hello World</p>
# </div>
<% tag(:ul) do %>
<li>item 1</li>
<%= tag(:li, 'item 2') %>
<li>item 3</li>
<% end %>
# <ul>
# <li>item 1</li>
# <li>item 2</li>
# <li>item 3</li>
# </ul>
# NOTE: ignores tag contents when given a block
<% tag(:div, 'ignored tag-content') do %>
<%= tag(:label, 'Comments:', for: :comments) %>
<%= tag(:textarea,'textarea contents', id: :comments) %>
<% end %>
# <div>
# <label for="comments">Comments:</label>
# <textarea id="comments">
# textarea contents
# </textarea>
# </div>
Boolean attributes
tag(:input, type: :checkbox, checked: true)
#=> <input checked="checked" type="checkbox">
tag(:option, 'Roda', value: "1" selected: true)
#=> <option selected="selected" value="1">Roda</option>
tag(:option, 'PHP', value: "0" selected: false)
#=> <option value="0">PHP</option>
The plugin also have a few other public helper methods:
-- merge_attr_classes(attr, *classes)
Updates attr[:class]
in the hash with the given classes
and returns attr
.
attr = { class: 'alert', id: :idval }
merge_attr_classes(attr, 'alert-info')
#=> { class: 'alert alert-info', id: :idval }
merge_attr_classes(attr, [:alert, 'alert-info'])
#=> { class: 'alert alert-info', id: :idval }
-- merge_classes(*classes)
Returns an alphabetised string from all given class values.
The method correctly handles a combination of arrays
, strings
& symbols
being passed in.
attr = { class: 'alert', id: :idval }
merge_classes(attr[:class], ['alert', 'alert-info']) #=> 'alert alert-info'
merge_classes(attr[:class], :text) #=> 'alert text'
merge_classes(attr[:class], [:text, :'alert-info']) #=> 'alert alert-info text'
Included Helper methods
The :tags
plugin also includes a few useful public helper methods for use
within other methods or gems.
-- capture(block='')
Captures and returns a captured ERB
block and restores the buffer afterwards.
-- capture_html(*args, &block)
Captures the HTML from a block of template code for ERB
or HAML
.
def some_method(*args, &block)
# <snip...>
res = capture_html(&block)
# <snip...>
end
-- concat_content(text="")
Outputs the given content to the buffer directly.
concat_content("This will be concatenated to the buffer")
-- block_is_template?(block)
Returns true
if the block is from an ERB
or HAML
template; false
otherwise. Used to determine if contents should be returned or concatenated
to output.
2. :tag_helpers
Plugin
-- form_tag(action, attrs={}, &block)
Constructs a <form>
without an object based on options passed.
form_tag('/register') do
...
end
# <form action="/register" id="register-form" method="post">
# ...
# </form>
Automatically adds a hidden faux method when :method
is NOT either POST
or GET
.
form_tag('/user/1/profile', method: :put, id: 'profile-form')
...
end
# <form action="/user/1/profile" id="profile-form" method="post" >
# <input name="_method" type="hidden" value="put"/>
# ...
# </form>
Add multipart support via:
form_tag('/upload', multipart: true)
# or
form_tag('/upload', multipart: 'multipart/form-data')
# or
form_tag('/upload', enctype: 'multipart/form-data')
# <form enctype="multipart/form-data" method="post" action="/upload">
# ...
# </form>
-- label_tag(field, attrs={}, &block)
Constructs a <label>
tag from the given options.
By default appends ':'
to the label name, based upon the plugin config
:tags_label_append
value.
label_tag(:name)
#=> <label for="name">Name:</label>
label_tag(:name, label: 'Custom label', class: 'sr-only')
#=> <label class="sr-only" for="name">Custom label:</label>
# uses a humanized version of the label name if { label: nil }
label_tag(:name, label: nil)
#=> <label for="name">Name:</label>
# removes the label text when { label: :false }
label_tag(:name, label: false)
#=> <label for="name"></label>
By default adds '<span>*</span>'
to the label name when { required: true }
is passed. Based upon the plugin config :tags_label_required_str
value.
label_tag(:name, required: true)
#=> <label for="name">Name: <span>*</span></label>
Label tags also supports passing blocks.
<% label_tag(:remember_me) do %>
<%= checkbox_tag :remember_me %>
<% end %>
# <label for="remember_me">Remember Me:
# <input
# class="checkbox"
# id="remember_me"
# name="remember_me"
# type="checkbox"
# value="1"
# >
# </label>
-- hidden_field_tag(name, attrs={})
Constructs a hidden input field from the given options. Only
[:value, :id, :name]
attributes are allowed.
hidden_field_tag(:snippet_name)
#=> <input id="snippet_name" name="snippet_name" type="hidden">
hidden_field_tag(:csrf, value: 'tokenval')
#=> <input id="csrf" name="csrf" type="hidden" value="tokenval">
hidden_field_tag(:snippet_id, id: 'some-id')
#=> <input id="some-id" name="snippet_id" type="hidden">
# removing the `:id` attribute completely.
hidden_field_tag(:snippet_name, id: false)
#=> <input name="snippet_name" type="hidden">
-- text_field_tag(name, attrs={})
- also aliased as textfield_tag()
Creates a standard <input type="text"...>
field from the given options.
text_field_tag(:snippet_name)
#=> <input class="text" id="snippet_name" name="snippet_name" type="text">
text_field_tag(:name, value: 'some-value')
#=> <input class="text" id="name" name="name" type="text" value="some-value">
text_field_tag(:name, id: 'some-id')
#=> <input class="text" id="some-id" name="name" type="text">
# removing the `:id` attribute completely. NB! bad practice.
text_field_tag(:name, id: false)
#=> <input class="text" name="name" type="text">
# append a CSS class to the existing class.
text_field_tag(:name, class: :big)
#=> <input class="big text" id="name" name="name" type="text">
# adds a `:title` attribute when passed `:ui_hint`
text_field_tag(:name, ui_hint: 'a user hint')
#=> <input class="text" id="name" name="name" title="a user hint" type="text">
# supports `:maxlength` & `:size` attributes
text_field_tag(:ip, maxlength: 15, size: 20)
#=> <input class="text" id="ip" maxlength="15" name="ip" size="20" type="text">
# `:disabled` attribute
text_field_tag(:name, disabled: true)
#=> <input class="text" disabled="disabled" id="name" name="name" type="text">
# `:readonly` attribute
text_field_tag(:name, readonly: true)
#=> <input class="text" id="name" name="name" readonly="readonly" type="text">
-- password_field_tag(name, attrs={})
- also aliased as passwordfield_tag()
Constructs a <input type="password"...>
field from the given options.
password_field_tag(:snippet_name)
#=> <input class="text" id="snippet_name" name="snippet_name" type="password">
password_field_tag(:snippet_name, value: 'some-value')
#=> <input
# class="text"
# id="snippet_name"
# name="snippet_name"
# type="password"
# value="some-value">
password_field_tag(:snippet_name, id: 'some-id')
#=> <input class="text" id="some-id" name="snippet_name" type="password">
password_field_tag(:snippet_name, id: false)
#=> <input class="text" name="snippet_name" type="password">
# append a CSS class to the existing class. Default class: `.text`.
password_field_tag(:snippet_name, class: :big )
#=> <input class="big text" id="snippet_name" name="snippet_name" type="password">
# adds a `:title` attribute when passed `:ui_hint`
password_field_tag(:name, ui_hint: 'a user hint')
#=> <input class="text" id="name" name="name" title="a user hint" type="password">
# supports `:maxlength` & `:size` attributes
password_field_tag(:ip_address, maxlength: 15, size: 20)
#=> <input
# class="text"
# id="ip_address"
# maxlength="15"
# name="ip_address"
# size="20"
# type="password">
# `disabled` attribute
password_field_tag(:name, disabled: true)
password_field_tag(:name, disabled: :disabled)
#=> <input class="text" id="name" disabled="disabled" name="name" type="password">
-- file_field_tag(name, attrs={})
- also aliased as filefield_tag()
Creates an <input type="file"...>
field from given options.
NOTE! If you are using file uploads then you will also need to set the multipart option for the form tag, like this:
<% form_tag('/upload', multipart: true) do %>
<%= label_tag(:file, label: "File to Upload") %>
<%= file_field_tag "file" %>
<%= submit_tag %>
<% end %>
The specified URL will then be passed a File object containing the selected file, or if the field was left blank, a StringIO object.
file_field_tag('attachment')
#=> <input class="file" id="attachment" name="attachment" type="file">
# ignores invalid :value attribute.
file_field_tag(:photo, value: 'some-value')
#=> <input class="file" id="photo" name="photo" type="file">
file_field_tag(:photo, id: 'some-id')
#=> <input class="file" id="some-id" name="photo" type="file">
# removing the `:id` attribute completely. NB! bad practice.
file_field_tag(:photo, id: false)
#=> <input class="file" name="photo" type="file">
# append a CSS class to the existing class. Default class: `.file`.
file_field_tag(:photo, class: :big )
#=> <input class="big file" id="photo" name="photo" type="file">
# adds a `:title` attribute when passed `:ui_hint`.
file_field_tag(:photo, ui_hint: 'a user hint')
#=> <input class="file" id="photo" name="photo" title="a user hint" type="file">
# `:disabled` attribute
file_field_tag(:photo, disabled: true)
#=> <input class="file" disabled="disabled" id="photo" name="photo" type="file">
# `:accept` attribute is subject to actual browser support.
file_field_tag(:photo, accept: 'image/png,image/jpeg' )
#=> <input
# accept="image/png,image/jpeg"
# class="file"
# id="photo"
# name="photo"
# type="file">
-- textarea_tag(name, attrs={})
- also aliased as text_area_tag()
Constructs a textarea input from the given options.
TODO: enable :escape functionality. How??
-
:escape
- By default, the contents of the text input are HTML escaped. If you need unescaped contents, set this to false.
textarea_tag('post')
#=> <textarea id="post" name="post">\n</textarea>
# add a value
textarea_tag(:bio, value: @actor.bio)
#=> <textarea id="bio" name="bio">This is my biography.\n</textarea>
# set a different :id
textarea_tag(:body, id: 'some-id')
#=> <textarea id="some-id" name="post">...</textarea>
# adds a CSS class. NB! :textarea have no default class.
textarea_tag(:body, class: 'big')
#=> <textarea class="big" id="post" name="post">...</textarea>
# adds a `:title` attribute when passed `:ui_hint`
textarea_tag(:body, ui_hint: 'a user hint')
#=> <textarea id="post" name="post" title="a user hint">...</textarea>
# supports `:rows` & `:cols` attributes
textarea_tag('body', rows: 10, cols: 25)
#=> <textarea cols="25" id="body" name="body" rows="10">...</textarea>
# alternative `:size` shortcut to set `:rows` & `:cols`
textarea_tag('body', size: "25x10")
#=> <textarea cols="25" id="body" name="body" rows="10">...</textarea>
# `:disabled` attribute
textarea_tag(:description, disabled: true)
#=> <textarea disabled="disabled" id="description" name="description">
# ...
# </textarea>
# `:readonly` attribute
textarea_tag(:description, readonly: true)
#=> <textarea id="description" name="description" readonly="readonly">
# ...
# </textarea>
-- field_set_tag(*args, &block)
- also aliased as fieldset_tag()
Creates a <fieldset..>
tag for grouping HTML form elements.
field_set_tag(:actor)
# <fieldset id="fieldset-actor">
# <legend>Actor</legend>
# ...
# </fieldset>
# sets the `<legend>` and `:id` attribute when given a single argument.
field_set_tag('User Details') do
...
end
# <fieldset id="fieldset-user-details">
# <legend>User Details</legend>
# ...
# </fieldset>
# supports `:legend` attribute
field_set_tag(:actor, legend: 'Details')
# <fieldset id="fieldset-actor">
# <legend>Details</legend>
# <snip...>
# remove `<legend>` tag by `{ legend: false }`
field_set_tag(:actor, legend: 'Details')
# <fieldset id="fieldset-actor">
# <legend>Details</legend>
# <snip...>
# append a CSS class. NB! fieldset has no other class by default.
field_set_tag(:actor, class: 'legend-class')
# <fieldset class="legend-class" id="fieldset-actor">
# <snip...>
# default to 'fieldset' when passed `nil` as the first arg
field_set_tag(nil, class: 'format')
# <fieldset class="format" id="fieldset">
# <snip...>
# removing the `:id` attribute completely
field_set_tag('Users', id: false)
# <fieldset>
# <legend>Users</legend>
# <snip...>
-- legend_tag(contents, attrs={})
Return a legend with contents from the given options.
legend_tag('User Details')
#=> <legend>User Details</legend>
# adding an :id attribute.
legend_tag('User', id: 'some-id')
#=> <legend id="some-id">User</legend>
# adds a CSS class. NB! legend tags have no default class
legend_tag('User', class: 'some-class')
#=> <legend class="some-class">User</legend>
-- check_box_tag(name, attrs={})
- also aliased as checkbox_tag()
Creates an <input type="checkbox"...>
tag from the given options.
check_box_tag(:accept) || checkbox_tag(:accept)
#=> <input class="checkbox" id="accept" name="accept" type="checkbox" value="1">
# providing a value
check_box_tag(:rock, value: 'rock music')
#=> <input class="checkbox" id="rock" name="rock" type="checkbox" value="rock music">
# setting a different :id
check_box_tag(:rock, :id => 'some-id')
#=> <input class="checkbox" id="some-id" name="rock" type="checkbox" value="1">
# append a CSS class. NB! default class: '.checkbox'
check_box_tag(:rock, class: 'small')
#=> <input class="small checkbox" id="rock" name="rock" type="checkbox" value="1">
# adds a `:title` attribute when passed `:ui_hint`
check_box_tag(:rock, ui_hint: 'a user hint')
#=> <input
# class="checkbox"
# id="rock"
# name="rock"
# title="a user hint"
# type="checkbox"
# value="1">
# `checked` attribute
check_box_tag(:rock, checked: true)
#=> <input
# checked="checked"
# class="checkbox"
# id="rock"
# name="rock"
# type="checkbox"
# value="1">
# `disabled` attribute
check_box_tag(:rock, disabled: true)
#=> <input
# class="checkbox"
# disabled="disabled"
# id="rock"
# name="rock"
# type="checkbox"
# value="1">
-- radio_button_tag(name, attrs={})
- also aliased as radiobutton_tag()
Creates a <input type="radio"...>
tag from the given options.
NOTE! use groups of radio buttons named the same to allow users to select from a group of options.
radio_button_tag(:accept) || radiobutton_tag(:accept)
#=> <input class="radio" id="accept_1" name="accept" type="radio" value="1">
radio_button_tag(:rock, value:'rock music')
#=> <input class="radio" id="rock_rock-music" name="rock" type="radio" value="rock music">
# setting a different :id.
radio_button_tag(:rock, id: 'some-id')
#=> <input class="radio" id="some-id_1" name="rock" type="radio" value="1">
# append a CSS class. NB! default class: '.radio'
radio_button_tag(:rock, class: 'big')
#=> <input class="big radio" id="rock_1" name="rock" type="radio" value="1">
# adds a `:title` attribute when passed `:ui_hint`
radio_button_tag(:rock, ui_hint: 'a user hint')
#=> <input class="radio" id="rock_1" value="1" name="rock" title="a user hint" type="radio">
# `checked` attribute
radio_button_tag(:yes, checked: true)
#=> <input checked="checked" class="radio" id="yes_1" name="yes" type="radio" value="1">
# `disabled` attribute
radio_button_tag(:yes, disabled: true)
#=> <input disabled="disabled" class="radio" id="yes_1" name="yes" type="radio" value="1">
-- submit_tag(value="Save Form", attrs={})
- also aliased as submit_button()
Creates a submit button with the text value as the caption.
submit_tag() || submit_button()
#=> <input name="submit" type="submit" value="Save Form">
submit_tag(nil)
#=> <input name="submit" type="submit" value="">
submit_tag('Custom Value')
#=> <input name="submit" type="submit" value="Custom Value">
# adds a CSS class. NB! input[:submit] has no other class by default.
submit_tag(class: 'some-class')
#=> <input class="some-class" name="submit" type="submit" value="Save Form">
# supports the :disabled attribute.
submit_tag('disabled: true)
#=> <input disabled="disabled" name="submit" type="submit" value="Save Form">
# adds a `:title` attribute when passed `:ui_hint`.
submit_tag(ui_hint: 'a user hint')
#=> <input name="submit" title="a user hint" type="submit" value="Save Form">
-- image_submit_tag(src, attrs={})
Adds a <input src=""...>
tag which displays an image.
@img = '/img/btn.png'
image_submit_tag(@img)
#=> <input src="/img/btn.png" type="image">
image_submit_tag(@img, disabled: true)
#=> <input disabled="disabled" src="/img/btn.png" type="image">
image_submit_tag(@img, class 'search-button')
#=> <input class="search-button" src="/img/btn.png" type="image">
-- reset_tag(value='Reset Form', attrs={})
- also aliased as reset_button()
Creates a reset button with the text value as the caption.
reset_tag() || reset_button()
#=> <input name="reset" type="reset" value="Reset Form">
reset_tag(nil)
#=> <input name="reset" type="reset" value="">
reset_tag('Custom Value')
#=> <input name="reset" type="reset" value="Custom Value">
# adds a CSS class. NB! input[:reset] has no other class by default
reset_tag(class: 'some-class')
#=> <input class="some-class" name="reset" type="reset" value="Reset Form">
# supports the `:disabled` attribute
reset_tag(disabled: true)
#=> <input disabled="disabled" name="reset" type="reset" value="Reset Form">
# adds a `:title` attribute when passed `:ui_hint`
reset_tag(ui_hint: 'a user hint')
#=> <input name="reset" title="a user hint" type="submit" value="Reset Form">
-- select_tag(name, options, attrs={})
Creates a <select..>
tag (dropdown menu), including the various select options.
Note! the format for the options values must be [value, key]
.
Passing options values as a Hash
.
select_tag(:letters, {a: 'A', b: 'B' })
# <select id="letters" name="letters">
# <option value="a">A</option>
# <option value="b">B</option>
# </select>
Passing options values as an Array
.
@letters = [[:a,'A'], [:b,'B']]
select_tag(:letters, @letters)
# <select id="letters" name="letters">
# <option value="a">A</option>
# <option value="b">B</option>
# </select>
Handling passed options:
select_tag(:letters, @letters, disabled: true)
# <select id="letters" disabled="disabled" name="letters">
# <snip...>
select_tag(:letters, @letters, id: 'my-letters')
# <select id="my-letters" name="letters">
# <snip...>
select_tag(:letters, @letters, class: 'funky-select')
# <select class="funky-select" id="my-letters" name="letters">
# <snip...>
Handling the prompt value:
select_tag(:letters, @letters, prompt: true)
# <select id="letters" name="letters">
# <option selected="selected" value="">- Select -</option>
# <snip...>
# setting a custom prompt
select_tag(:letters, @letters, prompt: 'Top Letters', selected: 'a')
# <select id="letters" name="letters">
# <option value="">Top Letters</option>
# <option selected="selected" value="a">A</option>
# <snip...>
Adding :selected
option.
select_tag(:letters, @letters, selected: :a)
# <select id="letters" name="letters">
# <option selected="selected" value="a">A</option>
# <snip...>
When passing multiple items to :selected
option or setting the
{ multiple: true }
option, the select menu automatically becomes
a multiple select box.
NOTE! the name="letters[]"
attribute.
select_tag(:letters, @letters, selected: [:a,'b'])
# <select id="letters" multiple="multiple" name="letters[]">
# <option selected="selected" value="a">A</option>
# <option selected="selected" value="b">B</option>
# </select>
select_tag(:letters, @letters, multiple: true)
# <select id="letters" name="letters[]" multiple="multiple">
# <snip...>
-- select_option(value, key, attrs={})
Creates an <option...>
tag for <select...>
menus.
select_option('a', 'Letter A')
#=> <option value="a">Letter A</option>
select_option('on', '') # , nil)
#=> <option value="on">On</option>
# handling selected options
select_option('a', 'Letter A', selected: true)
#=> <option selected="selected" value="a">Letter A</option>
select_option('a', 'Letter A', selected: false)
#=> <option value="a">Letter A</option>
-- faux_method(method='PUT')
faux_method() #=> <input name="_method" type="hidden" value="PUT">
# handling DELETE requests
faux_method(:delete) #=> <input name="_method" type="hidden" value="DELETE">
Plugin Configurations
The default settings should help you get moving quickly, and are fairly common sense based.
However the :tags
plugin supports these config options:
:tag_output_format_is_xhtml
Sets the HTML output format, toggling between HTML 5
(false
) and XHTML
(true
). Default is: false
.
This option is retained for legacy support and in memory of the "good old days" ;-).
:tag_add_newlines_after_tags
Sets the formatting of the HTML output, whether it should be more compact in
nature or slightly better formatted. Default is: true
.
The :tag_helpers
plugin supports these config options:
:tags_label_required_str
Sets the formatting of the string appended to required <label...>
tags.
Default is: '<span>*</span>'
.
:tags_label_append_str
Sets the formatting of the string appended to <label...>
tags. Default is: ':'
.
:tags_forms_default_class
Sets the default class value for form tags. Default is: ''
(empty).
This is a shortcut to automatically add something like
Bootstrap support with 'form-control'
NOTE!
Config options set in :tag_helpers
are passed on to the :tags
plugin.
# <snip...>
# support legacy XHTML formatted output
plugin :tag_helpers, { tag_output_format_is_xhtml: true, ... }
# <snip...>
RTFM
If the above is not clear enough, please check the specs for a better understanding.
Errors / Bugs
If something is not behaving intuitively, it is a bug, and should be reported. Report Issues here
TODOs
-
Keep it up to date with any changes in
Roda
orHTML
. -
Decide on if it's worth it to do validity checks on all attributes passed to tags ie: reject attributes based upon what is allowed for the tag.
tag(:base, href: 'url', target: '_self', id: 'is-ignored') #=> <base href="url", target="_self">
-
Decide on whether to add a number of convenience tags (methods), such as:
meta(name, contents)
img(src, attrs={})
-
Any other improvements we may think of.
Acknowledgements
Inspiration for this gem was taken from the ActiveSupport gem by DHH & Rails Core Team released under the MIT license.
Development
After checking out the repo, run bundle install
to install dependencies.
Then, run bundle exec rake spec
to run the tests.
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
- run
bundle exec rake release
, which will create a git tag for the version - push git commits and tags
- push the
.gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub.
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Copyright
Copyright (c) 2010 - 2024 Kematzy
Released under the MIT License. See LICENSE for further details.
License
The gem is available as open source under the terms of the MIT License.