sake92 / hepek

Typesafe HTML templates and static site generator in pure Scala
https://sake92.github.io/hepek/
Apache License 2.0
104 stars 10 forks source link

Support for HTMX attributes #273

Closed carlos-verdes closed 6 months ago

carlos-verdes commented 6 months ago

HTMX is a library to give the best UX using plain HTML following principles of hyper media https://htmx.org/

I plan to use Hepek in combination with HTMX and Alpine, having direct DSL support will save lot of time, have better code and avoid errors at compilation

carlos-verdes commented 6 months ago

I started with a local project to play around this concept, this is what I have so far

Example of usage:

  import Htmx.*
  div.hxGet("/hello").hxTrigger("load").hxSwap(Swap.innerHTML)("Loading...")

HtmxDependencies.scala

import ba.sake.hepek.html.*

trait HtmxDependencies extends PageDependencies:

  protected val dependencies: List[String] = List("https://unpkg.com/htmx.org")

  def withExtension(extension: String): HtmxDependencies =
    new HtmxDependencies:
      override val dependencies: List[String] = this.dependencies :+ extension

  override def scriptURLs: List[String] = dependencies

object HtmxDependencies:

  val Default = new HtmxDependencies {}

  val WithSSE = Default.withExtension(HtmxExtensions.SseExtension)

object HtmxExtensions:
  val SseExtension = "https://unpkg.com/htmx.org/dist/ext/sse.js"

Htmx.scala

import ba.sake.hepek.scalatags.all.*

object Htmx:

  def hxGetAtt(url: String) = attr("hx-get") := url
  def hxPostAtt(url: String) = attr("hx-post") := url
  def hxPutAtt(url: String) = attr("hx-put") := url
  def hxDeleteAtt(url: String) = attr("hx-delete") := url

  def hxSwapAtt(swap: Swap, extra: String = "") = 
    val value = if extra.isEmpty then swap.toString else swap.toString + " " + extra
    attr("hx-swap") := value

  def hxTriggerAtt(trigger: String) = attr("hx-trigger") := trigger
  def hxTargetAtt(target: String) = attr("hx-target") := target

  extension (tag: ConcreteHtmlTag[String])
    def hxGet(url: String): ConcreteHtmlTag[String] = tag(hxGetAtt(url))
    def hxPost(url: String): ConcreteHtmlTag[String] = tag(hxPostAtt(url))
    def hxPut(url: String): ConcreteHtmlTag[String] = tag(hxPutAtt(url))
    def hxDelete(url: String): ConcreteHtmlTag[String] = tag(hxDeleteAtt(url))

    def hxSwap(swap: Swap): ConcreteHtmlTag[String] = tag(hxSwapAtt(swap))
    def hxTrigger(trigger: String): ConcreteHtmlTag[String] = tag(hxTriggerAtt(trigger))
    def hxTarget(target: String): ConcreteHtmlTag[String] = tag(hxTargetAtt(target))

  enum Swap:
    case innerHTML
    case outerHTML
    case beforebegin
    case afterbegin
    case beforeend
    case afterend
    case delete
    case none