+++ /dev/null
-# SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
-# SPDX-License-Identifier: CC0-1.0
-
-[submodule "LesML"]
- path = .ππ
- url = https://git.ladys.computer/LesML.git
-[submodule "δΉ¦η€Ύ"]
- path = .β©π°
- url = https://git.ladys.computer/Shushe.git
+++ /dev/null
-Subproject commit 84e79eb9ea63d28dfa93dfe7d3acd457905cc53e
+++ /dev/null
-Subproject commit 608a1404e5b5f27df451d8a4c50c1c356a39a8d5
-# SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
+# SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
# SPDX-License-Identifier: MPL-2.0
SHELL = /bin/sh
ββ°βββββββββββββββββββββββββββββββ― β
ββ¬ ΒΆ Prerequisites ββββββββββββββββββββββββββββββββββββββββββββ¬β’
ββ ββ
-ββ Requires GΒ·NΒ·U Make, at least version 3.81, and all of the ββ
-ββ requirements of β©π° δΉ¦η€Ύ, which is included as a git ββ
-ββ submodule. Run `make help-shusheΒ΄ for more information. ββ
-ββ°βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ―β
-ββ¬ ΒΆ Usage ββββββββββββββββββββββββββββββββββββββββββββββββββββ¬β’
-ββ ββ
-ββ β’ `make allΒ΄ (default): Compile, but do not install, all ββ
-ββ files. ββ
-ββ ββ
-ββ β’ `make cleanΒ΄: Remove `BUILDDIRΒ΄. ββ
+ββ Requires GΒ·NΒ·U Make, at least version 3.81. Otherwise, ββ
+ββ only programs specified by Posix are required. The full ββ
+ββ list of program requirements is as follows :β ββ
ββ ββ
-ββ β’ `make cleanΒ΄: Remove `BUILDDIRΒ΄. ββ
+ββ β’ awk ββ
+ββ β’ mkdir ββ
+ββ β’ od ββ
+ββ β’ printf ββ
+ββ β’ sed ββ
+ββ β’ test ββ
+ββ β’ tr ββ
+ββ β’ xargs ββ
ββ ββ
-ββ β’ `make goneΒ΄: Remove `BUILDDIRΒ΄ and installed files. ββ
-ββ ββ
-ββ β’ `make helpΒ΄: Print this message. ββ
-ββ ββ
-ββ β’ `make installΒ΄: Compile all files and install in ββ
-ββ `DESTDIRΒ΄. ββ
+ββ In all cases, you can supply your own version of any ββ
+ββ program `programΒ΄ by overriding the corresponding variable ββ
+ββ `PROGRAMΒ΄ when calling Make. ββ
+ββ°βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ―β
+ββ¬ ΒΆ Usage ββββββββββββββββββββββββββββββββββββββββββββββββββββ¬β’
ββ ββ
-ββ β’ `make listΒ΄: List all recognized source files and their ββ
-ββ classification (including media type and dependencies). ββ
+ββ β’ `make help (default)Β΄: Print this message. ββ
ββ ββ
-ββ β’ `make uninstallΒ΄: Remove installed files, but not ββ
-ββ `BUILDDIRΒ΄. ββ
+ββ β’ `make wrmgΒ΄: Output a random unused identifier. ββ
ββ ββ
ββ β’ `make +β¨CATEGORYβ©Β΄: Create a new entry in β¨CATEGORYβ© and ββ
ββ output its path. ββ
ββ°βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ―β
ββ¬ ΒΆ Copyright & License ββββββββββββββββββββββββββββββββββββββ¬β’
ββ ββ
-ββ Copyright Β© 2024 Lady [@ Ladys Computer]. ββ
+ββ Copyright Β© 2024β2025 Lady [@ Ladys Computer]. ββ
ββ ββ
ββ This Source Code Form is subject to the terms of the ββ
ββ Mozilla Public License, v 2.0. If a copy of the MΒ·PΒ·L was ββ
# Programs needed to run this makeΒ·file.
#
# If these are not installed on your computer, or you need to use a different implementation, you can override the appropriate variable.
-#
-# See also the documentation for β©π° δΉ¦η€Ύ, which specifies additional programs.
AWK := awk
-CAT := cat
-GIT := git
MKDIR := mkdir
OD := od
PRINTF := printf
-RM := rm
SED := sed
TEST := test
TR := tr
XARGS := xargs
-XMLCATALOG := xmlcatalog
# The directory which contains the codex entries and related metadata.
-SRCDIR := entries
-
-# The directory which contains additional assets for the codex generator.
-ASSETDIR := assets
-
-# The directory which contains includes for additional assets for the codex generator.
-ASSETINCLUDEDIR := $(ASSETDIR)/includes
-
-# The directory in which to generate temporary buildfiles.
-BUILDDIR := build
-
-# The directory into which to output files on `makeΒ΄.
-DESTDIR := public
+SRCDIR := data/codex
-# The location of this Makefile, relative to the current working directory.
-#
-# It is expected that other files packaged as a part of πͺΎπ° Caudex can also be found in this directory.
-#
-# By default, this is inferred from the variable `MAKEFILE_LISTΒ΄.
-THISDIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
-
-# Extra magic files to forward to β©π° δΉ¦η€Ύ.
-#
-# Your computer probably has several already installed at `/usr/share/file/magicΒ΄.
-EXTRAMAGIC :=
-
-# Extra parsers to forward to β©π° δΉ¦η€Ύ.
-#
-# Which parsers are provided will influence which kinds of files are recognized as plaintext.
-EXTRAPARSERS :=
-
-# Extra transforms to forward to β©π° δΉ¦η€Ύ.
-EXTRATRANSFORMS :=
-
-# A description of the current git revision of πͺΎπ° Caudex.
-THISREV := $(shell cd $(THISDIR); $(GIT) describe 2> /dev/null || $(GIT) rev-parse HEAD 2> /dev/null || true)
-
-# Variables to communicate to further calls to Make.
-#
-# By default, `MAKEOVERRIDESΒ΄ contains all variable overrides specified on the commandline.
-# However, some values are specific to πͺΎπ° Caudex and may have different meaning in other makeΒ·files; filter these out.
-MAKEOVERRIDES := $(filter-out SRCDIR=% ASSETDIR=% BUILDDIR=% DESTDIR=% THISDIR=% EXTRAMAGIC=% EXTRAPARSERS=% EXTRATRANSFORMS=% THISREV=%,$(MAKEOVERRIDES))
-
-# The location of ππ LesΒ·MΒ·L.
-LESML := $(THISDIR)/.ππ
-
-# The location of β©π° δΉ¦η€Ύ.
-SHUSHE := $(THISDIR)/.β©π°
+# The default language for new entries.
+DOCLANG := en
# Set to a nonΒ·empty value to print all commands as they run.
VERBOSE :=
# The default target for this makefile.
-.DEFAULT_GOAL := all
+.DEFAULT_GOAL := help
# β Β§ BEGIN MAKEΒ·FILE βββββββββββββββββββββββββββββββββββββββββββββββββ
# Outputs an `@Β΄ to silence rules, unless `VERBOSEΒ΄ is nonempty.
override silent := $(if $(VERBOSE),,@)
-# The list of categories, determined by the set of directories in `SRCDIRΒ΄ with corresponding metadata files.
-override categories := $(sort $(patsubst $(SRCDIR)/%/@,%,$(wildcard $(SRCDIR)/*/@)))
-
-# (callable) The set of file locations for the entries of the provided categories.
-override entriesforcategory = $(sort $(foreach category,$1,$(wildcard $(SRCDIR)/$(category)/???-????) $(wildcard $(SRCDIR)/$(category)/???-????,*)))
-
# A random WΒ·RΒ·MΒ·G(Β·like) baseβΉ32 identifier.
#
# This variable returns a different value each time it is referenced.
# Use `foreachΒ΄ to save the value for repeated usage.
#
# This variable recursively calls itself to ensure there is no existing entry with the resulting identifier.
-override wrmg = $(foreach attempt,$(shell $(OD) -t u4 -N 4 /dev/random | $(SED) 's/^[0-9]* *//' | $(TR) -d ' \n' | $(AWK) 'BEGIN{chars="0123456789ABCDEFGHJKMNPQRSTVWXYZ&~@=U"}{d=32^5;r=$$0%(32^6);printf("%s",substr(chars,r%37,1));while(d>0){printf("%s", substr(chars,int(r/d),1));if(d==32^4)printf("%s", "-");r%=d;d=int(d/32)}}'),$(if $(wildcard $(SRCDIR)/*/($(attempt))*),$(call wrmg),$(attempt)))
-
-# (callable) Returns the identifiers of the provided entries.
-override identifier = $(shell $(PRINTF) '%s\n' $(call quote,$1) | $(TR) ' ' '\n' | $(SED) 's/^\(.*[/]\)\{0,1\}\(.\{3\}-.\{4\}\)\(,[^/]*\)\{0,1\}$$/\2/')
-
-# Output locations for compiled catalog files for categories.
-override categorycatalogs := $(patsubst %,$(BUILDDIR)/catalogs/categories/%/index,$(categories))
-
-# Output locations for compiled catalog files for entries.
-override entrycatalogs := $(foreach entry,$(call entriesforcategory,$(categories)),$(patsubst $(SRCDIR)/%,$(BUILDDIR)/catalogs/entries/%,$(entry)))
-
-# Output locations for all compiled catalog files.
-override allcatalogs := $(BUILDDIR)/catalogs/indices/index $(BUILDDIR)/catalogs/indices/fullindex $(categorycatalogs) $(entrycatalogs)
-
-# (overridable) Options to pass to β©π° δΉ¦η€Ύ.
-override shusheopts := SRCDIR=$(call quote,$(if $(wildcard $(ASSETDIR)),$(ASSETDIR),) $(if $(entrycatalogs),$(BUILDDIR)/catalogs/entries,) $(BUILDDIR)/catalogs/indices) BUILDDIR=$(call quote,$(BUILDDIR)/β©π°) INCLUDEDIR=$(call quote,$(SRCDIR) $(if $(wildcard $(ASSETINCLUDEDIR)),$(ASSETINCLUDEDIR),) $(if $(categorycatalogs),$(BUILDDIR)/catalogs/categories,)) DESTDIR=$(call quote,$(DESTDIR)) EXTRAMAGIC=$(call quote,$(sort $(patsubst ./%,%,$(wildcard $(THISDIR)/magic/*)) $(LESML)/magic $(EXTRAMAGIC))) EXTRAPARSERS=$(call quote,$(sort $(patsubst ./%,%,$(wildcard $(THISDIR)/parsers/*.xslt)) $(LESML)/parser.xslt $(EXTRAPARSERS))) EXTRATRANSFORMS=$(call quote,$(sort $(patsubst ./%,%,$(wildcard $(THISDIR)/transforms/*.xslt)) $(EXTRATRANSFORMS)))
+#
+# The checksum digits differ from WΒ·RΒ·MΒ·G to get around limitations in Make and to enable usage withΒ·in a UΒ·RΒ·N.
+override wrmg = $(foreach attempt,$(shell $(OD) -t u4 -N 4 /dev/random | $(SED) 's/^[0-9]* *//' | $(TR) -d ' \n' | $(AWK) 'BEGIN{chars="0123456789ABCDEFGHJKMNPQRSTVWXYZ+!@=U"}{d=32^5;r=$$0%(32^6);printf("%s",substr(chars,r%37,1));while(d>0){printf("%s", substr(chars,int(r/d),1));if(d==32^4)printf("%s", "-");r%=d;d=int(d/32)}}'),$(if $(wildcard $(SRCDIR)/*/$(attempt)*),$(call wrmg),$(attempt)))
# β ΒΆ Recipe Variable Definitions βββββββββββββββββββββββββββββββββββββ
# (callable) Check to see if the given directory exists and create it if not.
override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(call quote,$1); fi
-# (callable) Test to see if the file provided by the first argument exists and the dependencies provided by the third argument matches the value in the file corresponding to the second argument in `$(BUILDDIR)/lastprereqsΒ΄.
-# If not, return the fourth argument, plus an additional rule to save the new prerequisites.
-#
-# β» If the third argument is empty, the fourth argument is always returned.
-override makeandsavedeps = $(if $(or $(if $3,,1),$(if $(wildcard $1),,1),$(subst $(shell $(CAT) $(call quote,$(BUILDDIR)/lastdeps/$2) 2> /dev/null || true),,$3)),$4$(newline)$(silent)$(call ensuredirectory,$(BUILDDIR)/lastdeps)$(newline)$(silent)$(PRINTF) '%s\n' $(call quote,$3) > $(call quote,$(BUILDDIR)/lastdeps/$2),)
-
-# (callable) Make the catalog for the provided category.
-override define makecategorycatalog
-@$(PRINTF) '%s\n' $(call quote,Generating catalog for category `$1Β΄β¦)
-$(silent)$(call ensuredirectory,$(BUILDDIR)/catalogs/categories/$1)
-$(silent)$(XMLCATALOG) --create --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)
-$(silent)$(XMLCATALOG) --add uri '?' 'about:category' --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)
-$(silent)$(XMLCATALOG) --add uri '@' $(call quote,$1/@) --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)
-$(foreach entry,$(call entriesforcategory,$1),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call identifier,$(entry))) $(call quote,$(patsubst $(SRCDIR)/%,%,$(entry))) --noout $(call quote,$(BUILDDIR)/catalogs/categories/$1/index)$(newline))
-endef
-
-# (callable) Make the catalog for the dynamic or static index.
-override define makeindexcatalog
-@$(PRINTF) '%s\n' 'Generating $(if $1,static,dynamic) catalog indexβ¦'
-$(silent)$(call ensuredirectory,$(BUILDDIR)/catalogs/indices)
-$(silent)$(XMLCATALOG) --create --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
-$(silent)$(XMLCATALOG) --add uri '.' '$(if $1,standalone,index).xhtml' --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
-$(silent)$(XMLCATALOG) --add uri '?' 'about:$(if $1,full,)index' --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
-$(silent)$(XMLCATALOG) --add uri '@' '@' --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)
-$(foreach category,$(categories),$(silent)$(XMLCATALOG) --add uri $(call quote,$(category)) $(call quote,$(category)/index) --noout $(call quote,$(BUILDDIR)/catalogs/indices/$(if $1,full,)index)$(newline))
-endef
-
-# β ΒΆ β©π° δΉ¦η€Ύ Targets ββββββββββββββββββββββββββββββββββββββββββββββ
-
-# Targets to forward to β©π° δΉ¦η€Ύ.
-all install list uninstall : $(SHUSHE)/GNUmakefile catalogs
- $(silent)$(MAKE) -f $(call quote,$<) $(call quote,$@) $(shusheopts)
-%-shushe : $(SHUSHE)/GNUmakefile FORCE
- $(silent)$(MAKE) -f $(call quote,$<) $(call quote,$*) $(shusheopts)
-build/β©π°/% : $(SHUSHE)/GNUmakefile catalogs FORCE
- $(SILENT)$(MAKE) -f $(call quote,$<) $(call quote,$@) $(shusheopts)
-public/% : $(SHUSHE)/GNUmakefile catalogs FORCE
- $(SILENT)$(MAKE) -f $(call quote,$<) $(call quote,$@) $(shusheopts)
-
# β ΒΆ Phony Targets βββββββββββββββββββββββββββββββββββββββββββββββββββ
-# Generate all catalogs, then remove any which no longer have corresponding source files.
-catalogs : $(allcatalogs)
- @$(PRINTF) '%s\n' 'Removing any outdated catalogsβ¦'
- $(foreach deletedcategory,$(filter-out $(categorycatalogs),$(wildcard $(BUILDDIR)/catalogs/categories/*/index)),@$(PRINTF) '%s\n' $(call quote,Removing `$(patsubst $(BUILDDIR)/catalogs/categories/%/index,%,$(deletedcategory))Β΄β¦)$(newline)$(silent)$(RM) -rf $(call quote,./$(dir $(deletedcategory)))$(newline)$(silent)$(RM) -rf $(call quote,./$(patsubst $(BUILDDIR)/catalogs/categories/%,$(BUILDDIR)/catalogs/entries/%,$(dir $(deletedcategory))))$(newline))
- $(foreach deletedentry,$(filter-out $(entrycatalogs),$(wildcard $(BUILDDIR)/catalogs/entries/*/*)),@$(PRINTF) '%s\n' $(call quote,Removing `$(patsubst $(BUILDDIR)/catalogs/entries/%,%,$(deletedentry))Β΄β¦)$(newline)$(silent)$(RM) $(call quote,./$(deletedentry))$(newline))
-
-# Destroy buildfiles.
-clean:
- $(if $(BUILDDIR),$(silent)$(RM) -rf $(call quote,$(BUILDDIR)/),)
-
# Provide help.
help :
- @$(PRINTF) '%b' '$(subst $(newline),\n,$(makefileinfo))'
-
-# Destroy build directory and installed files.
-gone : clean uninstall ;
-
-# List the iΒ·dβs of all recognized entries.
-listids :
- @$(TR) '| ' ' \n' <<< '$(strip $(foreach category,$(categories),\0033[1m$(category)\0033[22m: $(patsubst %,β’|%,$(call identifier,$(call entriesforcategory,$(category)))) ))' | $(XARGS) -0 $(PRINTF) '%b'
+ @$(PRINTF) '%b' $(call quote,$(subst $(newline),\n,$(makefileinfo)))
# Output a random unused identifier.
wrmg :
@$(PRINTF) '%s\n' $(wrmg)
# Create a new entry in the provided category and output its path.
-+% : FORCE
++% : $(SRCDIR)/~ FORCE
$(silent)$(call ensuredirectory,$(SRCDIR)/$*)
- $(if $(wildcard $(SRCDIR)/$*/@),,$(silent)$(PRINTF) '%b' '%%\nCATEGORY : $*\n%%\n' > '$(SRCDIR)/$*/@')
- $(foreach identifier,$(wrmg),@$(PRINTF) '%b' '\0043!lesml\nENTRY : $(identifier)\n%%\n\n' > '$(SRCDIR)/$*/$(identifier)'$(newline)@$(PRINTF) '%s\n' '$(SRCDIR)/$*/$(identifier)')
+ $(if $(wildcard $(SRCDIR)/$*/~),,$(silent)$(PRINTF) '%b@%s$$ profile=urn:fdc:ladys.computer:20240204:Caudex:pf:category\n%s\n' '\0043!lesml' '$(DOCLANG)' '%%' >|$(call quote,$(SRCDIR)/$*/~))
+ $(foreach identifier,$(wrmg),$(silent)$(PRINTF) '%b@%s$$ profile=urn:fdc:ladys.computer:20240204:Caudex:pf:entry\n%s\n' '\0043!lesml' '$(DOCLANG)' '%%' >|$(call quote,$(SRCDIR)/$*/$(identifier))$(newline)$(silent)$(PRINTF) '%s\n' $(call quote,$(SRCDIR)/$*/$(identifier)))
# β ΒΆ Special Targets βββββββββββββββββββββββββββββββββββββββββββββββββ
-# Perform secondary expansion; this enables pattern rules to determine their prerequisites based on the matched pattern.
-.SECONDEXPANSION : ;
-
# Donβt use any implicit rules.
.SUFFIXES : ;
FORCE : ;
# Phony rules; always consider these outΒ·ofΒ·date.
-.PHONY : FORCE all build catalogs clean gone help install list listids uninstall wrmg ;
+.PHONY : FORCE help wrmg ;
# β ΒΆ Build Targets βββββββββββββββββββββββββββββββββββββββββββββββββββ
-# Initialize the β©π° δΉ¦η€Ύ repository if it is empty.
-ifneq ($(filter $(THISDIR)/%,$(SHUSHE)),)
-$(SHUSHE)/GNUmakefile : $(THISDIR)/%/GNUmakefile :
- @$(PRINTF) '%s\n' $(call quote,Initializing git submodule at `$*Β΄)
- $(silent)cd $(THISDIR) && $(GIT) submodule update --init $(call quote,$*)
-endif
-
-# Initialize the ππ LesΒ·MΒ·L repository if it is empty.
-ifneq ($(filter $(THISDIR)/%,$(LESML)),)
-$(LESML)/parser.xslt : $(THISDIR)/%/parser.xslt :
- @$(PRINTF) '%s\n' $(call quote,Initializing git submodule at `$*Β΄)
- $(silent)cd $(THISDIR) && $(GIT) submodule update --init $(call quote,$*)
-endif
-
# Create an empty codex metadata file if none exists.
-$(SRCDIR)/@ :
- $(silent)$(PRINTF) '%b' '%%\nCODEX :\n%%\n' > $(call quote,$@)
-
-# Create category catalogs.
-$(categorycatalogs) : $(BUILDDIR)/catalogs/categories/%/index : FORCE
- $(call makeandsavedeps,$@,$*,$(call entriesforcategory,$*),$(call makecategorycatalog,$*))
-
-# Create entry catalogs.
-$(entrycatalogs) : $(BUILDDIR)/catalogs/entries/% :
- @$(PRINTF) '%s\n' $(call quote,Generating catalog for document `$(call identifier,$*)Β΄β¦)
- $(silent)$(call ensuredirectory,$(dir $@))
- $(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
- $(silent)$(XMLCATALOG) --add uri '.' '$(call identifier,$*).xhtml' --noout $(call quote,$@)
- $(silent)$(XMLCATALOG) --add uri '?' 'about:entry' --noout $(call quote,$@)
- $(silent)$(XMLCATALOG) --add uri '@' $(call quote,$*) --noout $(call quote,$@)
-
-$(BUILDDIR)/catalogs/indices/index : FORCE | $(SRCDIR)/@
- $(call makeandsavedeps,$@,index,$(categories),$(call makeindexcatalog,))
-
-$(BUILDDIR)/catalogs/indices/fullindex : FORCE | $(SRCDIR)/@
- $(call makeandsavedeps,$@,fullindex,$(categories),$(call makeindexcatalog,1))
+$(SRCDIR)/~ :
+ $(silent)$(PRINTF) '%b@%s$$ profile=urn:fdc:ladys.computer:20240204:Caudex:pf:codex\n%s\n' '\0043!lesml' '$(DOCLANG)' '%%' >|$(call quote,$@)
<!--
-SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
+SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
SPDX-License-Identifier: CC0-1.0
-->
# πͺΎπ°Β Caudex
<b>A simple codex generator.</b>
<dfn>πͺΎπ°Β Caudex</dfn> is a static website generator aimed at
- generating simple, categoryβΉbased lists of documents akin to the
+ generating simple, categoryβbased lists of documents akin to the
βCodexβ feature of games like <cite>Dragon Age</cite>.
-It is built on top of [β©π°Β δΉ¦η€Ύ][Shushe] and consequently inherits
- all of the (few) dependencies and prerequisites of the latter.
-Using πͺΎπ°Β Caudex is fairly straightforward, but customizing its
- output requires some familiarity with XΒ·SΒ·LΒ·T and, probably, a
- minimal level of comfort using GΒ·NΒ·U Make.
+Actually, πͺΎπ°Β Caudex is a collection of files intended for use with
+ [ππΒ LesΒ·MΒ·L][LesML] and [β©π°Β δΉ¦η€Ύ][Shushe], which does the actual
+ site generation.
+It consists of the following componentsβ―:β β
+
+- The parser, `parser.xslt`, processes parsed ππΒ LesΒ·MΒ·L files into
+ an RΒ·DΒ·F representation of the codex.
+
+- The transform, `transform.xslt`, converts the RΒ·DΒ·F into rendered
+ XΒ·HΒ·TΒ·MΒ·L.
+
+- The makefile, `GNUmakefile` provides some conveniences for codex
+ creation.
## Nomenclature
It is the historical antecedent of Latin (and English) <i
lang="la">cΕdex</i>.
-## Basic Usage
-
-For an easy quickstart, you can simply clone the πͺΎπ°Β Caudex
- repository and work directly in that folder.
-
-```sh
-git clone https://git.ladys.computer/Caudex
+## Prerequisites
-# Create a new entry in `my_categoryΒ΄ :β
-make +my_category | xargs -o nano
+πͺΎπ°Β Caudex expects a β©π°Β δΉ¦η€Ύ setup which includes its parser and
+ transform as well as the ππΒ LesΒ·MΒ·L magic and parser.
-# Build the website
-make install
-```
+## Basic Usage
-However, the most flexible way to get started with πͺΎπ°Β Caudex is to
- include it in a project as a Git submoduleβ―:β β
+The most flexible way to get started with πͺΎπ°Β Caudex is to
+ include it in a project as a Git submodule, presumably alongside
+ β©π°Β δΉ¦η€Ύ and ππΒ LesΒ·MΒ·Lβ―:β β
```sh
-git submodule add https://git.ladys.computer/Caudex
+git submodule add https://git.ladys.computer/Shushe.git
+git submodule add https://git.ladys.computer/LesML.git
+git submodule add https://git.ladys.computer/Caudex.git
```
-It can then be conigured, and activated, through recursive invocation
- of GΒ·NΒ·U Makeβ―:β β
+You will then need to create a makeΒ·file for building your site.
+A sample one followsβ―:β β
```make
SHELL = /bin/sh
# Location of the πͺΎπ° Caudex submodule.
CAUDEX := Caudex
-# Additional options to pass to πͺΎπ° Caudex.
-#
-# Any variable overrides you explicitly give on the command line will
-# also automatically be forwarded.
-CAUDEXOPTS :=
+# Location of the β©π° δΉ¦η€Ύ submodule.
+LESML := LesML
-# Build the website by running πͺΎπ° Caudex `make installΒ΄.
-build: $(CAUDEX)/GNUmakefile
- $(MAKE) -f $(CAUDEX)/GNUmakefile install $(CAUDEXOPTS)
+# Location of the β©π° δΉ¦η€Ύ submodule.
+SHUSHE := Shushe
-# Forward targets which begin with a plus; these have special meaning
-# in πͺΎπ° Caudex.
-+%: $(CAUDEX)/GNUmakefile
- $(MAKE) -f $(CAUDEX)/GNUmakefile $@ $(CAUDEXOPTS)
+# Location of β©π° δΉ¦η€Ύ source files.
+SRCDIR := site
-# If the makeΒ·file of πͺΎπ° Caudex doesnβt exist, the submodule needs
-# to be initialized.
-$(CAUDEX)/GNUmakefile:
- git submodule update --init --recursive '$(CAUDEX)/GNUmakefile'
-```
+# Location of β©π° δΉ¦η€Ύ includes.
+INCLUDEDIR := data
-## Setup and Configuration
+# Location of the πͺΎπ° Caudex codexβshould be inside $(INCLUDEDIR).
+CODEXDIR := $(INCLUDEDIR)/codex
-πͺΎπ°Β Caudex inherits all of the dependencies of β©π°Β δΉ¦η€Ύ and enables
- you to override them in the same way.
-
-In addition to the configuration variables for β©π°Β δΉ¦η€Ύ, the
- following variables are recognized and treated specially by
- πͺΎπ°Β Caudexβ―:β β
-
-- **`SRCDIR`:**
- The location of the codex entries and related metadata (default:
- `entries`).
- Only one directory is supported.
-
-- **`ASSETDIR`:**
- The location of additional source files (default: `assets`).
- Multiple asset directories can be provided, so long as the same file
- subpath doesnβt exist in more than one of them.
-
-- **`ASSETINCLUDEDIR`:**
- The location of includes to be used by additional source files
- (default: `assets/includes`).
- Multiple asset include directories can be provided, so long as the
- same file subpath doesnβt exist in more than one of them.
-
-- **`BUILDDIR`:**
- The location of the (temporary) build directory (default: `build`).
- `make clean` will delete this, and it is recommended that it not be
- used for programs aside from πͺΎπ°Β Caudex.
-
-- **`DESTDIR`:**
- The location of directory to output files to (default: `public`).
- `make install` will overwrite files in this directory which
- correspond to those in `SRCDIR` and `ASSETDIR`.
- It *will not* touch other files, including those generated from files
- in `SRCDIR` which have since been deleted.
-
- Files are first compiled to `$(BUILDDIR)/β©π°/public` before they
- are copied to `DESTDIR`, so this folder is relatively quick and
- inexpensive to reΒ·create.
- Itβs reasonable to simply delete it before every `make install` to
- ensure stale content is removed.
-
-- **`THISDIR`:**
- The location of the πͺΎπ°Β Caudex `GNUmakefile`.
- This should be set automatically when calling Make and shouldnβt ever
- need to be set manually.
+# Options to pass to β©π° δΉ¦η€Ύ.
+#
+# This just identifies the source and include directories, and
+# identifies the appropriate ππ LesΒ·MΒ·L and πͺΎπ° Caudex files.
+SHUSHEOPTS := SRCDIR='$(SRCDIR)' INCLUDEDIR='$(INCLUDEDIR)' EXTRAMAGIC='$(LESML)/magic' EXTRAPARSERS='$(LESML)/parser.xslt $(CAUDEX)/parser.xslt' EXTRATRANSFORMS='$(CAUDEX)/transform.xslt'
-- **`EXTRAMAGIC`:**
- Additional magic files for β©π°Β δΉ¦η€Ύ.
+# Options to pass to πͺΎπ° Caudex.
+#
+# This identifies the codex directory.
+CAUDEXOPTS := SRCDIR='$(CODEXDIR)'
-- **`EXTRAPARSERS`:**
- Additional parsers for β©π°Β δΉ¦η€Ύ.
+# Build the website by running β©π° δΉ¦η€Ύ `make installΒ΄.
+build:
+ $(MAKE) -f $(SHUSHE)/GNUmakefile install $(SHUSHEOPTS)
-- **`EXTRATRANSFORMS`:**
- Additional transforms for β©π°Β δΉ¦η€Ύ.
+# Forward targets which begin with a plus to the πͺΎπ° Caudex
+# makeΒ·file.
++%:
+ $(MAKE) -f $(CAUDEX)/GNUmakefile $@ $(CAUDEXOPTS)
+```
-- **`GENERATOR`:**
- The name of the generator program (default: `πͺΎπ°Β Caudex`).
+The above makeΒ·file is intentionally simplified; in practice, it might
+ wind up considerably more complex.
-- **`VERSION`:**
- The current version of `GENERATOR` (default: derived from the current
- git tag/branch/commit).
+Once β©π°Β δΉ¦η€Ύ is set up, you can generate a codex at subdirectory
+ `codex/` in your site by creating a file `site/codex` with the
+ following contentsβ―:β β
-- **`SRCREV`:**
- The current version of the source files (default: derived from the
- current git tag/branch/commit).
+```xml
+<?xml version="1.0"?>
+<codex
+ xmlns="urn:fdc:ladys.computer:20240204:Caudex"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
+>
+ <δΉ¦η€Ύ:link
+ xlink:href="about:shushe?include=codex/"
+ xlink:show="embed"
+ />
+</codex>
+```
-- **`VERBOSE`:**
- If this variable has a value, every recipe instruction will be
- printed when it runs (default: empty).
- This is helpful for debugging, but typically too noisy for general
- usage.
+This code assumes that the codex directory (`data/codex/`) conforms to
+ the source file expectations below.
## Source Files
-Codex entries should be placed in subdirectories of `SRCDIR` and have
- a fileΒ·name of the form `???-????` or `???-????,*`, where `???-????`
- is a unique identifier for the entry within the codex.
+Codex entries should be placed in subdirectories of `CODEXDIR` and
+ should generally have a filename of the form `???-????` or
+ `???-????,*`, where `???-????` is a unique identifier for the entry
+ within the codex.
+Any characters following the comma are ignored; they may be used to
+ provide a humanβfriendly description of the files contents.
+
The command `make +β¨categoryβ©` is provided as a convenience to create
a new entry with a random identifier within the subdirectory
`β¨categoryβ©/`.
-If the identifier is followed by a comma, the remainder of the
- fileΒ·name may be used to provide a humanβΉfriendly description of the
- fileβs contents.
-Remember: The fileΒ·name still needs to be compatible with β©π°Β δΉ¦η€Ύ
+
+**Remember:** The filename still needs to be compatible with β©π°Β δΉ¦η€Ύ
and Make (it must not contain spaces or other fraught Ascii
characters).
-Entries need to be in [ππΒ LesΒ·MΒ·L][LesML] format.
+A file named `~` is required to be present in `CODEXDIR` and each
+ category directory.
+These files provide metadata for the codex and categories.
-## Metadata
+Codex entries and metadata files are expected to be in ππΒ LesΒ·MΒ·L
+ format and have a profile which is one of the followingβ―:β β
-Codices, categories, and entries should all have metadata.
-For entries, the metadata is provided by the record which begins the
- document.
-For codices and categories, the metadata is provided by a special file
- named `@` in `SRCDIR` or the category directory, respectively.
-In all cases, metadata is kept in the Record Jar format.
+- `urn:fdc:ladys.computer:20240204:Caudex:pf:codex` for codex metadata
-The following metadata fields are recognized by defaultβ―:β β
+- `urn:fdc:ladys.computer:20240204:Caudex:pf:category` for category
+ metadata
-- **`CATEGORY`:**
- Indicates that the current record is a category record.
- The value of this field gives the identifier for the category.
+- `urn:fdc:ladys.computer:20240204:Caudex:pf:entry` for codex entries
-- **`CODEX`:**
- Indicates that the current record is a codex record.
- The value of this field gives the identifier for the codex.
+## Metadata
+
+Codices, categories, and entries should all have metadata.
+For codices and categories, the metadata is provided by a special
+ ππΒ LesΒ·MΒ·L file named `~` in `$(CODEXDIR)` or the category
+ directory, respectively.
+The (nonβmetadata) contents of this file are presently ignored; in the
+ future they may be interpreted as a longerβform description.
-- **`ENTRY`:**
- Indicates that the current record is an entry record.
- The value of this field gives the identifier for the entry.
+The following metadata fields are recognized by defaultβ―:β β
- **`TITLE`:**
- For all record types, gives the title of the thing being described.
+ Gives the title of the thing being described.
-If the `@` file is missing from a category directory, none of the
+If the `~` file is missing from a category directory, none of the
entries in the category will be recognized.
-However, a minimal `@` file will be created for you when you create an
+However, a minimal `~` file will be created for you when you create an
entry in a new category using `make +β¨categoryβ©`.
## Output Files
-Assets are installed to their corresponding location in `DESTDIR`
- (default: `public/`).
-An entry with the identifier `%` will be installed to `%.xhtml`.
+Under the hood, πͺΎπ°Β Caudex defines codices as βexpanded
+ archivesββessentially, tarballs that β©π°Β δΉ¦η€Ύ automatically expands
+ into their final locations.
+This means that it is _not possible_ for a codex to appear in the root
+ directory of the install locationβit must be given a subdirectory.
+(Of course, it is always possible to just serve the site from that
+ subdirectory instead.)
-Two index files are createdβ―:β β `index.xhtml` loads entries
- dynamically upon request, and `standalone.xhtml` contains all of the
- entries and does not require a network connection.
+Within this conceptual archive, two index files are createdβ―:β β
+ `index.xhtml` loads entries dynamically upon request, and
+ `standalone.xhtml` contains all of the entries within its source code
+ and consequently does not require a network connection.
+Both files make use of (minimal) Javascript for full functionality.
Output can be customized by supplying additional transforms, β
normal
β©π°Β δΉ¦η€Ύ conventions.
The easiest way to customize the transform is to introduce new
templates which operate in the `δΉ¦η€Ύ:header`, `δΉ¦η€Ύ:footer`, or
`δΉ¦η€Ύ:metadata` modes.
-
-If you want to customize the actual main body output of πͺΎπ°Β Caudex,
- you will need a pattern like thisβ―:β β
-
-```xml
-<?xml version="1.0"?>
-<transform
- xmlns="http://www.w3.org/1999/XSL/Transform"
- xmlns:exsl="http://exslt.org/common"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
- exclude-result-prefixes="exsl"
- version="1.0"
->
- <δΉ¦η€Ύ:id>example:modify-caudex-index</δΉ¦η€Ύ:id>
- <!-- Create a template with increased priority, excluding elements with a `@data-caudex-parseΒ΄ attribute. -->
- <template match="/html:div[@δΉ¦η€Ύ:parsed-by='urn:fdc:ladys.computer:20240204:Caudex:catalog.xslt'][@class='index' or @class='fullindex'][not(@data-caudex-parse)]" priority="1">
- <!-- Add the attribute to the element in a variable. -->
- <variable name="toparse">
- <copy>
- <attribute name="data-caudex-parse"/>
- <copy-of select="@*|node()"/>
- </copy>
- </variable>
- <!-- Apply templates to the contents of the variable, saving the result. -->
- <variable name="parsed">
- <apply-templates select="exsl:node-set($toparse)/*"/>
- </variable>
- <!-- Do something with the result. -->
- <for-each select="exsl:node-set($parsed)/*">
- <!-- β¦ -->
- </for-each>
- </template>
-</transform>
-```
+Additionally, the `Caudex:codex-entry` mode is used to process the
+ contents of codex entries themselves.
[LesML]: <https://git.ladys.computer/LesML>
[Shushe]: <https://git.ladys.computer/Shushe>
-[draft-phillips-record-jar-01]: <https://datatracker.ietf.org/doc/html/draft-phillips-record-jar-01>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+SPDX-FileCopyrightText: 2025 Lady <https://www.ladys.computer/about/#lady>
+SPDX-License-Identifier: MPL-2.0
+-->
+<!--
+β πͺΎπ° Caudex β· parser.xslt
+
+Β© 2025 Lady [@ Ladys Computer].
+
+This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
+If a copy of the MΒ·PΒ·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+-->
+<!DOCTYPE transform [
+ <!ENTITY xhtml 'http://www.w3.org/1999/xhtml'>
+ <!ENTITY xsd 'http://www.w3.org/2001/XMLSchema#'>
+]>
+<transform
+ xmlns="http://www.w3.org/1999/XSL/Transform"
+ xmlns:awol="http://bblfish.net/work/atom-owl/2006-06-06/#"
+ xmlns:dcterms="http://purl.org/dc/terms/"
+ xmlns:exslstr="http://exslt.org/strings"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:html="&xhtml;"
+ xmlns:ore="http://www.openarchives.org/ore/terms/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:skos="http://www.w3.org/2004/02/skos/core#"
+ xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
+ extension-element-prefixes="exslstr"
+ version="1.0"
+>
+ <δΉ¦η€Ύ:id>urn:fdc:ladys.computer:20240204:Caudex:parser.xslt</δΉ¦η€Ύ:id>
+ <template match="html:div[html:article/@data-lesml-profile='urn:fdc:ladys.computer:20240204:Caudex:pf:codex']">
+ <for-each select="html:article">
+ <variable name="title" select="html:footer[@class='head']//html:dt[normalize-space()='TITLE']/following-sibling::html:dd"/>
+ <element name="ore:Aggregation">
+ <apply-templates select="@lang|@xml:lang"/>
+ <attribute name="rdf:nodeID">
+ <text>codex</text>
+ </attribute>
+ <if test="$title">
+ <attribute name="dcterms:title">
+ <value-of select="$title"/>
+ </attribute>
+ </if>
+ </element>
+ </for-each>
+ </template>
+ <template match="html:div[html:article/@data-lesml-profile='urn:fdc:ladys.computer:20240204:Caudex:pf:category']">
+ <variable name="identifier" select="exslstr:tokenize($IDENTIFIER, '/')[last()-1]"/>
+ <for-each select="html:article">
+ <variable name="title" select="html:footer[@class='head']//html:dt[normalize-space()='TITLE']/following-sibling::html:dd"/>
+ <element name="awol:Category">
+ <apply-templates select="@lang|@xml:lang"/>
+ <attribute name="rdf:nodeID">
+ <value-of select="$identifier"/>
+ </attribute>
+ <attribute name="awol:term">
+ <choose>
+ <when test="$title">
+ <value-of select="$title"/>
+ </when>
+ <otherwise>
+ <value-of select="$identifier"/>
+ </otherwise>
+ </choose>
+ </attribute>
+ <if test="$title">
+ <attribute name="dcterms:title">
+ <value-of select="$title"/>
+ </attribute>
+ </if>
+ </element>
+ </for-each>
+ </template>
+ <template match="html:div[html:article/@data-lesml-profile='urn:fdc:ladys.computer:20240204:Caudex:pf:entry']">
+ <for-each select="html:article">
+ <variable name="title" select="html:footer[@class='head']//html:dt[normalize-space()='TITLE']/following-sibling::html:dd"/>
+ <variable name="idstring" select="string(exslstr:tokenize($IDENTIFIER, '/')[last()])"/>
+ <element name="ore:Proxy">
+ <if test="$title">
+ <attribute name="dcterms:title">
+ <value-of select="$title"/>
+ </attribute>
+ </if>
+ <element name="awol:category">
+ <attribute name="rdf:nodeID">
+ <value-of select="exslstr:tokenize($IDENTIFIER, '/')[last()-1]"/>
+ </attribute>
+ </element>
+ <element name="skos:notation">
+ <attribute name="rdf:datatype">
+ <text>&xsd;string</text>
+ </attribute>
+ <choose>
+ <when test="contains($idstring, ',')">
+ <value-of select="substring-before($idstring, ',')"/>
+ </when>
+ <otherwise>
+ <value-of select="$idstring"/>
+ </otherwise>
+ </choose>
+ </element>
+ <element name="ore:proxyIn">
+ <attribute name="rdf:nodeID">
+ <text>codex</text>
+ </attribute>
+ </element>
+ <element name="ore:proxyFor">
+ <element name="foaf:Document">
+ <apply-templates select="@lang|@xml:lang"/>
+ <element name="awol:content">
+ <attribute name="rdf:parseType">
+ <text>Resource</text>
+ </attribute>
+ <element name="awol:body">
+ <attribute name="rdf:parseType">
+ <text>Literal</text>
+ </attribute>
+ <apply-templates select="node()[not(self::html:footer[@class='head'])]"/>
+ </element>
+ <element name="awol:mediaType">
+ <attribute name="rdf:datatype">
+ <text>&xsd;string</text>
+ </attribute>
+ <text>application/xml+xhtml</text>
+ </element>
+ </element>
+ </element>
+ </element>
+ </element>
+ </for-each>
+ </template>
+</transform>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
-SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
-SPDX-License-Identifier: MPL-2.0
--->
-<!--
-β πͺΎπ° Caudex β· parsers/catalog.xslt
-
-Β© 2024 Lady [@ Ladys Computer]
-
-This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
-If a copy of the MΒ·PΒ·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
--->
-<transform
- xmlns="http://www.w3.org/1999/XSL/Transform"
- xmlns:Caudex="urn:fdc:ladys.computer:20240204:Caudex"
- xmlns:catalog="urn:oasis:names:tc:entity:xmlns:xml:catalog"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
- exclude-result-prefixes="catalog"
- version="1.0"
->
- <δΉ¦η€Ύ:id>urn:fdc:ladys.computer:20240204:Caudex:catalog.xslt</δΉ¦η€Ύ:id>
- <template match="/catalog:catalog">
- <html:div class="{substring-after(catalog:uri[@name='?']/@uri, 'about:')}" δΉ¦η€Ύ:parsed-by="urn:fdc:ladys.computer:20240204:Caudex:catalog.xslt">
- <if test="catalog:uri[@name='.']">
- <attribute name="δΉ¦η€Ύ:destination">
- <value-of select="catalog:uri[@name='.']/@uri"/>
- </attribute>
- </if>
- <apply-templates select="catalog:uri[not(@name='?' or @name='.')]"/>
- </html:div>
- </template>
- <template match="catalog:uri[not(@name='?' or @name='.')]">
- <html:div id="{@name}">
- <if test="contains(@uri, '?cksum=')">
- <attribute name="Caudex:cksum">
- <value-of select="substring-after(@uri, '?cksum=')"/>
- </attribute>
- </if>
- <δΉ¦η€Ύ:link xlink:show="embed">
- <attribute name="xlink:href">
- <text>about:shushe?include=</text>
- <choose>
- <when test="contains(@uri, '?')">
- <value-of select="substring-before(@uri, '?')"/>
- </when>
- <otherwise>
- <value-of select="@uri"/>
- </otherwise>
- </choose>
- </attribute>
- </δΉ¦η€Ύ:link>
- </html:div>
- </template>
-</transform>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
+SPDX-License-Identifier: MPL-2.0
+-->
+<!--
+β πͺΎπ° Caudex β· transform.xslt
+
+Β© 2024β2025 Lady [@ Ladys Computer]
+
+This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
+If a copy of the MΒ·PΒ·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+-->
+<!DOCTYPE transform [
+ <!ENTITY xhtml 'http://www.w3.org/1999/xhtml'>
+ <!ENTITY δΉ¦η€Ύ 'urn:fdc:ladys.computer:20231231:Shu1She4'>
+]>
+<transform
+ xmlns="http://www.w3.org/1999/XSL/Transform"
+ xmlns:Caudex="urn:fdc:ladys.computer:20240204:Caudex"
+ xmlns:awol="http://bblfish.net/work/atom-owl/2006-06-06/#"
+ xmlns:dcterms="http://purl.org/dc/terms/"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:exslstr="http://exslt.org/strings"
+ xmlns:html="&xhtml;"
+ xmlns:ore="http://www.openarchives.org/ore/terms/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:skos="http://www.w3.org/2004/02/skos/core#"
+ xmlns:δΉ¦η€Ύ="&δΉ¦η€Ύ;"
+ extension-element-prefixes="exsl exslstr"
+ version="1.0"
+>
+ <δΉ¦η€Ύ:id>urn:fdc:ladys.computer:20240204:Caudex:transform.xslt</δΉ¦η€Ύ:id>
+ <template match="@id" mode="Caudex:codex-entry" priority="0">
+ <attribute name="id">
+ <value-of select="ancestor::*[skos:notation][1]/skos:notation"/>
+ <text>.</text>
+ <value-of select="."/>
+ </attribute>
+ </template>
+ <template match="@href[starts-with(., '#')]" mode="Caudex:codex-entry" priority="0">
+ <attribute name="href">
+ <text>#</text>
+ <value-of select="ancestor::*[skos:notation][1]/skos:notation"/>
+ <text>.</text>
+ <value-of select="substring-after(., '#')"/>
+ </attribute>
+ </template>
+ <template match="@*|node()" mode="Caudex:codex-entry" priority="-1">
+ <copy>
+ <apply-templates select="@*|node()" mode="Caudex:codex-entry"/>
+ </copy>
+ </template>
+ <template match="Caudex:codex" mode="δΉ¦η€Ύ:expand" priority="1">
+ <variable name="codex-fragment">
+ <apply-templates select="node()" mode="δΉ¦η€Ύ:expand"/>
+ </variable>
+ <variable name="codex" select="exsl:node-set($codex-fragment)"/>
+ <variable name="codex-rdf" select="$codex//ore:Aggregation[@rdf:nodeID='codex']"/>
+ <element name="δΉ¦η€Ύ:archive">
+ <attribute name="δΉ¦η€Ύ:expanded"/>
+ <for-each select="$codex-rdf">
+ <variable name="title-fragment">
+ <if test="@dcterms:title">
+ <element name="meta" namespace="&xhtml;">
+ <attribute name="itemprop">
+ <text>urn:fdc:ladys.computer:20231231:Shu1She4:title</text>
+ </attribute>
+ <attribute name="content">
+ <value-of select="@dcterms:title"/>
+ </attribute>
+ </element>
+ </if>
+ </variable>
+ <variable name="navigation-fragment">
+ <element name="nav" namespace="&xhtml;">
+ <element name="ul" namespace="&xhtml;">
+ <for-each select="$codex//awol:Category">
+ <variable name="category-id" select="string(@rdf:nodeID)"/>
+ <element name="li" namespace="&xhtml;">
+ <element name="strong" namespace="&xhtml;">
+ <value-of select="@awol:term"/>
+ </element>
+ <element name="ul" namespace="&xhtml;">
+ <for-each select="$codex//ore:Proxy[ore:proxyIn/@rdf:nodeID='codex' and awol:category/@rdf:nodeID=$category-id]">
+ <sort select="@dcterms:title"/>
+ <sort select="skos:notation"/>
+ <element name="li" namespace="&xhtml;">
+ <element name="a" namespace="&xhtml;">
+ <attribute name="href">
+ <text>./</text>
+ <value-of select="skos:notation"/>
+ <text>.xhtml</text>
+ </attribute>
+ <attribute name="data-identifier">
+ <value-of select="skos:notation"/>
+ </attribute>
+ <attribute name="data-cksum">
+ <value-of select="@δΉ¦η€Ύ:cksum"/>
+ </attribute>
+ <if test="@dcterms:title">
+ <value-of select="@dcterms:title"/>
+ <text> </text>
+ </if>
+ <element name="small" namespace="&xhtml;">
+ <text>(</text>
+ <element name="code" namespace="&xhtml;">
+ <attribute name="lang">
+ <text>zxx</text>
+ </attribute>
+ <attribute name="xml:lang">
+ <text>zxx</text>
+ </attribute>
+ <value-of select="skos:notation"/>
+ </element>
+ <text>)</text>
+ </element>
+ </element>
+ </element>
+ </for-each>
+ </element>
+ </element>
+ </for-each>
+ </element>
+ </element>
+ </variable>
+ <element name="div" namespace="&xhtml;">
+ <attribute name="Caudex:page">
+ <text>index</text>
+ </attribute>
+ <attribute name="δΉ¦η€Ύ:archived-as">
+ <text>index.xhtml</text>
+ </attribute>
+ <copy-of select="$title-fragment"/>
+ <element name="main" namespace="&xhtml;">
+ <copy-of select="$navigation-fragment"/>
+ <element name="div" namespace="&xhtml;">
+ <attribute name="id">
+ <text>Caudex.pane</text>
+ </attribute>
+ </element>
+ </element>
+ <element name="script" namespace="&xhtml;">
+ <attribute name="type">
+ <text>text/javascript</text>
+ </attribute>
+ <text><![CDATA[#!javascript
+~function(links){
+ var i=0
+ var cache={}
+ for(;i<links.length;++i){
+ ~function(link){
+ var identifier=link.getAttribute("data-identifier")
+ var cksum=link.getAttribute("data-cksum")
+ if(!(identifier&&cksum))return
+ link.addEventListener("click",function(event){
+ var pane=document.getElementById("Caudex.pane")
+ var request
+ if(identifier in cache){
+ pane.textContent=""
+ pane.appendChild(document.importNode(cache[identifier],true))
+ }else{
+ pane.textContent="Loadingβ¦"
+ request=new XMLHttpRequest
+ request.open("GET",link.href)
+ request.addEventListener("load",function(){
+ var k=0
+ var article=request.responseXML.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","article").item(0)
+ cache[identifier]=article
+ pane.textContent=""
+ pane.appendChild(document.importNode(article,true))
+ for(;k<links.length;++k){
+ ~function(linkk){
+ var parent=linkk.parentNode
+ if(linkk==link)parent.setAttribute("class","selected")
+ else parent.setAttribute("class","")
+ }(links.item(k))
+ }
+ link.setAttribute("class","cached read")
+ try{
+ localStorage.setItem(identifier,cksum)
+ }catch(e){}
+ },false)
+ request.responseType="document"
+ request.send()
+ }
+ event.preventDefault()
+ pane.focus()
+ },false)
+ try{
+ var lastReadCksum=localStorage.getItem(identifier)
+ if(lastReadCksum==cksum)link.setAttribute("class","read")
+ else if(lastReadCksum)link.setAttribute("class","updated")
+ else link.setAttribute("class","new")
+ }catch(e){}
+ }(links[i])
+ }
+}(document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","main")[0].children[0].getElementsByTagNameNS("http://www.w3.org/1999/xhtml","a"))
+]]></text>
+ </element>
+ </element>
+ <element name="div" namespace="&xhtml;">
+ <attribute name="Caudex:page">
+ <text>standalone</text>
+ </attribute>
+ <attribute name="δΉ¦η€Ύ:archived-as">
+ <text>standalone.xhtml</text>
+ </attribute>
+ <copy-of select="$title-fragment"/>
+ <element name="main" namespace="&xhtml;">
+ <copy-of select="$navigation-fragment"/>
+ <element name="div" namespace="&xhtml;">
+ <attribute name="id">
+ <text>Caudex.pane</text>
+ </attribute>
+ <for-each select="$codex//ore:Proxy">
+ <element name="article" namespace="&xhtml;">
+ <attribute name="id">
+ <value-of select="skos:notation"/>
+ </attribute>
+ <attribute name="hidden">
+ <text>hidden</text>
+ </attribute>
+ <apply-templates select="ore:proxyFor/*/awol:content/awol:body/node()" mode="Caudex:codex-entry"/>
+ </element>
+ </for-each>
+ </element>
+ </element>
+ <element name="script" namespace="&xhtml;">
+ <attribute name="type">
+ <text>text/javascript</text>
+ </attribute>
+ <text><![CDATA[#!javascript
+~function(links){
+ var i=0
+ for(;i<links.length;++i){
+ ~function(link){
+ var identifier=link.getAttribute("data-identifier")
+ var cksum=link.getAttribute("data-cksum")
+ if(!(identifier&&cksum))return
+ link.addEventListener("click",function(event){
+ var j=0
+ var k=0
+ var pane=document.getElementById("Caudex.pane")
+ var articles=pane.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","article")
+ for(;j<articles.length;++j){
+ ~function(article){
+ if(article.getAttribute("id")==identifier){
+ article.removeAttribute("hidden")
+ link.setAttribute("class","cached read")
+ try{
+ localStorage.setItem(identifier,cksum)
+ }catch(e){}
+ }
+ else article.setAttribute("hidden","hidden")
+ }(articles.item(j))
+ }
+ for(;k<links.length;++k){
+ ~function(linkk){
+ var parent=linkk.parentNode
+ if(linkk==link)parent.setAttribute("class","selected")
+ else parent.setAttribute("class","")
+ }(links.item(k))
+ }
+ event.preventDefault()
+ pane.focus()
+ },false)
+ try{
+ var lastReadCksum=localStorage.getItem(identifier)
+ if(lastReadCksum==cksum)link.setAttribute("class","cached read")
+ else if(lastReadCksum)link.setAttribute("class","cached updated")
+ else link.setAttribute("class","cached new")
+ }catch(e){}
+ }(links.item(i))
+ }
+}(document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","main")[0].children[0].getElementsByTagNameNS("http://www.w3.org/1999/xhtml","a"))
+]]></text>
+ </element>
+ </element>
+ </for-each>
+ <for-each select="$codex//ore:Proxy">
+ <element name="article" namespace="&xhtml;">
+ <attribute name="Caudex:page">
+ <value-of select="skos:notation"/>
+ </attribute>
+ <attribute name="δΉ¦η€Ύ:archived-as">
+ <value-of select="skos:notation"/>
+ <text>.xhtml</text>
+ </attribute>
+ <if test="@dcterms:title">
+ <element name="meta" namespace="&xhtml;">
+ <attribute name="itemprop">
+ <text>urn:fdc:ladys.computer:20231231:Shu1She4:title</text>
+ </attribute>
+ <attribute name="content">
+ <value-of select="@dcterms:title"/>
+ </attribute>
+ </element>
+ </if>
+ <apply-templates select="ore:proxyFor/*/awol:content/awol:body/node()" mode="Caudex:codex-entry"/>
+ </element>
+ </for-each>
+ </element>
+ </template>
+ <template match="html:div[@itemtype='&δΉ¦η€Ύ;:document' and @Caudex:page]" mode="δΉ¦η€Ύ:metadata" priority="0">
+ <element name="style" namespace="&xhtml;">
+ <text><![CDATA[@charset "UTF-8";
+@namespace "http://www.w3.org/1999/xhtml";
+*[hidden]{Display:None}
+]]></text>
+ <if test="@Caudex:page='index' or @Caudex:page='standalone'">
+ <text><![CDATA[/*Index styling*/
+main{Display:Block;Width:100%;Height:100%}
+main>*{Display:Inline-Block;Box-Sizing:Border-Box;Border:.5EM Transparent None;Height:100%;Width:50%;Vertical-Align:Top;Overflow:Auto}
+main>nav{Border-Right-Style:Solid;Overflow:Scroll}
+main>div{Border-Left-Style:Solid}
+]]></text>
+ </if>
+ </element>
+ </template>
+</transform>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
-SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
-SPDX-License-Identifier: MPL-2.0
--->
-<!--
-β πͺΎπ° Caudex β· transforms/entry.xslt
-
-Β© 2024 Lady [@ Ladys Computer]
-
-This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
-If a copy of the MΒ·PΒ·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
--->
-<!DOCTYPE transform [
- <!ENTITY Caudex "urn:fdc:ladys.computer:20240204:Caudex:">
- <!ENTITY LesML "urn:fdc:ladys.computer:20240512:LesML:">
- <!ENTITY δΉ¦η€Ύ "urn:fdc:ladys.computer:20231231:Shu1She4:">
-]>
-<transform
- xmlns="http://www.w3.org/1999/XSL/Transform"
- xmlns:Caudex="urn:fdc:ladys.computer:20240204:Caudex"
- xmlns:exsl="http://exslt.org/common"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
- exclude-result-prefixes="exsl Caudex"
- version="1.0"
->
- <δΉ¦η€Ύ:id>&Caudex;entry.xslt</δΉ¦η€Ύ:id>
- <template match="/html:div[@δΉ¦η€Ύ:parsed-by='&Caudex;catalog.xslt'][@class='entry']">
- <html:body>
- <for-each select="@*[namespace-uri()!='urn:fdc:ladys.computer:20231231:Shu1She4']">
- <copy/>
- </for-each>
- <for-each select="html:div[@id='@']/html:article[@δΉ¦η€Ύ:parsed-by='&LesML;parser.xslt']">
- <variable name="metadata" select="html:footer[@class='head']/html:dl[1]"/>
- <html:meta itemprop="&δΉ¦η€Ύ;title">
- <attribute name="content">
- <value-of select="$metadata//html:dt[string()='TITLE']/following-sibling::html:dd"/>
- <if test="$metadata//html:dt[string()='TITLE'] and $metadata//html:dt[string()='ENTRY']">
- <text> </text>
- </if>
- <if test="$metadata//html:dt[string()='ENTRY']">
- <text>(</text>
- <value-of select="$metadata//html:dt[string()='ENTRY']/following-sibling::html:dd"/>
- <text>)</text>
- </if>
- </attribute>
- </html:meta>
- <html:article>
- <if test="$metadata//html:dt[string()='TITLE']">
- <html:h1>
- <value-of select="$metadata//html:dt[string()='TITLE']/following-sibling::html:dd"/>
- </html:h1>
- </if>
- <apply-templates select="node()[not(self::html:footer[@class='head'])]"/>
- </html:article>
- </for-each>
- </html:body>
- </template>
-</transform>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
-SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
-SPDX-License-Identifier: MPL-2.0
--->
-<!--
-β πͺΎπ° Caudex β· transforms/index.xslt
-
-Β© 2024 Lady [@ Ladys Computer]
-
-This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
-If a copy of the MΒ·PΒ·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
--->
-<!DOCTYPE transform [
- <!ENTITY Caudex "urn:fdc:ladys.computer:20240204:Caudex:">
- <!ENTITY LesML "urn:fdc:ladys.computer:20240512:LesML:">
- <!ENTITY δΉ¦η€Ύ "urn:fdc:ladys.computer:20231231:Shu1She4:">
-]>
-<transform
- xmlns="http://www.w3.org/1999/XSL/Transform"
- xmlns:Caudex="urn:fdc:ladys.computer:20240204:Caudex"
- xmlns:exsl="http://exslt.org/common"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
- exclude-result-prefixes="exsl"
- version="1.0"
->
- <δΉ¦η€Ύ:id>&Caudex;index.xslt</δΉ¦η€Ύ:id>
- <template match="/html:div[@δΉ¦η€Ύ:parsed-by='&Caudex;catalog.xslt'][@class='index' or @class='fullindex']">
- <html:body>
- <for-each select="@*[namespace-uri()!='urn:fdc:ladys.computer:20231231:Shu1She4']">
- <copy/>
- </for-each>
- <variable name="metadata" select="html:div[@δΉ¦η€Ύ:parsed-by='&δΉ¦η€Ύ;record-jar.xslt']"/>
- <html:meta itemprop="&δΉ¦η€Ύ;title" content="{$metadata//html:dt[string()='TITLE']/following-sibling::html:dd}"/>
- <html:main>
- <html:nav>
- <html:ul>
- <for-each select=".//html:div[@δΉ¦η€Ύ:parsed-by='&Caudex;catalog.xslt'][@class='category']">
- <variable name="category-metadata" select="html:div[@id='@']/html:div[@δΉ¦η€Ύ:parsed-by='&δΉ¦η€Ύ;record-jar.xslt']"/>
- <html:li>
- <html:strong>
- <choose>
- <when test="$category-metadata//html:dt[string()='TITLE']">
- <value-of select="$category-metadata//html:dt[string()='TITLE']/following-sibling::html:dd"/>
- </when>
- <otherwise>
- <value-of select="../@id"/>
- </otherwise>
- </choose>
- </html:strong>
- <html:ul>
- <for-each select="html:div[@id!='@']/html:article[@δΉ¦η€Ύ:parsed-by='&LesML;parser.xslt']">
- <sort select="html:footer[@class='head']/html:dl[1]//html:dt[string()='TITLE']/following-sibling::html:dd"/>
- <sort select="../@id"/>
- <variable name="entry-metadata" select="html:footer[@class='head']/html:dl[1]"/>
- <html:li>
- <html:a href="{../@id}.xhtml" data-identifier="{../@id}" data-cksum="{@δΉ¦η€Ύ:cksum}">
- <value-of select="$entry-metadata//html:dt[string()='TITLE']/following-sibling::html:dd"/>
- <text> </text>
- <html:small>
- <text>(</text>
- <value-of select="../@id"/>
- <text>)</text>
- </html:small>
- </html:a>
- </html:li>
- </for-each>
- </html:ul>
- </html:li>
- </for-each>
- </html:ul>
- </html:nav>
- <html:div id="pane">
- <if test="@class='fullindex'">
- <for-each select=".//html:div[@δΉ¦η€Ύ:parsed-by='&Caudex;catalog.xslt'][@class='category']/html:div[@id!='@']/html:article[@δΉ¦η€Ύ:parsed-by='&LesML;parser.xslt']">
- <variable name="context" select="."/>
- <variable name="entry">
- <html:div δΉ¦η€Ύ:parsed-by="&Caudex;catalog.xslt" class="entry">
- <html:div id="@">
- <copy-of select="."/>
- </html:div>
- </html:div>
- </variable>
- <variable name="transformed-entry">
- <apply-templates select="exsl:node-set($entry)/*"/>
- </variable>
- <for-each select="exsl:node-set($transformed-entry)//html:article">
- <html:article id="{$context/../@id}" hidden="hidden">
- <copy-of select="@*|node()"/>
- </html:article>
- </for-each>
- </for-each>
- </if>
- </html:div>
- </html:main>
- <html:script type="text/javascript">
- <choose>
- <when test="@class='fullindex'">
- <text><![CDATA[#!javascript
-~function(links){
- var i=0
- for(;i<links.length;++i){
- ~function(link){
- var identifier=link.getAttribute("data-identifier")
- var cksum=link.getAttribute("data-cksum")
- if(!(identifier&&cksum))return
- link.addEventListener("click",function(event){
- var j=0
- var k=0
- var pane=document.getElementById("pane")
- var articles=pane.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","article")
- for(;j<articles.length;++j){
- ~function(article){
- if(article.getAttribute("id")==identifier){
- article.removeAttribute("hidden")
- link.setAttribute("class","cached read")
- try{
- localStorage.setItem(identifier,cksum)
- }catch(e){}
- }
- else article.setAttribute("hidden","hidden")
- }(articles.item(j))
- }
- for(;k<links.length;++k){
- ~function(linkk){
- var parent=linkk.parentNode
- if(linkk==link)parent.setAttribute("class","selected")
- else parent.setAttribute("class","")
- }(links.item(k))
- }
- event.preventDefault()
- pane.focus()
- },false)
- try{
- var lastReadCksum=localStorage.getItem(identifier)
- if(lastReadCksum==cksum)link.setAttribute("class","cached read")
- else if(lastReadCksum)link.setAttribute("class","cached updated")
- else link.setAttribute("class","cached new")
- }catch(e){}
- }(links.item(i))
- }
-}(document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","a"))
-]]></text>
- </when>
- <otherwise>
- <text><![CDATA[#!javascript
-~function(links){
- var i=0
- var cache={}
- for(;i<links.length;++i){
- ~function(link){
- var identifier=link.getAttribute("data-identifier")
- var cksum=link.getAttribute("data-cksum")
- if(!(identifier&&cksum))return
- link.addEventListener("click",function(event){
- var pane=document.getElementById("pane")
- var request
- if(identifier in cache){
- pane.textContent=""
- pane.appendChild(document.importNode(cache[identifier],true))
- }else{
- pane.textContent="Loadingβ¦"
- request=new XMLHttpRequest
- request.open("GET",link.href)
- request.addEventListener("load",function(){
- var k=0
- var article=request.responseXML.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","article").item(0)
- cache[identifier]=article
- pane.textContent=""
- pane.appendChild(document.importNode(article,true))
- for(;k<links.length;++k){
- ~function(linkk){
- var parent=linkk.parentNode
- if(linkk==link)parent.setAttribute("class","selected")
- else parent.setAttribute("class","")
- }(links.item(k))
- }
- link.setAttribute("class","cached read")
- try{
- localStorage.setItem(identifier,cksum)
- }catch(e){}
- },false)
- request.responseType="document"
- request.send()
- }
- event.preventDefault()
- pane.focus()
- },false)
- try{
- var lastReadCksum=localStorage.getItem(identifier)
- if(lastReadCksum==cksum)link.setAttribute("class","read")
- else if(lastReadCksum)link.setAttribute("class","updated")
- else link.setAttribute("class","new")
- }catch(e){}
- }(links[i])
- }
-}(document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","a"))
-]]></text>
- </otherwise>
- </choose>
- </html:script>
- </html:body>
- </template>
-</transform>
+++ /dev/null
-<?xml version="1.0"?>
-<!--
-SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
-SPDX-License-Identifier: MPL-2.0
--->
-<!--
-β πͺΎπ° Caudex β· transforms/metadata.xslt
-
-Β© 2024 Lady [@ Ladys Computer]
-
-This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
-If a copy of the MΒ·PΒ·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
--->
-<transform
- xmlns="http://www.w3.org/1999/XSL/Transform"
- xmlns:html="http://www.w3.org/1999/xhtml"
- xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
- xmlns:δΉ¦η€Ύ="urn:fdc:ladys.computer:20231231:Shu1She4"
- version="1.0"
->
- <δΉ¦η€Ύ:id>urn:fdc:ladys.computer:20240204:Caudex:metadata.xslt</δΉ¦η€Ύ:id>
- <template match="δΉ¦η€Ύ:id[string()='urn:fdc:ladys.computer:20240204:Caudex:metadata.xslt']" mode="δΉ¦η€Ύ:metadata">
- <html:style type="text/css">
- <text><![CDATA[@charset "UTF-8";
-@namespace html "http://www.w3.org/1999/xhtml";
-@namespace δΉ¦η€Ύ "urn:fdc:ladys.computer:20231231:Shu1She4";
-html*[hidden]{Display:None}
-]]></text>
- <if test="//html:body[@class='index' or @class='fullindex']">
- <text><![CDATA[/*Index styling*/
-html|html{Margin:0;Padding:0;Height:100%}
-html|body{Box-Sizing:Border-Box;Margin:0;Height:100%;Padding:1EM}
-html|main{Display:Block;Width:100%;Height:100%}
-html|main>html|*{Display:Inline-Block;Box-Sizing:Border-Box;Border:.5EM Transparent None;Height:100%;Width:50%;Vertical-Align:Top;Overflow:Auto}
-html|main>html|nav{Border-Right-Style:Solid;Overflow:Scroll}
-html|main>html|div{Border-Left-Style:Solid}
-]]></text>
- </if>
- </html:style>
- </template>
-</transform>