commit f01f01ed70594bc62c32c035d3f0f583bda7043c
parent 12e85119ad4486d702af1f0838aa2e75f410393d
Author: Luke Willis <lukejw@loquat.dev>
Date: Thu, 3 Jul 2025 21:45:09 -0400
Working simple-pages and copy-directory builders
Diffstat:
8 files changed, 94 insertions(+), 28 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1 @@
-index.md
-*.html
+example/site
diff --git a/Makefile.am b/Makefile.am
@@ -24,7 +24,8 @@ bin_SCRIPTS = \
scripts/grug
SOURCES = \
- grug/ui.scm
+ grug/ui.scm \
+ grug/utils.scm
EXTRA_DIST += \
README.md \
diff --git a/example/css/style.css b/example/css/style.css
diff --git a/example/pages/err/404.md b/example/pages/err/404.md
@@ -0,0 +1 @@
+You failed.
diff --git a/example/pages/foo.md b/example/pages/foo.md
@@ -0,0 +1,2 @@
+# Welcome to FOO PAGE
+Truly the best alternate page
diff --git a/example/pages/index.md b/example/pages/index.md
@@ -0,0 +1,22 @@
+# Hello, world!
+This is a test markdown file.
+
+I can use both **bold** and *italic* because `code` is super cool.
+What do you think?
+
+## Title 2
+
+### Title 3
+
+#### Title 4
+
+##### Title 5 (List edition)
+
+1. Numero uno
+2. Numero dos
+ - "That's rascist"
+ - No it's not
+ - I can count in spanish, too (two)!
+3. Numero tres
+
+The test is complete.
diff --git a/grug/ui.scm b/grug/ui.scm
@@ -1,6 +1,7 @@
;;; Grug user interface.
(define-module (grug ui)
+ #:use-module (grug utils)
#:use-module (htmlprag)
#:use-module (ice-9 popen)
#:use-module (ice-9 textual-ports)
@@ -8,6 +9,7 @@
#:export (main))
;; Pipe the contents of a markdown file into cmark
+;; TODO: Change to make compact HTML without messing up things like code blocks
(define (markdown->html path)
(let* ((cmd (string-append "cmark --to html --nobreaks < " path))
(port (open-input-pipe cmd))
@@ -15,39 +17,64 @@
(close-port port)
(string-delete #\newline html)))
-(define (test-layout body)
+(define (basic-template body)
`(*TOP* (*DECL* DOCTYPE html)
(html
(head
(meta (@ (charset "utf-8")))
- (title "Hello, world!"))
+ (title "Hello, world! m"))
(body
(h1 "Test site")
,@body))))
-(define* (main prog file . args)
- (format #t "Args: ~a~%" args)
+;; Copy the given directory to the output directory. Very simple.
+;; I would use this for copying CSS files and images, for example.
+(define* (copy-directory directory
+ #:key
+ (prefix "site"))
+ (display "copy-directory\n")
- (display "Stage 1 - parsed MD to HTML:\n")
- (define raw-html (markdown->html file))
- (display raw-html)
- (newline)
- (newline)
+ (for-each
+ (lambda (path)
+ (let* ((output-path (string-append prefix "/" path))
+ (output-dir (dirname output-path)))
+ (format #t "\t~A -> ~A\n" path output-path)
+ (unless (file-exists? output-dir) (mkdir output-dir))
+ (copy-file path output-path)))
+ (reverse (ls-recursive directory))))
- (display "Stage 2 - converted HTML to SXML:\n")
- (define base-html (delete '*TOP* (html->sxml raw-html)))
- (pretty-print base-html)
- (newline)
+;; Build pages from the given directory into the output directory.
+;; 'input-dir/index.md' will become 'output-dir/index.html'
+;; 'input-dir/subdir/index.md' will become 'output-dir/subdir/index.html'
+;; ...and so on.
+(define* (simple-pages directory
+ #:key
+ (prefix "site")
+ (template basic-template))
+ (display "simple-pages\n")
+
+ ;; Iterate through files in directory
+ (for-each
+ (lambda (path)
+ (let* ((base-sxml (delete '*TOP* (html->sxml (markdown->html path))))
+ (built-sxml (template base-sxml))
+ (output (sxml->html built-sxml))
+ (output-dir
+ (string-append prefix
+ (substring (dirname path)
+ (string-length directory))))
+ (output-path
+ (string-append output-dir "/"
+ (basename path ".md")
+ ".html")))
+ (unless (file-exists? output-dir) (mkdir output-dir))
+ (format #t "\t~A -> ~A\n" path output-path)
+ (call-with-output-file output-path
+ (lambda (port)
+ (display output port)))))
+ ;; Reverse the list so that base directories are listed first
+ (reverse (ls-recursive directory))))
- (display "Stage 3 - modified SXML:\n")
- (define new-html (test-layout base-html))
- (pretty-print new-html)
- (newline)
-
- (display "Stage 4 - converted SXML to HTML:\n")
- (define final-html (sxml->html new-html))
- (display final-html)
- (newline)
- (call-with-output-file (string-append file ".html")
- (lambda (port)
- (display final-html port))))
+(define* (main prog . args)
+ (simple-pages "pages")
+ (copy-directory "css"))
diff --git a/grug/utils.scm b/grug/utils.scm
@@ -0,0 +1,14 @@
+;;; Utility functions for Grug.
+
+(define-module (grug utils)
+ #:use-module (ice-9 ftw)
+ #:export (ls-recursive))
+
+;; Return a list of file paths by recursively searching a given directory.
+;; This is basically like running `ls -aR`.
+(define (ls-recursive directory)
+ (let ((enter? (lambda (path stat result) #t))
+ (leaf (lambda (path stat result) (cons path result)))
+ (err (lambda (path stat errno result) (error "Failed to list file" errno path)))
+ (noop (lambda (path stat result) result)))
+ (file-system-fold enter? leaf noop noop noop err '() directory)))