;; Outputs HTML to stdout.
(import svnwiki-sxml
(chicken format)
(chicken string)
(chicken process-context)
(chicken base))
;; Track current heading level so defs nest one level below their section
(define current-heading-level (make-parameter 0))
(define (escape-html str)
(string-translate* str
'(("&" . "&")
("<" . "<")
(">" . ">")
("\"" . """))))
(define (emit-nodes nodes)
(for-each emit-node nodes))
(define (emit-node node)
(cond
((string? node)
(display (escape-html node)))
((not (pair? node))
(void))
(else
(case (car node)
;; Shift heading levels by -1: svnwiki == (level 2) becomes h1
((section)
(let* ((level (cadr node))
(hl (max 1 (- level 1)))
(title (caddr node))
(body (cdddr node)))
(fprintf (current-output-port) "" hl)
(display (escape-html title))
(fprintf (current-output-port) "\n" hl)
(parameterize ((current-heading-level hl))
(emit-nodes body))))
;; Table of contents: omit (GitHub can generate its own)
((toc) (void))
((p)
(display "")
(emit-nodes (cdr node))
(display "
\n"))
;; Internal wiki links -> full Chicken wiki URLs
((int-link)
(let* ((path (cadr node))
(text (if (> (length node) 2) (caddr node) (cadr node))))
(display "")
(display (escape-html text))
(display "")))
;; External links
((link)
(let* ((url (cadr node))
(text (if (> (length node) 2) (caddr node) (cadr node))))
(display "")
(display (escape-html text))
(display "")))
;; Procedure definition: signature as a sub-heading, then body
((def)
(let ((sig (cadr node))
(body (cddr node))
(hl (+ 1 (current-heading-level))))
(fprintf (current-output-port) "" hl)
(emit-node sig)
(fprintf (current-output-port) "\n" hl)
(emit-nodes body)))
;; Signature container: just emit contents
((sig)
(emit-nodes (cdr node)))
;; Procedure type in a signature
((procedure)
(display "")
(display (escape-html (cadr node)))
(display ""))
;; Syntax type in a signature
((syntax)
(display "")
(display (escape-html (cadr node)))
(display ""))
;; Code blocks with syntax highlighting
((highlight)
(let ((lang (cadr node))
(code (cddr node)))
(fprintf (current-output-port) "" lang)
(for-each (lambda (c) (display (escape-html c))) code)
(display "
\n")))
;; Inline code
((tt)
(display "")
(emit-nodes (cdr node))
(display ""))
;; Bold
((b)
(display "")
(emit-nodes (cdr node))
(display ""))
;; Lists
((ul)
(display "\n")
(emit-nodes (cdr node))
(display "
\n"))
((li)
(display "")
(emit-nodes (cdr node))
(display "\n"))
;; Definition lists (used in version history)
((dl)
(display "\n")
(emit-nodes (cdr node))
(display "
\n"))
((dt)
(display "")
(emit-nodes (cdr node))
(display "\n"))
((dd)
(display "")
(emit-nodes (cdr node))
(display "\n"))
;; Fallback: emit children
(else
(emit-nodes (cdr node)))))))
(define (main)
(let* ((args (command-line-arguments))
(filename (car args))
(sxml (call-with-input-file filename svnwiki->sxml)))
(emit-nodes sxml)))
(main)