An open API service indexing awesome lists of open source software.

https://github.com/escherize/huff

Juicy hiccup in pure Clojure
https://github.com/escherize/huff

Last synced: 9 months ago
JSON representation

Juicy hiccup in pure Clojure

Awesome Lists containing this project

README

          

# huff

Hiccup in pure Clojure

## Usage

[![Clojars Project](https://img.shields.io/clojars/v/io.github.escherize/huff.svg)](https://clojars.org/io.github.escherize/huff)

``` clojure
(require '[huff2.core :as h])
```

## Rationale

When it comes to hiccup libraries, there's a venn-diagram "has ergonomic and modern affordances" and "works on babashka". So [huff](https://github.com/escherize/huff) is my way of saying why not both?

- [Weavejester's hiccup library](https://github.com/weavejester/hiccup) runs on babashka, but is missing some of the newer features hiccup afficianados have come to demand.

- [Lambda Island's hiccup](https://github.com/lambdaisland/hiccup) also provides a modern api, but overall I'd still call it a subset of huff's features.

## Features

- 🏭 Use [**functions** as **components**](#use-functons-as-components)
- 🎨 Style maps work as you'd expect `[:div {:style {:font-size 30}}]`
- 🔀 Include classes and ids tags [in any order](#tag-parsing)
- `:div.a#id.b` or `:div.a.c#id` or `:#id.a.c` all work!
- 🔒️ HTML-encoded by default
- 👵 Runs on [babashka](https://github.com/babashka/babashka) (unlike `lambdaisland/hiccup`)
- 🏎 Performance: 22-48% faster than hiccup/hiccup for runtime-generated HTML [without pre-compilation](https://github.com/escherize/huff/issues/8)
- 🙂 Hiccup-style fragments to return multiple forms `(list [:li.a] [:li.b])`
- 🙃 Reagent-style fragments to return multiple forms `[:<> [:li.a] [:li.b]]`
- 🤐 Extreme shorthand syntax `[:. {:color :red}]` `

`
- 🦺 Tested against slightly modified hiccup 2 tests
- 🪗 [Extensible grammar](#extendable-grammar)
- 📦 [raw-strings](https://github.com/escherize/huff/issues/5)

### Tag Parsing

Parse tags for id and class (in any order).

```clojure
(h/html [:div.hello#world "!"])
;; =>

!

```

#### Nested tag parsing

```clojure
(println (h/html [:div.left-aligned>p#user-parent>span {:id "user-name"} "Jason"]))

;=>

Jason


```

### [reagent](https://github.com/reagent-project/reagent)-like fragment tags

```clojure
(h/html [:<> [:div "d"] [:<> [:<> [:span "s"]]]])
;; =>

d
s
```

This is useful for returning multiple elements from a function:

```clojure
(defn twins [x] [:<>
[:div.a x]
[:div.b x]])

(h/html [:span.parent [twins "elements"]])
;;=>

elements

elements

```

Nest and combine them with lists to better convey intent to expand:

``` clojure
(h/html
[:ol
[:<> (for [x [1 2]]
[:li>p.green {:id (str "id-" x)} x])]])

;;=>



  1. 1




  2. 2



```

### Style map rendering

```clojure
(h/html [:div {:style {:border "1px red solid"
:background-color "#ff00ff"}}])
;; =>

(h/html [:. {:style {:width (h/px 3)}}])
;;=>


```

### Raw HTML tag:

This is nice if you want to e.g. render markdown in the middle of your hiccup. Note: We disable this by default and it must be manually enabled in the call to `html` or `page`,

``` clojure

(h/html [:hiccup/raw-html "

raw
"])
;; =Throws=> :hiccup/raw-html is not allowed. Maybe you meant to set allow-raw to true?

(h/html {:allow-raw true} [:hiccup/raw-html "

raw
"])
;;=>
raw

```

Another nice-to-have is to disallow raw html in un-trusted data getting passed into to the compiler, but being able to do that as a dev.

``` clojure
(h/html [:div [:hiccup/raw-html (h/raw-string "