Project

htmx

0.0
The project is in a healthy, maintained state
An augmenter and companion to the HTMX JavaScript library.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

~> 2.7
~> 12.10
 Project Readme

HTMX

A haiku from the HTMX team:

javascript fatigue:
longing for a hypertext
already in hand

…​and from Hypermedia Systems:

The goal of [HTMX] is not less JavaScript, but less code, more readable and hypermedia-friendly code.

This gem provides native Ruby support for the HTMX JavaScript library so you can build sophisticated web applications using pure Hypermedia REST APIs while avoiding unnecessary bloat and complexity common with the JavaScript ecosystem. By building upon the original foundations of Hypermedia REST APIs, you can build rich web applications with no additional JavaScript!

At the moment, the functionality of this gem is still in the early stages of development but the goal of this gem is to aid with the development of HTMX applications.

💡 This is used with the Hanamismith gem when building Hanami applications. Even better, you can play with the Hanami demo application to learn more. Enjoy!

Table of Contents
  • Features
  • Requirements
  • Setup
  • Usage
    • HTML Attribute Prefixes
    • HTTP Headers
      • Request
      • Response
    • Errors
  • Development
  • Tests
  • License
  • Security
  • Code of Conduct
  • Contributions
  • Developer Certificate of Origin
  • Versions
  • Community
  • Credits

Features

  • Augments the HTMX JavaScript library.

  • Speeds up HTMX development.

  • Compatible with Hanami, Roda, and other web frameworks.

Requirements

  1. A strong understanding of Hypermedia Systems.

  2. HTMX.

  3. Ruby.

Setup

To install with security, run:

# 💡 Skip this line if you already have the public certificate installed.
gem cert --add <(curl --compressed --location https://alchemists.io/gems.pem)
gem install htmx --trust-policy HighSecurity

To install without security, run:

gem install htmx

You can also add the gem directly to your project:

bundle add htmx

Once the gem is installed, you only need to require it:

require "htmx"

Usage

One of the first tasks you’ll want to tackle, when working with the HTMX library, is building HTMX specific HTML attributes. This can be accomplished by using the .[] method. For example, when implementing a Hanami view part, you could use the following:

tag.button(
  "Delete",
  class: "button decline",
  type: "submit",
  **HTMX[target: "closest .task", delete: "/tasks/#{value.id}"]
)

The above would produce the following:

<button class="button decline" type="submit" hx-target="closest .task" hx-delete="/tasks/1">
  Delete
</button>

Notice the appropriate HTMX hx-target and hx-delete attributes are built which are compatible with the HTMX library while not having to manually prefix each one of these attributes with the hx- prefix. You can even use symbols, strings, or a mix of both as well.

HTML Attribute Prefixes

As shown above, building HTMX attributes takes minimal effort but if you’d prefer the HTML data- prefix, which the HTMX library supports, you can customize by using the following:

prefixer = HTMX::Prefixer.new "data-hx"

tag.button(
  "Delete",
  class: "button decline",
  type: "submit",
  **prefixer.call(target: "closest .task", delete: "/tasks/#{value.id}")
)

This would then produce the following HTML code:

<button class="button decline"
        type="submit"
        data-hx-target="closest .task"
        data-hx-delete="/tasks/1"
>
  Delete
</button>

As you can see, the data-hx-target and data-hx-delete keys are used. These are definitely more verbose than the hx- keys. By the way, the HTMX::Prefixer is called when using the HTMX .[] as shown earlier. This means the following are equivalent:

HTMX[delete: "/tasks/1"]
HTMX::Prefixer.new.call delete: "/tasks/1"
HTMX::Prefixer.new("hx").call delete: "/tasks/1"

All three of the above will produce the same output which means you’ll most likely want to use the .[] method since it has the shortest syntax.

If you attempt to use an unsupported prefix, you’ll get an error:

HTMX::Prefixer.new "bogus"
# Invalid prefix: "bogus". Use: "hx" or "data-hx". (HTMX::Error)

Some HTMX attributes use dashes. For those situations, you can use strings for keys or underscored symbols to produce the correct HTMX syntax. Here’s and example using both a string and symbol for keys:

HTMX["swap-oob" => true, push_url: "/demo/123"]
# {"hx-swap-oob"=>true, "hx-push-url"=>"/demo/123"}

HTTP Headers

When working with HTTP requests/responses, especially HTTP headers, there are a few objects that can parse and make the data easier to work with. These objects are named accordingly: request and response. Here’s how to use them.

Request

The request object allows you to obtain a Data object to interact with when parsing HTMX HTTP request headers. Example:

HTMX::Headers::Request.new

# <data HTMX::Headers::Request boosted=nil,
#                              current_url=nil,
#                              history_restore_request=nil,
#                              prompt=nil,
#                              request=nil,
#                              target=nil,
#                              trigger_name=nil,
#                              trigger=nil
# >

Notice you get a Data instance where all members have the HX- prefix removed while each value defaults to nil. Even better — and more practical — is you can ask the request object to parse the incoming HTTP headers directly and give you exactly what you need:

HTMX::Headers::Request.for request.env

# <data HTMX::Headers::Request boosted="true",
#                              current_url="/demo",
#                              history_restore_request=nil,
#                              prompt="Yes",
#                              request="true",
#                              target="demo",
#                              trigger_name="save",
#                              trigger="demo"
# >

With the above, the .for method plucks out only the HTMX specific headers which may or may not have values. Extra header keys, which are not specific to HTMX, are ignored.

Response

The response object allows you to obtain a Data object to interact with when parsing HTMX HTTP response headers. Example:

HTMX::Headers::Response.new

# <data HTMX::Headers::Response location=nil,
#                               push_url=nil,
#                               redirect=nil,
#                               refresh=nil,
#                               replace_url=nil,
#                               reswap=nil,
#                               retarget=nil,
#                               trigger=nil,
#                               trigger_after_settle=nil,
#                               trigger_after_swap=nil
# >

Notice you get a Data instance where all members have the HX- prefix removed while each value defaults to nil. Even better — and more practical — is you can ask the response object to parse the incoming HTTP headers directly and give you exactly what you need:

HTMX::Headers::Response.for response.headers

# <data HTMX::Headers::Response location="/",
#                               push_url="/demo",
#                               redirect="/demo",
#                               refresh="true",
#                               replace_url="/demo",
#                               reswap="none",
#                               retarget=".demo",
#                               trigger="demo",
#                               trigger_after_settle="demo",
#                               trigger_after_swap="demo"
# >

With the above, the .for method plucks out only the HTMX specific headers which may or may not have values. Extra header keys, which are not specific to HTMX, are ignored.

Errors

As you’ve probably picked up by now, any/all errors issued by this gem will be an instance of the HTMX::Error class which inherits from StandardError. you can use this classification to catch and deal with these errors in your own implementation as desired.

Development

To contribute, run:

git clone https://github.com/bkuhlmann/htmx
cd htmx
bin/setup

You can also use the IRB console for direct access to all objects:

bin/console

Tests

To test, run:

bin/rake

Credits