Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

hx-live-hyperscript

Hyperscript-flavored shorthand for the htmx hx-live extension.

It rewrites shorthand expressions to the core q() API before hx-live evaluates them. It adds syntax, not state or runtime behavior.

Note

Packaging and standalone test infrastructure are still pending.

Load the Extension

Load scripts in this order:

htmx
└── hx-live
    └── hx-live-hyperscript

The extension source is at src/ext/hx-live-hyperscript.js.

Use Local State

Prefix an attribute with @ to read or write it on the current element.

<button aria-pressed="false"
        hx-on:click="@aria-pressed = !@aria-pressed">
    Mute
</button>

The core form is:

q(this).aria.pressed = !q(this).aria.pressed

The same syntax covers each state namespace:

@data-count++
@aria-expanded = true
@.active = true
@readonly = true

Use Shared State

Prefix an attribute with ^ to use its nearest owner, starting at the current element.

<section data-count="0">
    <button hx-on:click="^data-count++">Add</button>
    <output :text="^data-count"></output>
</section>
section[data-count]
       ▲
       │ ^data-count
     button

The core form is:

q(this).closest.data.count++

Use the same owner lookup after a selection:

q('.item').^data-open = true
q('.option').^aria-activedescendant = this.id

Select Elements

Use #id for an ID or <.../> for any selector accepted by q().

#cart.@data-count++
<.row/>.@hidden = true
<previous input/>.@value
<.error/>.^data-invalid = true
#cart              → q('#cart')
<.row/>            → q('.row')
<previous input/>  → q('previous input')

Directional selectors use the core q() grammar:

<first .item/>
<last .item/>
<next .item/>
<previous .item/>
<closest .field/>
<.item in #panel/>

Continue from a Selection

Use 's to access state or a property from a selector literal.

#cart's @data-count++
<.field/>'s @value

It is equivalent to continuing through the selected q() proxy.

Name Attributes in Helpers

Inside toggle() and take(), a sigil replaces the string attribute name.

toggle(@aria-expanded)
toggle(@data-view, 'grid', 'list')
take(@aria-selected)
take(@.active)

These have the same behavior as:

toggle('aria-expanded')
toggle('data-view', 'grid', 'list')
take('aria-selected')
take('.active')

Reference

Attribute Sigils

Shorthand Core expression
@data-count q(this).data.count
^data-count q(this).closest.data.count
@aria-expanded q(this).aria.expanded
^aria-expanded q(this).closest.aria.expanded
@.active q(this).class.active
^.active q(this).closest.class.active
@readonly q(this).attr.readonly
^readonly q(this).closest.attr.readonly

Namespaces

Use a wildcard or @class to access a whole namespace:

{ ...@data-* }
{ ...^data-* }
@class.assign({ active: true, loading: false })

Selector Literals

Shorthand Core expression
#cart q('#cart')
<.row/> q('.row')
<previous input/> q('previous input')
<.item in #panel/> q('.item in #panel')

How It Works

The extension hooks into expression compilation and rewrites supported syntax:

HTML expression
      │
      ▼
hx-live-hyperscript
      │  syntax rewrite
      ▼
core q() expression
      │
      ▼
hx-live evaluation

For example:

^data-count++
      ↓
q(this).closest.data.count++

The rewriter skips strings, comments, regular expressions, and raw template text. Normal JavaScript keeps its meaning when a value comes first:

flags ^ mask
count < max

Development

src/ext/hx-live-hyperscript.js        extension source
test/tests/ext/hx-live-hyperscript.js browser tests

License

BSD Zero Clause

About

Hyperscript-flavored syntax for the htmx hx-live extension

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages