Giter Club home page Giter Club logo

hiccup's Introduction

Hiccup Build Status

Hiccup is a library for representing HTML in Clojure. It uses vectors to represent elements, and maps to represent an element's attributes.

Install

Add the following dependency to your deps.edn file:

hiccup/hiccup {:mvn/version "2.0.0-RC3"}

Or to your Leiningen project.clj file:

[hiccup "2.0.0-RC3"]

Documentation

Syntax

Here is a basic example of Hiccup syntax:

user=> (require '[hiccup2.core :as h])
nil
user=> (str (h/html [:span {:class "foo"} "bar"]))
"<span class=\"foo\">bar</span>"

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

Hiccup is intelligent enough to render different HTML elements in different ways, in order to accommodate browser quirks:

user=> (str (h/html [:script]))
"<script></script>"
user=> (str (h/html [:p]))
"<p />"

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

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

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

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

Strings are automatically escaped:

user=> (str (h/html [:p "Tags in HTML are written with <>"]))
"<p>Tags in HTML are written with &lt;&gt;</p>"

To bypass this, use the hiccup2.core/raw function:

user=> (str (h/html [:p (h/raw "Hello <em>World</em>")]))
"<p>Hello <em>World</em></p>"

License

Copyright © 2023 James Reeves

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

hiccup's People

Contributors

algernon avatar arohner avatar asmala avatar bronsa avatar budu avatar ericlavigne avatar fracek avatar garmelon avatar gerrit-hntschl avatar iku000888 avatar indy avatar jcrossley3 avatar jiriknesl avatar joda avatar joodie avatar kfahy avatar kwrooijen avatar luontola avatar lynaghk avatar masaedw avatar panthevm avatar paraseba avatar shhivam avatar simon-nicholls avatar stefanvanburen avatar stesla avatar thheller avatar weavejester avatar wiseman avatar zehcnas34 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  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

hiccup's Issues

Wrong return type from hiccup.util/url

It seems the url function returns a java.net.URI object, not a string as stated by its documentation (and as it used to do in 0.3.8)

user=> (hiccup.util/url "/group/" 4 "/products" {:page 9})

<URI /group/4/products?page=9>

It looks like a call to str went lost during the refactoring.
Anyway, either the function or its documentation is wrong.

Regards,
Lorenzo

Quoting of special chars in character data

(Thank you for creating compojure. It is a real joy to work with!)

Special characters like "<" and the like are escaped in attributes, but not if they appear in character data. As a consequence, the following test case produces invalid xhtml with the unquoted "<&" string appearing as content of the

:

(deftest escaped-character-data
  (is (= (html [:div "<&"])
         "<div>&lt;&amp;</div>")))

lein ring server throws error due to older version of hiccup

I'm using hiccup-1.0.1-beta1 with Clojure 1.3.0 and compojure 1.0.1

(defproject Tasks "1.0.0-SNAPSHOT"
  :description ""
  :dependencies [[org.clojure/clojure "1.3.0-beta1"]
                 [compojure "1.0.1"]
                 [hiccup "1.0.0-beta1"]]
  :dev-dependencies [[lein-ring "0.5.4"]]
  :ring {:handler tasks.core/app})

Using hiccup 1.0.1-beta1 with ring handler results in the below error:

Caused by: java.lang.IllegalAccessError: defelem does not exist
    at clojure.core$refer.doInvoke(core.clj:3754)
    at clojure.lang.RestFn.applyTo(RestFn.java:139)
    at clojure.core$apply.invoke(core.clj:602)
    at clojure.core$load_lib.doInvoke(core.clj:5243)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:602)
    at clojure.core$load_libs.doInvoke(core.clj:5262)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:604)
    at clojure.core$use.doInvoke(core.clj:5354)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at hiccup.page_helpers$eval430$loading__4531__auto____431.invoke(page_helpers.clj:1)
    at hiccup.page_helpers$eval430.invoke(page_helpers.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6406)

This stackoverflow question says, it's because of ring-devel using an older version of hiccup-0.3.7.jar in lib/dev

