public inbox for [email protected]
help / color / mirror / Atom feedFrom: Peter Eisentraut <[email protected]>
To: pgsql-hackers <[email protected]>
Subject: Make documentation builds reproducible
Date: Wed, 23 Aug 2023 21:24:07 +0200
Message-ID: <[email protected]> (raw)
Somewhere at PGCon, I forgot exactly where, maybe in the same meeting
where we talked about getting rid of distprep, we talked about that the
documentation builds are not reproducible (in the sense of
https://reproducible-builds.org/). This is easily fixable, the fix is
available upstream
(https://github.com/docbook/xslt10-stylesheets/issues/54) but not
released. We can backpatch that into our customization layer. The
attached patch shows it.
I had actually often wanted this during development. When making
documentation tooling changes, it's useful to be able to compare the
output before and after, and this will eliminate false positives in that.
This patch addresses both the HTML and the FO output. The man output is
already reproducible AFAICT. Note that the final PDF output is
currently not reproducible; that's a different issue that needs to be
fixed in FOP. (See
https://wiki.debian.org/ReproducibleBuilds/TimestampsInPDFGeneratedByApacheFOP.)
From 9f2c7262445b6868c1d2c9f2d75ac1153b7c2a64 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Wed, 23 Aug 2023 16:38:44 +0200
Subject: [PATCH] Make documentation builds reproducible
---
doc/src/sgml/stylesheet-fo.xsl | 259 ++++++++++++++++++++++++
doc/src/sgml/stylesheet-html-common.xsl | 234 +++++++++++++++++++++
2 files changed, 493 insertions(+)
diff --git a/doc/src/sgml/stylesheet-fo.xsl b/doc/src/sgml/stylesheet-fo.xsl
index 5e7e132480..aff717ddbc 100644
--- a/doc/src/sgml/stylesheet-fo.xsl
+++ b/doc/src/sgml/stylesheet-fo.xsl
@@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE xsl:stylesheet [
+<!ENTITY % common.entities SYSTEM "http://docbook.sourceforge.net/release/xsl/current/common/entities.ent";
+%common.entities;
+]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format";
@@ -138,4 +142,259 @@
</fo:bookmark>
</xsl:template>
+<!-- make generated ids reproducible
+ (https://github.com/docbook/xslt10-stylesheets/issues/54) -->
+
+<!-- from fo/autoidx.xsl -->
+
+<xsl:template match="indexterm" mode="index-primary">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="key" select="&primary;"/>
+ <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
+
+ <xsl:variable name="term.separator">
+ <xsl:call-template name="index.separator">
+ <xsl:with-param name="key" select="'index.term.separator'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="range.separator">
+ <xsl:call-template name="index.separator">
+ <xsl:with-param name="key" select="'index.range.separator'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="number.separator">
+ <xsl:call-template name="index.separator">
+ <xsl:with-param name="key" select="'index.number.separator'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <fo:block xmlns:rx="http://www.renderx.com/XSL/Extensions"; xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions";
+ <xsl:if test="$autolink.index.see != 0">
+ <xsl:attribute name="id">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id"/>
+ <!-- pgsql-docs: end -->
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$axf.extensions != 0">
+ <xsl:attribute name="axf:suppress-duplicate-page-number">true</xsl:attribute>
+ </xsl:if>
+
+ <xsl:for-each select="$refs/primary">
+ <xsl:if test="@id or @xml:id">
+ <fo:inline id="{(@id|@xml:id)[1]}"/>
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:value-of select="primary"/>
+
+ <xsl:choose>
+ <xsl:when test="$xep.extensions != 0">
+ <xsl:if test="$refs[not(see) and not(secondary)]">
+ <xsl:copy-of select="$term.separator"/>
+ <xsl:variable name="primary" select="&primary;"/>
+ <xsl:variable name="primary.significant" select="concat(&primary;, $significant.flag)"/>
+ <rx:page-index list-separator="{$number.separator}"
+ range-separator="{$range.separator}">
+ <xsl:if test="$refs[@significance='preferred'][not(see) and not(secondary)]">
+ <rx:index-item xsl:use-attribute-sets="index.preferred.page.properties xep.index.item.properties"
+ ref-key="{$primary.significant}"/>
+ </xsl:if>
+ <xsl:if test="$refs[not(@significance) or @significance!='preferred'][not(see) and not(secondary)]">
+ <rx:index-item xsl:use-attribute-sets="xep.index.item.properties"
+ ref-key="{$primary}"/>
+ </xsl:if>
+ </rx:page-index>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="page-number-citations">
+ <xsl:for-each select="$refs[not(see)
+ and not(secondary)]">
+ <xsl:apply-templates select="." mode="reference">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:with-param name="position" select="position()"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:copy-of select="$page-number-citations"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$refs[not(secondary)]/*[self::see]">
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[&scope;][1])]"
+ mode="index-see">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </xsl:if>
+
+ </fo:block>
+
+ <xsl:if test="$refs/secondary or $refs[not(secondary)]/*[self::seealso]">
+ <fo:block start-indent="1pc">
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[&scope;][1])]"
+ mode="index-seealso">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]"
+ mode="index-secondary">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </fo:block>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-see">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="see" select="normalize-space(see)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in see "primary, secondary" entry -->
+ <xsl:variable name="seeprimary">
+ <xsl:choose>
+ <xsl:when test="contains($see, ',')">
+ <xsl:value-of select="substring-before($see, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seetarget" select="key('primaryonly', $seeprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seetarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seetarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <fo:inline xmlns:xlink='http://www.w3.org/1999/xlink';
+ <xsl:text> (</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'see'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="see/@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="see"/>
+ <xsl:with-param name="content" select="$see"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$see"/>
+ </xsl:when>
+ <xsl:when test="$seetarget">
+ <fo:basic-link internal-destination="{$linkend}"
+ xsl:use-attribute-sets="xref.properties">
+ <xsl:value-of select="$see"/>
+ </fo:basic-link>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+ </fo:inline>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-seealso">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:for-each select="seealso">
+ <xsl:sort select="translate(., &lowercase;, &uppercase;)"/>
+
+ <xsl:variable name="seealso" select="normalize-space(.)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in seealso "primary, secondary" entry -->
+ <xsl:variable name="seealsoprimary">
+ <xsl:choose>
+ <xsl:when test="contains($seealso, ',')">
+ <xsl:value-of select="substring-before($seealso, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seealsotarget" select="key('primaryonly', $seealsoprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seealsotarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seealsotarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <fo:block xmlns:xlink='http://www.w3.org/1999/xlink';
+ <xsl:text>(</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'seealso'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="."/>
+ <xsl:with-param name="content" select="$seealso"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$seealso"/>
+ </xsl:when>
+ <xsl:when test="$seealsotarget">
+ <fo:basic-link internal-destination="{$linkend}"
+ xsl:use-attribute-sets="xref.properties">
+ <xsl:value-of select="$seealso"/>
+ </fo:basic-link>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+ </fo:block>
+
+ </xsl:for-each>
+
+</xsl:template>
+
+
</xsl:stylesheet>
diff --git a/doc/src/sgml/stylesheet-html-common.xsl b/doc/src/sgml/stylesheet-html-common.xsl
index a368e0e199..7f541c0988 100644
--- a/doc/src/sgml/stylesheet-html-common.xsl
+++ b/doc/src/sgml/stylesheet-html-common.xsl
@@ -436,4 +436,238 @@ set toc,title
</xsl:choose>
</xsl:template>
+<!-- make generated ids reproducible
+ (https://github.com/docbook/xslt10-stylesheets/issues/54) -->
+
+<!-- from html/autoidx.xsl -->
+
+<xsl:template match="indexterm" mode="index-primary">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="key" select="&primary;"/>
+ <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
+ <dt>
+ <xsl:if test="$autolink.index.see != 0">
+ <!-- add internal id attribute to form see and seealso links -->
+ <xsl:attribute name="id">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id"/>
+ <!-- pgsql-docs: end -->
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="$refs/primary">
+ <xsl:if test="@id or @xml:id">
+ <xsl:choose>
+ <xsl:when test="$generate.id.attributes = 0">
+ <a name="{(@id|@xml:id)[1]}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <span>
+ <xsl:call-template name="id.attribute"/>
+ </span>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:value-of select="primary"/>
+ <xsl:choose>
+ <xsl:when test="$index.links.to.section = 1">
+ <xsl:for-each select="$refs[@zone != '' or generate-id() = generate-id(key('primary-section', concat($key, &sep;, §ion.id;))[&scope;][1])]">
+ <xsl:apply-templates select="." mode="reference">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="$refs[not(see)
+ and not(secondary)][&scope;]">
+ <xsl:apply-templates select="." mode="reference">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$refs[not(secondary)]/*[self::see]">
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[&scope;][1])]"
+ mode="index-see">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </dt>
+ <xsl:choose>
+ <xsl:when test="$refs/secondary or $refs[not(secondary)]/*[self::seealso]">
+ <dd>
+ <dl>
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[&scope;][1])]"
+ mode="index-seealso">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]"
+ mode="index-secondary">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </dl>
+ </dd>
+ </xsl:when>
+ <!-- HTML5 requires dd for each dt -->
+ <xsl:when test="$div.element = 'section'">
+ <dd></dd>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-see" xmlns:xlink='http://www.w3.org/1999/xlink';
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="see" select="normalize-space(see)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in see "primary, secondary" entry -->
+ <xsl:variable name="seeprimary">
+ <xsl:choose>
+ <xsl:when test="contains($see, ',')">
+ <xsl:value-of select="substring-before($see, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seetarget" select="key('primaryonly', $seeprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seetarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>#ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seetarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:text> (</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'see'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="see/@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="see"/>
+ <xsl:with-param name="content" select="$see"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$see"/>
+ </xsl:when>
+ <xsl:when test="$seetarget">
+ <a href="{$linkend}">
+ <xsl:value-of select="$see"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-seealso" xmlns:xlink='http://www.w3.org/1999/xlink';
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:for-each select="seealso">
+ <xsl:sort select="translate(., &lowercase;, &uppercase;)"/>
+
+ <xsl:variable name="seealso" select="normalize-space(.)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in seealso "primary, secondary" entry -->
+ <xsl:variable name="seealsoprimary">
+ <xsl:choose>
+ <xsl:when test="contains($seealso, ',')">
+ <xsl:value-of select="substring-before($seealso, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seealsotarget" select="key('primaryonly', $seealsoprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seealsotarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>#ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seealsotarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <dt>
+ <xsl:text>(</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'seealso'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="."/>
+ <xsl:with-param name="content" select="$seealso"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$seealso"/>
+ </xsl:when>
+ <xsl:when test="$seealsotarget">
+ <a href="{$linkend}">
+ <xsl:value-of select="$seealso"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+ </dt>
+
+ <xsl:if test="$div.element = 'section'">
+ <dd></dd>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
</xsl:stylesheet>
--
2.41.0
Attachments:
[text/plain] 0001-Make-documentation-builds-reproducible.patch (19.5K, ../[email protected]/2-0001-Make-documentation-builds-reproducible.patch)
download | inline diff:
From 9f2c7262445b6868c1d2c9f2d75ac1153b7c2a64 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Wed, 23 Aug 2023 16:38:44 +0200
Subject: [PATCH] Make documentation builds reproducible
---
doc/src/sgml/stylesheet-fo.xsl | 259 ++++++++++++++++++++++++
doc/src/sgml/stylesheet-html-common.xsl | 234 +++++++++++++++++++++
2 files changed, 493 insertions(+)
diff --git a/doc/src/sgml/stylesheet-fo.xsl b/doc/src/sgml/stylesheet-fo.xsl
index 5e7e132480..aff717ddbc 100644
--- a/doc/src/sgml/stylesheet-fo.xsl
+++ b/doc/src/sgml/stylesheet-fo.xsl
@@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE xsl:stylesheet [
+<!ENTITY % common.entities SYSTEM "http://docbook.sourceforge.net/release/xsl/current/common/entities.ent">
+%common.entities;
+]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
@@ -138,4 +142,259 @@
</fo:bookmark>
</xsl:template>
+<!-- make generated ids reproducible
+ (https://github.com/docbook/xslt10-stylesheets/issues/54) -->
+
+<!-- from fo/autoidx.xsl -->
+
+<xsl:template match="indexterm" mode="index-primary">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="key" select="&primary;"/>
+ <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
+
+ <xsl:variable name="term.separator">
+ <xsl:call-template name="index.separator">
+ <xsl:with-param name="key" select="'index.term.separator'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="range.separator">
+ <xsl:call-template name="index.separator">
+ <xsl:with-param name="key" select="'index.range.separator'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="number.separator">
+ <xsl:call-template name="index.separator">
+ <xsl:with-param name="key" select="'index.number.separator'"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <fo:block xmlns:rx="http://www.renderx.com/XSL/Extensions" xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions">
+ <xsl:if test="$autolink.index.see != 0">
+ <xsl:attribute name="id">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id"/>
+ <!-- pgsql-docs: end -->
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$axf.extensions != 0">
+ <xsl:attribute name="axf:suppress-duplicate-page-number">true</xsl:attribute>
+ </xsl:if>
+
+ <xsl:for-each select="$refs/primary">
+ <xsl:if test="@id or @xml:id">
+ <fo:inline id="{(@id|@xml:id)[1]}"/>
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:value-of select="primary"/>
+
+ <xsl:choose>
+ <xsl:when test="$xep.extensions != 0">
+ <xsl:if test="$refs[not(see) and not(secondary)]">
+ <xsl:copy-of select="$term.separator"/>
+ <xsl:variable name="primary" select="&primary;"/>
+ <xsl:variable name="primary.significant" select="concat(&primary;, $significant.flag)"/>
+ <rx:page-index list-separator="{$number.separator}"
+ range-separator="{$range.separator}">
+ <xsl:if test="$refs[@significance='preferred'][not(see) and not(secondary)]">
+ <rx:index-item xsl:use-attribute-sets="index.preferred.page.properties xep.index.item.properties"
+ ref-key="{$primary.significant}"/>
+ </xsl:if>
+ <xsl:if test="$refs[not(@significance) or @significance!='preferred'][not(see) and not(secondary)]">
+ <rx:index-item xsl:use-attribute-sets="xep.index.item.properties"
+ ref-key="{$primary}"/>
+ </xsl:if>
+ </rx:page-index>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="page-number-citations">
+ <xsl:for-each select="$refs[not(see)
+ and not(secondary)]">
+ <xsl:apply-templates select="." mode="reference">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:with-param name="position" select="position()"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:copy-of select="$page-number-citations"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$refs[not(secondary)]/*[self::see]">
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[&scope;][1])]"
+ mode="index-see">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </xsl:if>
+
+ </fo:block>
+
+ <xsl:if test="$refs/secondary or $refs[not(secondary)]/*[self::seealso]">
+ <fo:block start-indent="1pc">
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[&scope;][1])]"
+ mode="index-seealso">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]"
+ mode="index-secondary">
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </fo:block>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-see">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="see" select="normalize-space(see)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in see "primary, secondary" entry -->
+ <xsl:variable name="seeprimary">
+ <xsl:choose>
+ <xsl:when test="contains($see, ',')">
+ <xsl:value-of select="substring-before($see, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seetarget" select="key('primaryonly', $seeprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seetarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seetarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <fo:inline xmlns:xlink='http://www.w3.org/1999/xlink'>
+ <xsl:text> (</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'see'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="see/@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="see"/>
+ <xsl:with-param name="content" select="$see"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$see"/>
+ </xsl:when>
+ <xsl:when test="$seetarget">
+ <fo:basic-link internal-destination="{$linkend}"
+ xsl:use-attribute-sets="xref.properties">
+ <xsl:value-of select="$see"/>
+ </fo:basic-link>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+ </fo:inline>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-seealso">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:for-each select="seealso">
+ <xsl:sort select="translate(., &lowercase;, &uppercase;)"/>
+
+ <xsl:variable name="seealso" select="normalize-space(.)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in seealso "primary, secondary" entry -->
+ <xsl:variable name="seealsoprimary">
+ <xsl:choose>
+ <xsl:when test="contains($seealso, ',')">
+ <xsl:value-of select="substring-before($seealso, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seealsotarget" select="key('primaryonly', $seealsoprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seealsotarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seealsotarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <fo:block xmlns:xlink='http://www.w3.org/1999/xlink'>
+ <xsl:text>(</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'seealso'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="."/>
+ <xsl:with-param name="content" select="$seealso"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$seealso"/>
+ </xsl:when>
+ <xsl:when test="$seealsotarget">
+ <fo:basic-link internal-destination="{$linkend}"
+ xsl:use-attribute-sets="xref.properties">
+ <xsl:value-of select="$seealso"/>
+ </fo:basic-link>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+ </fo:block>
+
+ </xsl:for-each>
+
+</xsl:template>
+
+
</xsl:stylesheet>
diff --git a/doc/src/sgml/stylesheet-html-common.xsl b/doc/src/sgml/stylesheet-html-common.xsl
index a368e0e199..7f541c0988 100644
--- a/doc/src/sgml/stylesheet-html-common.xsl
+++ b/doc/src/sgml/stylesheet-html-common.xsl
@@ -436,4 +436,238 @@ set toc,title
</xsl:choose>
</xsl:template>
+<!-- make generated ids reproducible
+ (https://github.com/docbook/xslt10-stylesheets/issues/54) -->
+
+<!-- from html/autoidx.xsl -->
+
+<xsl:template match="indexterm" mode="index-primary">
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="key" select="&primary;"/>
+ <xsl:variable name="refs" select="key('primary', $key)[&scope;]"/>
+ <dt>
+ <xsl:if test="$autolink.index.see != 0">
+ <!-- add internal id attribute to form see and seealso links -->
+ <xsl:attribute name="id">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>ientry-</xsl:text>
+ <xsl:call-template name="object.id"/>
+ <!-- pgsql-docs: end -->
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="$refs/primary">
+ <xsl:if test="@id or @xml:id">
+ <xsl:choose>
+ <xsl:when test="$generate.id.attributes = 0">
+ <a name="{(@id|@xml:id)[1]}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <span>
+ <xsl:call-template name="id.attribute"/>
+ </span>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:value-of select="primary"/>
+ <xsl:choose>
+ <xsl:when test="$index.links.to.section = 1">
+ <xsl:for-each select="$refs[@zone != '' or generate-id() = generate-id(key('primary-section', concat($key, &sep;, §ion.id;))[&scope;][1])]">
+ <xsl:apply-templates select="." mode="reference">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="$refs[not(see)
+ and not(secondary)][&scope;]">
+ <xsl:apply-templates select="." mode="reference">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$refs[not(secondary)]/*[self::see]">
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see', concat(&primary;, &sep;, &sep;, &sep;, see))[&scope;][1])]"
+ mode="index-see">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(see, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </dt>
+ <xsl:choose>
+ <xsl:when test="$refs/secondary or $refs[not(secondary)]/*[self::seealso]">
+ <dd>
+ <dl>
+ <xsl:apply-templates select="$refs[generate-id() = generate-id(key('see-also', concat(&primary;, &sep;, &sep;, &sep;, seealso))[&scope;][1])]"
+ mode="index-seealso">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(seealso, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="$refs[secondary and count(.|key('secondary', concat($key, &sep;, &secondary;))[&scope;][1]) = 1]"
+ mode="index-secondary">
+ <xsl:with-param name="position" select="position()"/>
+ <xsl:with-param name="scope" select="$scope"/>
+ <xsl:with-param name="role" select="$role"/>
+ <xsl:with-param name="type" select="$type"/>
+ <xsl:sort select="translate(&secondary;, &lowercase;, &uppercase;)"/>
+ </xsl:apply-templates>
+ </dl>
+ </dd>
+ </xsl:when>
+ <!-- HTML5 requires dd for each dt -->
+ <xsl:when test="$div.element = 'section'">
+ <dd></dd>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-see" xmlns:xlink='http://www.w3.org/1999/xlink'>
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:variable name="see" select="normalize-space(see)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in see "primary, secondary" entry -->
+ <xsl:variable name="seeprimary">
+ <xsl:choose>
+ <xsl:when test="contains($see, ',')">
+ <xsl:value-of select="substring-before($see, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seetarget" select="key('primaryonly', $seeprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seetarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>#ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seetarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <xsl:text> (</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'see'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="see/@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="see"/>
+ <xsl:with-param name="content" select="$see"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$see"/>
+ </xsl:when>
+ <xsl:when test="$seetarget">
+ <a href="{$linkend}">
+ <xsl:value-of select="$see"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$see"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+</xsl:template>
+
+<xsl:template match="indexterm" mode="index-seealso" xmlns:xlink='http://www.w3.org/1999/xlink'>
+ <xsl:param name="scope" select="."/>
+ <xsl:param name="role" select="''"/>
+ <xsl:param name="type" select="''"/>
+
+ <xsl:for-each select="seealso">
+ <xsl:sort select="translate(., &lowercase;, &uppercase;)"/>
+
+ <xsl:variable name="seealso" select="normalize-space(.)"/>
+
+ <!-- can only link to primary, which should appear before comma
+ in seealso "primary, secondary" entry -->
+ <xsl:variable name="seealsoprimary">
+ <xsl:choose>
+ <xsl:when test="contains($seealso, ',')">
+ <xsl:value-of select="substring-before($seealso, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="seealsotarget" select="key('primaryonly', $seealsoprimary)[1]"/>
+
+ <xsl:variable name="linkend">
+ <xsl:if test="$seealsotarget">
+ <!-- pgsql-docs: begin -->
+ <xsl:text>#ientry-</xsl:text>
+ <xsl:call-template name="object.id">
+ <xsl:with-param name="object" select="$seealsotarget"/>
+ </xsl:call-template>
+ <!-- pgsql-docs: end -->
+ </xsl:if>
+ </xsl:variable>
+
+ <dt>
+ <xsl:text>(</xsl:text>
+ <xsl:call-template name="gentext">
+ <xsl:with-param name="key" select="'seealso'"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:choose>
+ <!-- manual links have precedence -->
+ <xsl:when test="@linkend or see/@xlink:href">
+ <xsl:call-template name="simple.xlink">
+ <xsl:with-param name="node" select="."/>
+ <xsl:with-param name="content" select="$seealso"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$autolink.index.see = 0">
+ <xsl:value-of select="$seealso"/>
+ </xsl:when>
+ <xsl:when test="$seealsotarget">
+ <a href="{$linkend}">
+ <xsl:value-of select="$seealso"/>
+ </a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$seealso"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>)</xsl:text>
+ </dt>
+
+ <xsl:if test="$div.element = 'section'">
+ <dd></dd>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
</xsl:stylesheet>
--
2.41.0
view thread (4+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: Make documentation builds reproducible
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox