]> Lady’s Gitweb - Shushe/commitdiff
Support multiple destinations current
authorLady <redacted>
Sat, 25 Oct 2025 01:06:15 +0000 (21:06 -0400)
committerLady <redacted>
Sat, 25 Oct 2025 01:06:15 +0000 (21:06 -0400)
This commit enables transforming the same source file to multiple
destinations, and provides a new variable for determining which
destination is currently being written to.

.metadata-format-changed-since
GNUmakefile
README.markdown
lib/catalog2transform.xslt
lib/expandmetadata.xslt

index b6faef57639ca664c7b0abe4a6feccd08e3d156d..36e448cb04f68706a11e03db61e91473aa7d8f26 100644 (file)
@@ -4,7 +4,7 @@ SPDX-License-Identifier: CC0-1.0
 The following hash indicates a commit in which the metadata format
 generated by ⛩📰 书社 was different than it currently is :⁠—
 
 The following hash indicates a commit in which the metadata format
 generated by ⛩📰 书社 was different than it currently is :⁠—
 
-338b26f8c92351bad03a180ad4b4f88e4cfeab76
+d64a8d34c7638243f90421664268766df75a42d7
 
 The purpose of this file is to serve as a trackable dependency which
 will prompt a rebuild of metadata when the generation mechanism
 
 The purpose of this file is to serve as a trackable dependency which
 will prompt a rebuild of metadata when the generation mechanism
index 8f62e4697d79709db8fbced4f9ab2e1e0d2e301f..a3624ccd944425e9185ab93f66f6ea3e78256037 100644 (file)
@@ -582,16 +582,16 @@ endif
 # (callable) Get the destination for the given source files, or return `.NOTDEF/$1´.
 #
 # The fallback here is because destinations are used to generate targets and thus must always be non·empty and should be unique, even when they haven’t been generated yet.
 # (callable) Get the destination for the given source files, or return `.NOTDEF/$1´.
 #
 # The fallback here is because destinations are used to generate targets and thus must always be non·empty and should be unique, even when they haven’t been generated yet.
-override destination = $(foreach file,$1,$(or $(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcedestinationpair))),.NOTDEF/$1))
+override destination = $(foreach file,$1,$(subst ;, ,$(or $(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcedestinationpair))),.NOTDEF/$1)))
 
 # Pair each source file with its compiled location.
 
 # Pair each source file with its compiled location.
-override sourcecompiledpair := $(foreach file,$(sourcefiles),$(file)|$(BUILDDIR)/results/$(call destination,$(file)))
+override sourcecompiledpair := $(foreach file,$(sourcefiles),$(file)|$(subst $(space),;,$(patsubst %,$(BUILDDIR)/results/%,$(call destination,$(file)))))
 
 # (callable) Get the location of the transformed X·M·L files for the given source files.
 
 # (callable) Get the location of the transformed X·M·L files for the given source files.
-override compiled = $(foreach file,$1,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcecompiledpair))))
+override compiled = $(foreach file,$1,$(subst ;, ,$(patsubst $(file)|%,%,$(filter $(file)|%,$(sourcecompiledpair)))))
 
 # (callable) Get the location of the source files for the given compiled file.
 
 # (callable) Get the location of the source files for the given compiled file.
-override uncompiled = $(foreach file,$1,$(patsubst %|$(file),%,$(filter %|$(file),$(sourcecompiledpair))))
+override uncompiled = $(foreach pair,$(sourcecompiledpair),$(foreach src,$(firstword $(subst |, , $(pair))),$(if $(filter $(subst ;, ,$(patsubst $(src)|%,%,$(pair))),$1),$(src),)))
 
 # (callable) Get the location of the final built files for the given source files.
 override built = $(foreach file,$1,$(patsubst $(BUILDDIR)/results/%,$(BUILDDIR)/public/%,$(call compiled,$(file))))
 
 # (callable) Get the location of the final built files for the given source files.
 override built = $(foreach file,$1,$(patsubst $(BUILDDIR)/results/%,$(BUILDDIR)/public/%,$(call compiled,$(file))))
