diff --git a/bump-version.sh b/bump-version.sh index 120dd40..f6d0ec7 100755 --- a/bump-version.sh +++ b/bump-version.sh @@ -41,7 +41,7 @@ if [[ -f VERSION ]]; then git add CHANGES VERSION sed -i "s/^declare -r VERSION=$/declare -r VERSION=${NEXT_VERSION}'/" bin/jqt sed -i "s/\[version .*\]/[version ${NEXT_VERSION}]/" bin/jqt - sed -i "s/^Version *:=.*/Version := ${NEXT_VERSION}/" docs/Makefile + sed -i "s/^version: *.*/version: ${NEXT_VERSION}/" docs/config.yaml git commit -am "Version bump to ${NEXT_VERSION}" git tag -a -m "Tagging version ${NEXT_VERSION}" "v${NEXT_VERSION}" [[ $PUSH == yes ]] && git push origin --tags diff --git a/docs/.gitignore b/docs/.gitignore index 8956c53..1bc0433 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -3,5 +3,3 @@ *.swp /.meta/ /_site/ -/content/xxx* -/content/yyy* diff --git a/docs/Makefile b/docs/Makefile index 4ad3d7a..1afd8a3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,136 +1,155 @@ ######################################################################## -# Makefile for web site management +# Makefile # # Project: jqt # Author: jordinas@gmail.com +# Description: Makefile for JQT web site management. # Published: https://fadado.github.io/jqt/ +# +# Variables: +# $(Metadata) +# Rules: +# $(Metadata) directory target and clobber method +# +######################################################################## + +######################################################################## +# Load _Make_ configuration. ######################################################################## -# Make configuration -include make.d/prelude.make +include make.d/configuration.make -# jqt version -Version := 0.5.1 +# Do not try to rebuilt static makefiles. +Makefile make.d/configuration.make: ; -# Metadata directory -Metadata := .meta +######################################################################## +# Metadata directory for all generated make and metadata files. +######################################################################## -# Do not build to clobber immediately +Metadata ?= .meta + +$(Metadata): + $(info ==> $@) + mkdir --parents $@ >/dev/null 2>&1 || true + +# Delete all generated metadata +clobber:: ; @rm -rf $(Metadata) + +######################################################################## +# Print debug info. +######################################################################## + +ifneq (,$(TRACE)) +ifdef MAKE_RESTARTS +$(info Makefile phase restarted: $(MAKE_RESTARTS)) +endif +endif + +######################################################################## +# Check command line sanity. +######################################################################## + +# Target 'clobber' must be alone. +ifeq (clobber,$(filter clobber,$(MAKECMDGOALS))) +ifneq (1,$(words $(MAKECMDGOALS))) +$(error Target "clobber" must be alone) +endif +endif + +# Do not build to clobber immediately. ifeq (clobber,$(MAKECMDGOALS)) ifeq (,$(wildcard $(Metadata))) $(error Nothing to clobber) endif endif -# Do not build to clean immediately +# Do not build to clean immediately. ifeq (clean,$(filter clean,$(MAKECMDGOALS))) ifeq (,$(wildcard $(Metadata))) $(error Nothing to clean) endif endif -# ====================================================================== +# Check _root_ intentions. +ifeq (,$(filter install uninstall,$(MAKECMDGOALS))) +ifeq (0,$(shell id --user)) +$(error Root only can make "(un)install" targets) +endif +else +ifneq (0,$(shell id --user)) +$(error Only root can make "(un)install" targets) +endif +endif + +######################################################################## +# Include all makefile phases. +######################################################################## + +# Recursive variable used in all included makefiles. This works because the +# included files do not include other makefiles. + +THIS = $(lastword $(MAKEFILE_LIST)) + +######################################################################## +# Derive metadata from `config.yaml` or `config.json`. + -include $(Metadata)/phase1.make - include make.d/config.make -# -# Variables defined in phase1.make: -# __phase_1 -# Assets -# Blocks -# Content -# Data -# Destination -# Layouts -# Styles -# Defined rules for: -# $(Metadata) -# $(Metadata)/config.json -# $(Metadata)/phase1.make -# $(Metadata)/site.json -# ====================================================================== + include make.d/phase1.make + +# Do not try to rebuilt static makefiles. +make.d/phase1.make: ; -# Warning: -# # If `__phase_1` is not defined because `phase1.make` does not exists, after -# this point most of the file is ignored, but `phase1.make` is built because a -# rule exists in the file `config.make`. Then this `Makefile` is restarted, -# `MAKE_RESTARTS` is be equal to 1, `phase1.make` is now loaded and +# this point the rest of the file is ignored, but `phase1.make` is built +# because a rule exists in the file `config.make`. Then this `Makefile` is +# restarted, `MAKE_RESTARTS` is be equal to 1, `phase1.make` is now loaded and # `__phase_1` is defined. Equivalent situation happens in all phases. ifdef __phase_1 -# ====================================================================== +######################################################################## +# Build metadata from filesystem introspection. + -include $(Metadata)/phase2.make - include make.d/data.make -# -# Variables defined in phase2.make: -# __phase_2 -# DataCSV -# DataJSON -# DataMD -# DataYAML -# DestinationPages -# DestinationPaths -# MetadataPages -# MetadataPaths -# Defined rules for: -# $(Metadata)/phase2.make -# $(DataFiles) -# $(DestinationPaths) -# $(Metadata)/pages-by-id.json -# $(MetadataPages) -# $(MetadataPaths) -# Defined targets: -# init -# ====================================================================== + include make.d/phase2.make + +# Do not try to rebuilt static makefiles. +make.d/phase2.make: ; ifdef __phase_2 -# ====================================================================== +######################################################################## +# Define standard rules and rules for HTML pages and nodes. + -include $(Metadata)/phase3.make - include make.d/pages.make -# -# Load rules for pages and nodes. -# -# Variables defined in phase3.make: -# __phase_3 -# Defined rules for: -# $(Metadata)/phase3.make -# Defined targets: -# all -# build -# clean -# clobber -# fresh -# touch -# ====================================================================== + include make.d/phase3.make + +# Do not try to rebuilt static makefiles. +make.d/phase3.make: ; ifdef __phase_3 -# ====================================================================== +######################################################################## +# Several complementary makefiles. + include make.d/sitemap.make include make.d/styles.make -include make.d/tools.make -# -# Several complementary files. -# -# Defined rules for: -# $(Destination)/sitemap.xml -# $(Destination)/sitemap.xml.gz -# $(Destination)/styles.css -# Defined targets: -# help -# lint -# valid -# ====================================================================== +##include make.d/tools.make + +# Do not try to rebuilt static makefiles. +make.d/sitemap.make: ; +make.d/styles.make: ; +##make.d/tools.make: ; ######################################################################## -include config.make -# # Project specific makefile. All the previous modules are expected to be # independent, valid for any project without any change. This file must # exist but can be empty. -######################################################################## + +include config.make + +# Do not try to rebuilt static makefiles. +config.make: ; endif # __phase_3 endif # __phase_2 diff --git a/docs/README.md b/docs/README.md index d7d910e..a4f84d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,27 +1,100 @@ +# Conventions + ## Extension conventions for content files -The files in the `content` directory must follow some conventions in the file +The files in the `content` and `data` directories must follow some conventions in the file extensions: * Web site pages - - content.md - - data.md - - engine.md - - home.md - - structure.md + - `content/content.md` + - `content/data.md` + - `content/engine.md` + - `content/index.md` + - `content/structure.md` * Partial MarkDown to be included - - EXAMPLE.txt - - FLOW.txt - - LINKS.txt - - opt/\*.txt - -* MarkDown snippets - - snippets.yaml + - `content/EXAMPLE.text` + - `content/FLOW.text` + - `content/LINKS.text` + - `content/opt/\*.text` * Other unrelated MarkDown files - - help.markdown - - jqt.1.markdown + - `content/help.text` + - `content/jqt.1.text` + +* Extension conventions for data files + - `data/table.csv` + - `data/snippets.md` + - `data/document.json` + - `data/document.yaml` + +# Variables + +Capitalized names are for global predefined variables. + +## Site variables + +All members defined in the configuration file, except `defaults`, and the +predefined variables: + +* `.site.Assets` +* `.site.Blocks` +* `.site.Content` +* `.site.Data` +* `.site.Destination` +* `.site.Layouts` +* `.site.Metadata` +* `.site.Styles` + +In the configuration file you can assign new values to all predefined variables +except `Metadata`, with hardcoded value in the file `Makefile`. + +## Page variables + +Front-matter members and the predefined variables. + +### Read only variables + +* `.page.Base` +* `.page.Date` +* `.page.Filename` +* `.page.Id` +* `.page.Layout` +* `.page.Path` +* `.page.Section` +* `.page.Slug` +* `.page.Source` +* `.page.URL` + +### Variables merged with defaults + +* `.page.Datasets` +* `.page.Dependencies` +* `.page.Flags` + +### Source for pathname related variables + +``` + Slug + |---^---| +content/name.html + |-^| + Id + + Section Slug + |--^-| |--^----| +content/extras/name.html + |-------v-| + |--v--| Id + Path + + Section Slug + |------^-----| |---^---| +content/extras/indexes/name.html + |---------------v-| + |-----v-------| Id + Path +``` - + <# # Meta elements @@ -13,12 +13,12 @@ <# More metadata #> - + <# Presentation #> - + - + {{._highlight}} <# diff --git a/docs/make.d/config.make b/docs/make.d/config.make deleted file mode 100644 index ad6050f..0000000 --- a/docs/make.d/config.make +++ /dev/null @@ -1,77 +0,0 @@ -######################################################################## -# config.make -# -# Build files derived from user defined configuration: -# config.{yaml,json} => config.json => site.json => phase1.make -# -# Variables defined in phase1.make: -# __phase_1 -# Assets -# Blocks -# Content -# Data -# Destination -# Layouts -# Styles -# Defined rules for: -# $(Metadata) -# $(Metadata)/config.json -# $(Metadata)/phase1.make -# $(Metadata)/site.json - -######################################################################## -# Metadata directory for all generated make and metadata files -######################################################################## - -$(Metadata): - $(info ==> $@) - @mkdir --parents $@ >/dev/null 2>&1 || true - -######################################################################## -# Files derived from user defined configuration file -######################################################################## - -# -# Create `$(Metadata)/config.json` from `config.yaml` or `config.json`. -# -ifeq (config.yaml,$(wildcard config.yaml)) - -# Convert `config.yaml` to `$(Metadata)/config.json`. -$(Metadata)/config.json: config.yaml \ -| $(Metadata) - $(info ==> $@) - @yaml2json < $< > $@ - -else ifeq (config.json,$(wildcard config.json)) - -# Convert `config.json` to `$(Metadata)/config.json`. -$(Metadata)/config.json: config.json \ -| $(Metadata) - $(info ==> $@) - @jqt -Pjson < $< > $@ - -else -$(error Configuration file not found) -endif - -# -# Create `$(Metadata)/site.json` from `$(Metadata)/config.json`. -# -$(Metadata)/site.json: $(Metadata)/config.json make.d/config.make make.d/site.jq - $(info ==> $@) - @jq --sort-keys \ - --from-file make.d/site.jq \ - --arg Version $(Version) \ - --arg Metadata $(Metadata) \ - < $< > $@ - -# -# Create `$(Metadata)/phase1.make` from `$(Metadata)/site.json`. -# -$(Metadata)/phase1.make: $(Metadata)/site.json make.d/config.make make.d/phase1.jq - $(info ==> $@) - @jq --raw-output \ - --from-file make.d/phase1.jq \ - < $< > $@ - -# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/prelude.make b/docs/make.d/configuration.make similarity index 68% rename from docs/make.d/prelude.make rename to docs/make.d/configuration.make index 81003af..d5f78a1 100644 --- a/docs/make.d/prelude.make +++ b/docs/make.d/configuration.make @@ -1,48 +1,29 @@ ######################################################################## -# prelude.make -# -# The project prelude: common module available in all makefile modules +# configuration.make -- Global GMake configuration. # +# Debugging variables: +# VERBOSE +# TRACE -# Debug tool -ifdef MAKE_RESTARTS -$(info Makefile restarted: $(MAKE_RESTARTS)) -endif +TRACE ?= +VERBOSE ?= ######################################################################## -# Prerequisites +# Prerequisites. ######################################################################## # We are using some of the newest GNU Make features... so require GNU -# Make version >= 3.82 +# Make version >= 3.82. version_test := $(filter 3.82,$(firstword $(sort $(MAKE_VERSION) 3.82))) ifndef version_test $(error GNU Make version $(MAKE_VERSION); version >= 3.82 is needed) endif -# Only one target at the same time +# Only one target at the same time. MAKECMDGOALS ?= all -# Check 'root' intentions -ifeq (,$(filter install uninstall,$(MAKECMDGOALS))) -ifeq (0,$(shell id --user)) -$(error Root only can make "(un)install" targets) -endif -else -ifneq (0,$(shell id --user)) -$(error Only root can make "(un)install" targets) -endif -endif - -# Target 'clobber' must be alone -ifeq (clobber,$(filter clobber,$(MAKECMDGOALS))) -ifneq (1,$(words $(MAKECMDGOALS))) -$(error Target "clobber" must be alone) -endif -endif - ######################################################################## -# Make configuration +# Make configuration. ######################################################################## # Disable builtins. @@ -53,7 +34,7 @@ MAKEFLAGS += --no-builtin-variables MAKEFLAGS += --warn-undefined-variables # Make will not print the recipe used to remake files. -#.SILENT: +$(VERBOSE).SILENT: # Eliminate use of the built-in implicit rules. Also clear out the # default list of suffixes for suffix rules. @@ -75,25 +56,25 @@ SHELL := /bin/bash # exits with a nonzero exit status. .DELETE_ON_ERROR: -# Enable a second expansion of the prerequisites +# Enable a second expansion of the prerequisites. .SECONDEXPANSION: ######################################################################## # Common macros ######################################################################## -# Hacks for string manipulation +# Hacks for string manipulation. #!comma := , #!empty := #!space := $(empty) $(empty) #!tab := $(empty) $(empty) -# Hack for list manipulation +# Hack for list manipulation. #!define rest = #!$(wordlist 2,2147483648,$1) #!endef -# File name without extension nor directory +# File name without extension nor directory. #!define filename #!$(basename $(notdir $1)) #!endef diff --git a/docs/make.d/data.make b/docs/make.d/data.make deleted file mode 100644 index 3df3dc2..0000000 --- a/docs/make.d/data.make +++ /dev/null @@ -1,151 +0,0 @@ -######################################################################## -# data.make -# -# Build metadata from filesystem introspection. -# -# Variables defined in phase2.make: -# __phase_2 -# DataCSV -# DataJSON -# DataMD -# DataYAML -# DestinationPages -# DestinationPaths -# MetadataPages -# MetadataPaths -# Defined rules for: -# $(Metadata)/phase2.make -# $(DataFiles) -# $(DestinationPaths) -# $(Metadata)/pages-by-id.json -# $(MetadataPages) -# $(MetadataPaths) -# Targets: -# init - -######################################################################## -# Create makefile defining global variables about pathnames and rules to -# generate JSON metadata files for each page. -######################################################################## - -$(Metadata)/phase2.make: make.d/data.make make.d/phase2.jq $(Metadata)/phase1.make - $(info ==> $@) - @find $(Content) -type f -a \ - -name '[!_]*.md' -o \ - -name '[!_]*.mkd' -o \ - -name '[!_]*.markdown' \ - | jq --raw-input \ - --slurp \ - --raw-output \ - --from-file make.d/phase2.jq \ - --arg DF "$$(find $(Data) -name '*.*')" \ - --arg Content $(Content) \ - --arg Data $(Data) \ - --arg Destination $(Destination) \ - --arg Metadata $(Metadata) \ - > $@ - -ifdef __phase_2 - -# -# Variables used when building JSON files in phase2.make. -# - -define EXTRACT_FRONT_MATTER = - sed -n -e '1d' \ - -e '/^---$$/q' \ - -e '/^\.\.\.$$/q' \ - -e '/^\#/d' \ - -e 'p' -endef - -define BUILD_JSON - yaml2json | \ - jq --sort-keys \ - --arg Source $< \ - --arg Target $@ \ - --arg Metadata $(Metadata) \ - --slurpfile config $(Metadata)/config.json \ - --from-file make.d/page.jq -endef - -######################################################################## -# Extra dependencies -######################################################################## - -$(DestinationPages): $(Destination)/%.html : $(Metadata)/pages/%.json -$(DestinationPages): $(Layouts)/default.html -$(DestinationPages): | $$(dir $$@) - -$(MetadataPages): $(Metadata)/config.json -$(MetadataPages): | $$(dir $$@) - -######################################################################## -# Rules for directories -######################################################################## - -# Directories starting at `$(Destination)/` -$(DestinationPaths): - $(info ==> $@) - @mkdir --parents $@ >/dev/null 2>&1 || true - -# Directories starting at `$(Metadata)/pages/`. -$(MetadataPaths): - $(info ==> $@) - @mkdir --parents $@ >/dev/null 2>&1 || true - -######################################################################## -# Group metadata -######################################################################## - -# Bundle all pages as a relation (id => page) -$(Metadata)/pages-by-id.json: $(MetadataPages) - $(info ==> $@) - @jq --slurp 'reduce .[] as $$p ({}; . + {($$p.id): $$p})' $^ > $@ - -######################################################################## -# Files derived from $(Data)/* -######################################################################## - -ifneq (,$(DataMD)) -$(DataMD): $(Metadata)/%.json : $(Data)/%.md | $(Metadata) - $(info ==> $@) - @jqt -T < $< | yaml2json > $@ -endif - -ifneq (,$(DataYAML)) -$(DataYAML): $(Metadata)/%.json : $(Data)/%.yaml | $(Metadata) - $(info ==> $@) - @yaml2json > $@ -endif - -ifneq (,$(DataJSON)) -$(DataJSON): $(Metadata)/%.json : $(Data)/%.yaml | $(Metadata) - $(info ==> $@) - @jqt -P json < $< > $@ -endif - -ifneq (,$(DataCSV)) -$(DataCSV): $(Metadata)/%.json : $(Data)/%.yaml | $(Metadata) - $(info ==> $@) - @csv2json < $< > $@ -endif - -DataFiles := $(DataMD) $(DataYAML) $(DataJSON) $(DataCSV) - -######################################################################## - -$(DestinationPages): $(DataFiles) - -# make all metadata and data files -init:: -ifdef MAKE_RESTARTS - @$(MAKE) -s $(DataFiles) -else - @rm -rf $(Metadata) - @$(MAKE) -s $(DataFiles) -endif - -endif # __phase_2 - -# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/pages.make b/docs/make.d/pages.make deleted file mode 100644 index 19ed048..0000000 --- a/docs/make.d/pages.make +++ /dev/null @@ -1,93 +0,0 @@ -######################################################################## -# pages.make -# -# Define standard rules and rules for HTML pages and nodes. -# -# Defined rules for: -# $(Metadata)/phase3.make -# Defined targets: -# all -# build -# clean -# clobber -# fresh -# touch - -######################################################################## -# Create makefile containing rules for all HTML files -######################################################################## - -# Build rules for each page -$(Metadata)/phase3.make: $(Metadata)/pages-by-id.json make.d/pages.make make.d/phase3.jq $(Metadata)/phase2.make - $(info ==> $@) - @jq --raw-output \ - --arg Metadata $(Metadata) \ - --arg Layouts $(Layouts) \ - --arg Destination $(Destination) \ - --from-file make.d/phase3.jq \ - < $< > $@ - -ifdef __phase_3 - -# -# Variables used in $(Metadata)/phase3.make. -# - -define JQTFLAGS := - -msite:$(Metadata)/site.json \ - -I./ -L$(Metadata) -L$(Blocks) \ - -ifilters -endef - -JQT = jqt $(JQTFLAGS) - -define DETAILS := - sed -e 's/^

