spaik 0.3.1

The SPAIK Programming Language
Documentation
(defun escape (s)
  (or (and (or (number? s) (bool? s)) (string s))
      (and (symbol? s) (escape (string s)))
      (let ((out (vec)))
        (dolist (x s)
          (push out
                (cond ((= x (chr "<")) "&lt;")
                      ((= x (chr ">")) "&gt;")
                      ((= x (chr "&")) "&amp;")
                      (true x))))
        (apply concat out))))

(defun escape-attr (s)
  (or (and (or (number? s) (bool? s)) s)
      (and (symbol? s) s)
      (let ((out (vec)))
        (dolist (x s)
          (push out
                (cond ((= x (chr "<")) "&lt;")
                      ((= x (chr ">")) "&gt;")
                      ((= x (chr "&")) "&amp;")
                      ((= x (chr "\"")) "&quot;")
                      ((= x (chr "'")) "&#39;")
                      (true x))))
        (apply concat out))))

(defmacro html (&body b)
  (let ((s (vec 'vec)))
    (dolist (elem b)
      (if (cons? elem)
          (progn
            (if (symbol? (car elem))
                (let ((tag (string (car elem))))
                  (push s "<")
                  (push s tag)
                  (while (keyword? (cadr elem))
                    (push s " ")
                    (push s (keyword-name (cadr elem)))
                    (set elem (cdr elem))
                    (push s "=\"")
                    (if (cons? (cadr elem))
                        (push s (cadr elem))
                      (push s (escape-attr (cadr elem))))
                    (set elem (cdr elem))
                    (push s "\""))
                  (push s ">")
                  (push s `(html ,@(cdr elem)))
                  (push s "</")
                  (push s tag)
                  (push s ">"))
              (push s elem)))
        (if (symbol? elem)
            (push s elem)
          (push s (escape elem)))))
    `(apply concat
      ,(apply (lambda (&rest r) r) s))))