Giter Club home page Giter Club logo

hiccups's Introduction

Hiccups

Hiccups is a ClojureScript port of the Hiccup HTML generation library. It uses vectors to represent tags, and maps to represent a tag's attributes.

The goal is to provide similar performance to Closure Templates with a much more Clojure friendly syntax.

Differences from Hiccup

  • In ClojureScript, macros need to be defined in separate Clojure namespaces. Because of this, core functionality is split into two files: core.clj contains the macros and compile-time only functions, and runtime.cljs contains functions that are also available at runtime. The contents of runtime.cljs are also used at compile-time, so the goal is to keep it portable between ClojureScript and Clojure.
  • Unit tests are run in a PhantomJS browser using lein-cljsbuild and Closure's testing libs.
  • Not everything has been ported yet. See ToDo.

Alternatives

  • Crate is an alternative Hiccup style library for ClojureScript. The main difference between Crate and Hiccups is that Crate generates DOM nodes and Hiccups generates strings. There are a few reasons why you might consider Hiccups over Crate (YMMV, of course):
    • As with the original Hiccup, Hiccups tries to do as much as possible at compile time, with macro expansion.
    • Working with strings can be much more performant than working with DOM nodes, especially with large amounts of markup, and especially with older browsers.
    • Easier to use in headless environments like Node.js
  • Closure Templates is Google's Closure templating library.

Install

Add the following dependency to your project.clj file:

[hiccups "0.3.0"]

Usage

Require both the core macros and the runtime functions in your namespace declaration:

(ns myns
  (:require-macros [hiccups.core :as hiccups :refer [html]])
  (:require [hiccups.runtime :as hiccupsrt]))

(hiccups/defhtml my-template []
  [:div
    [:a {:href "https://github.com/weavejester/hiccup"}
      "Hiccup"]])

Syntax

Here is a basic example of Hiccups syntax:

(html [:span {:class "foo"} "bar"])
"<span class=\"foo\">bar</span>"

The first element of the vector is used as the tag name. The second attribute can optionally be a map, in which case it is used to supply the tag's attributes. Every other element is considered part of the tag's body.

Hiccups is intelligent enough to render different HTML tags in different ways, in order to accommodate browser quirks:

(html [:script])
"<script></script>"
(html [:p])
"<p />"

And provides a CSS-like shortcut for denoting id and class attributes:

(html [:div#foo.bar.baz "bang"])
"<div id=\"foo\" class=\"bar baz\">bang</div>"

If the body of the tag is a seq, its contents will be expanded out into the tag body. This makes working with forms like map and for more convenient:

(html [:ul
        (for [x (range 1 4)]
          [:li x])])
"<ul><li>1</li><li>2</li><li>3</li></ul>"

Note that while lists are considered to be seqs in Clojure(Script), vectors and sets are not. As a consequence, Hiccups will bail out if a vector is passed in without a tag: [[:div] [:div]].

See the Hiccup wiki for more information.

ToDo

  • Catch up with recent changes in Hiccup.
  • Form helpers
  • Page helpers
  • Figure out if the runtime can be pulled in without an explicit require by the user
  • Explore potential performance improvements using Google's StringBuffer et al.

hiccups's People

Contributors

decadent avatar ikitommi avatar jonase avatar kennyjwilli avatar magomimmo avatar mpenet avatar teropa avatar whamtet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hiccups's Issues

#id sugar doesn't work for forms nor inputs

Great work on this library! I have actually been working on something similar to be included in the ClojureScript standard library.

One small bug, though: I seem not to be able to use the :element#id syntax with forms nor with inputs. The elements render without a tag name, causing them to print as strings when added to the DOM.

This:

(hiccups/defhtml sign-in-form []
  [:form#sign-in {:action "#/sign-in" :method "post"}
   [:fieldset {:legend "Sign In"}
    [:ol.form-elements
     [:li.text
      [:label {:for "sign-in-email"} "Email"]
      [:input#sign-in-email {:name "email" :type "text"}]]
     [:li.password
      [:label {:for "sign-in-password"} "Password"]
      [:input#sign-in-password {:name "password" :type "password"}]]
     [:li.submit
      [:input {:type "submit" :value "Sign in"}]]]]])

Outputs this:

"< action=\"#/sign-in\" method=\"post\"><fieldset legend=\"Sign In\"><ol class=\"form-elements\"><li class=\"text\"><label for=\"sign-in-email\">Email</label>< name=\"email\" type=\"text\" /></li><li class=\"password\"><label for=\"sign-in-password\">Password</label>< name=\"password\" type=\"password\" /></li><li class=\"submit\"><input type=\"submit\" value=\"Sign in\" /></li></ol></fieldset></>"

Notice the missing form and input element names.

Hiccup with parameters gives compiler error

I'm trying to use select2 library with hiccups. select2 wants templateResults parameter, which is a function, which returns HTML string wrapped inside jQuery. Like this:

(.select2 dom-node (clj->js {:templateResult (fn [state]
                                               (js/$ (html
                                                       [:div
                                                        [:label "Value"]
                                                        [:div "Something"]])))}))

It seems that if I want to use parameters from state, the html macro does not work anymore. I get a compile warning saying that hiccups is not even defined if I do this

(.select2 dom-node (clj->js {:templateResult (fn [state]
                                               (js/$ (html
                                                       [:div
                                                        [:label (:text state)]
                                                        [:div "Something"]])))}))

I wonder if this because html is a macro instead of function. Would it be possible to implement html as a function to make this work?

Tags with more than two classes don't normalize properly

When using "." syntax to specify CSS classes as part of the tag name, hiccups fails when there are three or more classes:

What currently happens (note the extraneous period character in the output class):

(hiccups-runtime/normalize-element [:button.alpha.beta.gamma])
;=> ["button" {:id nil, :class "alpha beta.gamma"} nil]

What should happen:

(hiccups-runtime/normalize-element [:button.alpha.beta.gamma])
;=> ["button" {:id nil, :class "alpha beta gamma"} nil]

Library status?

Hi Tero,

Just wondering what the status of Hiccups is? Do you have plans to continue maintaining it? I notice there's an open issue from a year ago.

I see a lot of people seem to be using Crate, but I much prefer the approach you've taken here.

Thanks,

Call for maintainers

The project is getting stars pretty regularly so I gather it's being used. Since I'm not actively maintaining or using it, I'd be happy to have someone else take the reins on maintaining the project.

Reply or shoot me a message at [email protected] if you're interested.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.