<\/p>/
/' \ - -e 's/^

<\/details><\/p>/<\/details>/' \ - -e 's/^

//' \ - -e 's/<\/summary><\/p>/<\/summary>/' -endef - -######################################################################## -# Standard targets -######################################################################## - -.PHONY: clean clobber build touch fresh - -# Copy Assets after create HTML pages -all:: $(DestinationPages) | $(Destination) - @cp --verbose --recursive --update $(Assets)/* $(Destination) \ - | sed "s/^.*-> ./==> /;s/.$$//" - -# Delete generated files and logs -clean:: - @rm -rf *.log $(Destination)/* - -# Delete all generated files and directories -clobber:: clean - @rm -rf *~ *.bak $(Destination) $(Metadata) - -# Build again all documents -build: clean all - -# Clobber and build again -define TEST_AND_TOUCH.sh - if test -e config.yaml; \ - then touch config.yaml; \ - elif test -e config.json; \ - then touch config.json; \ - else false; \ - fi -endef - -touch: - @$(TEST_AND_TOUCH.sh) - @$(MAKE) -s all - -# Clobber and build again -fresh: clobber - @$(MAKE) -s all - -endif # __phase_3 - -# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/phase1.jq b/docs/make.d/phase1.jq index b465cd5..1f78415 100644 --- a/docs/make.d/phase1.jq +++ b/docs/make.d/phase1.jq @@ -1,16 +1,14 @@ -# Called from config.make to create auxiliar makefile. +######################################################################## +# phase1.jq -- Define contents for `$(Metadata)/phase2.make`. # -# phase1.jq +# jq -r -f phase1.jq # < $(Metadata)/site.json # > $(Metadata)/phase1.make -# Function to cheat vim -def comment: "# vim:syntax=make"; - # -# Format some members as make variables +# Output makefile # -"__phase_1 := 1", +"__phase_1 := 1\n", "Assets := " + .Assets, "Blocks := " + .Blocks, "Content := " + .Content, @@ -18,6 +16,6 @@ def comment: "# vim:syntax=make"; "Destination := " + .Destination, "Layouts := " + .Layouts, "Styles := " + .Styles, -comment +"\n# \u0076im:syntax=make" # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/docs/make.d/phase1.make b/docs/make.d/phase1.make new file mode 100644 index 0000000..b79b2b4 --- /dev/null +++ b/docs/make.d/phase1.make @@ -0,0 +1,88 @@ +######################################################################## +# phase1.make -- Rules for files derived from user defined configuration. +# +# Variables defined in $(Metadata)/phase1.make: +# __phase_1 +# Assets +# Blocks +# Content +# Data +# Destination +# Layouts +# Styles +# +# Rules defined in make.d/phase1.make: +# $(Metadata)/config.json +# $(Metadata)/site.json +# $(Metadata)/phase1.make +# $(Destination) directory rule and clobber and clean targets + +SUPER := Makefile + +######################################################################## +# Files derived from user defined configuration file. +######################################################################## + +# +# Create `$(Metadata)/config.json` from `config.yaml` or `config.json`. +# +ifeq (config.yaml,$(wildcard config.yaml)) + +# Convert `config.yaml` to `$(Metadata)/config.json`. +$(Metadata)/config.json: config.yaml $(SUPER) $(THIS) \ +| $(Metadata) + $(info ==> $@) + yaml2json < $< > $@ + +else ifeq (config.json,$(wildcard config.json)) + +# Convert `config.json` to `$(Metadata)/config.json`. +$(Metadata)/config.json: config.json $(SUPER) $(THIS) \ +| $(Metadata) + $(info ==> $@) + jqt -Pjson < $< > $@ + +else +$(error Configuration file not found) +endif + +# +# Create `$(Metadata)/site.json` from `$(Metadata)/config.json` using +# `make.d/phase1_site.jq`. +# +$(Metadata)/site.json: $(Metadata)/config.json make.d/phase1_site.jq + $(info ==> $@) + jq --sort-keys \ + --from-file make.d/phase1_site.jq \ + --arg Metadata $(Metadata) \ + < $< > $@ + +# +# Create `$(Metadata)/phase1.make` from `$(Metadata)/site.json` using +# `make.d/phase1.jq`. +# +$(Metadata)/phase1.make: $(Metadata)/site.json make.d/phase1.jq + $(info ==> $@) + jq --raw-output \ + --from-file make.d/phase1.jq \ + < $< > $@ + +ifdef __phase_1 + +######################################################################## +# Site destination directory. +######################################################################## + +$(Destination): + $(info ==> $@) + mkdir --parents $@ >/dev/null 2>&1 || true + +# Delete generated files. +clean: ; @rm -rf $(Destination)/* + +# Delete destination directory. +clobber:: ; @rm -rf $(Destination) + +endif # __phase_1 + +# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/site.jq b/docs/make.d/phase1_site.jq similarity index 65% rename from docs/make.d/site.jq rename to docs/make.d/phase1_site.jq index cd29c50..12e9f45 100644 --- a/docs/make.d/site.jq +++ b/docs/make.d/phase1_site.jq @@ -1,26 +1,23 @@ -# Called from config.make to adapt user defined configuration. +######################################################################## +# phase1_site.jq -- Define global members using default values. # -# site.jq -# --arg Version $(Version) -# --arg Metadata $(Metadata) +# jq -S -f phase1_site.jq --arg Metadata $(Metadata) # < $(Metadata)/config.json # > $(Metadata)/site.json -# # Delete `.defaults` and add some new members with default value if not defined # in the configuration file. # del(.defaults) + { - Destination: (.Destination // "_site"), + Metadata: $Metadata, Assets: (.Assets // "assets"), Blocks: (.Blocks // "blocks"), Content: (.Content // "content"), Data: (.Data // "data"), + Destination: (.Destination // "_site"), Layouts: (.Layouts // "layouts"), - Styles: (.Styles // "styles"), - Metadata: (.Metadata // $Metadata), - Version: (.Version // $Version) + Styles: (.Styles // "styles") } # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/docs/make.d/phase2.jq b/docs/make.d/phase2.jq index a704cfa..be6d669 100644 --- a/docs/make.d/phase2.jq +++ b/docs/make.d/phase2.jq @@ -1,100 +1,110 @@ -# Called from data.make to create auxiliar makefile. +######################################################################## +# phase2.jq -- Define contents for `$(Metadata)/phase2.make`. # # find $(Content) all MarkDown files | -# phase2.jq +# jq -s -Rr -f phase2.jq # --arg DF "$$(find $(Data) -name '*.*')" # --arg Content $(Content) # --arg Data $(Data) # --arg Destination $(Destination) # --arg Metadata $(Metadata) -# > $(Metadata)/phase1.make - -# Function to cheat vim -def comment: "# vim:syntax=make"; +# > $(Metadata)/phase2.make +# Extract pathname directory. def dir: if test("/") then sub("/[^/]+$"; "/") else "./" end ; -def dpaths($paths): +# destination_paths := _site/jqt/ _site/jqt/blog/ ... +def destination_paths($paths): def dpath: sub("^" + $Content; $Destination) ; - "DestinationPaths := " + ([$paths[] | dpath] | join(" ")) + "destination_paths := " + ([$paths[] | dpath] | join(" ")) + "\n" ; -def mpaths($paths): +# metadata_paths := .meta/pages/ .meta/pages/blog/ ... +def metadata_paths($paths): def mpath: sub("^" + $Content; $Metadata + "/pages") ; - "MetadataPaths := " + ([$paths[] | mpath] | join(" ")) + "metadata_paths := " + ([$paths[] | mpath] | join(" ")) + "\n" +; + +# data_md := .meta/snippets.json +# data_yaml := +# data_json := +# data_csv := +def data_files($files): + def d2m($x): + sub("\\."+$x+"$"; ".json") + | sub("^"+$Data; $Metadata) + ; + ($files / "\n") as $names + | [$names[] | select(test(".md$"))] as $data_md + | [$names[] | select(test(".yaml$"))] as $data_yaml + | [$names[] | select(test(".json$"))] as $data_json + | [$names[] | select(test(".csv$"))] as $data_csv + | if ($data_md|length) == 0 then "data_md :=\n" + else "data_md := " + ($data_md | map(d2m("md")) | join(" ")) + "\n" end + + if ($data_yaml|length) == 0 then "data_yaml :=\n" + else "data_yaml := " + ($data_yaml | map(d2m("yaml")) | join(" ")) + "\n" end + + if ($data_json|length) == 0 then "data_json :=\n" + else "data_json := " + ($data_json | map(d2m("json")) | join(" ")) + "\n" end + + if ($data_csv|length) == 0 then "data_csv :=\n" + else "data_csv := " + ($data_csv | map(d2m("csv")) | join(" ")) + "\n" end ; -def dpages($documents): +# PagesHTML := _site/jqt/content.html _site/jqt/blog/2017-04-13-hello.html ... +def pages_html($documents): def dpage: sub("^" + $Content; $Destination) | sub("\\.(?:markdown|mk?d)$"; ".html") ; - "DestinationPages := " + ([$documents[] | dpage] | join(" ")) + "PagesHTML := " + ([$documents[] | dpage] | join(" ")) + "\n" ; -def mpages($documents): - def mpage: - sub("^" + $Content; $Metadata + "/pages") - | sub("\\.(?:markdown|mk?d)$"; ".json") - ; - def mrule: - [ $documents[] - | mpage + ": " + . + "\n" + - "\t$(info ==> $@)\n" + - "\t@$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_JSON) > $@" - ] | join("\n") - ; - [$documents[] | mpage] as $json - | "MetadataPages := " + ($json | join(" ")) + "\n" + mrule +# PagesJSON := .meta/pages/content.json .meta/pages/blog/2017-04-13-hello.json ... +def md2json: + sub("^" + $Content; $Metadata + "/pages") + | sub("\\.(?:markdown|mk?d)$"; ".json") ; -def data($files): - def d2m($x): - sub("\\."+$x+"$"; ".json") - | sub("^"+$Data; $Metadata) - ; - ($files / "\n") as $names - | [$names[] | select(test(".md$"))] as $DataMD - | [$names[] | select(test(".yaml$"))] as $DataYAML - | [$names[] | select(test(".json$"))] as $DataJSON - | [$names[] | select(test(".csv$"))] as $DataCSV - | if ($DataMD|length) == 0 then "DataMD :=\n" - else "DataMD := " + ($DataMD | map(d2m("md")) | join(" ")) + "\n" end - + if ($DataYAML|length) == 0 then "DataYAML :=\n" - else "DataYAML := " + ($DataYAML | map(d2m("yaml")) | join(" ")) + "\n" end - + if ($DataJSON|length) == 0 then "DataJSON :=\n" - else "DataJSON := " + ($DataJSON | map(d2m("json")) | join(" ")) + "\n" end - + if ($DataCSV|length) == 0 then "DataCSV :=\n" - else "DataCSV := " + ($DataCSV | map(d2m("csv")) | join(" ")) + "\n" end +def pages_json($documents): + [$documents[] | md2json] as $json + | "PagesJSON := " + ($json | join(" ")) + "\n" +; + +# .meta/pages/content.json: content/content.md +# $(info ==> $@) +# @$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_PAGE_JSON) > $@ +# ... +# .meta/pages/blog/2017-04-13-hello.json: content/blog/2017-04-13-hello.md +# $(info ==> $@) +# @$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_PAGE_JSON) > $@ +def pages_json_rules($documents): + [ $documents[] + | md2json + ": " + . + "\n" + + "\t$(info ==> $@)\n" + + "\t@$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_PAGE_JSON) > $@" + ] | join("\n") ; # # Output makefile # - (.[:-1] / "\n") as $documents -| [$documents[] | dir] | unique as $paths -| dpaths($paths) as $DestinationPaths -| mpaths($paths) as $MetadataPaths -| dpages($documents) as $DestinationPages -| mpages($documents) as $MetadataPages -| data($DF) as $DataFiles +| ([$documents[] | dir] | unique) as $paths | -# print now -"__phase_2 := 1", -$DestinationPaths, -$MetadataPaths, -$DestinationPages, -$MetadataPages, -$DataFiles, -comment +"__phase_2 := 1\n", +destination_paths($paths), +metadata_paths($paths), +data_files($DF), +pages_html($documents), +pages_json($documents), +pages_json_rules($documents), +"\n# \u0076im:syntax=make" # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/docs/make.d/phase2.make b/docs/make.d/phase2.make new file mode 100644 index 0000000..bd383b1 --- /dev/null +++ b/docs/make.d/phase2.make @@ -0,0 +1,193 @@ +######################################################################## +# phase2.make -- Build metadata from filesystem introspection. +# +# Variables defined in $(Metadata)/phase2.make: +# __phase_2 +# data_csv +# data_json +# data_md +# data_yaml +# destination_paths +# metadata_paths +# PagesHTML +# PagesJSON +# +# Rules defined in $(Metadata)/phase2.make: +# metadata JSON files for each HTML page +# +# Variables defined in make.d/phase2.make: +# DataFiles +# +# Rules defined in make.d/phase2.make: +# $(data_csv) +# $(data_json) +# $(data_md) +# $(data_yaml) +# $(destination_paths) +# $(metadata_paths) +# $(Metadata)/content.text +# $(Metadata)/data.text +# $(Metadata)/phase2.make +# $(Metadata)/pages-by-id.json + +SUPER := $(Metadata)/phase1.make + +######################################################################## +# Create makefile defining global variables about pathnames and rules to +# generate JSON metadata files for each page. +######################################################################## + +$(Metadata)/content.text: $(THIS) + $(info ==> $@) + find $(Content) -type f -a \ + -name '[!_]*.md' -o \ + -name '[!_]*.mkd' -o \ + -name '[!_]*.markdown' \ + > $@ + +$(Metadata)/data.text: $(THIS) + $(info ==> $@) + find $(Data) -name '*.*' > $@ + +# +# Create `$(Metadata)/phase2.make` from `find` output using `make.d/phase2.jq`. +# +$(Metadata)/phase2.make: CONTENT := $(Metadata)/content.text +$(Metadata)/phase2.make: DATA := $(Metadata)/data.text +$(Metadata)/phase2.make: make.d/phase2.jq $(Metadata)/content.text $(Metadata)/data.text $(SUPER) $(THIS) + $(info ==> $@) + jq --raw-input \ + --raw-output \ + --slurp \ + --from-file make.d/phase2.jq \ + --arg DF "$$(<$(DATA))" \ + --arg Content $(Content) \ + --arg Data $(Data) \ + --arg Destination $(Destination) \ + --arg Metadata $(Metadata) \ + < $(CONTENT) > $@ + +ifdef __phase_2 + +# +# Variables used when building JSON files in `$(Metadata)/phase2.make`. +# + +define EXTRACT_FRONT_MATTER = + sed -n -e '1d' \ + -e '/^---$$/q' \ + -e '/^\.\.\.$$/q' \ + -e '/^\#/d' \ + -e 'p' +endef + +define BUILD_PAGE_JSON + yaml2json | \ + jq --sort-keys \ + --arg Source $< \ + --arg Target $@ \ + --arg Metadata $(Metadata) \ + --slurpfile config $(Metadata)/config.json \ + --from-file make.d/phase2_page.jq +endef + +# +# Extra prerequisites for JSON metadata pages. +# + +$(PagesJSON): $(Metadata)/config.json make.d/phase2_page.jq $(THIS) \ +| $$(dir $$@) + +# Content example for `$(Metadata)/phase2.make`: + +# __phase_2 := 1 +# destination_paths := _site/jqt/ _site/jqt/blog/ +# metadata_paths := .meta/pages/ .meta/pages/blog/ +# data_md := .meta/snippets.json +# data_yaml := +# data_json := +# data_csv := +# PagesHTML := _site/jqt/content.html _site/jqt/blog/2017-04-13-hello.html _site/jqt/blog/index.html +# PagesJSON := .meta/pages/content.json .meta/pages/blog/2017-04-13-hello.json .meta/pages/blog/index.json +# .meta/pages/content.json: content/content.md +# $(info ==> $@) +# @$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_PAGE_JSON) > $@ +# ... +# .meta/pages/blog/2017-04-13-hello.json: content/blog/2017-04-13-hello.md +# $(info ==> $@) +# @$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_PAGE_JSON) > $@ +# .meta/pages/blog/index.json: content/blog/index.md +# $(info ==> $@) +# @$(EXTRACT_FRONT_MATTER) < $< | $(BUILD_PAGE_JSON) > $@ + +######################################################################## +# Rules for directories. +######################################################################## + +# Directories starting at `$(Destination)/`. +$(destination_paths): + $(info ==> $@) + mkdir --parents $@ >/dev/null 2>&1 || true + +# Directories starting at `$(Metadata)/pages/`. +$(metadata_paths): + $(info ==> $@) + mkdir --parents $@ >/dev/null 2>&1 || true + +######################################################################## +# Group metadata. +######################################################################## + +# Bundle all pages as a relation (Id => page) +# TODO: use xargs? write $^ to a temp file with file()? +$(Metadata)/pages-by-id.json: $(PagesJSON) + $(info ==> $@) + cat $^ \ + | jq -n 'reduce inputs as $$p ({}; . + {($$p.Id):$$p})' \ + > $@ + +#$(Metadata)/pages-by-id.json: $(PagesJSON) +# $(info ==> $@) +# @jq --slurp 'reduce .[] as $$p ({}; . + {($$p.Id): $$p})' $^ > $@ + +######################################################################## +# Files derived from `$(Data)/*`. +######################################################################## + +DataFiles := + +ifneq (,$(data_md)) +$(data_md): $(Metadata)/%.json : $(Data)/%.md \ +| $(Metadata) + $(info ==> $@) + jqt -T < $< | yaml2json > $@ +DataFiles += $(data_md) +endif + +ifneq (,$(data_yaml)) +$(data_yaml): $(Metadata)/%.json : $(Data)/%.yaml \ +| $(Metadata) + $(info ==> $@) + yaml2json > $@ +DataFiles += $(data_yaml) +endif + +ifneq (,$(data_json)) +$(data_json): $(Metadata)/%.json : $(Data)/%.json \ +| $(Metadata) + $(info ==> $@) + jqt -P json < $< > $@ +DataFiles += $(data_json) +endif + +ifneq (,$(data_csv)) +$(data_csv): $(Metadata)/%.json : $(Data)/%.csv \ +| $(Metadata) + $(info ==> $@) + csv2json < $< > $@ +DataFiles += $(data_csv) +endif + +endif # __phase_2 + +# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/page.jq b/docs/make.d/phase2_page.jq similarity index 58% rename from docs/make.d/page.jq rename to docs/make.d/phase2_page.jq index 16b0080..f1c2b5e 100644 --- a/docs/make.d/page.jq +++ b/docs/make.d/phase2_page.jq @@ -1,14 +1,15 @@ -# Called for each source document, from macro BUILD_JSON in created +# Called for each source document, from macro BUILD_PAGE_JSON in created # phase2.make, to build the JSON file for each page. # # input is page front-matter converted to JSON | -# page.jq +# jq -S -f phase2_page.jq # --arg Source $(Content)/.../PAGE.md # --arg Target $(Metadata)/pages/.../PAGE.json # --arg Metadata $(Metadata) # --slurpfile config $(Metadata)/config.json -# > $(Metadata)/pages/PAGE.json +# > $(Metadata)/pages/.../PAGE.json +# Pathname functions def basename: sub("\\.[^/]+$"; "") ; @@ -23,20 +24,20 @@ def notdir: sub("^.*/"; "") ; -# `$(Metadata)/pages/path/to/page.json` => `path/to/page` -def page_id: - # . as $target - basename | sub($Metadata+"/pages/"; "") -; - # `$(Metadata)/pages/path/to/page.json` => `(../)+` def page_base: # . as $target ("../" * (((. / "/") | length) - 3)) // "" ; +# `$(Metadata)/pages/path/to/page.json` => `path/to/page` +def page_id: + # . as $target + basename | sub($Metadata+"/pages/"; "") +; + # `$(Metadata)/pages/path/to/page.json` => `page` -def page_name: +def page_filename: # . as $target notdir | basename ; @@ -44,7 +45,7 @@ def page_name: # `$(Metadata)/pages/path/to/page.json` => `path/to/` def page_path: # . as $obj - .id | dir + .Id | dir ; # `$(Metadata)/pages/path/to/page.json` => `path/to` @@ -52,25 +53,27 @@ def page_section: #. as $obj if $Target | test("(? `page.html` def page_slug: # . as $obj - .filename + ".html" + .Filename + ".html" ; -def page_date: +# `$(Metadata)/pages/path/to/page.json` => `path/to/page.html` +def page_url: # . as $obj - .filename | - (capture("^(?\\d{4}-\\d{2}-\\d{2})-") | .YMD) - // "" + .Path + .Slug ; -def page_url: +# Extract date if present. +def page_date: # . as $obj - .path + .slug + .Filename | + (capture("^(?\\d{4}-\\d{2}-\\d{2})-") | .YMD) + // "" ; ######################################################################## @@ -78,8 +81,8 @@ def page_url: ######################################################################## def defaults: - # . as $target - page_id as $id + $Target + | page_id as $id | reduce $config[0].defaults[] as $d ({}; if $id | test("^" + $d.idprefix) then . + $d.properties @@ -87,35 +90,37 @@ def defaults: ; def properties: - # . as $target - { id: page_id, - base: page_base, - filename: page_name, - source: $Source + $Target + | { + Base: page_base, + Filename: page_filename, + Source: $Source, + Id: page_id } # in the following order! - | .path = page_path - | .section = page_section - | .date = page_date - | .slug = page_slug - | .url = page_url + | .Path = page_path + | .Section = page_section + | .Slug = page_slug + | .URL = page_url + | .Date = page_date +; + +######################################################################## +# Generate object to be found in `.page`. +######################################################################## + +def merge($k; $d; $f): + if ($k|in($d)) and ($k|in($f)) + then .[$k] = $d[$k] + $f[$k] # merge list + else . end ; -. as $front_matter | -$Target | defaults + properties + $front_matter - -# section slug -# ⊢--^-⊣ ⊢--^----⊣ -#content/extras/name.html -# ⊢--------v⊣ -# ⊢--v--⊣ id -# path - -# path slug -# ⊢-------^-----⊣⊢------^--------⊣ -#content/extras/indexes/name-example.html -# ⊢------------------v------⊣ -# ⊢-----v------⊣ id -# section? or limit to one level? +. as $f # front_matter +| defaults as $d +| properties as $p +| $d * $f + $p +| merge("Datasets"; $d; $f) +| merge("Dependencies"; $d; $f) +| merge("Flags"; $d; $f) # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/docs/make.d/phase3.jq b/docs/make.d/phase3.jq index c6e4b5e..7514fb4 100644 --- a/docs/make.d/phase3.jq +++ b/docs/make.d/phase3.jq @@ -1,54 +1,58 @@ -# Called from page.make to create auxiliar makefile. +######################################################################## +# phase3.jq -- Define contents for `$(Metadata)/phase3.make`. # -# phase3.jq +# jq -r -f phase3.jq # --arg Metadata $(Metadata) # --arg Layouts $(Layouts) # --arg Destination $(Destination) # < $(Metadata)/pages-by-id.json # > $(Metadata)/phase3.make -# Function to cheat vim -def comment: "# vim:syntax=make"; - -def use: - if .use - then " " + (.use | join(" ")) +def dependencies: + if .Dependencies + then " " + (.Dependencies | join(" ")) else "" end ; -def data: - if .data - then " " + (.data | map("-m\(.):$(Metadata)/snippets.json") | join(" ")) +def dataset: + if .Datasets + then " " + (.Datasets | map("-m\(.):\($Metadata)/\(.).json") | join(" ")) else "" end ; def flags: - if .flags - then " " + (.flags | join(" ")) + if .Flags + then " " + (.Flags | join(" ")) else "" end ; def page: - " -mpage:" + $Metadata + "/pages/" + .id + ".json" + " -mpage:\($Metadata)/pages/\(.Id).json" ; def layout: - " " + $Layouts + "/" + .layout + ".html" + " \($Layouts)/\(.Layout).html" ; -# makefile rule for HTML page +# _site/jqt/index.html: content/index.md layouts/page.html content/macros.m content/LINKS.txt content/EXAMPLE.txt +# $(info ==> $@) +# @$(JQT) -d $< -mpage:.meta/pages/index.json layouts/page.html | $(DETAILS) > $@ +# ... +# _site/jqt/blog/2017-04-13-hello.html: content/blog/2017-04-13-hello.md layouts/page.html +# $(info ==> $@) +# @$(JQT) -d $< -mpage:.meta/pages/blog/2017-04-13-hello.json layouts/page.html | $(DETAILS) > $@ def page_rule: - $Destination+"/"+.url+": " + .source + layout + use, + $Destination+"/"+.URL+": " + .Source + layout + dependencies, "\t$(info ==> $@)", - "\t@$(JQT) -d $<" + data + flags + page + layout + " | $(DETAILS) > $@" + "\t@$(JQT) -d $<" + dataset + flags + page + layout + " | $(DETAILS) > $@" ; # # Output makefile # -"__phase_3 := 1", +"__phase_3 := 1\n", (.[] | page_rule), # for each page -comment +"\n# \u0076im:syntax=make" # vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/docs/make.d/phase3.make b/docs/make.d/phase3.make new file mode 100644 index 0000000..11d36b5 --- /dev/null +++ b/docs/make.d/phase3.make @@ -0,0 +1,135 @@ +######################################################################## +# phase3.make -- Define standard rules and rules for HTML pages and nodes. +# +# Rules defined in $(Metadata)/phase3.make: +# all HTML target files +# +# Rules defined in make.d/phase3.make: +# $(Metadata)/phase3.make +# +# Targets defined in make.d/phase3.make: +# all +# build +# clean +# clobber +# dbg.meta +# dbg.fresh +# dbg.touch + +SUPER := $(Metadata)/phase2.make + +######################################################################## +# Create makefile containing rules for all HTML files. +######################################################################## + +# Build rules for each page. +$(Metadata)/phase3.make: $(Metadata)/pages-by-id.json make.d/phase3.jq $(SUPER) $(THIS) + $(info ==> $@) + jq --raw-output \ + --arg Metadata $(Metadata) \ + --arg Layouts $(Layouts) \ + --arg Destination $(Destination) \ + --from-file make.d/phase3.jq \ + < $< > $@ + +ifdef __phase_3 + +# +# Variables used in `$(Metadata)/phase3.make`. +# + +define JQTFLAGS := + -msite:$(Metadata)/site.json \ + -I./ \ + -L$(Metadata) \ + -L$(Blocks) \ + -ifilters +endef + +JQT = jqt $(JQTFLAGS) + +define DETAILS := + sed -e 's/^