@@ -600,7 +600,7 @@ override built = $(foreach file,$1,$(patsubst $(BUILDDIR)/results/%,$(BUILDDIR)/
 override unbuilt = $(foreach file,$1,$(call uncompiled,$(patsubst $(BUILDDIR)/public/%,$(BUILDDIR)/results/%,$(file))))
 
 # (callable) Get the installed locations for the given source files.
 override unbuilt = $(foreach file,$1,$(call uncompiled,$(patsubst $(BUILDDIR)/public/%,$(BUILDDIR)/results/%,$(file))))
 
 # (callable) Get the installed locations for the given source files.
-override installed = $(foreach file,$1,$(DESTDIR)/$(call destination,$(file)))
+override installed = $(foreach file,$1,$(patsubst %,$(DESTDIR)/%,$(call destination,$(file))))
 
 # ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
 
 
 # ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
 
@@ -624,7 +624,7 @@ install : $(call installed,$(recursivefiles) $(installablefiles)) ;
 
 # List all source files and includes and their computed types.
 list :
 
 # List all source files and includes and their computed types.
 list :
-       @$(PRINTF) '%b' $(call quote,$(foreach file,$(sort $(sourcefiles)) $(sort $(sourceincludes)),\0033[1m$(file)\0033[22m|$(call typeoffile,$(file))|[\0033[3m$(if $(filter $(file),$(xmlfiles)),xml,$(if $(filter $(file),$(plaintextfiles)),text,asset))$(if $(filter $(file),$(sourceincludes)),|include,)\0033[23m]$(if $(call dependencies,$(file))$(call recursives,$(file)), $(strip $(foreach recursive,$(call recursives,$(file)),\0033[93;41m•|Recursive|Dependency|\0033[39;49m|$(recursive)) $(foreach dependency,$(call dependencies,$(file)),\0033[2m•|Dependency|\0033[22m|$(dependency))))$(if $(filter $(file),$(sourcefiles)), →|<\0033[4m/$(call destination,$(file))\0033[24m>,) )) | $(TR) ' |' '\n '
+       @$(PRINTF) '%b' $(call quote,$(foreach file,$(sort $(sourcefiles)) $(sort $(sourceincludes)),\0033[1m$(file)\0033[22m|$(call typeoffile,$(file))|[\0033[3m$(if $(filter $(file),$(xmlfiles)),xml,$(if $(filter $(file),$(plaintextfiles)),text,asset))$(if $(filter $(file),$(sourceincludes)),|include,)\0033[23m]$(if $(call dependencies,$(file))$(call recursives,$(file)), $(strip $(foreach recursive,$(call recursives,$(file)),\0033[93;41m•|Recursive|Dependency|\0033[39;49m|$(recursive)) $(foreach dependency,$(call dependencies,$(file)),\0033[2m•|Dependency|\0033[22m|$(dependency))))$(if $(filter $(file),$(sourcefiles)), $(foreach dest,$(call destination,$(file)),→|<\0033[4m/$(dest)\0033[24m>),) )) | $(TR) ' |' '\n '
 
 # Lists out the destinations of all resulting files (relative to `DESTDIR´).
 listout :
 
 # Lists out the destinations of all resulting files (relative to `DESTDIR´).
 listout :
@@ -714,7 +714,7 @@ $(BUILDDIR)/transform.xslt : $(BUILDDIR)/transform.catalog $(BUILDDIR)/metadata
 $(call compiled,$(compilablefiles)) : $(BUILDDIR)/results/% : $$(call parseresult,$$(call uncompiled,$$@)) $$(call parseresult,$$(call dependencies,$$(call uncompiled,$$@))) $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt $(TRANSFORMLIBS) $$(call metadata,$$(call dependencies,$$(call uncompiled,$$@)))
        $(call inform,$(PRINTF) '%s\n' $(call quote,Compiling </$*>…) >&2)
        $(silent)$(call ensuredirectory,$(dir $@))
 $(call compiled,$(compilablefiles)) : $(BUILDDIR)/results/% : $$(call parseresult,$$(call uncompiled,$$@)) $$(call parseresult,$$(call dependencies,$$(call uncompiled,$$@))) $(BUILDDIR)/transform.catalog $(THISDIR)/lib/catalog2transform.xslt $(TRANSFORMLIBS) $$(call metadata,$$(call dependencies,$$(call uncompiled,$$@)))
        $(call inform,$(PRINTF) '%s\n' $(call quote,Compiling </$*>…) >&2)
        $(silent)$(call ensuredirectory,$(dir $@))
-       $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite --stringparam METADATA 'metadata' --stringparam BUILDTIME $$($(DATE) -u '+%Y-%m-%dT%H:%M:%SZ') --stringparam IDENTIFIER $(call quote,$(call localuri,$(call uncompiled,$@)))$(if $(THISREV), --stringparam THISREV $(call quote,$(THISREV)),)$(if $(SRCREV), --stringparam SRCREV $(call quote,$(SRCREV)),) $(call quote,$(BUILDDIR)/transform.xslt) $(call quote,$<) >|$(call quote,$@)
+       $(silent)$(XSLTPROC) --nonet --novalid --nomkdir --nowrite --stringparam METADATA 'metadata' --stringparam BUILDTIME $$($(DATE) -u '+%Y-%m-%dT%H:%M:%SZ') --stringparam IDENTIFIER $(call quote,$(call localuri,$(call uncompiled,$@)))$(if $(THISREV), --stringparam THISREV $(call quote,$(THISREV)),)$(if $(SRCREV), --stringparam SRCREV $(call quote,$(SRCREV)),) --stringparam DESTINATION $(call quote,$*) $(call quote,$(BUILDDIR)/transform.xslt) $(call quote,$<) >|$(call quote,$@)
 
 # Create the final files from the compiled results (or error in the case of recursive ones).
 $(call built,$(compilablefiles)) : $(BUILDDIR)/public/% : $(BUILDDIR)/results/% $(THISDIR)/lib/archive2extractor.xslt
 
 # Create the final files from the compiled results (or error in the case of recursive ones).
 $(call built,$(compilablefiles)) : $(BUILDDIR)/public/% : $(BUILDDIR)/results/% $(THISDIR)/lib/archive2extractor.xslt
index 9b649d21df4eb381c71d27595bbe42c5646e6939..4671064e2238f8d323ca98ac44295464917ffa96 100644 (file)
@@ -569,6 +569,9 @@ This behaviour can be customized by setting the `@书社:destination`
 This attribute is read after parsing, but before transformation (where
   it is silently dropped).
 
 This attribute is read after parsing, but before transformation (where
   it is silently dropped).
 
+Multiple destinations can be provided if the same file should be output to multiple places.
+The file is retransformed each time, with the value of the `DESTINATION` global param set appropriately.
+
 ## Embedding
 
 Documents can be embedded in other documents using a `<书社:link>`
 ## Embedding
 
 Documents can be embedded in other documents using a `<书社:link>`
@@ -708,6 +711,9 @@ The following params are made available globally in parsers and
 
 In transforms, the following params are additionally available :⁠—
 
 
 In transforms, the following params are additionally available :⁠—
 
+- **`DESTINATION`:**
+  The destination being targeted by this transform.
+
 - **`书社:about`:**
   R·D·F metadata about all of the documents ⛩📰 书社 knows about.
   Use `$书社:about//*[@rdf:about=$IDENTIFIER]` to get the metadata for
 - **`书社:about`:**
   R·D·F metadata about all of the documents ⛩📰 书社 knows about.
   Use `$书社:about//*[@rdf:about=$IDENTIFIER]` to get the metadata for
index 0ba07f40752c89c396bc1766009994496d6c93ce..747225b122f43cc31878f6e86c6fcdf3575f25ad 100644 (file)
@@ -54,6 +54,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                </variable>
                <xslt:transform exclude-result-prefixes="nfo 书社vocab" extension-element-prefixes="exsl exslfunc exslstr" version="1.0">
                        <xslt:param name="BUILDTIME" select="'1972-12-31T00:00:00Z'"/>
                </variable>
                <xslt:transform exclude-result-prefixes="nfo 书社vocab" extension-element-prefixes="exsl exslfunc exslstr" version="1.0">
                        <xslt:param name="BUILDTIME" select="'1972-12-31T00:00:00Z'"/>
+                       <xslt:param name="DESTINATION" select="false()"/>
                        <xslt:param name="IDENTIFIER" select="false()"/>
                        <xslt:param name="SRCREV" select="false()"/>
                        <xslt:param name="THISREV" select="false()"/>
                        <xslt:param name="IDENTIFIER" select="false()"/>
                        <xslt:param name="SRCREV" select="false()"/>
                        <xslt:param name="THISREV" select="false()"/>
index 027aaa74d4b2ae67dd131efc179c9d7ca6ca8f1b..423924a3d35eb889c8ab4bd46e46a937e6d54c02 100644 (file)
@@ -14,13 +14,14 @@ 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:exsl="http://exslt.org/common"
 <transform
        xmlns="http://www.w3.org/1999/XSL/Transform"
        xmlns:exsl="http://exslt.org/common"
+       xmlns:exslstr="http://exslt.org/strings"
        xmlns:nie="http://www.semanticdesktop.org/ontologies/2007/01/19/nie#"
        xmlns:nfo="http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#"
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
        xmlns:书社vocab="urn:fdc:ladys.computer:20231231:Shu1She4:vocab:"
        xmlns:nie="http://www.semanticdesktop.org/ontologies/2007/01/19/nie#"
        xmlns:nfo="http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#"
        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
        xmlns:书社vocab="urn:fdc:ladys.computer:20231231:Shu1She4:vocab:"
-       extension-element-prefixes="exsl"
+       extension-element-prefixes="exsl exslstr"
        version="1.0"
 >
        <variable name="builddir" select="//书社vocab:BuildDirectory/@nfo:fileUrl"/>
        version="1.0"
 >
        <variable name="builddir" select="//书社vocab:BuildDirectory/@nfo:fileUrl"/>
@@ -89,34 +90,40 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
        <template match="//书社vocab:SourceFile[not(nie:interpretedAs/nfo:PlainTextDocument)]" priority="1">
                <copy>
                        <apply-templates select="@*"/>
        <template match="//书社vocab:SourceFile[not(nie:interpretedAs/nfo:PlainTextDocument)]" priority="1">
                <copy>
                        <apply-templates select="@*"/>
-                       <attribute name="书社vocab:destination">
-                               <value-of select="@书社vocab:path"/>
-                       </attribute>
                        <apply-templates select="node()"/>
                        <apply-templates select="node()"/>
+                       <element name="书社vocab:destination">
+                               <value-of select="@书社vocab:path"/>
+                       </element>
                </copy>
        </template>
        <template match="//书社vocab:SourceFile[nie:interpretedAs/nfo:PlainTextDocument]" priority="1">
                <variable name="parsed" select="document(书社vocab:hasParsedFile/@nfo:fileUrl)"/>
                </copy>
        </template>
        <template match="//书社vocab:SourceFile[nie:interpretedAs/nfo:PlainTextDocument]" priority="1">
                <variable name="parsed" select="document(书社vocab:hasParsedFile/@nfo:fileUrl)"/>
-               <variable name="destination-delim" select="concat('/', $parsed/*/@书社:destination, '/')"/>
-               <variable name="destination">
-                       <choose>
-                               <when test="not(contains($destination-delim, '//') or contains($destination-delim, '/./') or contains($destination-delim, '/../'))">
-                                       <value-of select="$parsed/*/@书社:destination"/>
-                               </when>
-                               <otherwise>
-                                       <value-of select="@书社vocab:path"/>
-                               </otherwise>
-                       </choose>
+               <variable name="provided-destinations" select="normalize-space($parsed/*/@书社:destination)"/>
+               <variable name="destinations-fragment">
+                       <if test="$provided-destinations!=''">
+                               <for-each select="exslstr:tokenize($provided-destinations)">
+                                       <element name="书社vocab:destination">
+                                               <value-of select="."/>
+                                       </element>
+                               </for-each>
+                       </if>
                </variable>
                <variable name="dependencies-fragment">
                        <apply-templates select="." mode="书社:dependencies"/>
                </variable>
                <variable name="dependencies" select="exsl:node-set($dependencies-fragment)"/>
                </variable>
                <variable name="dependencies-fragment">
                        <apply-templates select="." mode="书社:dependencies"/>
                </variable>
                <variable name="dependencies" select="exsl:node-set($dependencies-fragment)"/>
+               <variable name="destinations" select="exsl:node-set($destinations-fragment)/node()"/>
+               <variable name="bad-destinations-fragment">
+                       <for-each select="$destinations">
+                               <variable name="destination-delim" select="concat('/', ., '/')"/>
+                               <if test="contains($destination-delim, '//') or contains($destination-delim, '/./') or contains($destination-delim, '/../')">
+                                       <copy-of select="."/>
+                               </if>
+                       </for-each>
+               </variable>
+               <variable name="bad-destinations" select="exsl:node-set($bad-destinations-fragment)/node()"/>
                <copy>
                        <apply-templates select="@*"/>
                <copy>
                        <apply-templates select="@*"/>
-                       <attribute name="书社vocab:destination">
-                               <value-of select="$destination"/>
-                       </attribute>
                        <apply-templates select="node()"/>
                        <for-each select="$dependencies/书社:dependency">
                                <书社vocab:hasDependencyOn rdf:resource="{.}"/>
                        <apply-templates select="node()"/>
                        <for-each select="$dependencies/书社:dependency">
                                <书社vocab:hasDependencyOn rdf:resource="{.}"/>
@@ -124,6 +131,36 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        <for-each select="$dependencies/书社:recursive-dependency">
                                <书社vocab:hasRecursiveDependencyOn rdf:resource="{.}"/>
                        </for-each>
                        <for-each select="$dependencies/书社:recursive-dependency">
                                <书社vocab:hasRecursiveDependencyOn rdf:resource="{.}"/>
                        </for-each>
+                       <choose>
+                               <when test="not($destinations)">
+                                       <element name="书社vocab:destination">
+                                               <value-of select="@书社vocab:path"/>
+                                       </element>
+                               </when>
+                               <when test="$bad-destinations">
+                                       <message terminate="no">
+                                               <text>Bad destinations: </text>
+                                               <for-each select="$bad-destinations">
+                                                       <if test="position()>1">
+                                                               <text> </text>
+                                                       </if>
+                                                       <text>&lt;</text>
+                                                       <value-of select="."/>
+                                                       <text>></text>
+                                               </for-each>
+                                       </message>
+                                       <element name="书社vocab:destination">
+                                               <value-of select="@书社vocab:path"/>
+                                       </element>
+                               </when>
+                               <otherwise>
+                                       <for-each select="$destinations">
+                                               <element name="书社vocab:destination">
+                                                       <value-of select="."/>
+                                               </element>
+                                       </for-each>
+                               </otherwise>
+                       </choose>
                </copy>
        </template>
        <template match="//书社vocab:IncludeFile[nie:interpretedAs/nfo:PlainTextDocument]" priority="1">
                </copy>
        </template>
        <template match="//书社vocab:IncludeFile[nie:interpretedAs/nfo:PlainTextDocument]" priority="1">
@@ -169,7 +206,12 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        <for-each select="$result//书社vocab:SourceFile">
                                <value-of select="@rdf:about"/>
                                <text>|</text>
                        <for-each select="$result//书社vocab:SourceFile">
                                <value-of select="@rdf:about"/>
                                <text>|</text>
-                               <value-of select="@书社vocab:destination"/>
+                               <for-each select="书社vocab:destination">
+                                       <if test="position()>1">
+                                               <text>;</text>
+                                       </if>
+                                       <value-of select="."/>
+                               </for-each>
                                <text>&#xA;</text>
                        </for-each>
                </exsl:document>
                                <text>&#xA;</text>
                        </for-each>
                </exsl:document>
This page took 0.059178 seconds and 4 git commands to generate.