http://stackoverflow.com/questions/9572150/hiccup-1-0-0-beta1-error

After excluding hiccup in lein-ring:

 :dev-dependencies [[lein-ring "0.5.4" :exclusions [hiccup]]]

I'm still getting an error

Caused by: java.io.FileNotFoundException: Could not locate hiccup/page_helpers__init.class or hiccup/page_helpers.clj on classpath: 
    at clojure.lang.RT.load(RT.java:430)
    at clojure.lang.RT.load(RT.java:398)
    at clojure.core$load$fn__4636.invoke(core.clj:5377)
    at clojure.core$load.doInvoke(core.clj:5376)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invoke(core.clj:5191)
    at clojure.core$load_lib.doInvoke(core.clj:5228)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invoke(core.clj:602)
    at clojure.core$load_libs.doInvoke(core.clj:5262)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invoke(core.clj:604)
    at clojure.core$use.doInvoke(core.clj:5354)
    at clojure.lang.RestFn.invoke(RestFn.java:482)
    at ring.middleware.stacktrace$eval96$loading__4531__auto____97.invoke(stacktrace.clj:1)
    at ring.middleware.stacktrace$eval96.invoke(stacktrace.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6406)

Can you please fix this issue?

Inconsistent *html-mode* and lazyness

I'm using hiccup 0.2.5 and am trying to set the mode to be :sgml, but for some tags it is still the default :xml. Here's an example,

user> (html {:mode :sgml} [:html [:title] [:link] (list [:link])])
"<html><title><link /><link></html>"

Notice that the first link tag is closed <link />. The behaviour is very sensitive to the input, and adding or removing other tags will make the output a correct link tag. The (list [:link]) at the end is meant to be the return of a helper function like include-css.

It looks like a lazy sequence is being evaluated outside the *html-mode* binding. Adding a doall to collapse-strs fixed it, but there might be a more appropriate spot.

(defn- collapse-strs
  "Collapse nested str expressions into one, where possible."
  [expr]
  (if (seq? expr)
    (do
      (doall expr)
      (cons
        (first expr)
        (mapcat
         #(if (and (seq? %) (symbol? (first %)) (= (first %) (first expr) `str))
            (rest (collapse-strs %))
            (list (collapse-strs %)))
          (rest expr))))
    expr))

Unicode in tag values

Something is wrong with unicode as tag contents. This code:

[:a {:href "/search/"} "Поиск"]

evaluates to:

< a href="#" >?????< /a >

forms, drop-down

Is it possible with drop-down to specify the <option value>? This way the name can be different than the posted value.

Thanks

Attribute values defined as clojure data structures render incorrectly

(hc/html [:div {:data-stuff (map inc [1 2 3])}]))

<div data-stuff="clojure.lang.LazySeq@7c42"></div>

This is particularly relevant if you are using clojure data in data- attributes.

I use pr-str to get around this when writing hiccup for rendering.

However, recently I have "hiccup style" data structures for manipulation where I don't want to convert these to strings - except when rendering.

Escape by default

This feature is like the one in Rails 3.

I think it would be best if Hiccup does HTML-escape by default, and if one need to use raw string, he would write (raw "my string").

I guess the "raw" function would add metadata to the string. Then when rendering, Hiccup would check if the string has the metadata attached.

<p /> is not valid HTML

In README.md is stated:

Hiccup is intelligent enough to render different HTML 
elements in different ways, in order to accommodate browser quirks:

user=> (html [:p])
"<p />"

But <p /> in not valid HTML code.

