doc: Make HTML ids discoverable
authorPeter Eisentraut <[email protected]>
Thu, 13 Apr 2023 08:15:20 +0000 (10:15 +0200)
committerPeter Eisentraut <[email protected]>
Thu, 13 Apr 2023 08:16:33 +0000 (10:16 +0200)
In the HTML output, this decorates section headers and variable list
terms with a marker ("#") that is a link to the same section/term.
That way, links inside a page can be discovered for easier sharing.
The marker only appears when hovering.

This now requires that all elements that are candidates for such a
link have an id attribute.  Otherwise, an error will be generated.
All previously missing ids have been added prior to this .

Author: Brar Piening <[email protected]>
Reviewed-by: Karl O. Pinc <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/CAB8KJ=jpuQU9QJe4+RgWENrK5g9jhoysMw2nvTN_esoOU0=a_w@mail.gmail.com

doc/src/sgml/stylesheet-html-common.xsl
doc/src/sgml/stylesheet.css

index bb6429ef7cf63a0d4bfe91d40109feb883e3f5d9..a368e0e199087fa4b5e0c1fb6f82367cd60e07de 100644 (file)
@@ -309,4 +309,131 @@ set       toc,title
   </xsl:choose>
 </xsl:template>
 
+
+<!-- Add an id link to each section heading. -->
+
+<!-- from html/sections.xsl -->
+<xsl:template name="section.heading">
+  <xsl:param name="section" select="."/>
+  <xsl:param name="level" select="1"/>
+  <xsl:param name="allow-anchors" select="1"/>
+  <xsl:param name="title"/>
+  <xsl:param name="class" select="'title'"/>
+
+  <xsl:variable name="id">
+    <xsl:choose>
+      <!-- Make sure the subtitle doesn't get the same id as the title -->
+      <xsl:when test="self::subtitle">
+        <xsl:call-template name="object.id">
+          <xsl:with-param name="object" select="."/>
+        </xsl:call-template>
+      </xsl:when>
+      <!-- if title is in an *info wrapper, get the grandparent -->
+      <xsl:when test="contains(local-name(..), 'info')">
+        <xsl:call-template name="object.id">
+          <xsl:with-param name="object" select="../.."/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="object.id">
+          <xsl:with-param name="object" select=".."/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <!-- HTML H level is one higher than section level -->
+  <xsl:variable name="hlevel">
+    <xsl:choose>
+      <!-- highest valid HTML H level is H6; so anything nested deeper
+           than 5 levels down just becomes H6 -->
+      <xsl:when test="$level &gt; 5">6</xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$level + 1"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+  <xsl:element name="h{$hlevel}" namespace="http://www.w3.org/1999/xhtml">
+    <xsl:attribute name="class"><xsl:value-of select="$class"/></xsl:attribute>
+    <xsl:if test="$css.decoration != '0'">
+      <xsl:if test="$hlevel&lt;3">
+        <xsl:attribute name="style">clear: both</xsl:attribute>
+      </xsl:if>
+    </xsl:if>
+    <xsl:if test="$allow-anchors != 0">
+      <xsl:call-template name="anchor">
+        <xsl:with-param name="node" select="$section"/>
+        <xsl:with-param name="conditional" select="0"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:copy-of select="$title"/>
+    <!-- pgsql-docs: begin -->
+    <xsl:call-template name="pg.id.link">
+      <xsl:with-param name="object" select="$section"/>
+    </xsl:call-template>
+    <!-- pgsql-docs: end -->
+  </xsl:element>
+</xsl:template>
+
+
+<!-- Add an id link after the last term of a varlistentry. -->
+
+<!-- overrides html/lists.xsl -->
+<xsl:template match="varlistentry/term">
+  <xsl:apply-imports/>
+
+  <!-- Add the link after the last term -->
+  <xsl:if test="position() = last()">
+    <xsl:call-template name="pg.id.link">
+      <xsl:with-param name="object" select="parent::varlistentry"/>
+    </xsl:call-template>
+  </xsl:if>
+</xsl:template>
+
+
+<!-- Create a link pointing to an id within the document -->
+<xsl:template name="pg.id.link">
+  <xsl:param name="object" select="."/>
+  <xsl:choose>
+    <xsl:when test="$object/@id or $object/@xml:id">
+      <xsl:text> </xsl:text>
+      <a>
+        <xsl:attribute name="href">
+          <xsl:text>#</xsl:text>
+          <xsl:call-template name="object.id">
+            <xsl:with-param name="object" select="$object"/>
+          </xsl:call-template>
+        </xsl:attribute>
+        <xsl:attribute name="class">
+          <xsl:text>id_link</xsl:text>
+        </xsl:attribute>
+        <xsl:text>#</xsl:text>
+      </a>
+    </xsl:when>
+    <xsl:otherwise>
+      <!-- Only complain about varlistentries if at least one entry in
+           the list has an id -->
+      <xsl:if test="name($object) != 'varlistentry'
+                    or $object/parent::variablelist/varlistentry[@id]">
+        <xsl:message terminate="yes">
+          <xsl:text>ERROR: id attribute missing on &lt;</xsl:text>
+          <xsl:value-of select ="name($object)"/>
+          <xsl:text>&gt; element under </xsl:text>
+          <xsl:for-each select="$object/ancestor::*">
+            <xsl:text>/</xsl:text>
+            <xsl:value-of select ="name(.)"/>
+            <xsl:if test="@id|@xml:id">
+              <xsl:text>[@</xsl:text>
+              <xsl:value-of select ="name(@id|@xml:id)"/>
+              <xsl:text> = '</xsl:text>
+              <xsl:value-of select ="@id"/>
+              <xsl:text>']</xsl:text>
+            </xsl:if>
+          </xsl:for-each>
+        </xsl:message>
+      </xsl:if>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
 </xsl:stylesheet>
index cc14efa1ca3ca10834940033a7b367bde287cd62..86a8edb9268709991e40591592508169ebbce4ab 100644 (file)
@@ -169,3 +169,14 @@ acronym        { font-style: inherit; }
     width: 75%;
   }
 }
+
+/* links to ids of headers and definition terms */
+
+a.id_link {
+   color: inherit;
+   visibility: hidden;
+}
+
+*:hover > a.id_link {
+   visibility: visible;
+}