Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hiccup and Enlive #7

Open
alienscience opened this issue Sep 13, 2010 · 8 comments
Open

Hiccup and Enlive #7

alienscience opened this issue Sep 13, 2010 · 8 comments

Comments

@alienscience
Copy link

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

@weavejester
Copy link
Owner

It's possible in theory. It might need a bit of rearranging to do, but I'd be okay with it in principle. I've been meaning to tidy up Hiccup's source code for a while, as all that precompilation has made the code a bit labyrinthine.

@fxt
Copy link

fxt commented May 1, 2011

Connecting hiccup and enlive would really be very useful.
I have written a render-nodes function that takes a hiccup form and turns it into a node or seq of nodes that enlive is happy with. I had to write it inside src/hiccup/core.clj because it uses the normalize-element private function defined there.
I did not spend time yet developing something to pre-compile the nodes like hiccup does for HTML. It would be great to have that too.

Here is the code I have written. Please, feel free to use it to add to hiccup. If you do not have time for it, please, let me know and I will continue work on my fork. Thank you for such a useful library.
fxt

(defn- nodalize-attribute [[name value]]
  (cond
   (true? value) [(as-str name) (escape-html name)]
   (not value) nil
   :else [(as-str name) (escape-html value)]))

(defn- nodalize-attr-map [attrs]
  (if (nil? attrs)
    nil
    (->> attrs seq (map nodalize-attribute) (remove nil?)
         (apply concat) (apply sorted-map))))

(defmulti render-nodes
  "Turn a Clojure data type into a seq of XML nodes."
  {:private false}
  type)

(defn- nodalize-element
  "Render an tag vector as an XML node."
  [element]
  (let [[tag attrs content] (normalize-element element)]
    {:tag tag
     :attrs (nodalize-attr-map attrs)
     :content (render-nodes content)}))

(defmethod render-nodes IPersistentVector [element]
  (nodalize-element element))

(defmethod render-nodes ISeq [coll]
  (map render-nodes coll))

(defmethod render-nodes nil [_]
  nil)

(defmethod render-nodes :default [x]
  (str x))

BTW, I did some little bit of testing of the type (html [hiccup stuff]) == (enlive-html/emit* (render-nodes [hiccup stuff])) and got the two to agree. That is why I did a bit of transformation on the attribute map and used a sorted-map for it.

@weavejester
Copy link
Owner

I think if I was going to add this capability, I'd want the library refactored so that the output was controlled by a protocol that could be changed depending on whether you wanted a string of HTML, a string of XML or a tree of XML node maps.

So I don't think there should be a separate render-nodes function, but what you're written is a good start and feel free to continue refining it.

@theJohnnyBrown
Copy link

since #36, normalize-element is a public function, so you can use @fxt's code in your project like so:

(ns myproject.utils.hiccup2xml
  (:require [hiccup.compiler :as cpl])
  (:use [hiccup.util :only [as-str escape-html]])
  (:import (clojure.lang IPersistentVector ISeq)))

; ... as above

@asmala
Copy link
Collaborator

asmala commented Apr 24, 2014

Enlive added a hiccup-like helper about a year ago (v1.1.0), so I wonder if this feature request is necessary anymore? @weavejester, mind taking a look and closing this ticket if you agree?

@weavejester
Copy link
Owner

I think there's benefit in allowing hiccup to emit different output structures. Having an output to a Clojure XML structure doesn't sound a bad idea. Aside from Enlive, it would allow the use of the clojure.xml libraries.

@DerGuteMoritz
Copy link

Hey James, I was wondering what the status of this issue and the refactor branch mentioned in #64 is?

@weavejester
Copy link
Owner

The latest branch is 2.0. I haven't done any more work on it in a while.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants