Is there an Emacs Lisp library for generating HTML

2020-02-17 09:31发布

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.

5条回答
劳资没心,怎么记你
2楼-- · 2020-02-17 10:15

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.

查看更多
仙女界的扛把子
3楼-- · 2020-02-17 10:17

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

查看更多
Fickle 薄情
4楼-- · 2020-02-17 10:18

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.

查看更多
迷人小祖宗
5楼-- · 2020-02-17 10:27

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).

查看更多
劳资没心,怎么记你
6楼-- · 2020-02-17 10:31

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

查看更多
登录 后发表回答