grug

A static website generator written for Guile Scheme
Log | Files | Refs | README | LICENSE

commit d43a90e6955e953d9e065ac682f3e45dbabde1e8
parent dabb4ff9068c0d9ebc56567c3f347eb0b9ea71ea
Author: Luke Willis <lukejw@loquat.dev>
Date:   Tue, 17 Jun 2025 14:21:20 -0400

Working demo

Diffstat:
A.gitignore | 2++
MMakefile.am | 12++++++------
Mconfigure.ac | 2++
Dgrug/hello.scm | 6------
Agrug/ui.scm | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Mguix.scm | 9+++++++--
Mscripts/grug.in | 4++--
7 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +index.md +*.html diff --git a/Makefile.am b/Makefile.am @@ -20,14 +20,14 @@ SUFFIXES = .scm .go moddir=$(prefix)/share/guile/site/$(GUILE_EFFECTIVE_VERSION) godir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache -bin_SCRIPTS = \ +bin_SCRIPTS = \ scripts/grug -SOURCES = \ - grug/hello.scm +SOURCES = \ + grug/ui.scm -EXTRA_DIST += \ - README.md \ - guix.scm \ +EXTRA_DIST += \ + README.md \ + guix.scm \ pre-inst-env.in diff --git a/configure.ac b/configure.ac @@ -20,4 +20,6 @@ guileobjectdir="`eval echo ${libdir}/guile/$GUILE_EFFECTIVE_VERSION/site-ccache AC_SUBST([guilemoduledir]) AC_SUBST([guileobjectdir]) +GUILE_MODULE_AVAILABLE([have_guile_htmlprag], [(htmlprag)]) + AC_OUTPUT diff --git a/grug/hello.scm b/grug/hello.scm @@ -1,6 +0,0 @@ -(define-module (grug hello) - #:export (hello-world)) - -(define (hello-world) - (display "Hello, World!") - (newline)) diff --git a/grug/ui.scm b/grug/ui.scm @@ -0,0 +1,53 @@ +;;; Grug user interface. + +(define-module (grug ui) + #:use-module (htmlprag) + #:use-module (ice-9 popen) + #:use-module (ice-9 textual-ports) + #:use-module (ice-9 pretty-print) + #:export (main)) + +;; Pipe the contents of a markdown file into cmark +(define (markdown->html path) + (let* ((cmd (string-append "cmark --to html --nobreaks < " path)) + (port (open-input-pipe cmd)) + (html (get-string-all port))) + (close-port port) + (string-delete #\newline html))) + +(define (test-layout body) + `(*TOP* (*DECL* DOCTYPE html) + (html + (head + (meta (@ (charset "utf-8"))) + (title "Hello, world!")) + (body + (h1 "Test site") + ,@body)))) + +(define* (main prog file . args) + (format #t "Args: ~a~%" args) + + (display "Stage 1 - parsed MD to HTML:\n") + (define raw-html (markdown->html file)) + (display raw-html) + (newline) + (newline) + + (display "Stage 2 - converted HTML to SXML:\n") + (define base-html (delete '*TOP* (html->sxml raw-html))) + (pretty-print base-html) + (newline) + + (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)))) diff --git a/guix.scm b/guix.scm @@ -2,14 +2,14 @@ (guix licenses) (guix git) (guix build-system gnu) + (guix gexp) (gnu packages) (gnu packages autotools) (gnu packages base) (gnu packages guile) (gnu packages guile-xyz) (gnu packages pkg-config) - (gnu packages rsync) - (gnu packages texinfo) + (gnu packages markup) (gnu packages version-control)) (package @@ -17,8 +17,13 @@ (version "0.1.0") (source (git-checkout (url (dirname (current-filename))))) (build-system gnu-build-system) + (arguments + (list #:make-flags #~(list "GUILE_AUTO_COMPILE=0") + #:phases #~(modify-phases %standard-phases + (delete 'strip)))) (native-inputs (list autoconf automake pkg-config)) (inputs (list guile-3.0)) + (propagated-inputs (list guile-lib cmark)) (synopsis "Functional static site generator") (description #f) (home-page #f) diff --git a/scripts/grug.in b/scripts/grug.in @@ -10,6 +10,6 @@ (push! "@guilemoduledir@" %load-path) (push! "@guileobjectdir@" %load-compiled-path)) -(use-modules (grug hello)) +(use-modules (grug ui)) -(hello-world) +(apply main (command-line))