aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Isaac2023-08-25 23:56:09 +0100
committerArun Isaac2023-08-28 14:28:43 +0100
commitcd6ac77684194a5f0ee9a8672f207d1edfdd6640 (patch)
treef9643b46ff36e3ef6e36b0907c4b77836933181e
parent5331529fc45225724d208ad2939c85e445007871 (diff)
downloadskribilo-cd6ac77684194a5f0ee9a8672f207d1edfdd6640.tar.gz
skribilo-cd6ac77684194a5f0ee9a8672f207d1edfdd6640.tar.lz
skribilo-cd6ac77684194a5f0ee9a8672f207d1edfdd6640.zip
html: Abstract out opening and closing of HTML tags.
* src/guile/skribilo/engine/html.scm: Import (srfi srfi-26). (html-open, html-close): New functions. (html-markup-class, &html-head, &html-body, &html-page, &html-header-favicon, &html-header-css, &html-header-javascript, &html-generic-title, &html-footnotes, html-title-authors, author, toc, chapter, html-section-title, paragraph, footnote, linebreak, hrule, color, frame, font, flush, itemize, enumerate, description, item, blockquote, figure, &html-figure-legend, table, tr, tc, image, mailto, mark, ref, url-ref, &prog-line, &bib-entry-label, &the-index-header): Use html-open and html-close.
-rw-r--r--src/guile/skribilo/engine/html.scm848
1 files changed, 499 insertions, 349 deletions
diff --git a/src/guile/skribilo/engine/html.scm b/src/guile/skribilo/engine/html.scm
index da40475..088d168 100644
--- a/src/guile/skribilo/engine/html.scm
+++ b/src/guile/skribilo/engine/html.scm
@@ -44,6 +44,7 @@
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-13)
#:use-module (srfi srfi-14)
+ #:use-module (srfi srfi-26)
#:use-module (srfi srfi-39)
#:export (html-engine html-title-engine html-file
@@ -575,13 +576,41 @@
(format #t " class=\"~a\"" c)))))
;*---------------------------------------------------------------------*/
+;* html-open ... */
+;*---------------------------------------------------------------------*/
+(define* (html-open tag #:optional (attributes '()))
+ "Output opening TAG with ATTRIBUTES, an association list mapping
+attribute names to their values. Attribute names may be symbols or
+strings. Values may be symbols, strings or numbers. Attributes with
+unspecified or #f values are ignored."
+ (display "<")
+ (display tag)
+ (for-each (match-lambda
+ ((name . value)
+ (when (and value
+ (not (unspecified? value)))
+ (format #t " ~a=\"~a\"" name value))))
+ attributes)
+ (display ">")
+ (newline))
+
+;*---------------------------------------------------------------------*/
+;* html-close ... */
+;*---------------------------------------------------------------------*/
+(define (html-close tag)
+ "Output closing TAG."
+ (display "</")
+ (display tag)
+ (display ">")
+ (newline))
+
+;*---------------------------------------------------------------------*/
;* html-markup-class ... */
;*---------------------------------------------------------------------*/
(define (html-markup-class m)
- (lambda (n e)
- (format #t "<~a" m)
- (html-class n)
- (display ">")))
+ (lambda (n e)
+ (html-open m
+ `((class . ,(markup-class n))))))
;*---------------------------------------------------------------------*/
;* html-color-spec? ... */
@@ -629,10 +658,12 @@
;*---------------------------------------------------------------------*/
(markup-writer '&html-head
:before (lambda (n e)
- (display "<head>\n")
- (display "<meta http-equiv=\"Content-Type\" content=\"text/html;")
- (format #t "charset=~A\">\n" (engine-custom (find-engine 'html)
- 'charset))
+ (html-open 'head)
+ (html-open 'meta
+ `((http-equiv . "Content-Type")
+ (content . "text/html;")
+ (charset . ,(engine-custom (find-engine 'html)
+ 'charset))))
(let ((head (engine-custom e 'head)))
(when head
(display head)
@@ -655,10 +686,10 @@
(markup-writer '&html-body
:before (lambda (n e)
(let ((bg (engine-custom e 'background)))
- (display "<body")
- (html-class n)
- (when (html-color-spec? bg) (format #t " bgcolor=\"~a\"" bg))
- (display ">\n")))
+ (html-open 'body
+ `((class . ,(markup-class n))
+ (bgcolor . ,(and (html-color-spec? bg)
+ bg))))))
:after "</body>\n")
;*---------------------------------------------------------------------*/
@@ -667,26 +698,30 @@
(markup-writer '&html-page
:action (lambda (n e)
(define (html-margin m fn size bg fg cla)
- (format #t "<td align=\"left\" valign=\"top\" class=\"~a\"" cla)
- (if size
- (format #t " width=\"~a\"" (html-width size)))
- (if (html-color-spec? bg)
- (format #t " bgcolor=\"~a\">" bg)
- (display ">"))
- (format #t "<div class=\"~a\">\n" cla)
- (cond
- ((and (string? fg) (string? fn))
- (format #t "<font color=\"~a\" \"~a\">" fg fn))
- ((string? fg)
- (format #t "<font color=\"~a\">" fg))
- ((string? fn)
- (format #t "<font \"~a\">" fn)))
- (if (procedure? m)
- (evaluate-document (m n e) e)
- (output m e))
- (if (or (string? fg) (string? fn))
- (display "</font>"))
- (display "</div></td>\n"))
+ (html-open 'td
+ `((align . "left")
+ (valign . "top")
+ (class . ,cla)
+ (width . ,(and size (html-width size)))
+ (bgcolor . ,(and (html-color-spec? bg)
+ bg))))
+ (html-open 'div
+ `((class . ,cla)))
+ (cond
+ ((and (string? fg) (string? fn))
+ (format #t "<font color=\"~a\" \"~a\">" fg fn))
+ ((string? fg)
+ (html-open 'font
+ `((color . ,fg))))
+ ((string? fn)
+ (format #t "<font \"~a\">" fn)))
+ (if (procedure? m)
+ (evaluate-document (m n e) e)
+ (output m e))
+ (if (or (string? fg) (string? fn))
+ (html-close 'font))
+ (html-close 'div)
+ (html-close 'td))
(let ((body (markup-body n))
(lm (engine-custom e 'left-margin))
(lmfn (engine-custom e 'left-margin-font))
@@ -702,27 +737,45 @@
((and lm rm)
(let* ((ep (engine-custom e 'margin-padding))
(ac (if (number? ep) ep 0)))
- (format #t "<table cellpadding=\"~a\" cellspacing=\"0\" width=\"100%\" class=\"skribilo-margins\"><tr>\n" ac))
+ (html-open 'table
+ `((cellpadding . ,ac)
+ (cellspacing . "0")
+ (width . "100%")
+ (class . "skribilo-margins")))
+ (html-open 'tr))
(html-margin lm lmfn lms lmbg lmfg "skribilo-left-margin")
(html-margin body #f #f #f #f "skribilo-body")
(html-margin rm rmfn rms rmbg rmfg "skribilo-right-margin")
- (display "</tr></table>"))
+ (html-close 'tr)
+ (html-close 'table))
(lm
(let* ((ep (engine-custom e 'margin-padding))
(ac (if (number? ep) ep 0)))
- (format #t "<table cellpadding=\"~a\" cellspacing=\"0\" width=\"100%\" class=\"skribilo-margins\"><tr>\n" ac))
+ (html-open 'table
+ `((cellpadding . ,ac)
+ (cellspacing . "0")
+ (width . "100%")
+ (class . "skribilo-margins")))
+ (html-open 'tr))
(html-margin lm lmfn lms lmbg lmfg "skribilo-left-margin")
(html-margin body #f #f #f #f "skribilo-body")
- (display "</tr></table>"))
+ (html-close 'tr)
+ (html-close 'table))
(rm
- (display "<table cellpadding=\"~a\" cellspacing=\"0\" width=\"100%\" class=\"skribilo-margins\"><tr>\n")
+ (html-open 'table
+ `((cellspacing . "0")
+ (width . "100%")
+ (class . "skribilo-margins")))
+ (html-open 'tr)
(html-margin body #f #f #f #f "skribilo-body")
(html-margin rm rmfn rms rmbg rmfg "skribilo-right-margin")
- (display "</tr></table>"))
+ (html-close 'tr)
+ (html-close 'table))
(else
- (display "<div class=\"skribilo-body\">\n")
+ (html-open 'div
+ '((class . "skribilo-body")))
(output body e)
- (display "</div>\n"))))))
+ (html-close 'div))))))
;*---------------------------------------------------------------------*/
;* &html-generic-header ... */
@@ -788,15 +841,20 @@
:action (lambda (n e)
(let ((i (markup-body n)))
(when i
- (format #t " <link rel=\"shortcut icon\" href=~s>\n" i)))))
+ (html-open 'link
+ `((rel . "shortcut icon")
+ (href . ,i)))))))
(markup-writer '&html-header-css
:action (lambda (n e)
(let ((css (markup-body n)))
- (when (pair? css)
- (for-each (lambda (css)
- (format #t " <link href=~s rel=\"stylesheet\" type=\"text/css\">\n" css))
- css)))))
+ (when (pair? css)
+ (for-each (lambda (css)
+ (html-open 'link
+ `((rel . "stylesheet")
+ (type . "text/css")
+ (href . ,css))))
+ css)))))
(markup-writer '&html-header-style
:before " <style type=\"text/css\">\n <!--\n"
@@ -834,7 +892,9 @@
(markup-writer '&html-header-javascript
:action (lambda (n e)
(when (engine-custom e 'javascript)
- (display " <script language=\"JavaScript\" type=\"text/javascript\">\n")
+ (html-open 'script
+ '((language . "JavaScript")
+ (type . "text/javascript")))
(display " <!--\n")
(display " function skribenospam( n, d, f ) {\n")
(display " nn=n.replace( / /g , \".\" );\n" )
@@ -845,7 +905,7 @@
(display " }\n")
(display " }\n")
(display " -->\n")
- (display " </script>\n"))
+ (html-close 'script))
(let* ((ejs (engine-custom e 'js))
(js (cond
((string? ejs)
@@ -855,7 +915,10 @@
(else
'()))))
(for-each (lambda (s)
- (format #t "<script type=\"text/javascript\" src=\"~a\"></script>" s))
+ (html-open 'script
+ `((type . "text/javascript")
+ (src . ,s)))
+ (html-close 'script))
js))))
@@ -894,31 +957,45 @@
(tfg (engine-custom e 'title-foreground))
(tfont (engine-custom e 'title-font)))
(when title
- (display "<table width=\"100%\" class=\"skribilo-title\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n<tr>")
+ (html-open 'table
+ `((width . "100%")
+ (class . "skribilo-title")
+ (cellspacing . "0")
+ (cellpadding . "0")))
+ (html-open 'tbody)
+ (html-open 'tr)
(if (html-color-spec? tbg)
- (format #t "<td align=\"center\"~A>"
- (if (html-color-spec? tbg)
- (string-append "bgcolor=\"" tbg "\"")
- ""))
- (display "<td align=\"center\">"))
+ (html-open 'td
+ `((align . "center")
+ (bgcolor . ,(and (html-color-spec? tbg)
+ tbg))))
+ (html-open 'td
+ '((align . "center"))))
(if (string? tfg)
- (format #t "<font color=\"~a\">" tfg))
+ (html-open 'font
+ `((color . ,tfg))))
(when title
(if (string? tfont)
(begin
- (format #t "<font ~a><strong>" tfont)
- (output title e)
- (display "</strong></font>"))
+ (format #t "<font ~a>" tfont)
+ (html-open 'strong)
+ (output title e)
+ (html-close 'strong)
+ (html-close 'font))
(begin
- (display "<div class=\"skribilo-title\">")
- (output title e)
- (display "</div>"))))
+ (html-open 'div
+ '((class . "skribilo-title")))
+ (output title e)
+ (html-close 'div))))
(if (not authors)
(display "\n")
(html-title-authors authors e))
(if (string? tfg)
- (display "</font>"))
- (display "</td></tr></tbody></table>\n"))))
+ (html-close 'font))
+ (html-close 'td)
+ (html-close 'tr)
+ (html-close 'tbody)
+ (html-close 'table))))
;*---------------------------------------------------------------------*/
;* &html-document-title ... */
@@ -936,29 +1013,38 @@
:before (lambda (n e)
(let ((footnotes (markup-body n)))
(when (pair? footnotes)
- (display "<div class=\"skribilo-footnote\">")
- (display "<hr width='20%' size='2' align='left'>\n"))))
+ (html-open 'div
+ '((class . "skribilo-footnote")))
+ (html-open 'hr
+ '((width . "20%")
+ (size . "2")
+ (align . "left"))))))
:action (lambda (n e)
(let ((footnotes (markup-body n)))
(for-each (lambda (fn)
- (display "\n<div class=\"footnote\">")
-
+ (html-open 'div
+ '((class . "footnote")))
;; Note: the <a> tags must not be nested.
-
- (format #t "<a name=\"footnote-~a\"></a>"
- (string-canonicalize
- (container-ident fn)))
- (format #t "<a href=\"#footnote-site-~a\">"
- (string-canonicalize
- (container-ident fn)))
- (format #t "<sup><small>~a</small></sup></a>"
- (markup-option fn :label))
+ (html-open 'a
+ `((name . ,(string-append "footnote-"
+ (string-canonicalize
+ (container-ident fn))))))
+ (html-close 'a)
+ (html-open 'a
+ `((href . ,(string-append "#footnote-site-"
+ (string-canonicalize
+ (container-ident fn))))))
+ (html-open 'sup)
+ (html-open 'small)
+ (display (markup-option fn :label))
+ (html-close 'small)
+ (html-close 'sup)
+ (html-close 'a)
(output (markup-body fn) e)
-
- (display "\n</div>\n"))
+ (html-close 'div))
footnotes)
(when (pair? footnotes)
- (display "</div>")))))
+ (html-close 'div)))))
;*---------------------------------------------------------------------*/
;* html-title-authors ... */
@@ -995,7 +1081,7 @@
e))
(cond
((pair? authors)
- (display "<center>\n")
+ (html-open 'center)
(let ((len (length authors)))
(case len
((1)
@@ -1006,7 +1092,7 @@
(html-authorsN authors 2 #f))
(else
(html-authorsN authors 3 #t))))
- (display "</center>\n"))
+ (html-close 'center))
(else
(html-title-authors (list authors) e))))
@@ -1016,9 +1102,9 @@
(markup-writer 'author
:options '(:name :title :affiliation :email :url :address :phone :photo :align)
:before (lambda (n e)
- (display "<table")
- (html-class n)
- (display "><tbody>\n"))
+ (html-open 'table
+ `((class . ,(markup-class n))))
+ (html-open 'tbody))
:action (lambda (n e)
(let ((name (markup-option n :name))
(title (markup-option n :title))
@@ -1030,15 +1116,21 @@
(nfn (engine-custom e 'author-font))
(align (markup-option n :align)))
(define (row n)
- (format #t "<tr><td align=\"~a\">" align)
- (output n e)
- (display "</td></tr>"))
+ (html-open 'tr)
+ (html-open 'td
+ `((align . ,align)))
+ (output n e)
+ (html-close 'td)
+ (html-close 'tr))
;; name
- (format #t "<tr><td align=\"~a\">" align)
+ (html-open 'tr)
+ (html-open 'td
+ `((align . ,align)))
(if nfn (format #t "<font ~a>\n" nfn))
(output name e)
- (if nfn (display "</font>\n"))
- (display "</td></tr>")
+ (if nfn (html-close 'font))
+ (html-close 'td)
+ (html-close 'tr)
;; title
(if title (row title))
;; affiliation
@@ -1061,18 +1153,20 @@
:options '(:name :title :affiliation :email :url :address :phone :photo :align)
:predicate (lambda (n e) (markup-option n :photo))
:before (lambda (n e)
- (display "<table")
- (html-class n)
- (display "><tbody>\n<tr>"))
+ (html-open 'table
+ `((class . ,(markup-class n))))
+ (html-open 'tbody)
+ (html-open 'tr))
:action (lambda (n e)
(let ((photo (markup-option n :photo)))
- (display "<td>")
- (output photo e)
- (display "</td><td>")
- (markup-option-add! n :photo #f)
- (output n e)
- (markup-option-add! n :photo photo)
- (display "</td>")))
+ (html-open 'td)
+ (output photo e)
+ (html-close 'td)
+ (html-open 'td)
+ (markup-option-add! n :photo #f)
+ (output n e)
+ (markup-option-add! n :photo photo)
+ (html-close 'td)))
:after "</tr>\n</tbody></table>")
;*---------------------------------------------------------------------*/
@@ -1085,8 +1179,9 @@
(let loop ((i 0))
(if (< i n)
(begin
- (display "<td></td>")
- (loop (+ i 1))))))
+ (html-open 'td)
+ (html-close 'td)
+ (loop (+ i 1))))))
(define (toc-entry fe level)
(match fe
((c ch ...)
@@ -1096,24 +1191,30 @@
(skribe-error 'toc
(format #f "invalid identifier '~a'" id)
c))
- (display " <tr>")
+ (html-open 'tr)
;; blank columns
(col level)
;; number
- (format #t "<td valign=\"top\" align=\"left\">~a</td>"
- (html-container-number c e))
+ (html-open 'td
+ '((valign . "top")
+ (align . "left")))
+ (display (html-container-number c e))
+ (html-close 'td)
;; title
- (format #t "<td colspan=\"~a\" width=\"100%\">"
- (- 4 level))
- (format #t "<a href=\"~a#~a\">"
- (if (and (*destination-file*)
- (string=? f (*destination-file*)))
- ""
- (strip-ref-base (or f (*destination-file*) "")))
- (string-canonicalize id))
+ (html-open 'td
+ `((colspan . ,(- 4 level))
+ (width . "100%")))
+ (html-open 'a
+ `((href . ,(string-append
+ (if (and (*destination-file*)
+ (string=? f (*destination-file*)))
+ ""
+ (strip-ref-base (or f (*destination-file*) "")))
+ (string-canonicalize id)))))
(output (markup-option c :title) e)
- (display "</a></td>")
- (display "</tr>\n")
+ (html-close 'a)
+ (html-close 'td)
+ (html-close 'tr)
;; the children
(for-each (lambda (n) (toc-entry n (+ 1 level))) ch)))))
@@ -1143,13 +1244,15 @@
(container-body bb))))
;; avoid to produce an empty table
(unless (null? lst)
- (display "<table cellspacing=\"1\" cellpadding=\"1\" width=\"100%\"")
- (html-class n)
- (display ">\n<tbody>\n")
-
- (for-each (lambda (n) (toc-entry n 0)) lst)
-
- (display "</tbody>\n</table>\n")))))))
+ (html-open 'table
+ `((class . ,(markup-class n))
+ (cellspacing . "1")
+ (cellpadding . "1")
+ (width . "100%")))
+ (html-open 'tbody)
+ (for-each (lambda (n) (toc-entry n 0)) lst)
+ (html-close 'tbody)
+ (html-close 'table)))))))
(define (sections-in-same-file? n1 n2 e)
;; Return #t when N1 and N2 are to be output in the same file according to
@@ -1297,16 +1400,17 @@
(display "<!-- ")
(output title html-title-engine)
(display " -->\n")
- (display "<a name=\"")
- (display (string-canonicalize ident))
- (display "\"></a>")
- (display "<center><h1")
- (html-class n)
- (display ">")
+ (html-open 'a
+ `((name . ,(string-canonicalize ident))))
+ (html-close 'a)
+ (html-open 'center)
+ (html-open 'h1
+ `((class . ,(markup-class n))))
(output (html-container-number n e) e)
(display " ")
(output (markup-option n :title) e)
- (display "</h1></center>"))))
+ (html-close 'h1)
+ (html-close 'center))))
;; This writer is invoked only for chapters rendered inside separate files!
(markup-writer 'chapter
@@ -1334,30 +1438,38 @@
(display "<!-- ")
(output title html-title-engine)
(display " -->\n")
- (display "<a name=\"")
- (display (string-canonicalize ident))
- (display "\"></a>")
+ (html-open 'a
+ `((name . ,(string-canonicalize ident))))
+ (html-close 'a)
(if c
- (format #t "<div class=\"~a-title\">" c)
- (format #t "<div class=\"skribilo-~a-title\">" (markup-markup n)))
+ (html-open 'div
+ `((class . ,(string-append c "-title"))))
+ (html-open 'div
+ `((class . ,(string-append "skribilo-" (markup-markup n) "-title")))))
(when (html-color-spec? tbg)
- (display "<table width=\"100%\">")
- (format #t "<tr><td bgcolor=\"~a\">" tbg))
+ (html-open 'table
+ '((width . "100%")))
+ (html-open 'tr)
+ (html-open 'td
+ `((bgcolor . ,tbg))))
(display tstart)
- (if tfg (format #t "<font color=\"~a\">" tfg))
+ (if tfg
+ (html-open 'font
+ `((color . ,tfg))))
(if number
(begin
(output (html-container-number n e) e)
(output nsep e)))
(output title e)
- (if tfg (display "</font>\n"))
+ (if tfg
+ (html-close 'font))
(display tstop)
(when (and (string? tbg) (> (string-length tbg) 0))
- (display "</td></tr></table>\n"))
- (display "</div>")
- (display "<div")
- (html-class n)
- (display ">"))
+ (html-close 'td)
+ (html-close 'tr)
+ (html-close 'table))
+ (html-close 'div)
+ ((html-markup-class "div") n e))
(newline))
;*---------------------------------------------------------------------*/
@@ -1414,8 +1526,10 @@
(markup-writer 'paragraph
:before (lambda (n e)
(when (and (>= (*debug*) 2) (location? (ast-loc n)))
- (format #t "<span style=\"display: block; position: relative; left: -2cm; font-size: x-small; font-style: italic; color: ff8e1e;\">~a</span>"
- (ast-loc n)))
+ (html-open 'span
+ '((style . "display: block; position: relative; left: -2cm; font-size: x-small; font-style: italic; color: ff8e1e;")))
+ (ast-loc n)
+ (html-close 'span))
((html-markup-class "p") n e))
:after "</p>")
@@ -1433,21 +1547,28 @@
(markup-writer 'footnote
:options '(:label)
:action (lambda (n e)
- (format #t "<a name=\"footnote-site-~a\">"
- (string-canonicalize (container-ident n)))
- (format #t "<a href=\"#footnote-~a\"><sup><small>~a</small></sup></a>"
- (string-canonicalize (container-ident n))
- (markup-option n :label))
- (format #t "</a>")))
+ (html-open 'a
+ `((name . ,(string-append "footnote-site-"
+ (string-canonicalize
+ (container-ident n))))))
+ (html-open 'a
+ `((href . ,(string-append "#footnote-"
+ (string-canonicalize
+ (container-ident n))))))
+ (html-open 'sup)
+ (html-open 'small)
+ (display (markup-option n :label))
+ (html-close 'small)
+ (html-close 'sup)
+ (html-close 'a)))
;*---------------------------------------------------------------------*/
;* linebreak ... */
;*---------------------------------------------------------------------*/
(markup-writer 'linebreak
:before (lambda (n e)
- (display "<br")
- (html-class n)
- (display "/>")))
+ (html-open 'br
+ `((class . ,(html-class n))))))
;*---------------------------------------------------------------------*/
;* hrule ... */
@@ -1457,13 +1578,11 @@
:before (lambda (n e)
(let ((width (markup-option n :width))
(height (markup-option n :height)))
- (display "<hr")
- (html-class n)
- (if (< width 100)
- (format #t " width=\"~a\"" (html-width width)))
- (if (> height 1)
- (format #t " size=\"~a\"" height))
- (display ">"))))
+ (html-open 'hr
+ `((width . ,(and (< width 100)
+ (html-width width)))
+ (size . ,(and (> height 1)
+ height)))))))
;*---------------------------------------------------------------------*/
;* color ... */
@@ -1476,23 +1595,28 @@
(bg (markup-option n :bg))
(fg (markup-option n :fg)))
(when (html-color-spec? bg)
- (display "<table cellspacing=\"0\"")
- (html-class n)
- (format #t " cellpadding=\"~a\"" (if m m 0))
- (if w (format #t " width=\"~a\"" (html-width w)))
- (display "><tbody>\n<tr>")
- (display "<td bgcolor=\"")
- (output bg e)
- (display "\">"))
+ (html-open 'table
+ `((class . ,(markup-class n))
+ (cellspacing . "0")
+ (cellpadding . ,(or m 0))
+ (width . ,(and w (html-width w)))))
+ (html-open 'tbody)
+ (html-open 'tr)
+ (html-open 'td
+ `((bgcolor . ,(with-output-to-string
+ (cut output bg e))))))
(when (html-color-spec? fg)
- (display "<font color=\"")
- (output fg e)
- (display "\">"))))
+ (html-open 'font
+ `((color . ,(with-output-to-string
+ (cut output fg e))))))))
:after (lambda (n e)
(when (html-color-spec? (markup-option n :fg))
- (display "</font>"))
+ (html-close 'font))
(when (html-color-spec? (markup-option n :bg))
- (display "</td></tr>\n</tbody></table>"))))
+ (html-close 'td)
+ (html-close 'tr)
+ (html-close 'tbody)
+ (html-close 'table))))
;*---------------------------------------------------------------------*/
;* frame ... */
@@ -1503,12 +1627,15 @@
(let ((m (markup-option n :margin))
(b (markup-option n :border))
(w (markup-option n :width)))
- (display "<table cellspacing=\"0\"")
- (html-class n)
- (format #t " cellpadding=\"~a\"" (if m m 0))
- (format #t " border=\"~a\"" (if b b 0))
- (if w (format #t " width=\"~a\"" (html-width w)))
- (display "><tbody>\n<tr><td>")))
+ (html-open 'table
+ `((class . ,(markup-class n))
+ (cellspacing . "0")
+ (cellpadding . ,(or m 0))
+ (border . ,(or b 0))
+ (width . ,(and w (html-width w)))))
+ (html-open 'tbody)
+ (html-open 'tr)
+ (html-open 'td)))
:after "</td></tr>\n</tbody></table>")
;*---------------------------------------------------------------------*/
@@ -1520,30 +1647,31 @@
(let ((size (markup-option n :size))
(face (markup-option n :face)))
(when (and (number? size) (inexact? size))
- (let ((s (if (> size 0) "<big>" "<small>"))
+ (let ((s (if (> size 0) 'big 'small))
(d (if (> size 0) 1 -1)))
(do ((i (inexact->exact size) (- i d)))
((= i 0))
- (display s))))
+ (html-open s))))
(when (or (and (number? size) (exact? size)) face)
- (display "<font")
- (html-class n)
- (when (and (number? size) (exact? size) (not (= size 0)))
- (format #t " size=\"~a\"" size))
- (when face (format #t " face=\"~a\"" face))
- (display ">"))))
+ (html-open 'font
+ `((class . ,(markup-class n))
+ (size . ,(and (number? size)
+ (exact? size)
+ (not (zero? size))
+ size))
+ (face . ,face))))))
:after (lambda (n e)
(let ((size (markup-option n :size))
(face (markup-option n :face)))
(when (or (and (number? size) (exact? size) (not (= size 0)))
face)
- (display "</font>"))
+ (html-close 'font))
(when (and (number? size) (inexact? size))
- (let ((s (if (> size 0) "</big>" "</small>"))
+ (let ((s (if (> size 0) 'big 'small))
(d (if (> size 0) 1 -1)))
(do ((i (inexact->exact size) (- i d)))
((= i 0))
- (display s)))))))
+ (html-close s)))))))
;*---------------------------------------------------------------------*/
;* flush ... */
@@ -1553,17 +1681,21 @@
:before (lambda (n e)
(case (markup-option n :side)
((center)
- (display "<center")
- (html-class n)
- (display ">\n"))
+ (html-open 'center
+ `((class . ,(markup-class n)))))
((left)
- (display "<p style=\"text-align:left;\"")
- (html-class n)
- (display ">\n"))
+ (html-open 'p
+ `((class . ,(markup-class n))
+ (style . "text-align:left;"))))
((right)
- (display "<table ")
- (html-class n)
- (display "width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr><td align=\"right\">"))
+ (html-open 'table
+ `((width . "100%")
+ (cellpadding . "0")
+ (cellspacing . "0")
+ (border . "0")))
+ (html-open 'tr)
+ (html-open 'td
+ '((align . "right"))))
(else
(skribe-error 'flush
"Invalid side"
@@ -1571,11 +1703,13 @@
:after (lambda (n e)
(case (markup-option n :side)
((center)
- (display "</center>\n"))
+ (html-close 'center))
((right)
- (display "</td></tr></table>\n"))
+ (html-close 'td)
+ (html-close 'tr)
+ (html-close 'table))
((left)
- (display "</p>\n")))))
+ (html-close 'p)))))
;*---------------------------------------------------------------------*/
;* center ... */
@@ -1607,14 +1741,14 @@
(for-each (lambda (item)
(let ((ident (and (markup? item)
(markup-ident item))))
- (display "<li")
- (html-class item)
- (display ">")
+ (html-open 'li
+ `((class . ,(markup-class item))))
(if ident ;; produce an anchor
- (format #t "\n<a name=\"~a\"></a>"
- (string-canonicalize ident)))
+ (html-open 'a
+ `((name . ,(string-canonicalize ident))))
+ (html-close 'a))
(output item e)
- (display "</li>\n")))
+ (html-close 'li)))
(markup-body n)))
:after "</ul>")
@@ -1628,13 +1762,14 @@
(for-each (lambda (item)
(let ((ident (and (markup? item)
(markup-ident item))))
- (display "<li")
- (html-class item)
- (display ">")
+ (html-open 'li
+ `((class . ,(markup-class item))))
(if ident ;; produce an anchor
- (format #t "\n<a name=\"~a\"></a>" ident))
- (output item e)
- (display "</li>\n")))
+ (html-open 'a
+ `((name . ,ident)))
+ (html-close 'a))
+ (output item e)
+ (html-close 'li)))
(markup-body n)))
:after "</ol>")
@@ -1648,17 +1783,16 @@
(for-each (lambda (item)
(let ((k (markup-option item :key)))
(for-each (lambda (i)
- (display " <dt")
- (html-class i)
- (display ">")
- (output i e)
- (display "</dt>"))
+ (html-open 'dt
+ `((class . ,(and (markup? i)
+ (markup-class i)))))
+ (output i e)
+ (html-close 'dt))
(if (pair? k) k (list k)))
- (display "<dd")
- (html-class item)
- (display ">")
+ (html-open 'dd
+ `((class . ,(markup-class item))))
(output (markup-body item) e)
- (display "</dd>\n")))
+ (html-close 'dd)))
(markup-body n)))
:after "</dl>")
@@ -1671,11 +1805,10 @@
(let ((k (markup-option n :key)))
(if k
(begin
- (display "<b")
- (html-class n)
- (display ">")
- (output k e)
- (display "</b> "))))
+ (html-open 'b
+ `((class . ,(markup-class n))))
+ (output k e)
+ (html-close 'b))))
(output (markup-body n) e)))
;*---------------------------------------------------------------------*/
@@ -1684,9 +1817,8 @@
(markup-writer 'blockquote
:options '()
:before (lambda (n e)
- (display "<blockquote ")
- (html-class n)
- (display ">\n"))
+ (html-open 'blockquote
+ `((class . ,(markup-class n)))))
:after "\n</blockquote>\n")
;*---------------------------------------------------------------------*/
@@ -1699,19 +1831,19 @@
(let ((ident (markup-ident n))
(number (markup-option n :number))
(legend (markup-option n :legend)))
- (display "<a name=\"")
- (display (string-canonicalize ident))
- (display "\"></a>")
- (output (markup-body n) e)
- (display "<br>\n")
- (output (new markup
- (markup '&html-figure-legend)
- (parent n)
- (ident (string-append ident "-legend"))
- (class (markup-class n))
- (options `((:number ,number)))
- (body legend))
- e)))
+ (html-open 'a
+ `((name . ,(string-canonicalize ident))))
+ (html-close 'a)
+ (output (markup-body n) e)
+ (html-open 'br)
+ (output (new markup
+ (markup '&html-figure-legend)
+ (parent n)
+ (ident (string-append ident "-legend"))
+ (class (markup-class n))
+ (options `((:number ,number)))
+ (body legend))
+ e)))
:after "<br>")
;*---------------------------------------------------------------------*/
@@ -1720,11 +1852,19 @@
(markup-writer '&html-figure-legend
:options '(:number)
:before (lambda (n e)
- (display "<center>")
+ (html-open 'center)
(let ((number (markup-option n :number)))
- (if number
- (format #t "<strong>Fig. ~a:</strong> " number)
- (display "<strong>Fig. :</strong> "))))
+ (if number
+ (begin
+ (html-open 'strong)
+ (display "Fig. ")
+ (display (number->string number))
+ (display ":")
+ (html-close 'strong))
+ (begin
+ (html-open 'strong)
+ (display "Fig. :")
+ (html-close 'strong)))))
:after "</center>")
;*---------------------------------------------------------------------*/
@@ -1740,27 +1880,37 @@
(cstyle (markup-option n :cellstyle))
(cp (markup-option n :cellpadding))
(cs (markup-option n :cellspacing)))
- (display "<table")
- (html-class n)
- (if width (format #t " width=\"~a\"" (html-width width)))
- (if border (format #t " border=\"~a\"" border))
- (if (and (number? cp) (>= cp 0))
- (format #t " cellpadding=\"~a\"" cp))
- (if (and (number? cs) (>= cs 0))
- (format #t " cellspacing=\"~a\"" cs))
- (cond
- ((symbol? cstyle)
- (format #t " style=\"border-collapse: ~a;\"" cstyle))
- ((string? cstyle)
- (format #t " style=\"border-collapse: separate; border-spacing=~a\"" cstyle))
- ((number? cstyle)
- (format #t " style=\"border-collapse: separate; border-spacing=~apt\"" cstyle)))
- (if frame
- (format #t " frame=\"~a\""
- (if (eq? frame 'none) "void" frame)))
- (if (and rules (not (eq? rules 'header)))
- (format #t " rules=\"~a\"" rules))
- (display "><tbody>\n")))
+ (html-open 'table
+ `((class . ,(markup-class n))
+ (width . ,(and width
+ (html-width width)))
+ (border . ,border)
+ (cellpadding . ,(and (number? cp)
+ (>= cp 0)
+ cp))
+ (cellspacing . ,(and (number? cs)
+ (>= cs 0)
+ cs))
+ (style . ,(cond
+ ((symbol? cstyle)
+ (string-append "border-collapse: "
+ (symbol->string cstyle)
+ ";"))
+ ((string? cstyle)
+ (string-append "border-collapse: separate; border-spacing="
+ cstyle))
+ ((number? cstyle)
+ (string-append "border-collapse: separate; border-spacing="
+ cstyle
+ "pt"))
+ (else #f)))
+ (frame . ,(and frame
+ (if (eq? frame 'none)
+ "void"
+ frame)))
+ (rules . ,(and (not (eq? rules 'header))
+ rules))))
+ (html-open 'tbody)))
:after "</tbody></table>\n")
;*---------------------------------------------------------------------*/
@@ -1770,10 +1920,10 @@
:options '(:bg)
:before (lambda (n e)
(let ((bg (markup-option n :bg)))
- (display "<tr")
- (html-class n)
- (when (html-color-spec? bg) (format #t " bgcolor=\"~a\"" bg))
- (display ">")))
+ (html-open 'tr
+ `((class . ,(markup-class n))
+ (bgcolor . ,(and (html-color-spec? bg)
+ bg))))))
:after "</tr>\n")
;*---------------------------------------------------------------------*/
@@ -1790,24 +1940,23 @@
((or (eq? v 'center)
(equal? v "center"))
"middle")
- (else
- v))))
+ (else
+ v))))
(colspan (markup-option n :colspan))
(rowspan (markup-option n :rowspan))
(bg (markup-option n :bg)))
- (format #t "<~a" markup)
- (html-class n)
- (if width (format #t " width=\"~a\"" (html-width width)))
- (if align (format #t " align=\"~a\"" align))
- (if valign (format #t " valign=\"~a\"" valign))
- (if colspan (format #t " colspan=\"~a\"" colspan))
- (if rowspan (format #t " rowspan=\"~a\"" rowspan))
- (when (html-color-spec? bg)
- (format #t " bgcolor=\"~a\"" bg))
- (display ">")))
+ (html-open markup
+ `((class . ,(markup-class n))
+ (width . ,(and width (html-width width)))
+ (align . ,align)
+ (valign . ,valign)
+ (colspan . ,colspan)
+ (rowspan . ,rowspan)
+ (bgcolor . ,(and (html-color-spec? bg)
+ bg))))))
:after (lambda (n e)
(let ((markup (or (markup-option n 'markup) 'td)))
- (format #t "</~a>" markup))))
+ (html-close markup))))
;*---------------------------------------------------------------------*/
;* image ... @label image@ */
@@ -1827,18 +1976,17 @@
'("gif" "jpg" "png"))))))
(if (not (string? img))
(skribe-error 'html "Invalid image" file)
- (begin
- (format #t "<img src=\"~a\" border=\"0\"" img)
- (html-class n)
- (if body
- (begin
- (display " alt=\"")
- (output body e)
- (display "\""))
- (format #t " alt=\"~a\"" file))
- (if width (format #t " width=\"~a\"" (html-width width)))
- (if height (format #t " height=\"~a\"" height))
- (display ">"))))))
+ (html-open 'img
+ `((class . ,(markup-class n))
+ (src . ,img)
+ (border . "0")
+ (alt . ,(if body
+ (with-output-to-string
+ (cut output body e))
+ file))
+ (width . ,(and width
+ (html-width width)))
+ (height . ,height)))))))
;*---------------------------------------------------------------------*/
;* Ornaments ... */
@@ -1873,15 +2021,15 @@
:options '(:text)
:action (lambda (n e)
(let ((text (markup-option n :text)))
- (display "<a href=\"mailto:")
- (output (markup-body n) e)
- (display #\")
- (html-class n)
- (display #\>)
- (if text
- (output text e)
- (evaluate-document (tt (markup-body n)) e))
- (display "</a>"))))
+ (html-open 'a
+ `((class . ,(markup-class n))
+ (href . ,(string-append "mailto:"
+ (with-output-to-string
+ (cut output (markup-body n) e))))))
+ (if text
+ (output text e)
+ (evaluate-document (tt (markup-body n)) e))
+ (html-close 'a))))
;*---------------------------------------------------------------------*/
;* mailto ... @label mailto@ */
@@ -1909,24 +2057,29 @@
(dd (regexp-substitute/global #f "\\." do
'pre " " 'post))
(text (markup-option n :text)))
- (display "<script language=\"JavaScript\" type=\"text/javascript\"")
+ (html-open 'script
+ `((language . "JavaScript")
+ (type . "text/javascript")))
(if (not text)
- (format #t ">skribenospam( ~s, ~s, true )" nn dd)
+ (format #t "skribenospam( ~s, ~s, true )" nn dd)
(begin
- (format #t ">skribenospam( ~s, ~s, false )" nn dd)
- (display "</script>")
+ (format #t "skribenospam( ~s, ~s, false )" nn dd)
+ (html-close 'script)
(output text e)
- (display "<script language=\"JavaScript\" type=\"text/javascript\">document.write(\"</\" + \"a>\")")))
- (display "</script>\n"))))
+ (html-open 'script
+ `((language . "JavaScript")
+ (type . "text/javascript")))
+ (display "document.write(\"</\" + \"a>\")")))
+ (html-close 'script))))
;*---------------------------------------------------------------------*/
;* mark ... @label mark@ */
;*---------------------------------------------------------------------*/
(markup-writer 'mark
:before (lambda (n e)
- (format #t "<a name=\"~a\"" (string-canonicalize (markup-ident n)))
- (html-class n)
- (display ">"))
+ (html-open 'a
+ `((class . ,(markup-class n))
+ (name . ,(string-canonicalize (markup-ident n))))))
:after "</a>")
;*---------------------------------------------------------------------*/
@@ -1941,14 +2094,14 @@
(class (if (markup-class n)
(markup-class n)
"skribilo-ref")))
- (format #t "<a href=\"~a#~a\" class=\"~a\""
- (if (and (*destination-file*) f
- (string=? f (*destination-file*)))
- ""
- (strip-ref-base (or f (*destination-file*) "")))
- (string-canonicalize id)
- class)
- (display ">")))
+ (html-open 'a
+ `((href . ,(string-append (if (and (*destination-file*) f
+ (string=? f (*destination-file*)))
+ ""
+ (strip-ref-base (or f (*destination-file*) "")))
+ "#"
+ (string-canonicalize id)))
+ (class . ,class)))))
:action (lambda (n e)
(let ((t (markup-option n :text))
(m (markup-option n 'mark))
@@ -2052,11 +2205,10 @@
(substring url 0 i))
(else
(loop (+ i 1))))))))))
- (display "<a href=\"")
- (output url html-title-engine)
- (display "\"")
- (when class (format #t " class=\"~a\"" class))
- (display ">")))
+ (html-open 'a
+ `((href . ,(with-output-to-string
+ (cut output url html-title-engine)))
+ (class . ,class)))))
:action (lambda (n e)
(let ((v (markup-option n :text)))
(output (or v (markup-option n :url)) e)))
@@ -2070,10 +2222,9 @@
:before (lambda (n e)
(let ((before (writer-before
(markup-writer-get '&prog-line base-engine))))
- (format #t "<a name=\"~a\""
- (string-canonicalize (markup-ident n)))
- (html-class n)
- (display ">")
+ (html-open 'a
+ `((class . ,(markup-class n))
+ (name . ,(string-canonicalize (markup-ident n)))))
(before n e)))
:after "</a>\n")
@@ -2109,9 +2260,9 @@
(markup-writer '&bib-entry-label
:options '(:title)
:before (lambda (n e)
- (format #t "<a name=\"~a\"" (string-canonicalize (markup-ident n)))
- (html-class n)
- (display ">"))
+ (html-open 'a
+ `((class . ,(markup-class n))
+ (name . ,(string-canonicalize (markup-ident n))))))
:action (lambda (n e)
(output n e (markup-writer-get '&bib-entry-label base-engine)))
:after "</a>")
@@ -2143,18 +2294,17 @@
;*---------------------------------------------------------------------*/
(markup-writer '&the-index-header
:action (lambda (n e)
- (display "<center")
- (html-class n)
- (display ">")
- (for-each (lambda (h)
- (let ((f (engine-custom e 'index-header-font-size)))
- (if f
- (evaluate-document (font :size f (bold (it h))) e)
- (output h e))
- (display " ")))
- (markup-body n))
- (display "</center>")
- (evaluate-document (linebreak 2) e)))
+ (html-open 'center
+ `((class . ,(markup-class n))))
+ (for-each (lambda (h)
+ (let ((f (engine-custom e 'index-header-font-size)))
+ (if f
+ (evaluate-document (font :size f (bold (it h))) e)
+ (output h e))
+ (display " ")))
+ (markup-body n))
+ (html-close 'center)
+ (evaluate-document (linebreak 2) e)))
;*---------------------------------------------------------------------*/
;* &source-comment ... */