In old HTML 4: backslash is not valid at all (it is so-called NET syntax http://en.wikipedia.org/wiki/Standard_Generalized_Markup_Language#NET and no HTML browser recognizes it).

In new HTML 5: a "/" character may be present only if the element is a void (see http://www.w3.org/TR/html-markup/syntax.html#syntax-elements) and p is non-void element.

In XHTML 1.0: there is a HTML Compatibility Guidelines (http://www.w3.org/TR/xhtml1/#C_3), which says:

Given an empty instance of an element whose content 
model is not EMPTY (for example, an empty title or paragraph) 
do not use the minimized form (e.g. use <p> </p> and not <p />).

Feature request for handling seqs of seqs.

It would be nice if (html [[:h1 "foo"] [:h2 "bar"]]) yielded "<h1>foo</h1><h2>bar</h2>". I would consider it the expected behavior but that might just be me.

The use case is for-loops that need to generate several tags, e.g. (html [:h1 "Foo"] (for [id ids] [[:h2 (title id)] [:p (contents id)]])).

Enquiry: Separate out hiccup rendering from helper functions ??

This is not so much an issue as an enquiry.

I use both hiccup and crate and now dommy and it occured to me that hiccup is doing two distinct functions today. (and Crate replicates some this).

  1. rendering hiccup data structures
  2. providing a library of functions to build hiccup data structures.

Do you think it might be worth considering splitting the two into two independent libraries?

  1. A rendering library
  2. A set of generic clojure library functions as a base to be portable across multiple clojure implementations (cljs and maybe clr)

Make normalize-element public

Would it be reasonable to make this public? I'd like to post process elements before handing them off for rendering (modifying tags based on attrs in some way).

Documentation on seq-inclusion could be more clear

Though it can be deduced from the Syntax docs, it's not immediately clear that whatever collection one wishes to include in an element's vector must not be a vector on itself, which is easy to overlook at first, vectors being the most commonly used sequence in Clojure and all.

Problem with class

When you try and specify a class inside a map as well as part of the attribute name the class in the attribute name is lost. See:

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

In this case I think the output should be:

"<a class=\"foo bar\"></a>"

Please allow adding properties to the html element with html5

I was recently building a site with hiccup, and was suprised that when using the html5 macro, it is not possible to add properties to the <html> element itself other than lang. It would be very neat if I could add arbitrary properties, such as prefix (for ogp and similar things).

As far as I see, it would only mean something along these lines:

`(let [options# ~options]
  (html {:mode :html}
    (doctype :html5)
    [:html (merge {:lang (options# :lang)}
                         (options# :root-options)) ~@contents]))

I'll send a pull request later, that does this at every appropriate place within the macro.

Unminified output

Is there a way making hiccup generate unminified output so it would be easier to debug in the browser?

Html outputs as one long line of html...

Using the latest version (1.0.5), I don't see any line breaks or formatting of the html output (see the image below). Am I doing something wrong here with how I'm using the "html" function?

http://cubeupload.com/im/pwbndI.png

Thanks for your time; from browsing through previous issues, I didn't see mention of output comprising of a single line.

No url encoding

Hiccup doesn't encode the urls. For example url /asdf+ encoded becomes /asdf%2B.

My fix up:

(defn replace-all [#^String text coll](reduce %28fn [url [match replacement]]
%28clojure.string/replace url match replacement%29%29
text coll))

(def url-escape-codes
[["$" "%24"]
["&" "%26"]
["+" "%2B"]
["," "%2C"]
["/" "%2F"]
[":" "%3A"]
[";" "%3B"]
["=" "%3D"]
["?" "%3F"]
["@" "%40"]])

(defn escape-url [url](replace-all %28as-str url%29 url-escape-codes))

(defn build-url
([] "")
([#^String url](str "/" %28escape-url url)))
([#^String url & rest](str %28build-url url%29 %28apply build-url rest%29)))

<video> tag should be closing

I was trying to put a video element on a page and it started to swallow the follwing image element. Looking around the internet seems to suggest that the video tag needs a closing tag.

[:video]
[:img {:src "..."}]

outputs as:

<video><img src="...">

should be:

<video></video><img src="...">

Indentation

What do you think of adding a feature to automatically indent html output, rather than outputting a ball of unindented html?

I could use htmltidy but, I use hiccup along with django templates. Tidy chokes on django template tags & snippets of html.

Hiccup and Enlive

Hello,
This is a feature request and not a bug. I was recently using Hiccup with Enlive and found that I had to parse Hiccup output into Clojure-XML format. This resulted in the following conversions:

hiccup datastructure -> string -> clojure-xml datastructure -> html page

This is a bit clunky and could potentially lead to performance problems.

The author of Enlive suggested that a function to convert Hiccup datastructures into clojure-xml form would be optimal for use with Enlive.

Developers on the #clojure-web freenode channel thought that such a facility would be useful elsewhere to produce clojure-xml compatible datastructures, since the Hiccup representation is much more convenient to write.

Would it be possible to add such a function to Hiccup? If not, would a patch to do this be accepted in principle?

Thanks in advance for your help.
Saul

Hiccup 1.0.4 breaks lein ring reload

Upon upgrading from hiccup 1.0.2 to 1.0.4, I noticed that lein-ring no longer regenerates HTML from hiccup properly. Although lein-ring is recompiling the underlying code, the output HTML never changes. Downgrading back to 1.0.2 fixes this problem.

hiccup.form/form-to action parameter optional

I'd like to request that the action parameter of hiccup.form/form-to be optional -- if omitted then no action attribute is needed in the HTML markup which will default the form to submit to the current url.

Below is an example of my use case:

(ns myapp.routes
  (:require [myapp.views :as form]))

(defroutes app-routes
  (GET "/myform" [] form/show)
  (POST "/myform" [] form/update))
(ns myapp.views)

(defn show [request]
  (layout/standard
    [:h1 "My Test Form"]
    (form/form-to
      [:post ""]
      (form/label :name "Name")
      (form/text-field :name)
      (form/submit-button "Submit"))))

(defn update [request]
  (do-stuff)
  (redirect "/"))

I do this frequently and just thought it would be a sensible default.

Replace 'tag' with 'element' in documentation

The Hiccup documentation refers to (XML) elements as 'tags', with the result that it produces confusing error messages.

<foo> is a tag -- a 'start tag'. </foo> is also a tag -- an 'end-tag'. Together they delimit the 'foo' element, that is, the element with element-name 'foo'. (Start-) Tags contain attributes; elements do not. Elements contain text and other elements; tags do not. Elements have names; there's no such thing as a "tag name" (that's like saying 'what is the name of a comma').

They're completely different things (one is a syntax fragment, the other a bit of large-scale structure in a document), but Hiccup conflates them, which means that it produces confusing error messages such as "[:li "boo"] is not a valid tag name", which had me seriously scratching my head, looking for Clojure maps where this appears as a map key (which seemed the most reasonable interpretation of "tag name" in this context).

Sorry if this sounds picky, and I know that a lot of people conflate the two terms, but it confuses the hell out of anyone who knows the difference!

All the best,

Norman

noscript tag

Hi,

I want to use the noscript tag but it's not part of the container-tags
and my attempts to embed a style tag within a noscript tag has not been successful.

I expected [:noscript [:style ....]] to work.

Does it mean that support needs to be added to hiccup for this tag ?

Thank you,
Luc

could you add an optional "options" parameter to include-css?

(include-css & styles) => (include-css options & styles) like (xhtml options & contents)?

this would allow us to write

(include-css {:media "screen, projector, print"} "/css/app.css")

instead of

[:link {:href "/css/app.css" :media "screen, projector, print" :rel "stylesheet" :type "text/css"} ]

cheers
JL

escape-html should escape apostrophe's

(defn escape-html
  "Change special characters into HTML character entities."
  [text]
  (.. ^String (as-str text)
    (replace "&" "&amp;")
    (replace "<" "&lt;")
    (replace ">" "&gt;")
    (replace "\"" "&quot;")
    (replace "'" "&apos;")))

Exception after upgrade from 1.0.4 to 1.0.5

Hi, just upgraded hiccup to 1.0.5 and now I'm receiving error message:

Caused by: java.lang.IllegalStateException: *html-mode* already refers to: 'hiccup.util/*html-mode* in namespace: hiccup.compiler

What changed? I just refer all hiccup.core namespace in my code.

Thanks!

image should encode the url

for example if you have an image link with a filename 12 - 2.jpg

this will work correctly

[:img {:src "/img/12 - 2.jpg"}]

but using image does not

(image "/img/12 - 2.jpg")

because to-url will throw an exception parsing the string

URI.java:2829   java.net.URI$Parser.fail
URI.java:3002   java.net.URI$Parser.checkChars
URI.java:3086   java.net.URI$Parser.parseHierarchical
URI.java:3044   java.net.URI$Parser.parse
URI.java:595    java.net.URI.<init>
util.clj:47 hiccup.util/eval1841[fn]
...

Ambiguity in using form-to

The example: (form-to [method action] uses :put "/post" and suggests that "/post" is a route. It's not clear what that route stands for. If I use defpage "/post", then I get the "missing page" message when http://localhost:8080/post fires based on the form (a login form). If I click refresh, the code fires, but not when called programmatically. What am I missing? Many thanks.

Hiccup produces invalid HTML

When using an HTML document type, such as HTML 4.01 strict, having a tag such as <br /> is syntactically equivalent to <br >> and causes validation errors. Hiccup should have a method to switch between printing empty tags as <br /> and <br >. This is actually also a problem in compojure 0.3.x.

I have forked hiccup and patched (here: sattvik/hiccup@43fc6b2) it so that it has a new var html-mode which dictates how tags should self close.

It works as follows, roughly:
(binding [html-mode :xhtml-strict](html [:br]))
=> "
"
(binding [html-mode :html4](html [:br]))
=> "
"

It may not be the most optimal solution, but it works well enough for me.

[:script runs body twice

I had the following code:

(html [:script (init-json-data ref filter-func name)])

And was trying to figure out why init-json-data was being called twice. It appears that :script will evaluate it's argument twice in the above example. Moving init-json-data out to a let fixed the issue, but this is not what I would have expected when I read the code.

Coerce fractions to floats in element attrs

Should Hiccup be smart enough to automatically coerce fractions to floats when rendering HTML or SVG attributes, or is that outside of its contract with the user?

If the former, I'd be happy to submit a pull request.

Clojure Map to HTML List

While the unordered-list and ordered-list functions work great for things like vectors, Clojure maps need a little more help.

I've put a link to a Gist of mine that takes a Clojure map and uses hiccup to print it out as a set of nested HTML lists, going recursively through the whole map and into child maps, etc. I've included some extra parameters, just thinking about what might be useful when using a function like this. If you think any part of the function could be useful, please include it in hiccup.

https://gist.github.com/807755

I'm also happy to fork, branch and issue a pull request, just wasn't sure how exactly you'd want to handle this function.

Enhancement: Integrate CSSLJ for CSS file generation

It seems like it would be nice to have Hiccup generate CSS as well. That way you can ensure the syntax is completely uniform between the HTML and CSS generator libs, and any enhancements can cross-pollinate between the two modes more easily.

'CSSLJ' describes itself as follows:
CSSLJ is a library for representing CSS in Clojure in the same style as Hiccup.

It is found at:
http://github.com/programble/csslj

I'm all for seeing this become a 'hiccup.css' module.

Just throwing it out there - it would certainly be fine to have two separate projects for these two libraries as well.

Thanks for putting in the time and making a brilliantly simple solution for HTML generation. It's so fun to use; it's really nice to be able to work with it.

ordered list documentation bug

Hi,
in page-helpers.clj there is a typo:

(defelem ordered-list
"Wrap a collection in an unordered list" ...
:-)

best regards
Jakub

hiccup does not handle URLs without protocol correctly in include-js

When deploying with a context root if a url does not specify a protoco then it will be treated as a relative URL:

(include-js  "//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js")
[:script {:type "text/javascript", :src #<URI //ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js>}]

plain text

I would like to use a plain text view, but only html is available.

url, link-to, and with-base-url are incompatible

Because url and link-to both call resolve-uri, code such as (link-to (url "/foo" {...})...) will result in the base URL being prepended twice.

Maybe I'm using the methods in a way they aren't intended? url is very convenient - helpful for generating links as well as redirect locations - and in my (very limited) time using Hiccup, almost every occasion I'm using link-to for a relative path, I also want to use url.

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.