diff --git a/Makefile b/Makefile index 371a3b8..c867eb6 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,14 @@ +######################################################################## # jqt management -# +######################################################################## -project := jqt +# Parameters: +# prefix +# bindir +# datadir +# mandir -######################################################################## -# Parameters (redefine as you like) -######################################################################## +PROJECT := jqt prefix ?= /usr/local bindir ?= $(prefix)/bin @@ -104,18 +107,18 @@ clobber: clean install: [[ -e jqt.1.gz ]] || { cd docs && make ../jqt.1.gz; } test -d $(bindir) || $(SUDO) mkdir --verbose --parents $(bindir) - test -d $(datadir)/$(project) || $(SUDO) mkdir --verbose --parents $(datadir)/$(project) + test -d $(datadir)/$(PROJECT) || $(SUDO) mkdir --verbose --parents $(datadir)/$(PROJECT) test -d $(mandir)/man1 || $(SUDO) mkdir --verbose --parents $(mandir)/man1 $(SUDO) install --verbose --compare --mode 555 bin/* $(bindir) - $(SUDO) install --verbose --compare --mode 644 share/* $(datadir)/$(project) + $(SUDO) install --verbose --compare --mode 644 share/* $(datadir)/$(PROJECT) $(SUDO) install --verbose --compare --mode 644 jqt.1.gz $(mandir)/man1 $(SUDO) sed -i -e "s#DATADIR='.*'#DATADIR='$(datadir)'#" $(bindir)/jqt uninstall: $(SUDO) rm --verbose --force -- $(addprefix $(prefix)/,$(wildcard bin/*)) $(SUDO) rm --verbose --force -- $(mandir)/man1/jqt.1.gz - test -d $(datadir)/$(project) \ - && $(SUDO) rm --verbose --force --recursive $(datadir)/$(project) \ + test -d $(datadir)/$(PROJECT) \ + && $(SUDO) rm --verbose --force --recursive $(datadir)/$(PROJECT) \ || true # Show targets diff --git a/docs/Makefile b/docs/Makefile index 075e212..6dc6aee 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,7 +1,17 @@ -# jqt documentation management +######################################################################## +# Makefile for web site management +# +# Project: jqt +# Author: jordinas@gmail.com +# Published: https://fadado.github.io/jqt/ +######################################################################## +# Make configuration include make.d/prelude.make +# jqt/yummy version +Version := $(shell cat ../VERSION) + ######################################################################## # Globals and setup ######################################################################## @@ -9,11 +19,7 @@ include make.d/prelude.make # Metadata directory Metadata := .yummy -# jqt/yummy version -Version := $(shell cat ../VERSION) - # Load global parameters -# As a side effect config.json and site.json are built -include $(Metadata)/globals.make # Defined in globals.make @@ -34,22 +40,21 @@ ifneq (clobber,$(MAKECMDGOALS)) # Define targets for basic metadata include make.d/config.make -# Defined in metadata.make -# ======================== +# Defined in config.make +# ====================== # Targets: # $(Metadata) # $(Metadata)/config.json # $(Metadata)/site.json # $(Metadata)/globals.make -# $(Metadata)/pages/**.json -# Build metadata from introspection +# Build metadata from filesystem introspection ifdef __globals__ -include make.d/introspect.make +include make.d/pathnames.make endif -# Defined in introspect.make -# ========================== +# Defined in pathnames.make +# ========================= # Variables: # HomePage # Pages @@ -58,8 +63,19 @@ endif # NodesJSON # Targets: # $(Destination) -# all paths at $(Destination) and $(Metadata) -# each page from his metadata +# all paths starting at $(Destination) and $(Metadata) + +# Build metadata from files front-matter +ifdef __globals__ +include make.d/front-matter.make +endif + +# Defined in front-matter.make +# ============================ +# Targets: +# JSON metadata files at $(Metadata)/pages/ and $(Metadata)/nodes/ +# Additional dependencies defined: +# each page and node from his metadata endif # not clobbering @@ -67,12 +83,12 @@ endif # not clobbering # # If `__globals__` is not defined because `globals.make` does not exists, after # this point most of the file is ignored, but `globals.make` is built because a -# rule exists in the file `metadata.make` (only if the target is not `clobber`). +# rule exists in the file `config.make` (only if the target is not `clobber`). # Then `Makefile` is restarted, `MAKE_RESTARTS` will be equal to 1, # `globals.make` is loaded and `__globals__` is defined. ######################################################################## -# jqt command with options +# Commands ######################################################################## ifdef __globals__ @@ -144,7 +160,7 @@ other_pages := $(filter-out $(HomePage),$(Pages)) $(other_pages): \ $(Content)/FLOW.txt \ $(Content)/opt/*.txt \ - $(Layouts)/page.html \ + $(Layouts)/default.html \ $(HomePage) \ $(Destination)/structure.html: \ @@ -184,11 +200,11 @@ $(Destination)/$(1).html: $(Content)/$(1).md $(Layouts)/$(2).html \ @$(JQT) -d $$< $(Layouts)/$(2).html | $(DETAILS) > $$@ endef -# TODO: instrospect -Home := index -Other := content data engine structure -$(eval $(call Target,$(Home),page)) -$(foreach p,$(Other),$(eval $(call Target,$(p),page-toc))) +# TODO: introspect +home := index +other := content data engine structure +$(eval $(call Target,$(home),page)) +$(foreach p,$(other),$(eval $(call Target,$(p),page-toc))) # CSS stylesheet $(Destination)/styles.css: $(Styles)/page.css @@ -220,32 +236,30 @@ endif # __globals__ ifndef __globals__ -clobber: ; +# If clobbering a not initialized project do nothing +clobber: ;@: else +# Delete generated publications clean: @rm -rf $(Destination)/* $(ManPage) +# Delete all generated files and directories clobber: @rm -rf $(Destination) $(ManPage) $(Metadata) +# Build again all documents build: clean all -endif # __globals__ - -######################################################################## -# External utilities -######################################################################## - -ifdef __globals__ +# Build again all documents and metadata +xbuild: + @touch config.yaml + @$(MAKE) -s all # help and other targets include make.d/tools.make -# HTML 5 validation -include make.d/vnu.make - endif # __globals__ # vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/blocks/default.html b/docs/blocks/default.html new file mode 100644 index 0000000..ddebfbe --- /dev/null +++ b/docs/blocks/default.html @@ -0,0 +1,40 @@ +<# Top-level page markup #>& + + + + +<# + # Meta elements + #> + +<# Document title and related metadata #> + jqt · {{.page.title}} + + + +<# More metadata #> + + +<# Presentation #> + + + + {{.page._highlight}} + +<# + # Document body + #> + + <%include blocks/header/markup.html>& +<%ifndef BODY_BLOCK>& + <%error Descendent layout must define BODY_BLOCK macro> +<%else>& + <%call BODY_BLOCK> +<%endif>& + <%include blocks/footer/markup.html>& + <%partial analytics 'UA-82432866-1'>& + + +<# +vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=html +#> diff --git a/docs/blocks/node.html b/docs/blocks/node.html new file mode 100644 index 0000000..5eaa1d3 --- /dev/null +++ b/docs/blocks/node.html @@ -0,0 +1,14 @@ +<# Default node #>& +<# + # Main page block for content + #>& +<%define BODY_BLOCK + <%include blocks/body/markup.html> +>& +<# + # Inherit default layout + #>& +<%include blocks/default.html>& +<# +vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=perl +#>& diff --git a/docs/blocks/page-toc.html b/docs/blocks/page-toc.html index 9e7cbc9..3d53000 100644 --- a/docs/blocks/page-toc.html +++ b/docs/blocks/page-toc.html @@ -8,7 +8,7 @@ <# # Inherit default layout #>& -<%include blocks/page.html>& +<%include blocks/default.html>& <# vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=perl #>& diff --git a/docs/blocks/page.html b/docs/blocks/page.html index df26eeb..548c693 100644 --- a/docs/blocks/page.html +++ b/docs/blocks/page.html @@ -1,40 +1,14 @@ -<# Top-level page markup #>& - - - - +<# Default page #>& <# - # Meta elements - #> - -<# Document title and related metadata #> - jqt · {{.page.title}} - - - -<# More metadata #> - - -<# Presentation #> - - - - {{.page._highlight}} - + # Main page block for content + #>& +<%define BODY_BLOCK + <%include blocks/body/markup.html> +>& <# - # Document body - #> - - <%include blocks/header/markup.html>& -<%ifndef BODY_BLOCK>& - <%include blocks/body/markup.html>& -<%else>& - <%call BODY_BLOCK> -<%endif>& - <%include blocks/footer/markup.html>& - <%partial analytics 'UA-82432866-1'>& - - + # Inherit default layout + #>& +<%include blocks/default.html>& <# -vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=html -#> +vim:ts=2:sw=2:ai:et:fileencoding=utf8:syntax=perl +#>& diff --git a/docs/config.yaml b/docs/config.yaml index 7388378..70d83b3 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -28,6 +28,8 @@ Layouts: ./blocks # shared space # Site parameters # +baseurl: https://fadado.github.io/jqt + title: jqt, the jq template engine baseURL: https://fadado.github.com/jqt/ lang: &lang en diff --git a/docs/make.d/config.make b/docs/make.d/config.make index e8e92cf..4ca5d37 100644 --- a/docs/make.d/config.make +++ b/docs/make.d/config.make @@ -1,5 +1,5 @@ ######################################################################## -# Configuration +# Build files derived from user defined configuration ######################################################################## # Imported variables: @@ -18,9 +18,9 @@ $(Metadata): $(info ==> $@) @mkdir --parents $@ >/dev/null 2>&1 || true -# +######################################################################## # Target files -# +######################################################################## # Create $(Metadata)/config.json # Input is user defined config.yaml or config.json. @@ -45,7 +45,7 @@ $(error Configuration file not found) endif # Globals definition to mix with config.json -define m_SITE_JSON := +define m_SITE_JSON.jq := del(.defaults) \ | . + { \ Destination: (.Destination // "./_site"), \ @@ -61,10 +61,10 @@ endef $(Metadata)/site.json: $(Metadata)/config.json $(info ==> $@) - @jq --sort-keys '$(m_SITE_JSON)' < $< > $@ + @jq --sort-keys '$(m_SITE_JSON.jq)' < $< > $@ # Variables to define in globals.make -define m_GLOBALS_MAKE := +define m_GLOBALS_MAKE.jq := "__globals__ := 1", \ "Assets := " + .Assets, \ "Blocks := " + .Blocks, \ @@ -79,6 +79,6 @@ endef # Create globals.make $(Metadata)/globals.make: $(Metadata)/site.json $(info ==> $@) - @jq --raw-output '$(m_GLOBALS_MAKE)' < $< > $@ + @jq --raw-output '$(m_GLOBALS_MAKE.jq)' < $< > $@ # vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/front-matter.make b/docs/make.d/front-matter.make new file mode 100644 index 0000000..1dccf08 --- /dev/null +++ b/docs/make.d/front-matter.make @@ -0,0 +1,122 @@ +######################################################################## +# Collect metadata in files front-matter +######################################################################## + +# Imported variables: +# Metadata +# Content +# Exported targets: +# JSON metadata files for pages and nodes + +######################################################################## +# Collect metadata for pages +######################################################################## + +# $(Metadata)/pages/path/to/page.json ==> path/to/page +define i_page_id = +$(subst $(Metadata)/pages/,,$(basename $1)) +endef + +# $(Metadata)/pages/path/to/page.json ==> ../+ +define i_page_base = +$(patsubst ../../%,%,$(subst $(space),$(empty),$(patsubst %,../,$(subst /,$(space),$1)))) +endef + +# $(Metadata)/pages/path/to/page.json ==> page +define i_page_name = +$(basename $(notdir $1)) +endef + +# $(Metadata)/pages/path/to/page.json ==> path/to/page.html +define i_page_url = +$(call i_page_id,$1).html +endef + +# $(Metadata)/pages/path/to/page.json ==> path/to/ +define i_page_path = +$(dir $(call i_page_id,$1)) +endef + +# $(Metadata)/pages/path/to/page.json ==> path/to +define i_page_section = +$(patsubst %/,%,$(call i_page_path,$1)) +endef + +# . is a MarkDown file front matter +define i_PAGE_JSON.jq = + . + { \ + id: "$(call i_page_id,$1)", \ + base: "$(call i_page_base,$1)", \ + filename: "$(call i_page_name,$1)", \ + path: "$(call i_page_path,$1)", \ + url: "$(call i_page_url,$1)", \ + section: "$(call i_page_section,$1)", \ + isnode: false, \ + ispage: true \ + } as $$page | \ + $$config[0].defaults as $$defaults | \ + reduce $$defaults[] as $$d \ + ({}; if "$(call i_page_id,$1)" | test("^" + $$d.idprefix) \ + then . + $$d.properties \ + else . end) + $$page +endef + +# Extract YAML front matter +define i_extract_front_matter = + sed -n -e '1d' \ + -e '/^---$$/q' \ + -e '/^\.\.\.$$/q' \ + -e '/^\#/d' \ + -e 'p' +endef + +# Build metadata for pages +$(PagesJSON): $(Metadata)/config.json +$(PagesJSON): $(Metadata)/pages/%.json : $(Content)/%.md + $(info ==> $@) + @$(i_extract_front_matter) < $< \ + | yaml2json \ + | jq --sort-keys \ + --slurpfile config $(Metadata)/config.json \ + '$(call i_PAGE_JSON.jq,$@)' > $@ + +######################################################################## +# Collect metadata for nodes +######################################################################## + +define i_node_id = +$(subst $(Metadata)/nodes/,$(empty),$(basename $1))/index +endef + +# . is $(Metadata)/config.json +define i_NODE_JSON.jq = + { id: "$(call i_node_id,$1)", \ + base: "$(call i_page_base,$1)", \ + title: "$(call md_page_name,$1)", \ + filename: "$(call i_page_name,$1)", \ + path: "$(call i_page_path,$1)", \ + url: "$(call i_page_url,$1)", \ + section: "$(call i_page_section,$1)", \ + date: (now | todateiso8601), \ + ishome: false, \ + isnode: true, \ + ispage: false \ + } as $$node | \ + reduce .defaults[] as $$d \ + ({}; if "$(call i_node_id,$1)" | test("^" + $$d.idprefix) \ + then . + $$d.properties \ + else . end) + $$node +endef + +# Build metadata for nodes +$(NodesJSON): $(Metadata)/config.json + $(info ==> $@) + jq --sort-keys '$(call i_NODE_JSON.jq,$@)' < $< > $@ + +######################################################################### +# Test +.PHONY: front-matter +front-matter: + @: + +# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/make.d/introspect.make b/docs/make.d/pathnames.make similarity index 55% rename from docs/make.d/introspect.make rename to docs/make.d/pathnames.make index 61d6c94..b3b0d8e 100644 --- a/docs/make.d/introspect.make +++ b/docs/make.d/pathnames.make @@ -1,5 +1,5 @@ ######################################################################## -# Introspection of filesystem +# Filesystem introspection ######################################################################## # Imported variables: @@ -15,9 +15,9 @@ # Exported targets: # $(Destination) # all paths at $(Destination) and $(Metadata) -# Additional dependencies -# each page from his metadata -# each node from his metadata +# Additional dependencies defined: +# each HTML page from his metadata and directory +# each HTML node from his metadata and directory # Markdown documents found in the filesystem (only .md extensions) i_documents := $(sort $(shell find $(Content) -type f -a -name '*.md')) @@ -34,9 +34,9 @@ i_paths_metadata_nodes := $(patsubst $(Content)%,$(Metadata)/nodes%,$(i_paths)) # Paths to pages at $(Metadata) i_paths_metadata_pages := $(patsubst $(Content)%,$(Metadata)/pages%,$(i_paths)) -# +######################################################################## # Targets for directories -# +######################################################################## # Destination directory $(Destination): @@ -58,9 +58,9 @@ $(i_paths_metadata_nodes): $(info ==> $@) @mkdir --parents $@ >/dev/null 2>&1 || true -# +######################################################################## # Exported variables -# +######################################################################## # Home page HomePage := $(Destination)/index.html @@ -77,88 +77,25 @@ Nodes := $(addsuffix index.html,$(i_paths_destination)) # JSON for each node to generate at $(Metadata)/nodes NodesJSON := $(call rest,$(patsubst %/,%.json,$(i_paths_metadata_nodes))) -# -# Pages metadata -# - -# $(Metadata)/pages/path/to/page.json ==> path/to/page -define i_page_id = -$(subst $(Metadata)/pages/,,$(basename $1)) -endef - -# $(Metadata)/pages/path/to/page.json ==> ../+ -define i_page_base = -$(patsubst ../../%,%,$(subst $(space),$(empty),$(patsubst %,../,$(subst /,$(space),$1)))) -endef - -# $(Metadata)/pages/path/to/page.json ==> page -define i_page_name = -$(basename $(notdir $1)) -endef - -# $(Metadata)/pages/path/to/page.json ==> path/to/page.html -define i_page_url = -$(call i_page_id,$1).html -endef - -# $(Metadata)/pages/path/to/page.json ==> path/to/ -define i_page_path = -$(dir $(call i_page_id,$1)) -endef - -# $(Metadata)/pages/path/to/page.json ==> path/to -define i_page_section = -$(patsubst %/,%,$(call i_page_path,$1)) -endef - -# . is a MarkDown file front matter -define i_PAGE_JSON = - . + { \ - "id": "$(call i_page_id,$1)", \ - "base": "$(call i_page_base,$1)", \ - "filename": "$(call i_page_name,$1)", \ - "path": "$(call i_page_path,$1)", \ - "url": "$(call i_page_url,$1)", \ - "section": "$(call i_page_section,$1)", \ - "isnode": false, \ - "ispage": true \ - } as $$page | \ - $$config[0].defaults as $$defaults | \ - reduce $$defaults[] as $$d \ - ({}; if "$(call i_page_id,$1)" | test("^" + $$d.idprefix) \ - then . + $$d.properties \ - else . end) + $$page -endef - -# Extract YAML front matter -define i_extract_front_matter - sed -n -e '1d' \ - -e '/^---$$/q' \ - -e '/^\.\.\.$$/q' \ - -e '/^\#/d' \ - -e 'p' -endef - -# Build metadata for a page -$(PagesJSON): $(Metadata)/pages/%.json : $(Content)/%.md \ -| $$(dir $$@) - $(info ==> $@) - @$(i_extract_front_matter) < $< \ - | yaml2json \ - | jq --sort-keys \ - --slurpfile config $(Metadata)/config.json \ - '$(call i_PAGE_JSON,$@)' > $@ +######################################################################## +# Dependencies +######################################################################## -# Each page depend on his metadata +# Each HTML file depends on his metadata and directory $(Pages): $(Destination)/%.html : $(Metadata)/pages/%.json +$(Pages): | $$(dir $$@) + +$(Nodes): $(Destination)/%.html : $(Metadata)/nodes/%.json +$(Nodes): | $$(dir $$@) -# Each node depend on his metadata -#$(Nodes): $(Destination)/%.html : $(Metadata)/nodes/%.json +# Each JSON file depends on his directory +$(PagesJSON): | $$(dir $$@) +$(NodesJSON): | $$(dir $$@) ######################################################################### # Test -.PHONY: intro -intro: +.PHONY: introspect +introspect: @echo 'Metadata: $(Metadata)' @echo 'Content: $(Content)' @echo 'Destination: $(Destination)' diff --git a/docs/make.d/prelude.make b/docs/make.d/prelude.make index da7007f..be02c1e 100644 --- a/docs/make.d/prelude.make +++ b/docs/make.d/prelude.make @@ -1,5 +1,5 @@ ######################################################################## -# Prelude +# The project prelude: common module available in all makefile modules ######################################################################## # Exported macros: @@ -9,9 +9,9 @@ # rest # filename -# +######################################################################## # Prerequisites -# +######################################################################## # We are using some of the newest GNU Make features... so require GNU # Make version >= 3.82 @@ -40,9 +40,9 @@ $(error Target "clobber" must be alone) endif endif -# +######################################################################## # Make configuration -# +######################################################################## # Disable builtins. MAKEFLAGS += --no-builtin-rules @@ -77,9 +77,9 @@ SHELL := /bin/bash # Enable a second expansion of the prerequisites .SECONDEXPANSION: -# +######################################################################## # Common macros -# +######################################################################## # Hacks for string manipulation comma := , diff --git a/docs/make.d/tools.make b/docs/make.d/tools.make index c9fbaae..86c4b91 100644 --- a/docs/make.d/tools.make +++ b/docs/make.d/tools.make @@ -1,9 +1,14 @@ +######################################################################## # Miscelaneous tools +######################################################################## + +######################################################################## +# Show targets +######################################################################## # Exported targets: # help -# Show targets .PHONY: help help: @echo 'Usage: make TARGET [parameter=value...]' @@ -15,4 +20,34 @@ help: | sed 's/:\+$$//' \ | pr --omit-pagination --indent=4 --width=80 --columns=4 +######################################################################## +# HTML 5 validation +######################################################################## + +# Parameters: +# vnudir +# Imported variables: +# Destination +# Exported targets: +# valid +# lint + +.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/make.d/vnu.make b/docs/make.d/vnu.make deleted file mode 100644 index cc707ee..0000000 --- a/docs/make.d/vnu.make +++ /dev/null @@ -1,23 +0,0 @@ -# HTML 5 validation - -# Imported variables: -# Destination -# Exported targets: -# valid -# lint - -.PHONY: valid lint - -VNU := /usr/local/vnu/vnu.jar - -# Validation using vnu.jar -valid: all - @xmlwf $(Destination)/*.html - @java -jar $(VNU) --errors-only --format gnu $(Destination)/*.html - -# Validation with warnings using vnu.jar -lint: all - @xmlwf $(Destination)/*.html - @java -jar $(VNU) --format text $(Destination)/*.html - -# vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make