flat-files.scm 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. ;;; Spritely Institute website
  2. ;;; Copyright © 2022 Christine Lemmer-Webber <cwebber@dustycloud.org>
  3. ;;;
  4. ;;; Site code and contents dual licensed under CC BY 4.0 and Apache v2.
  5. (define-module (flat-files)
  6. #:use-module (ice-9 control)
  7. #:use-module (ice-9 ftw)
  8. #:use-module (ice-9 match)
  9. #:use-module (ice-9 regex)
  10. #:use-module (srfi srfi-1)
  11. #:use-module (srfi srfi-9)
  12. #:use-module (haunt html)
  13. #:use-module (haunt site)
  14. #:use-module (haunt reader)
  15. #:use-module (haunt artifact)
  16. #:export (flat-files))
  17. ;; For storing intermediate data while walking the tree
  18. (define-record-type <walked>
  19. (make-walked dir entries)
  20. walked?
  21. (dir walked-dir)
  22. (entries walked-entries))
  23. (define (default-template site posts body metadata)
  24. (define title (assoc-ref metadata 'title))
  25. `((doctype "html")
  26. (html
  27. (head
  28. (meta (@ (charset "utf-8")))
  29. (title ,(if title
  30. (string-append title " — " (site-title site))
  31. (site-title site))))
  32. (body ,body))))
  33. (define default-templates
  34. `((default . ,default-template)))
  35. (define* (flat-files directory
  36. #:key
  37. (templates default-templates)
  38. (default-metadata '())
  39. (skip-unrecognized? #t))
  40. (lambda (site posts)
  41. (define (flat-file->sxml path return-early)
  42. (define reader
  43. (or (find (lambda (reader)
  44. (reader-match? reader path))
  45. (site-readers site))
  46. ;; escape early if nothing found... files we don't have
  47. ;; readers for are skipped
  48. (if skip-unrecognized?
  49. (return-early)
  50. (error "No reader for file:" path))))
  51. (define-values (file-metadata file-sxml)
  52. ((reader-proc reader) path))
  53. (define metadata
  54. (append file-metadata default-metadata))
  55. (define template-name
  56. (or (and=> (assoc-ref metadata 'template) string->symbol)
  57. 'default))
  58. (define template
  59. (or (assoc-ref templates template-name)
  60. (error "No such template: " template-name)))
  61. (template site posts file-sxml metadata))
  62. (define enter? (const #t)) ; enter all subdirectories
  63. (define (leaf path stat result) ; render a file
  64. (call/ec
  65. (lambda (return)
  66. (define (return-early)
  67. (return result))
  68. (match result
  69. (($ <walked> dir entries)
  70. (let* ((in-basename (basename path))
  71. (out-filename
  72. (cond
  73. ;; If the file (sans extension suffix) ends with __index,
  74. ;; then the user wants us to put this under <foo>/index.html
  75. ((string-match "^(.+)__index\\..+$" in-basename)
  76. =>
  77. (lambda (sm)
  78. (regexp-substitute #f sm
  79. 1 file-name-separator-string
  80. "index.html")))
  81. ;; Otherwise, just write this as <foo>.html
  82. (else
  83. (regexp-substitute #f (string-match "^(.+)\\..+$"
  84. in-basename)
  85. 1 ".html"))))
  86. (out-filename-with-path
  87. (string-join (cdr (reverse (cons out-filename dir)))
  88. file-name-separator-string))
  89. (contents (flat-file->sxml path return-early))
  90. (entry (serialized-artifact out-filename-with-path
  91. contents
  92. sxml->html)))
  93. (make-walked dir (cons entry entries))))))))
  94. ;; keep track of the current subdirectory we're in
  95. (define (down path stat result) ; add to current-dir stack
  96. (match result
  97. (($ <walked> dir entries)
  98. (make-walked (cons (basename path) dir)
  99. entries))))
  100. (define (up path stat result) ; pop from current-dir stack
  101. (match result
  102. (($ <walked> dir entries)
  103. (make-walked (cdr dir)
  104. entries))))
  105. (define (skip path stat result) result) ; no-op
  106. (define (err file-name stat errno result)
  107. (error "file processing failed with errno: " file-name errno))
  108. (walked-entries
  109. (file-system-fold enter? leaf down up skip err
  110. (make-walked '() '()) directory))))