summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile3
-rw-r--r--boudin.egg22
-rw-r--r--boudin.page.index.scm95
-rw-r--r--boudin.page.post.scm77
-rw-r--r--boudin.page.scm32
-rw-r--r--boudin.page.style.scm47
-rw-r--r--boudin.page.write.scm101
-rw-r--r--boudin.scm31
-rw-r--r--boudin.util.scm19
-rw-r--r--test/out/feed.xml25
-rw-r--r--test/out/foo/index.html5
-rw-r--r--test/out/index.html1
13 files changed, 289 insertions, 172 deletions
diff --git a/.gitignore b/.gitignore index 0b68fed..b4aa44a 100644 --- a/.gitignore +++ b/.gitignore
@@ -6,4 +6,5 @@ boudin
6*.import.scm 6*.import.scm
7*.types 7*.types
8*.build.sh 8*.build.sh
9*.install.sh \ No newline at end of file 9*.install.sh
10test/out/ \ No newline at end of file
diff --git a/Makefile b/Makefile index bd8289d..501354d 100644 --- a/Makefile +++ b/Makefile
@@ -10,7 +10,8 @@ install:
10 10
11.PHONY: test 11.PHONY: test
12test: build 12test: build
13 cd test; ../boudin *.html && (cd out; python -m http.server) 13 ./boudin -C test '*.html'
14 cock test/out # my own little server
14 15
15.PHONY: clean 16.PHONY: clean
16clean: 17clean:
diff --git a/boudin.egg b/boudin.egg index 353d1d4..3606695 100644 --- a/boudin.egg +++ b/boudin.egg
@@ -1,34 +1,44 @@
1;;; boudin 1;;; boudin
2 2
3((synopsis "a small, tasty ssg.") 3((synopsis "a tiny, tasty ssg.")
4 (author "Case Duckworth") 4 (author "Case Duckworth")
5 (license "God Willing") 5 (license "God Willing")
6 (version "0.1.1") 6 (version 1728)
7 (build-dependencies module-declarations)
7 (dependencies atom 8 (dependencies atom
8 html-parser 9 html-parser
9 module-declarations
10 schmaltz 10 schmaltz
11 srfi-1 11 srfi-1
12 srfi-152 12 srfi-152
13 sxml-serializer 13 sxml-serializer
14 scss
14 utf8) 15 utf8)
15 (component-options 16 (component-options
16 (csc-options -X module-declarations -X utf8)) 17 (csc-options -X module-declarations -X utf8
18 -O2 -d1))
17 (components 19 (components
18 (program boudin 20 (program boudin
19 (component-dependencies boudin.page 21 (component-dependencies boudin.page
20 boudin.page.instances 22 boudin.page.index
23 boudin.page.post
24 boudin.page.style
21 boudin.page.write 25 boudin.page.write
22 boudin.site 26 boudin.site
23 boudin.util)) 27 boudin.util))
24 (extension boudin.page 28 (extension boudin.page
25 (component-dependencies boudin.site 29 (component-dependencies boudin.site
26 boudin.util)) 30 boudin.util))
27 (extension boudin.page.instances 31 (extension boudin.page.index
32 (component-dependencies boudin.page
33 boudin.page.write
34 boudin.site))
35 (extension boudin.page.post
28 (component-dependencies boudin.page 36 (component-dependencies boudin.page
29 boudin.page.write 37 boudin.page.write
30 boudin.site 38 boudin.site
31 boudin.util)) 39 boudin.util))
40 (extension boudin.page.style
41 (component-dependencies boudin.page))
32 (extension boudin.page.write 42 (extension boudin.page.write
33 (component-dependencies boudin.page 43 (component-dependencies boudin.page
34 boudin.site)) 44 boudin.site))
diff --git a/boudin.page.index.scm b/boudin.page.index.scm new file mode 100644 index 0000000..4ff3fd9 --- /dev/null +++ b/boudin.page.index.scm
@@ -0,0 +1,95 @@
1(declare (module (boudin page index))
2 (export make-index
3 index-template
4 index-writer
5 make-feed
6 feed-template
7 feed-writer))
8
9(import (boudin page)
10 (boudin page write)
11 (boudin site)
12 (chicken pathname)
13 (html-parser)
14 (sxml-serializer)
15 (rename (atom)
16 (make-feed atom/make-feed)))
17
18(define (make-index pgs)
19 (make-page ((index-template) pgs)
20 (make-pathname (site-output) "index.html")
21 page-content
22 (index-writer)
23 `()))
24
25(define index-writer
26 (make-parameter
27 sxml-display-as-html))
28
29(define index-template
30 (make-parameter
31 (lambda (pgs)
32 `(html (@ (lang "en-us"))
33 (head ,@(html-head)
34 (title ,(site-name)))
35 (body (h1 ,(site-name))
36 (ul ,@(map (lambda (pg)
37 `(li (a (@ (href ,(page-slug pg)))
38 ,(or (page-ref pg "title")
39 (page-slug pg)))))
40 ((site-sort) pgs))))))))
41
42(define (make-feed pgs)
43 (make-page ((feed-template) pgs)
44 (make-pathname (site-output) "feed.xml")
45 page-content
46 (feed-writer)
47 `()))
48
49(define feed-writer
50 (make-parameter
51 (lambda (sxml)
52 (serialize-sxml sxml
53 output: (current-output-port)
54 cdata-section-elements: '(atom:content)
55 ns-prefixes:
56 `((*default* . "http://www.w3.org/2005/Atom")
57 (*default* . "http://www.w3.org/1999/xhtml")
58 ,@(atom-ns-prefixes))
59 allow-prefix-redeclarations: #t))))
60
61(define feed-template
62 (make-parameter
63 (lambda (pgs)
64 (make-atom-doc
65 (atom/make-feed
66 title: (make-title (site-name))
67 id: (site-host)
68 updated: (site-build-time)
69 authors: (list (make-author name: (site-author)
70 uri: (site-host)))
71 links: (list (make-link type: 'html
72 uri-language: "en"
73 uri: (site-host))
74 (make-link relation: "self"
75 type: "application/atom+xml"
76 uri: (make-pathname
77 (site-host) "feed" "xml")))
78 rights: (make-rights (force (site-rights)))
79 generator: (make-generator "Boudin"
80 uri: "https://git.acdw.net/boudin"
81 version: "rice")
82 entries: (map (lambda (pg)
83 (make-entry
84 title: (make-title
85 (or (page-ref pg "title") "[untitled]"))
86 links: (list (make-link type: 'html
87 uri: (page-url pg)))
88 id: (page-url pg)
89 updated: (page-updated pg)
90 ;;published:
91 content: (make-content
92 (sxml->html
93 (page-content pg))
94 type: 'html)))
95 ((site-sort) pgs)))))))
diff --git a/boudin.page.post.scm b/boudin.page.post.scm new file mode 100644 index 0000000..002d7bf --- /dev/null +++ b/boudin.page.post.scm
@@ -0,0 +1,77 @@
1(declare (module (boudin page post))
2 (export make-post
3 post-path-transformers
4 post-text-transformers
5 post-template
6 post-writer))
7
8(import (boudin page)
9 (boudin page write)
10 (boudin site)
11 (boudin util)
12 (chicken pathname)
13 (html-parser)
14 (except (schmaltz)
15 render-specials
16 render-unprintables)
17 (schmaltz chicken)
18 (srfi 152))
19
20(define (make-post path)
21 (let ((sxml ((apply o (post-text-transformers))
22 (with-input-from-file path slurp))))
23 (make-page sxml
24 ((apply o (post-path-transformers)) path)
25 (post-template)
26 (post-writer)
27 (cons (cons "source" path)
28 (*extract-metadata sxml)))))
29
30(define (*extract-metadata sxml)
31 (let loop ((tree sxml)
32 (acc '()))
33 (cond
34 ((not (pair? tree))
35 (reverse acc))
36 ((and (list? (car tree))
37 (eq? (caar tree) '*COMMENT*))
38 (loop (cdr tree)
39 (map (lambda (ln)
40 (let ((kv (string-split ln ":" 'infix 1)))
41 (cons (string-trim-both (car kv))
42 (string-trim (cdr kv)))))
43 (string-split (cadar tree) "\n"))))
44 ((list? (car tree))
45 (loop (cdr tree)
46 (let ((subtree (loop (car tree) '())))
47 (if (null? subtree)
48 acc
49 (cons subtree acc)))))
50 (else (loop (cdr tree) acc)))))
51
52(define post-text-transformers
53 (make-parameter
54 (list html->sxml
55 wrap-paragraphs
56 render-string->string)))
57
58(define post-path-transformers
59 (make-parameter
60 (list (lambda (path)
61 (make-pathname (list (site-output)
62 (pathname-strip-extension path))
63 "index.html")))))
64
65(define post-template
66 (make-parameter
67 (lambda (pg)
68 (let ((title (page-ref pg "title")))
69 `(html (@ (lang "en-us"))
70 (head ,@(html-head)
71 (title ,(or title "[untitled]")))
72 (body ,(if title `(h1 ,title) "")
73 ,@(cdr (page-content pg))))))))
74
75(define post-writer
76 (make-parameter
77 sxml-display-as-html))
diff --git a/boudin.page.scm b/boudin.page.scm index 004e750..cf60c20 100644 --- a/boudin.page.scm +++ b/boudin.page.scm
@@ -1,24 +1,16 @@
1(declare (module (boudin page)) 1(declare (module (boudin page))
2 (export make-page 2 (export make-page page?
3 page-content 3 page-content page-output page-template page-writer
4 page-meta 4 page-meta page-meta-set! page-ref page-set!
5 page-meta-set! 5 page-slug page-updated page-url))
6 page-output 6
7 page-ref 7(import (boudin site)
8 page-set! 8 (boudin util)
9 page-slug 9 (chicken file posix)
10 page-template 10 (chicken file)
11 page-updated 11 (chicken pathname)
12 page-url 12 (chicken time posix)
13 page-writer 13 (srfi 1))
14 page?)
15 (import (boudin site)
16 (boudin util)
17 (chicken file posix)
18 (chicken file)
19 (chicken pathname)
20 (chicken time posix)
21 (srfi 1)))
22 14
23(define-record-type page 15(define-record-type page
24 (make-page content output template writer meta) 16 (make-page content output template writer meta)
diff --git a/boudin.page.style.scm b/boudin.page.style.scm new file mode 100644 index 0000000..351cf1a --- /dev/null +++ b/boudin.page.style.scm
@@ -0,0 +1,47 @@
1(declare (module (boudin page style))
2 (export make-style
3 style
4 page-style
5 style-template
6 site-style
7 style-writer))
8
9(import (boudin page)
10 (boudin site)
11 (scss)
12 (html-parser)
13 (srfi 152)
14 (chicken pathname))
15
16(define (make-style . rules)
17 (make-page rules
18 (make-pathname (site-output) "style.css")
19 (style-template)
20 (style-writer)
21 '()))
22
23(define (style props)
24 ;; sxml: `(el (@ ,(style '((padding 3em) (color red)))) content ...)
25 (let ((sty (scss->css `(css+ (_ ,@props)))))
26 (list 'style
27 (substring sty 4 (- (string-length sty) 2)))))
28
29(define (page-style . rules)
30 ;; sxml: `(html (head ,(page-style '(body (margin auto)))))
31 `(style ,(scss->css `(css+ ,@rules))))
32
33(define style-template
34 (make-parameter
35 (lambda (pg)
36 `(css+ ,@(page-content pg)))))
37
38(define site-style
39 (make-parameter
40 '((body (font 18px/1.4 sans-serif)
41 (max-width 70ch)
42 (padding 2ch)
43 (margin 0 auto)))))
44
45(define style-writer
46 (make-parameter
47 write-css))
diff --git a/boudin.page.write.scm b/boudin.page.write.scm index eb719b7..39e916c 100644 --- a/boudin.page.write.scm +++ b/boudin.page.write.scm
@@ -1,20 +1,10 @@
1(declare (module (boudin page write)) 1(declare (module (boudin page write))
2 (export feed-template 2 (export html-head
3 feed-writer
4 html-head
5 index-template
6 index-writer
7 post-template
8 post-writer
9 write-page)) 3 write-page))
10 4
11(import (atom) 5(import (boudin page)
12 (boudin page)
13 (boudin site)
14 (chicken file) 6 (chicken file)
15 (chicken pathname) 7 (chicken pathname))
16 (html-parser)
17 (sxml-serializer))
18 8
19(define (write-page pg) 9(define (write-page pg)
20 (let ((outfile (page-output pg))) 10 (let ((outfile (page-output pg)))
@@ -22,9 +12,9 @@
22 'parents) 12 'parents)
23 (with-output-to-file outfile 13 (with-output-to-file outfile
24 (lambda () 14 (lambda ()
25 ((page-writer pg) 15 ((o (page-writer pg)
26 ((page-template pg) 16 (page-template pg))
27 pg)))))) 17 pg)))))
28 18
29(define html-head 19(define html-head
30 (make-parameter 20 (make-parameter
@@ -33,82 +23,3 @@
33 (content "initial-scale=1.0"))) 23 (content "initial-scale=1.0")))
34 (link (@ (href "/style.css") 24 (link (@ (href "/style.css")
35 (rel "stylesheet")))))) 25 (rel "stylesheet"))))))
36
37(define post-writer
38 (make-parameter
39 sxml-display-as-html))
40
41(define post-template
42 (make-parameter
43 (lambda (pg)
44 (let ((title (page-ref pg "title")))
45 `(html (@ (lang "en-us"))
46 (head ,@(html-head)
47 (title ,(or title "[untitled]")))
48 (body ,(if title `(h1 ,title) "")
49 ,@(cdr (page-content pg))))))))
50
51(define index-writer
52 (make-parameter
53 sxml-display-as-html))
54
55(define index-template
56 (make-parameter
57 (lambda (pgs)
58 `(html (@ (lang "en-us"))
59 (head ,@(html-head)
60 (title ,(site-name)))
61 (body (h1 ,(site-name))
62 (ul ,@(map (lambda (pg)
63 `(li (a (@ (href ,(page-slug pg)))
64 ,(or (page-ref pg "title")
65 (page-slug pg)))))
66 ((site-sort) pgs))))))))
67
68(define feed-writer
69 (make-parameter
70 (lambda (sxml)
71 (serialize-sxml sxml
72 output: (current-output-port)
73 cdata-section-elements: '(atom:content)
74 ns-prefixes:
75 `((*default* . "http://www.w3.org/2005/Atom")
76 (*default* . "http://www.w3.org/1999/xhtml")
77 ,@(atom-ns-prefixes))
78 allow-prefix-redeclarations: #t))))
79
80(define feed-template
81 (make-parameter
82 (lambda (pgs)
83 (make-atom-doc
84 (make-feed
85 title: (make-title (site-name))
86 id: (site-host)
87 updated: (site-build-time)
88 authors: (list (make-author name: (site-author)
89 uri: (site-host)))
90 links: (list (make-link type: 'html
91 uri-language: "en"
92 uri: (site-host))
93 (make-link relation: "self"
94 type: "application/atom+xml"
95 uri: (make-pathname
96 (site-host) "feed" "xml")))
97 rights: (make-rights (force (site-rights)))
98 generator: (make-generator "Boudin"
99 uri: "https://git.acdw.net/boudin"
100 version: "rice")
101 entries: (map (lambda (pg)
102 (make-entry
103 title: (make-title
104 (or (page-ref pg "title") "[untitled]"))
105 links: (list (make-link type: 'html
106 uri: (page-url pg)))
107 id: (page-url pg)
108 updated: (page-updated pg)
109 ;;published:
110 content: (make-content
111 (sxml->html
112 (page-content pg))
113 type: 'html)))
114 ((site-sort) pgs)))))))
diff --git a/boudin.scm b/boudin.scm index 4f6a1b3..b56b93b 100644 --- a/boudin.scm +++ b/boudin.scm
@@ -1,7 +1,9 @@
1;;; boudin 1;;; boudin
2 2
3(import (boudin page) 3(import (boudin page)
4 (boudin page instances) 4 (boudin page post)
5 (boudin page index)
6 (boudin page style)
5 (boudin page write) 7 (boudin page write)
6 (boudin site) 8 (boudin site)
7 (boudin util) 9 (boudin util)
@@ -37,29 +39,46 @@
37 (with-progress (string-append "Writing " (page-output pg)) 39 (with-progress (string-append "Writing " (page-output pg))
38 (lambda () (write-page pg)))) 40 (lambda () (write-page pg))))
39 (append posts 41 (append posts
40 (list (make-index posts) 42 (list (apply make-style (site-style))
43 (make-index posts)
41 (make-feed posts))))) 44 (make-feed posts)))))
42 (eprint "Done!")) 45 (eprint "Done!"))
43 46
44(define (main args) 47(define (main args)
45 (define *current #f) 48 (define *current #f)
49 (define glob? #t)
50 (when (null? args)
51 (exit 1))
46 (let loop ((args args)) 52 (let loop ((args args))
47 (cond 53 (cond
48 ((null? args) (go!)) 54 ((null? args)
55 (for-each print (site-posts))
56 (go!))
57 ;; Configuration file: -c FILE
49 ((equal? (car args) "-c") 58 ((equal? (car args) "-c")
50 (site-config (cadr args)) 59 (site-config (cadr args))
51 (loop (cddr args))) 60 (loop (cddr args)))
52 ((not *current) ; add to posts by default 61 ;; Change directory: -C DIRECTORY
53 (site-posts (cons (car args) (site-posts))) 62 ((equal? (car args) "-C")
63 (change-directory (cadr args))
64 (loop (cddr args)))
65 ;; Don't glob filenames: -r (raw)
66 ((equal? (car args) "-r")
67 (set! glob? #f)
54 (loop (cdr args))) 68 (loop (cdr args)))
69 ;; Posts follow -p
55 ((equal? (car args) "-p") 70 ((equal? (car args) "-p")
56 (set! *current site-posts) 71 (set! *current site-posts)
57 (loop (cdr args))) 72 (loop (cdr args)))
73 ;; Files follow -f
58 ((equal? (car args) "-f") 74 ((equal? (car args) "-f")
59 (set! *current site-files) 75 (set! *current site-files)
60 (loop (cdr args))) 76 (loop (cdr args)))
77 ;; Append current path to *current
61 (else 78 (else
62 (*current (cons (car args) (*current))) 79 (let ((*current (or *current site-posts))) ; posts by default
80 (*current (append ((if glob? glob list) (car args))
81 (*current))))
63 (loop (cdr args)))))) 82 (loop (cdr args))))))
64 83
65(cond-expand 84(cond-expand
diff --git a/boudin.util.scm b/boudin.util.scm index 2683730..b5c3efe 100644 --- a/boudin.util.scm +++ b/boudin.util.scm
@@ -5,17 +5,16 @@
5 edisplay 5 edisplay
6 eprint)) 6 eprint))
7 7
8(import (srfi 1) 8(import (chicken io)
9 (srfi 1)
9 (srfi 152)) 10 (srfi 152))
10 11
11(define (edisplay x) 12(define (edisplay x)
12 (parameterize ((current-output-port (current-error-port))) 13 (display x (current-error-port)))
13 (display x)))
14 14
15(define (eprint . xs) 15(define (eprint . xs)
16 (parameterize ((current-output-port (current-error-port))) 16 (for-each edisplay xs)
17 (for-each display xs) 17 (newline (current-error-port)))
18 (newline)))
19 18
20(define (assoc-ref k alist) 19(define (assoc-ref k alist)
21 (let ((k/v (and (pair? alist) 20 (let ((k/v (and (pair? alist)
@@ -60,9 +59,5 @@
60 (case-lambda 59 (case-lambda
61 (() (slurp (current-input-port))) 60 (() (slurp (current-input-port)))
62 ((port) 61 ((port)
63 (let loop ((ch (read-char port)) 62 (read-string #f port) ; CHICKEN-ism
64 (acc '())) 63 )))
65 (if (eof-object? ch)
66 (list->string (reverse acc))
67 (loop (read-char port)
68 (cons ch acc)))))))
diff --git a/test/out/feed.xml b/test/out/feed.xml deleted file mode 100644 index 2f1f29f..0000000 --- a/test/out/feed.xml +++ /dev/null
@@ -1,25 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<feed xmlns="http://www.w3.org/2005/Atom">
3 <author>
4 <name>nobody</name>
5 <uri>example.com</uri>
6 </author>
7 <generator uri="https://git.acdw.net/boudin" version="rice">Boudin</generator>
8 <id>example.com</id>
9 <link href="example.com" rel="alternate" type="text/html" hreflang="en" />
10 <link href="example.com/feed.xml" rel="self" type="application/atom+xml" />
11 <rights type="text">(C) nobody</rights>
12 <title type="text">a boudin site</title>
13 <updated>2023-09-07T03:42:00Z</updated>
14 <entry>
15 <content type="html"><![CDATA[<p>a test file
16</p>
17<p>3
18</p>
19]]></content>
20 <id>https:/example.com/foo/index.html</id>
21 <title type="text">[untitled]</title>
22 <updated>Wed Sep 6 04:59:10 2023</updated>
23 <link href="https:/example.com/foo/index.html" rel="alternate" type="text/html" />
24 </entry>
25</feed> \ No newline at end of file
diff --git a/test/out/foo/index.html b/test/out/foo/index.html deleted file mode 100644 index 7d408f6..0000000 --- a/test/out/foo/index.html +++ /dev/null
@@ -1,5 +0,0 @@
1<html lang="en-us"><head><meta charset="utf-8"></meta><meta name="viewport" content="initial-scale=1.0"></meta><link href="/style.css" rel="stylesheet"></link><title>[untitled]</title></head><body><p>a test file
2</p>
3<p>3
4</p>
5</body></html> \ No newline at end of file
diff --git a/test/out/index.html b/test/out/index.html deleted file mode 100644 index 2267cf0..0000000 --- a/test/out/index.html +++ /dev/null
@@ -1 +0,0 @@
1<html lang="en-us"><head><meta charset="utf-8"></meta><meta name="viewport" content="initial-scale=1.0"></meta><link href="/style.css" rel="stylesheet"></link><title>a boudin site</title></head><body><h1>a boudin site</h1><ul><li><a href="/foo/">/foo/</a></li></ul></body></html> \ No newline at end of file