Index: .fossil-settings/ignore-glob
==================================================================
--- .fossil-settings/ignore-glob
+++ .fossil-settings/ignore-glob
@@ -13,6 +13,6 @@
*.ltx
*.aux
*.log
*.xml
*.toc
-
+*.mark
Index: blog.rkt
==================================================================
--- blog.rkt
+++ blog.rkt
@@ -26,33 +26,35 @@
(require "crystalize.rkt"
"snippets-html.rkt"
racket/file
sugar/list)
+
+(provide main)
;; How many items per blog page
-(define per-page 1)
+(define per-page 5)
;; Returns a string containing the entire HTML contents of a given blog page
(define (blog-page posts-str pagenum total-pages)
(define page-nav (html$-paginate-navlinks pagenum total-pages "blog"))
◊string-append{
-
-
-◊html$-page-head[(format "The Local Yarn: Blog, p. ~a" pagenum)]
-◊html$-page-body-open[]
-
-
-
-
-
-◊posts-str
-
-
-
-◊html$-page-body-close[]
-})
+
+
+ ◊html$-page-head[(format "The Local Yarn: Blog, p. ~a" pagenum)]
+ ◊html$-page-body-open[]
+
+
+
+
+
+ ◊posts-str
+
+
+
+ ◊html$-page-body-close[]
+ })
;; Grabs all the articles+notes from the cache and writes out all the blog page files
(define (build-blog)
(spell-of-summoning!) ; Turn on the DB
@@ -60,13 +62,14 @@
(define pagecount (length articles+notes))
(for ([pagenum (in-range 1 (+ 1 pagecount))]
[page (in-list articles+notes)])
(define filename (format "blog-pg~a.html" pagenum))
- (println (format "Writing: ~a" filename))
+ (displayln (format "Writing: ~a" filename))
(display-to-file (blog-page (apply string-append page) pagenum pagecount)
filename
#:mode 'text
#:exists 'replace)))
-;; Do it!
-(build-blog)
+(define (main)
+ ;; Do it!
+ (build-blog))
Index: dust.rkt
==================================================================
--- dust.rkt
+++ dust.rkt
@@ -27,10 +27,11 @@
pollen/file
net/uri-codec
gregor
txexpr
racket/list
+ racket/system
racket/string)
;; Provides common helper functions used throughout the project
(provide maybe-meta ; Select from (current-metas) or default value ("") if not available
@@ -37,10 +38,11 @@
maybe-attr ; Return an attribute’s value or a default ("") if not available
here-output-path
series-noun ; Retrieve noun-singular from current 'series meta, or ""
series-title ; Retrieve title of series in current 'series meta, or ""
series-pagenode
+ invalidate-series
make-tag-predicate
tx-strs
ymd->english
ymd->dateformat
default-authorname
@@ -59,13 +61,15 @@
(define series-folder "series")
(define articles-folder "articles")
(define (default-title body-txprs)
(format "“~a…”" (first-words body-txprs 5)))
+
(define (maybe-meta m [missing ""])
- (or (select-from-metas m (current-metas)) missing))
+ (cond [(current-metas) (or (select-from-metas m (current-metas)) missing)]
+ [else missing]))
;; Return the current output path, relative to (current-project-root)
;; Similar to the variable 'here' which is only accessible in Pollen templates,
;; except this is an actual path, not a string.
(define (here-output-path)
@@ -94,10 +98,23 @@
(define (series-title)
(define series-pnode (series-pagenode))
(case series-pnode
['|| ""] ; no series specified
[else (or (select-from-metas 'title series-pnode) "")]))
+
+;; “Touches” the last-modified date on the current article’s series, if there is one
+
+(define (invalidate-series)
+ (define series-name (maybe-meta 'series #f))
+ (when series-name
+ (define series-file (build-path (current-project-root)
+ series-folder
+ (format "~a.poly.pm" series-name)))
+ (when (file-exists? series-file)
+ (case (system-type 'os)
+ ['windows (system (format "type nul >> ~a" series-file))]
+ [else (system (format "touch ~a" series-file))]))))
;; ~~~ Project-wide Pagetrees ~~~
(define (include-in-pagetree folder extension)
(define (matching-file? f)
Index: makefile
==================================================================
--- makefile
+++ makefile
@@ -4,16 +4,85 @@
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved. This file is offered as-is,
# without any warranty.
#
+SHELL = /bin/bash
+
+# ~~~ Variables used by rules ~~~
+#
+
+core-files := pollen.rkt dust.rkt
+html-deps := snippets-html.rkt tags-html.rkt
+
+article-sources := $(wildcard articles/*.poly.pm)
+articles-html := $(patsubst %.poly.pm, %.html, $(article-sources))
+articles-pdf := $(patsubst %.poly.pm, %.pdf, $(article-sources))
+
+series-sources := $(wildcard series/*.poly.pm)
+series-html := $(patsubst %.poly.pm, %.html, $(series-sources))
+
+# ~~~ Rules ~~
+#
+
+# The order of these dependencies is important. They will be processed left to right.
+web: _article_htmls.mark $(articles-html) $(series-html) blog-pg1.html
+web: ## Rebuild all web content (not PDFs)
+
+# The file article_htmls.mark is a zero-byte file that serves only as a marker. If it is older than
+# any of its dependencies (or missing) all of the articles will be rebuilt. Its dependencies are
+# also on the Pollen cache watchlist (see pollen.rkt)
+_article_htmls.mark: $(core-files) $(html-deps) template.html.p
+ raco pollen setup articles/
+ raco pollen render -p -t html articles/*.poly.p
+ raco pollen setup series/
+ raco pollen render -p -t html series/*.poly.pm
+ touch article_htmls.mark
+
+# If the rule for article_htmls.mark was triggered, all the article HTML files will already have
+# been re-rendered. (That rule comes before this one in the list of dependencies for "all") But if
+# not, any individual files that have been edited will get re-rendered.
+$(articles-html): %.html: %.poly.pm
+ raco pollen render $@
+
+# Note that if any article is part of a series, it will touch its series .poly.pm file during its
+# render, triggering this rule for that series.
+$(series-html): %.html: %.poly.pm
+ raco pollen render $@
+# This target will also rebuild pg2, pg3, etc.
+blog-pg1.html: $(core-files) $(html-deps) $(articles-html) blog.rkt
+ rm -f blog*.html
+ racket -tm blog.rkt
spritz: ## Clear Pollen and Scribble cache
rm -rf compiled code-docs/compiled articles/compiled series/compiled
fossil clean code-docs/
+publish: check-env
+publish: ## Sync all HTML and PDF stuff to the public web server (does not rebuild any files)
+ raco pollen publish
+ rsync -av ~/Desktop/publish/ -e 'ssh -p $(WEB_SRV_PORT)' $(LOCALYARN_SRV) \
+ --delete \
+ --exclude=drafts \
+ --exclude=code-docs \
+ --exclude=util \
+ --exclude=x-mockup \
+ --exclude=repo-www \
+ --exclude=scribbled \
+ --exclude='*.sqlite' \
+ --exclude='*.fossil' \
+ --exclude=.fossil-settings \
+ --exclude=.fslckout \
+ --exclude='*.ltx' \
+ --exclude='*.swp' \
+ --exclude='*.mark' \
+ --exclude=.DS_Store \
+ --exclude='template*.*' \
+ --exclude=makefile
+ rm -rf ~/Desktop/publish
+
scribble: ## Rebuild code documentation and update Fossil repo
scribble --htmls +m --redirect https://docs.racket-lang.org/local-redirect/ code-docs/main.scrbl
fossil uv rm scribbled/*
rm -rf scribbled/*
mv main/* scribbled/
@@ -27,8 +96,16 @@
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
article: ## Start a new article from a template
racket util/newpost.rkt
-.PHONY: scribble help spritz article
+.PHONY: all scribble help spritz article publish check-env
.DEFAULT_GOAL := help
+
+check-env:
+ifndef LOCALYARN_SRV
+ $(error LOCALYARN_SRV env variable not set, should be a destination valid for rsync)
+endif
+ifndef WEB_SRV_PORT
+ $(error WEB_SRV_PORT env variable not set, should be SSH port number for web server)
+endif
Index: tags-html.rkt
==================================================================
--- tags-html.rkt
+++ tags-html.rkt
@@ -95,10 +95,11 @@
(define (html-block . elements)
`(section [[class "content-block"]] (div [[class "content-block-main"]] ,@elements)))
(define (html-root . elements)
+ (invalidate-series)
(define first-pass
(decode-elements (append elements (list (html-footnote-block)))
#:txexpr-elements-proc decode-hardwrapped-paragraphs
#:exclude-tags '(script style figure table pre)))
(define second-pass