Index: html-parser.scm
===================================================================
--- html-parser.scm	(revision 46409)
+++ html-parser.scm	(working copy)
@@ -1,8 +1,8 @@
 ;; html-parser.scm -- SSAX-like tree-folding html parser
-;; Copyright (c) 2003-2014 Alex Shinn.  All rights reserved.
+;; Copyright (c) 2003-2020 Alex Shinn.  All rights reserved.
 ;; BSD-style license: http://synthcode.com/license.txt
 
-;;> A permissive HTML parser supporting scalable streaming with a
+;;> A permissive HTML parser supporting scalable streaming with a tree
 ;;> folding interface.  This copies the interface of Oleg Kiselyov's
 ;;> SSAX parser, as well as providing simple convenience utilities.
 ;;> It correctly handles all invalid HTML, inserting "virtual"
@@ -307,9 +307,11 @@
           (if (string=? name "")
               (loop attrs)
               (let ((name (string->symbol (string-downcase name))))
+                (skip-whitespace in)
                 (cond
                  ((eqv? (peek-char in) #\=)
                   (read-char in)
+                  (skip-whitespace in)
                   (let ((value (if (memv (peek-char in) '(#\" #\'))
                                    (apply string-append
                                           (read-quoted in entities))
@@ -381,10 +383,10 @@
   '(html (head body) table (thead tbody) tr (th td) p (b i u s)))
 
 (define *unnestables*
-  '(p li td tr))
+  '(p li td tr th dt dd rt rp optgroup option))
 
 (define *bodyless*
-  '(img hr br meta link))
+  '(img hr br area base col embed input link meta param source track wbr))
 
 (define *literals*
   '(script xmp))
@@ -637,14 +639,33 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; simple conversions
 
+;; concatenate adjacent top-level strings in ls
+(define (reverse-condensing-strings ls)
+  (let lp1 ((ls ls) (res '()))
+    (cond
+     ((null? ls) res)
+     ((null? (cdr ls)) (cons (car ls) res))
+     ((and (string? (car ls)) (string? (cadr ls)))
+      (let lp2 ((ls (cdr ls)) (strs (list (car ls))))
+        (cond
+         ((null? ls) (cons (apply string-append strs) res))
+         ((string? (car ls)) (lp2 (cdr ls) (cons (car ls) strs)))
+         (else (lp1 ls (cons (apply string-append strs) res))))))
+     (else (lp1 (cdr ls) (cons (car ls) res))))))
+
+;;> \procedure{(html->sxml [port])}
+;;> Returns the SXML representation of the document from \var{port},
+;;> using the default parsing options.
+
 (define html->sxml
   (let ((parse
          (make-html-parser
           'start: (lambda (tag attrs seed virtual?) '())
           'end:   (lambda (tag attrs parent-seed seed virtual?)
-                    `((,tag ,@(if (pair? attrs)
-                                  `((@ ,@attrs) ,@(reverse seed))
-                                  (reverse seed)))
+                    `((,tag
+                       ,@(if (pair? attrs)
+                             `((@ ,@attrs) ,@(reverse-condensing-strings seed))
+                             (reverse-condensing-strings seed)))
                       ,@parent-seed))
           'decl:    (lambda (tag attrs seed) `((*DECL* ,tag ,@attrs) ,@seed))
           'process: (lambda (attrs seed) `((*PI* ,@attrs) ,@seed))