<\/p>/
/' \ + -e 's/^

<\/details><\/p>/<\/details>/' \ + -e 's/^

//' \ + -e 's/<\/summary><\/p>/<\/summary>/' +endef + +# +# Extra prerequisites for HTML pages. +# + +$(PagesHTML): $(Destination)/%.html : $(Metadata)/pages/%.json +$(PagesHTML): $(Metadata)/phase3.make $(Blocks)/*/markup.html $(Blocks)/*/*/markup.html \ +| $$(dir $$@) +ifneq (,$(DataFiles)) +$(PagesHTML): $(DataFiles) +endif + +# Content example for `$(Metadata)/phase3.make`: + +# __phase_3 := 1 +# _site/jqt/index.html: content/index.md layouts/page.html content/macros.m content/LINKS.txt content/EXAMPLE.txt +# $(info ==> $@) +# @$(JQT) -d $< -mpage:.meta/pages/index.json layouts/page.html | $(DETAILS) > $@ +# ... +# _site/jqt/blog/2017-04-13-hello.html: content/blog/2017-04-13-hello.md layouts/page.html +# $(info ==> $@) +# @$(JQT) -d $< -mpage:.meta/pages/blog/2017-04-13-hello.json layouts/page.html | $(DETAILS) > $@ +# _site/jqt/blog/index.html: content/blog/index.md layouts/blog.html +# $(info ==> $@) +# @$(JQT) -d $< -mpage:.meta/pages/blog/index.json layouts/blog.html | $(DETAILS) > $@ + +######################################################################## +# Standard targets. +######################################################################## + +.PHONY: clean clobber build + +# Copy Assets after create HTML pages. +all:: $(PagesHTML) + @cp --verbose --recursive --update $(Assets)/* $(Destination) \ + | sed "s/^.*-> ./==> /;s/.$$//" + +# Delete secondary files. +clobber:: ; @rm -rf *~ *.bak *.log + +# Build again all documents. +build: clean all + +######################################################################## +# Debug variations on the `build` target. + +.PHONY: dbg.meta dbg.touch dbg.fresh + +# Touch top file +define TEST_AND_TOUCH.sh + if test -e config.yaml; \ + then touch config.yaml; \ + elif test -e config.json; \ + then touch config.json; \ + else false; \ + fi +endef + +# Force regeneration of all metadata and data files. +dbg.meta: +ifdef MAKE_RESTARTS + @$(MAKE) -s $(DataFiles) VERBOSE=$(VERBOSE) TRACE=$(TRACE) +else + @rm -rf $(Metadata) + @$(MAKE) -s $(DataFiles) VERBOSE=$(VERBOSE) TRACE=$(TRACE) +endif + +# Make after touching `config.{yaml,json}`. +dbg.touch: + @$(TEST_AND_TOUCH.sh) + @$(MAKE) -s all VERBOSE=$(VERBOSE) TRACE=$(TRACE) + +# Clobber and build again. +dbg.fresh: clobber + @$(MAKE) -s all VERBOSE=$(VERBOSE) TRACE=$(TRACE) + +endif # __phase_3 + +# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/sitemap.jq b/docs/make.d/sitemap.jq new file mode 100644 index 0000000..82efacf --- /dev/null +++ b/docs/make.d/sitemap.jq @@ -0,0 +1,24 @@ +######################################################################## +# sitemap.jq -- Generate site map XML file. +# +# jq -r -f sitemap.jq +# --slurpfile site $(Metadata)/site.json +# < $(Metadata)/pages-by-id.json +# > $(Destination)/sitemap.xml + +$site[0].baseurl as $baseurl | + +"", + +"", + +(.[] | + "\t", + "\t\t" + $baseurl + "/" + .url + "", + "\t\t" + .updated + "", + "\t" +), + +"" + +# vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=jq diff --git a/docs/make.d/sitemap.make b/docs/make.d/sitemap.make index e1ea146..52f372c 100644 --- a/docs/make.d/sitemap.make +++ b/docs/make.d/sitemap.make @@ -1,30 +1,17 @@ ######################################################################## -# sitemap.make -# -# Define rules for sitemap. +# sitemap.make -- Define rules for site map. # # Exported rules for: # $(Destination)/sitemap.xml # $(Destination)/sitemap.xml.gz -# XML sitemap -define SITEMAP.jq - $$site[0].baseurl as $$baseurl | \ - " \ - ", \ - (.[] | ( "\t", \ - "\t\t" + $$baseurl + "/" + .url + "", \ - "\t\t" + .updated + "", \ - "\t")), \ - "" -endef - -$(Destination)/sitemap.xml: $(Metadata)/pages-by-id.json $(Metadata)/site.json \ +$(Destination)/sitemap.xml: $(Metadata)/pages-by-id.json $(Metadata)/site.json make.d/sitemap.jq $(THIS) \ | $(Destination) $(info ==> $@) - @jq --raw-output --slurpfile site $(Metadata)/site.json '$(SITEMAP.jq)' < $< > $@ + jq --raw-output \ + --slurpfile site $(Metadata)/site.json \ + --from-file make.d/sitemap.jq \ + < $< > $@ $(Destination)/sitemap.xml.gz: $(Destination)/sitemap.xml $(info ==> $@) diff --git a/docs/make.d/styles.make b/docs/make.d/styles.make index ee2bf1a..7068678 100644 --- a/docs/make.d/styles.make +++ b/docs/make.d/styles.make @@ -1,12 +1,10 @@ ######################################################################## -# styles.make -# -# Generate main CSS stylesheet. +# styles.make -- Generate main CSS stylesheet. # # Exported rules for: # $(Destination)/styles.css -# Styles +# Secondary prerequisites. $(Destination)/styles.css: \ $(Blocks)/*/style.css \ $(Blocks)/*/*/style.css \ @@ -14,10 +12,11 @@ $(Destination)/styles.css: \ $(Styles)/*.m \ $(Styles)/milligram/*.css \ -$(Destination)/styles.css: $(Styles)/main.css +$(Destination)/styles.css: $(Styles)/main.css $(THIS) \ +| $(Destination) $(info ==> $@) @jqt -P CSS-min -I$(Styles) < $< > $@ -all:: $(Destination)/styles.css | $(Destination) +all:: $(Destination)/styles.css # vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/tools.make b/docs/make.d/tools.make index 0714b5e..ac10fd9 100644 --- a/docs/make.d/tools.make +++ b/docs/make.d/tools.make @@ -3,15 +3,11 @@ # # Miscelaneous tools. # -# Parameters: -# vnudir # Defined targets: # help -# lint -# valid ######################################################################## -# Show all targets +# Show all targets. ######################################################################## .PHONY: help @@ -28,26 +24,4 @@ help: | pr --omit-pagination --indent=4 --width=80 --columns=4\ || true -######################################################################## -# HTML 5 validation -######################################################################## - -.PHONY: valid lint - -# Parameter, definable at runtime -vnudir ?= /usr/local/vnu - -# Validation tool -VNU := $(vnudir)/vnu.jar - -# Validation -valid: all - @xmlwf $(Destination)/*.html - @java -jar $(VNU) --errors-only --format gnu $(Destination)/*.html - -# Validation with warnings -lint: all - @xmlwf $(Destination)/*.html - @java -jar $(VNU) --format text $(Destination)/*.html - # vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/styles/milligram/spacing.css b/docs/styles/milligram/spacing.css index 8b2c9b2..e0a7e4b 100644 --- a/docs/styles/milligram/spacing.css +++ b/docs/styles/milligram/spacing.css @@ -18,7 +18,7 @@ // Spacing // –––––––––––––––––––––––––––––––––––––––––––––––––– -&BEM{button}, +.button, button, dd, dt, diff --git a/docs/styles/normalize.css b/docs/styles/normalize.css index b26c100..192eb9c 100644 --- a/docs/styles/normalize.css +++ b/docs/styles/normalize.css @@ -1,17 +1,15 @@ -/*! normalize.css v6.0.0 | MIT License | github.com/necolas/normalize.css */ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ /* Document ========================================================================== */ /** * 1. Correct the line height in all browsers. - * 2. Prevent adjustments of font size after orientation changes in - * IE on Windows Phone and in iOS. + * 2. Prevent adjustments of font size after orientation changes in iOS. */ html { line-height: 1.15; /* 1 */ - -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } @@ -19,15 +17,18 @@ html { ========================================================================== */ /** - * Add the correct display in IE 9-. + * Remove the margin in all browsers. */ -article, -aside, -footer, -header, -nav, -section { +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { display: block; } @@ -44,25 +45,6 @@ h1 { /* Grouping content ========================================================================== */ -/** - * Add the correct display in IE 9-. - * 1. Add the correct display in IE. - */ - -figcaption, -figure, -main { /* 1 */ - display: block; -} - -/** - * Add the correct margin in IE 8. - */ - -figure { - margin: 1em 40px; -} - /** * 1. Add the correct box sizing in Firefox. * 2. Show the overflow in Edge and IE. @@ -88,17 +70,15 @@ pre { ========================================================================== */ /** - * 1. Remove the gray background on active links in IE 10. - * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + * Remove the gray background on active links in IE 10. */ a { - background-color: transparent; /* 1 */ - -webkit-text-decoration-skip: objects; /* 2 */ + background-color: transparent; } /** - * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 1. Remove the bottom border in Chrome 57- * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ @@ -108,15 +88,6 @@ abbr[title] { text-decoration: underline dotted; /* 2 */ } -/** - * Prevent the duplicate application of `bolder` by the next rule in Safari 6. - */ - -b, -strong { - font-weight: inherit; -} - /** * Add the correct font weight in Chrome, Edge, and Safari. */ @@ -138,23 +109,6 @@ samp { font-size: 1em; /* 2 */ } -/** - * Add the correct font style in Android 4.3-. - */ - -dfn { - font-style: italic; -} - -/** - * Add the correct background and color in IE 9-. - */ - -mark { - background-color: #ff0; - color: #000; -} - /** * Add the correct font size in all browsers. */ @@ -188,44 +142,19 @@ sup { ========================================================================== */ /** - * Add the correct display in IE 9-. - */ - -audio, -video { - display: inline-block; -} - -/** - * Add the correct display in iOS 4-7. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Remove the border on images inside links in IE 10-. + * Remove the border on images inside links in IE 10. */ img { border-style: none; } -/** - * Hide the overflow in IE. - */ - -svg:not(:root) { - overflow: hidden; -} - /* Forms ========================================================================== */ /** - * Remove the margin in Firefox and Safari. + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. */ button, @@ -233,7 +162,10 @@ input, optgroup, select, textarea { - margin: 0; + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ } /** @@ -257,16 +189,14 @@ select { /* 1 */ } /** - * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` - * controls in Android 4. - * 2. Correct the inability to style clickable types in iOS and Safari. + * Correct the inability to style clickable types in iOS and Safari. */ button, -html [type="button"], /* 1 */ +[type="button"], [type="reset"], [type="submit"] { - -webkit-appearance: button; /* 2 */ + -webkit-appearance: button; } /** @@ -292,6 +222,14 @@ button:-moz-focusring, outline: 1px dotted ButtonText; } +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + /** * 1. Correct the text wrapping in Edge and IE. * 2. Correct the color inheritance from `fieldset` elements in IE. @@ -309,17 +247,15 @@ legend { } /** - * 1. Add the correct display in IE 9-. - * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + * Add the correct vertical alignment in Chrome, Firefox, and Opera. */ progress { - display: inline-block; /* 1 */ - vertical-align: baseline; /* 2 */ + vertical-align: baseline; } /** - * Remove the default vertical scrollbar in IE. + * Remove the default vertical scrollbar in IE 10+. */ textarea { @@ -327,8 +263,8 @@ textarea { } /** - * 1. Add the correct box sizing in IE 10-. - * 2. Remove the padding in IE 10-. + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. */ [type="checkbox"], @@ -357,10 +293,9 @@ textarea { } /** - * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + * Remove the inner padding in Chrome and Safari on macOS. */ -[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } @@ -379,12 +314,10 @@ textarea { ========================================================================== */ /* - * Add the correct display in IE 9-. - * 1. Add the correct display in Edge, IE, and Firefox. + * Add the correct display in Edge, IE 10+, and Firefox. */ -details, /* 1 */ -menu { +details { display: block; } @@ -396,30 +329,19 @@ summary { display: list-item; } -/* Scripting +/* Misc ========================================================================== */ /** - * Add the correct display in IE 9-. - */ - -canvas { - display: inline-block; -} - -/** - * Add the correct display in IE. + * Add the correct display in IE 10+. */ template { display: none; } -/* Hidden - ========================================================================== */ - /** - * Add the correct display in IE 10-. + * Add the correct display in IE 10. */ [hidden] {