Defining custom tags using hiccup ?

723 views
Skip to first unread message

Murtaza Husain

unread,
May 12, 2012, 12:12:53 PM5/12/12
to clo...@googlegroups.com
Hi,

I like the way hiccup allows you to represent html elements as datastructure. However this is limited to native elements. If you want to represent custom elements, the solution is to crate a function which will then spit out the basic html tags that hiccup compiler understands.

It would be great if hiccup allowed the ability to define custom tags. ie a macro which allows us to define custom tags, which is then picked up by hiccup's compiler.

eg to define a new element (from hiccup's code)-

(defelem link-to
  "Wraps some content in a HTML hyperlink with the supplied URL."
  [url & content]
  [:a {:href (to-uri url)} content])

which is then called as (link-to "http://google.com" "Hi this is google").

Instead of that if it allowed an extensible compiler with the same macro defelem, I could call -

[:link-to {:url "http://google.com"} "Hi this is google"]

Will that not be more clojurey :)
 
This functinality would be similar to AngularJS, which bills itself as an html compiler. Has anyone tried out something similar with hiccup?

Thanks,
Murtaza

James Reeves

unread,
May 12, 2012, 10:36:35 PM5/12/12
to clo...@googlegroups.com
On 12 May 2012 17:12, Murtaza Husain <murtaza...@sevenolives.com> wrote:
> Instead of that if it allowed an extensible compiler with the same macro
> defelem, I could call -
>
> [:link-to {:url "http://google.com"} "Hi this is google"]
>
> Will that not be more clojurey :)

That seems more complicated, IMO. Why require an custom macro system
when normal functions do the same job? What's the advantage?

- James

Walter Tetzner

unread,
May 12, 2012, 11:01:01 PM5/12/12
to clo...@googlegroups.com
On Saturday, May 12, 2012 10:36:35 PM UTC-4, James Reeves wrote:
That seems more complicated, IMO. Why require an custom macro system
when normal functions do the same job? What's the advantage?

The same reason hiccup uses data structures to represent HTML instead
of using nested functions: you can manipulate the vectors with
code. Function calls are opaque.
 

Dave Sann

unread,
May 12, 2012, 11:48:01 PM5/12/12
to clo...@googlegroups.com
As I see it, link-to is a function that saves you a little bit of typing if you choose to use it.

But if you don't, you could just write [:a {:href "blah"} "Blah"] where :a is exactly :link-to, just spelt differently.

what is proposed above seems to be renaming of elements and attributes - but for what purpose?

Dave

Murtaza Husain

unread,
May 13, 2012, 12:35:46 AM5/13/12
to clo...@googlegroups.com

Thats the whole idea. The ability to build abstractions. Currently I have a host of functions that I have defined for higher level components, which then return datastructures defined in terms of basic html tags.

It would be a great idea if I could directly represent even custom tags as the basic tags, rather than a function call, and as Walter mentioned then have the ability to manipulate the data structures alike.

And this is not to take away the excellent library that hiccup is and what it enables us to do. This conversation would not have been possible without that.

Thanks,
Murtaza

Walter Tetzner

unread,
May 13, 2012, 10:31:48 AM5/13/12
to clo...@googlegroups.com
You could do this without adding anything to hiccup.

If you wrote a function that, say, used walk, you could have it go
through the vectors, and replace the custom tags with what they
represent. Then you could just call that before calling `html'.

(html
  (transform
    [:html
      [:head
        [:title "some page"]]
      [:body
        [:link-to {:url "http://www.google.com/"} "Hi this is Google"]]]))

The benefit to doing it this way over having the macro is that it's
clear where the custom tags come from when looking at the invocation
of `html'.

If you really want `html' to handle it, maybe it could be called with
a map of tranform functions?

(html {:link-to link-to}
 [:html
   [:head
     [:title "some page"]]
  [:body
    [:link-to {:url "http://www.google.com/"} "Hi this is Google"]]])

Either way, I think this ends up being nicer than a macro that changes
the behavior of `html'.


On Sunday, May 13, 2012 12:35:46 AM UTC-4, Murtaza Husain wrote:

Dave Sann

unread,
Apr 25, 2013, 4:55:52 AM4/25/13
to clo...@googlegroups.com
I replied to this a long time ago and in the original case - I did not see huge value in the suggestion. But recently I wanted to do exactly what Murtaza suggests.

There are a couple of reasons why I think this capability would be useful. (And rereading Murtaza's email - I think this is what he meant)

1. The functions defined in hiccup and other libraries are not portable. if you rely on these, they will only work if the library maintained has copied the function interface exactly. This is not always the case. (as a separate comment these utility functions 
would be better separated from the rendering code).

2. I would be great to write markup that describes your domain, not HTML so
[:address :street "here" :city "there"]

rather than [:div ....lots of html specific bits ... street...]

3. It would be great to be able to switch the rendering of your domain without editing the overall markup structure.

4. if webcomponents take off - which I hope they do - you may be able to gracefully transition by disabling the various tag rewriting again, not touching the main markup logic.

So I had a look to see if this can be done - and it can - relatively easily. 
I implemented it the easiest way initially - but there are alternative possibilities for how this might work. Currently it uses a multimethod - but it might be better to pass in "tag expanding functions" when rendering - this would be more flexible.

The changes to hiccup to achieve this are quite minor.


I added a basic repl example file

A nice thing here is that incompatibilities between hiccup and cljs equivalents could be mitigated if we could agree on a "standard" for allowing custom tags.

Thoughts anyone?

Dave

Dave Sann

unread,
Apr 25, 2013, 5:17:42 AM4/25/13
to clo...@googlegroups.com

Dave Sann

unread,
Apr 25, 2013, 5:43:24 AM4/25/13
to clo...@googlegroups.com
one other thought.

It is possible just to manipulate the hiccup data as suggested by Walter above. This may be better because it is independent. But I wonder about performance costs of processing the structures twice (expand and then render) rather than once (render).

Dave

Carlos Fontes

unread,
Mar 20, 2014, 4:01:55 PM3/20/14
to clo...@googlegroups.com
Dave Sann

Custom tags are awesome! Just what I was looking for!
Do you have this anywhere in clojars.org?

Carlos Fontes

unread,
Mar 20, 2014, 9:20:48 PM3/20/14
to clo...@googlegroups.com
Hey, I provided it here: [ccfontes/hiccup "1.0.3-custom-tags"] so don't bother if you didn't do it.
Btw, it's working alright, thanks!
Reply all
Reply to author
Forward
0 new messages