From: Lady <redacted>
Date: Mon, 1 Jan 2024 16:19:37 +0000 (-0500)
Subject: Allow creation of metadata without matching result
X-Git-Tag: 0.2.0~8
X-Git-Url: https://git.ladys.computer/Shushe/commitdiff_plain/af8b42c720c6aaa54199b556a656d40e8b8951a6

Allow creation of metadata without matching result

Each node in the result can only be matched once in any given mode, and
transforms need a mechanism for inserting elements without requiring a
match. This commit gives them a means of doing so by also matching
every `<xslt:include>` in the main transform. If a transform has a
`书社:id` top‐level element which is an i·r·i, then its include will
have a corresponding attribute, and transforms can (by convention)
match this include without fear of conflicts.

This commit also makes the expansion and result available as top‐level
variables in the `书社:` namespace, so that transforms can easily match
within them.
---

diff --git a/GNUmakefile b/GNUmakefile
index e0cb8e1..72712c8 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -224,6 +224,9 @@ override assetfiles := $(filter-out $(xmlfiles) $(plaintextfiles),$(sourcefiles)
 # (callable) Get the types of the given files.
 override typeoffile = $(patsubst $(foreach file,$1,$(file)?type=%),%,$(filter $(foreach file,$1,$(file)?type=%),$(types)))
 
+# (callable) Get the identifier for the given transform.
+override id = $(or $(shell $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $1),$(basename $(notdir $1)) | $(SED))
+
 # (callable) Get base64 data u·r·i’s for the given files.
 override datauri = $(foreach file,$1,data:$(call typeoffile,$(file));base64,$(shell $(UUENCODE) -m -r $(call quote,$(file)) _ | tr -d ' \n'))
 
@@ -378,7 +381,7 @@ $(BUILDDIR)/magic.mgc: $(wildcard $(MAGICDIR)/*)
 $(BUILDDIR)/parser.catalog: $(PARSERS)
 	@$(ECHO) "Generating catalog of parsers…"
 	$(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-	$(foreach parser,$(PARSERS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(basename $(notdir $(parser)))) $(call quote,../$(parser)) --noout $(call quote,$@)$(newline))
+	$(foreach parser,$(PARSERS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(parser))) $(call quote,../$(parser)) --noout $(call quote,$@)$(newline))
 $(BUILDDIR)/parser.xslt: $(BUILDDIR)/parser.catalog $(THISDIR)/lib/catalog2parser.xslt
 	@$(ECHO) "Generating main parser…"
 	$(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2parser.xslt) $(call quote,$<)
@@ -419,7 +422,7 @@ $(BUILDDIR)/dependencies: $(BUILDDIR)/catalog $(call parsed,$(plaintextfiles) $(
 $(BUILDDIR)/transform.catalog: $(TRANSFORMS)
 	@$(ECHO) "Generating catalog of transforms…"
 	$(silent)$(XMLCATALOG) --create --noout $(call quote,$@)
-	$(foreach transform,$(TRANSFORMS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(basename $(notdir $(transform)))) $(call quote,../$(transform)) --noout $(call quote,$@)$(newline))
+	$(foreach transform,$(TRANSFORMS),$(silent)$(XMLCATALOG) --add uri $(call quote,$(call id,$(transform))) $(call quote,../$(transform)) --noout $(call quote,$@)$(newline))
 $(BUILDDIR)/transform.xslt: $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt
 	@$(ECHO) "Generating main transform…"
 	$(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/catalog2transform.xslt) $(call quote,$<)
diff --git a/README.markdown b/README.markdown
index 2dd0eff..84c3206 100644
--- a/README.markdown
+++ b/README.markdown
@@ -313,10 +313,41 @@ The following are recommendations on effective creation of
 ⛩️📰 书社 will wrap the final output of the transforms in appropriate
   `<html:html>` and `<html:body>` elements, so it is not necessary for
   transforms to do this explicitly.
-The `<html:head>` of the output will contain the result tree generated
-  by matching the root node in the `书社:metadata` mode; the provided
-  `transforms/metadata.xslt` transform uses this mode to generate basic
-  metadata, but it is possible for other transforms to add their own.
+After performing the initial transform, ⛩️📰 书社 will match the root
+  node of the result in the following modes to fill in areas of the
+  wrapper :⁠—
+
+- **`书社:metadata`:**
+  The result of matching in this mode is inserted into the
+    `<html:head>` of the output.
+
+In addition to being called with the transform result, each of these
+  modes will additionally be called with a `<xslt:include>` element
+  corresponding to each transform.
+If a transform has a `<书社:id>` top‐level element whose value is an
+  i·r·i, its `<xslt:import>` element will have a corresponding
+  `@书社:id` attribute.
+This mechanism can be used to allow transforms to insert content
+  without matching any elements in the result; for example, the
+  following transform adds a link to a stylesheet to the `<html:head>`
+  of every page :⁠—
+
+```xml
+<?xml version="1.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"
+	exclude-result-prefixes="书社"
+	version="1.0"
+>
+	<书社:id>example:add-stylesheet-links.xslt</书社:id>
+	<template match="xslt:include[@书社:id='example:add-stylesheet-links.xslt']" mode="书社:metadata">
+	  <html:link rel="stylesheet" type="text/css" href="/style.css"/>
+	</template>
+</transform>
+```
 
 ## License
 
diff --git a/lib/catalog2parser.xslt b/lib/catalog2parser.xslt
index d044503..0da26b8 100644
--- a/lib/catalog2parser.xslt
+++ b/lib/catalog2parser.xslt
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ lib/catalog2parser.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s 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/>.
@@ -10,21 +10,28 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
 <transform
 	xmlns="http://www.w3.org/1999/XSL/Transform"
 	xmlns:catalog="urn:oasis:names:tc:entity:xmlns:xml:catalog"
-	xmlns:xsla="http://www.w3.org/1999/XSL/TransformAlias"
+	xmlns:xslt="http://www.w3.org/1999/XSL/TransformAlias"
+	xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
 	exclude-result-prefixes="catalog"
 	version="1.0"
 >
-	<namespace-alias stylesheet-prefix="xsla" result-prefix="#default"/>
+	<namespace-alias stylesheet-prefix="xslt" result-prefix="#default"/>
 	<template match="/">
-		<xsla:transform version="1.0">
+		<xslt:transform version="1.0">
 			<for-each select="//catalog:uri">
-				<xsla:include href="{@uri}"/>
+				<xslt:include href="{@uri}">
+					<if test="contains(@name, ':')">
+						<attribute name="书社:id">
+							<value-of select="@name"/>
+						</attribute>
+					</if>
+				</xslt:include>
 			</for-each>
-			<xsla:template match="@*|node()" priority="-1">
-				<xsla:copy>
-					<xsla:apply-templates select="@*|node()"/>
-				</xsla:copy>
-			</xsla:template>
-		</xsla:transform>
+			<xslt:template match="@*|node()" priority="-1">
+				<xslt:copy>
+					<xslt:apply-templates select="@*|node()"/>
+				</xslt:copy>
+			</xslt:template>
+		</xslt:transform>
 	</template>
 </transform>
diff --git a/lib/catalog2transform.xslt b/lib/catalog2transform.xslt
index 4a09235..e7640e8 100644
--- a/lib/catalog2transform.xslt
+++ b/lib/catalog2transform.xslt
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ lib/catalog2transform.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s 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/>.
@@ -21,36 +21,43 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
 	<template match="/">
 		<xslt:transform exclude-result-prefixes="catalog exsl" version="1.0">
 			<xslt:param name="catalog" select="'catalog'"/>
+			<xslt:variable name="书社:expansion">
+				<xslt:apply-templates select="/" mode="书社:expand"/>
+			</xslt:variable>
+			<xslt:variable name="书社:result">
+				<xslt:apply-templates select="exsl:node-set($书社:expansion)/*"/>
+			</xslt:variable>
 			<for-each select="//catalog:uri">
-				<xslt:include href="{@uri}"/>
+				<xslt:include href="{@uri}">
+					<if test="contains(@name, ':')">
+						<attribute name="书社:id">
+							<value-of select="@name"/>
+						</attribute>
+					</if>
+				</xslt:include>
 			</for-each>
 			<xslt:template match="/" priority="1">
-				<xslt:variable name="expansion">
-					<xslt:apply-templates select="." mode="书社:expand"/>
-				</xslt:variable>
-				<xslt:variable name="result">
-					<xslt:apply-templates select="exsl:node-set($expansion)/*"/>
-				</xslt:variable>
 				<xslt:variable name="metadata">
-					<xslt:copy-of select="exsl:node-set($result)/html/head/*"/>
-					<xslt:apply-templates select="exsl:node-set($result)" mode="书社:metadata"/>
+					<xslt:copy-of select="exsl:node-set($书社:result)/html/head/*"/>
+					<xslt:apply-templates select="exsl:node-set($书社:result)" mode="书社:metadata"/>
+					<xslt:apply-templates select="document('')/xslt:transform/xslt:include" mode="书社:metadata"/>
 				</xslt:variable>
 				<html:html>
-					<xslt:copy-of select="exsl:node-set($result)/html:html/@*"/>
+					<xslt:copy-of select="exsl:node-set($书社:result)/html:html/@*"/>
 					<html:head>
-						<xslt:copy-of select="exsl:node-set($result)/html:html/html:head/@*"/>
+						<xslt:copy-of select="exsl:node-set($书社:result)/html:html/html:head/@*"/>
 						<html:title>
 							<xslt:for-each select="exsl:node-set($metadata)/html:title">
 								<xslt:value-of select="."/>
 							</xslt:for-each>
 						</html:title>
-						<xslt:copy-of select="exsl:node-set($metadata)/*[not(self::html:title)]"/>
+						<xslt:copy-of select="exsl:node-set($metadata)/node()[self::comment() or self::* and not(self::html:title)]"/>
 						<xslt:if test="not(exsl:node-set($metadata)/html:meta[@name='generator'])">
 							<html:meta name="generator" content="⛩️📰 书社"/>
 						</xslt:if>
 					</html:head>
 					<html:body>
-						<xslt:copy-of select="exsl:node-set($result)/*[not(self::html:html or self::html:body)]|exsl:node-set($result)/html:html/*[not(self::html:head or self::html:body)]|exsl:node-set($result)/html:html/html:body/*|exsl:node-set($result)/html:body/*"/>
+						<xslt:copy-of select="exsl:node-set($书社:result)/*[not(self::html:html or self::html:body)]|exsl:node-set($书社:result)/html:html/*[not(self::html:head or self::html:body)]|exsl:node-set($书社:result)/html:html/html:body/*|exsl:node-set($书社:result)/html:body/*"/>
 					</html:body>
 				</html:html>
 			</xslt:template>
diff --git a/parsers/plain.xslt b/parsers/plain.xslt
index 0f61bfe..c12cbe5 100644
--- a/parsers/plain.xslt
+++ b/parsers/plain.xslt
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ parsers/plain.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s 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/>.
@@ -10,9 +10,11 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
 <transform
 	xmlns="http://www.w3.org/1999/XSL/Transform"
 	xmlns:html="http://www.w3.org/1999/xhtml"
+	xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
 	version="1.0"
 >
+	<书社:id>urn:fdc:ladys.computer:20231231:Shu1She4:plain.xslt</书社:id>
 	<template match="html:script[@type='text/plain']">
-		<html:pre><value-of select="."/></html:pre>
+		<html:pre class="plain"><value-of select="."/></html:pre>
 	</template>
 </transform>
diff --git a/parsers/tsv.xslt b/parsers/tsv.xslt
index 4de3b98..ad7052e 100644
--- a/parsers/tsv.xslt
+++ b/parsers/tsv.xslt
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ parsers/tsv.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s 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/>.
@@ -12,25 +12,27 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
 	xmlns:exsl="http://exslt.org/common"
 	xmlns:exslstr="http://exslt.org/strings"
 	xmlns:html="http://www.w3.org/1999/xhtml"
+	xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
 	exclude-result-prefixes="exsl exslstr"
 	version="1.0"
 >
+	<书社:id>urn:fdc:ladys.computer:20231231:Shu1She4:tsv.xslt</书社:id>
 	<template match="html:script[@type='text/tab-separated-values']">
 		<variable name="rows" select="exslstr:tokenize(., '&#xA;')[normalize-space(.) and not(starts-with(., '#'))]"/>
-		<variable name="head" select="exsl:node-set($rows)[1]"/>
-		<variable name="body" select="exsl:node-set($rows)[not(position()=1)]"/>
-		<html:table>
+		<variable name="head" select="$rows[1]"/>
+		<variable name="body" select="$rows[not(position()=1)]"/>
+		<html:table class="tsv">
 			<html:thead>
 				<html:tr>
 					<for-each select="exslstr:tokenize($head, '&#x9;')">
-						<html:th scope="row">
+						<html:th scope="col">
 							<value-of select="."/>
 						</html:th>
 					</for-each>
 				</html:tr>
 			</html:thead>
 			<html:tbody>
-				<for-each select="exsl:node-set($body)">
+				<for-each select="$body">
 					<html:tr>
 						<for-each select="exslstr:tokenize(., '&#x9;')">
 							<html:td>
diff --git a/transforms/asset.xslt b/transforms/asset.xslt
index a85c891..90c8dbd 100644
--- a/transforms/asset.xslt
+++ b/transforms/asset.xslt
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ transforms/asset.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s 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/>.
@@ -14,6 +14,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
 	exclude-result-prefixes="书社"
 	version="1.0"
 >
+	<书社:id>urn:fdc:ladys.computer:20231231:Shu1She4:asset.xslt</书社:id>
 	<template match="html:object[@type='text/css']">
 		<comment>
 			<text>[书社:CSS] </text>
diff --git a/transforms/metadata.xslt b/transforms/metadata.xslt
index d4be493..88877a4 100644
--- a/transforms/metadata.xslt
+++ b/transforms/metadata.xslt
@@ -2,7 +2,7 @@
 <!--
 ⁌ ⛩️📰 书社 ∷ transforms/metadata.xslt
 
-© 2023 Lady [@ Lady’s Computer]
+© 2023–2024 Lady [@ Lady’s 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/>.
@@ -14,6 +14,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
 	exclude-result-prefixes="书社"
 	version="1.0"
 >
+	<书社:id>urn:fdc:ladys.computer:20231231:Shu1She4:metadata.xslt</书社:id>
 	<template match="html:*[@itemscope][1]//html:meta[not(@name) and starts-with(@itemprop, 'urn:fdc:ladys.computer:20231231:Shu1She4:')]">
 		<comment>
 			<text>[书社:META] </text>