diff --git a/packages.lisp b/packages.lisp
index e5656d7..bde2826 100644
--- a/packages.lisp
+++ b/packages.lisp
@@ -42,6 +42,7 @@
:*html-no-indent-tags*
:*html-empty-tags*
:*html-empty-tag-aware-p*
+ :*short-leaf-content-length*
:conc
:convert-attributes
:convert-tag-to-string-list
diff --git a/specials.lisp b/specials.lisp
index c55c3e0..3a35625 100644
--- a/specials.lisp
+++ b/specials.lisp
@@ -120,6 +120,9 @@ in *HTML-EMPTY-TAGS* as \(XHTML mode) or \(SGML
mode and HTML5 mode). For all other tags, it will always generate
.")
+(defvar *short-leaf-content-length* 72
+ "Below this threshold leaf tags won't be indented.")
+
(defconstant +newline+ (make-string 1 :initial-element #\Newline)
"Used for indentation.")
diff --git a/who.lisp b/who.lisp
index 6315612..a0e780c 100644
--- a/who.lisp
+++ b/who.lisp
@@ -59,30 +59,34 @@ XHTML and :HTML5 for HTML5 (HTML syntax)."
"Returns a string list corresponding to the `HTML' \(in CL-WHO
syntax) in SEXP. Uses the generic function CONVERT-TO-STRING-LIST
internally. Utility function used by TREE-TO-TEMPLATE."
- (let (tag attr-list body)
- (cond
- ((keywordp sexp)
- (setq tag sexp))
- ((atom (first sexp))
- (setq tag (first sexp))
- ;; collect attribute/value pairs into ATTR-LIST and tag body (if
- ;; any) into BODY
- (loop for rest on (cdr sexp) by #'cddr
- if (keywordp (first rest))
- collect (cons (first rest) (second rest)) into attr
- else
- do (progn (setq attr-list attr)
- (setq body rest)
- (return))
- finally (setq attr-list attr)))
- ((listp (first sexp))
- (setq tag (first (first sexp)))
- (loop for rest on (cdr (first sexp)) by #'cddr
- if (keywordp (first rest))
- collect (cons (first rest) (second rest)) into attr
- finally (setq attr-list attr))
- (setq body (cdr sexp))))
- (convert-tag-to-string-list tag attr-list body body-fn)))
+ (flet ((short-leaf-p (s)
+ (and (loop for e in (rest s) never (and (listp e) (keywordp (first e))))
+ (< (loop for e in (rest s) when (stringp e) sum (length e))
+ *short-leaf-content-length*))))
+ (let (tag attr-list body)
+ (cond
+ ((keywordp sexp)
+ (setq tag sexp))
+ ((atom (first sexp))
+ (setq tag (first sexp))
+ ;; collect attribute/value pairs into ATTR-LIST and tag body (if
+ ;; any) into BODY
+ (loop for rest on (cdr sexp) by #'cddr
+ if (keywordp (first rest))
+ collect (cons (first rest) (second rest)) into attr
+ else
+ do (progn (setq attr-list attr)
+ (setq body rest)
+ (return))
+ finally (setq attr-list attr)))
+ ((listp (first sexp))
+ (setq tag (first (first sexp)))
+ (loop for rest on (cdr (first sexp)) by #'cddr
+ if (keywordp (first rest))
+ collect (cons (first rest) (second rest)) into attr
+ finally (setq attr-list attr))
+ (setq body (cdr sexp))))
+ (convert-tag-to-string-list tag attr-list body body-fn (short-leaf-p sexp)))))
(defun convert-attributes (attr-list)
"Helper function for CONVERT-TAG-TO-STRING-LIST which converts the
@@ -132,15 +136,17 @@ forms."
,=var=
*attribute-quote-char*)))))))
-(defgeneric convert-tag-to-string-list (tag attr-list body body-fn)
+(defgeneric convert-tag-to-string-list (tag attr-list body body-fn leaf-p)
(:documentation "Used by PROCESS-TAG to convert `HTML' into a list
of strings. TAG is a keyword symbol naming the outer tag, ATTR-LIST
is an alist of its attributes \(the car is the attribute's name as a
keyword, the cdr is its value), BODY is the tag's body, and BODY-FN is
a function which should be applied to BODY. The function must return
-a list of strings or Lisp forms."))
+a list of strings or Lisp forms. SHORT-LEAF-P is t when the TAG is a
+leaf and its content is shorter than *SHORT-LEAF-CONTENT-LENGTH* then
+it is not indented."))
-(defmethod convert-tag-to-string-list (tag attr-list body body-fn)
+(defmethod convert-tag-to-string-list (tag attr-list body body-fn short-leaf-p)
"The standard method which is not specialized. The idea is that you
can use EQL specializers on the first argument."
(declare (optimize speed space))
@@ -164,7 +170,7 @@ can use EQL specializers on the first argument."
;; now hand over the tag's body to TREE-TO-TEMPLATE
(let ((*indent* body-indent))
(funcall body-fn body))
- (when body-indent
+ (when (and body-indent (not short-leaf-p))
;; indentation
(list +newline+ (n-spaces *indent*)))
;; closing tag