Is there an Emacs Lisp library for generating HTML?
Asked Answered
W

6

17

I'm looking for a solution that allows me to write native Emacs Lisp code and at compile time turns it into HTML, like Franz's htmlgen:

(html
 ((:div class "post")
  (:h1 "Title")
  (:p "Hello, World!")))

Of course I can write my own macros, but I'm interested if there are any projects around this problem.

Weekender answered 28/4, 2009 at 11:37 Comment(2)
Why do you want it to be in Emacs Lisp, an antiquated dialect? You can easily interface with Common Lisp using SLIME, and then you could use htmlgen or yaclml or htout or LML(2) or CL-WHO or Scribble or ...Personable
I use a framework written in Emacs Lisp that I'd like to extend with this HTML generating feature. It is tightly integrated with Emacs, that's why I'm looking for an Elisp solution.Weekender
W
1

Meanwhile, I found some code that contains something similar I want. Now I can write:

(views-with-html
 ((body)
  (h1 "Title")
  ((p (class . "entry")) "Hello, World!")))

The implementation has a few limitations (e.g. hard-coded element list), but it seems to be a good starting point.

Weekender answered 28/4, 2009 at 14:12 Comment(0)
W
6

As you found out, xmlgen generates XML from a list structure. What I did find disappointing with the ``xmlgen` package that the format it supports is not quite the inverse of Emacs' xml parser.

I did add this to my copy of xmlgen:

;; this creates a routine to be the inverse of what xml-parse does
;;;###autoload
(defun xml-gen (form &optional in-elm level)
  "Convert a sexp to xml:
  '(p :class \"big\")) => \"<p class=\\\"big\\\" />\""
  (let ((level (or level 0)))
    (cond
     ((numberp form) (number-to-string form))
     ((stringp form) form)
     ((listp form)
      (destructuring-bind (xml attrs) (xml-gen-extract-plist form)
        (let ((el (car xml)))
          (unless (symbolp el)
            (error "Element must be a symbol (got '%S')." el))
          (setq el (symbol-name el))
          (concat "<" el (xml-gen-attr-to-string attrs)
                  (if (> (length xml) 1)
                      (concat ">" (mapconcat
                                   (lambda (s) (xml-gen s el (1+ level)))
                                   (cdr xml)
                                   "")
                              "</" el ">")
                    "/>"))))))))

(defun xml-gen-attr-to-string (plist)
  (reduce 'concat (mapcar (lambda (p) (concat " " (symbol-name (car p)) "=\"" (cdr p) "\"")) plist)))

(defun xml-gen-extract-plist (list)
  (list (cons (car list) (let ((kids (xml-node-children list)))
                           (if (= 1 (length kids))
                               kids
                             (remove-if-not 'listp kids))))
        (xml-node-attributes list)))

Note: the interface for this is xml-gen (not xmlgen which is the original parsing).

With this interface, the following holds:

(string-equal (xml-gen (car (xml-parse-region <some-region-of-xml>)))
              <some-region-of-xml>)

and

(equal (car (xml-parse-region (insert (xml-gen <some-xml-form>))))
       <some-xml-form>)

The new xml-gen does not strive to preserve the whitespace around that the xml-parse-region routine generates.

Wein answered 8/10, 2009 at 17:35 Comment(1)
This is great, thanks. Would be nice if this functionality was part of xml.el ;-)Kingly
E
2

This could be a starting point: http://www.emacswiki.org/emacs/HtmlLite

Effort answered 28/4, 2009 at 14:9 Comment(1)
Thanks, this is useful, too. My only problem with it that it pollutes the namespace with many functions instead of using a macro.Weekender
W
1

This is not quite what you're looking for, but there's a 20 minute video where a guy creates a simple website using UCW, the UnCommon Web application framework. It's all done in Emacs using lisp...

Here is a link to the transcript (all the code (~25 lines) is available at the end of the transcript).

Wein answered 28/4, 2009 at 14:1 Comment(1)
Thanks, but that's really not what I'm looking for. I've got an existing Elisp framework that has some HTML generating facilities—currently with hard-coded HTML strings I'd like to replace.Weekender
W
1

Meanwhile, I found some code that contains something similar I want. Now I can write:

(views-with-html
 ((body)
  (h1 "Title")
  ((p (class . "entry")) "Hello, World!")))

The implementation has a few limitations (e.g. hard-coded element list), but it seems to be a good starting point.

Weekender answered 28/4, 2009 at 14:12 Comment(0)
K
1

I had a similar requirement to be able to parse xml using xml-parse functions, transform it, and then output it back as a xml string.

Trey's solution almost worked except I needed to retain the whitespace xml elements. So I wrote my own implementation here:

https://github.com/upgradingdave/xml-to-string

Kingly answered 8/9, 2012 at 15:0 Comment(0)
M
0

Have you considered yaclml? yaclml (Yet Another Common Lisp Markup Language) is an HTML generator and HTML template library. yaclml is used as the html templating backend for the ucw web framework. https://www.cliki.net/yaclml

It is in common lisp. Not elisp. But, ...

Mainstream answered 23/11, 2021 at 6:49 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewAntoniettaantonin

© 2022 - 2024 — McMap. All rights reserved.