]> granicus.if.org Git - docbook-dsssl/commitdiff
Fixed a bug that caused broken links in some TOCs.
authorMichael Smith <xmldoc@users.sourceforge.net>
Thu, 19 Jul 2007 07:17:45 +0000 (07:17 +0000)
committerMichael Smith <xmldoc@users.sourceforge.net>
Thu, 19 Jul 2007 07:17:45 +0000 (07:17 +0000)
This change affects the code for generating links in HTML output.
It adds a new optional "toc.context" parameter to the href.target
template, and based on the value of that parameter, handles
link-generation in TOCs differently under a certain condition.

The gory details:

  The code now checks to see if the output dir of any file being
  linked to in a particular TOC is different from the output dir
  the TOC is written to. If it is different, we do not call the
  trim.common.uri.paths[1] template.

  The reason is that, given the following case:

  1. we are chunking into separate dirs

  2. output for the TOC is written to current dir, but the file
     being linked to is written to some subdir "foo".

  For that case, links to that file in that TOC did not show
  the correct path - they omitted the "foo".

  The cause of that problem was that the trim.common.uri.paths
  template was being called under all conditions. But it's
  apparent that we don't want to call trim.common.uri.paths in
  the case where a linked file is being written to a different
  directory than the TOC that contains the link, because doing
  so will cause a necessary (not redundant) directory-name
  part of the link to get inadvertently trimmed, resulting in
  a broken link to that file.

  Thus, the conditional check was added to catch this case and to
  handle it differently

  [1] The purpose of the trim.common.uri.paths template is to
  prevent cases where, if we didn't call it, we end up with
  unnecessary, redundant directory names getting output; for
  example, "foo/foo/refname.html".

xsl/html/autotoc.xsl
xsl/html/chunk-common.xsl

index 767f1a66d5ad08f454977d8135784c08cf1ceea3..fabb2ecc7872583fa98fdf55cd38d82ebca946e4 100644 (file)
     <xsl:attribute name="href">
       <xsl:call-template name="href.target">
         <xsl:with-param name="context" select="$toc-context"/>
+        <xsl:with-param name="toc-context" select="$toc-context"/>
       </xsl:call-template>
     </xsl:attribute>
     
     <span class='refentrytitle'>
       <a>
         <xsl:attribute name="href">
-          <xsl:call-template name="href.target"/>
+          <xsl:call-template name="href.target">
+            <xsl:with-param name="toc-context" select="$toc-context"/>
+          </xsl:call-template>
         </xsl:attribute>
         <xsl:copy-of select="$title"/>
       </a>
     <xsl:attribute name="href">
       <xsl:call-template name="href.target">
         <xsl:with-param name="object" select=".."/>
+        <xsl:with-param name="toc-context" select="$toc-context"/>
       </xsl:call-template>
     </xsl:attribute>
     <xsl:apply-templates/>
         <xsl:attribute name="href">
           <xsl:call-template name="href.target">
             <xsl:with-param name="object" select="$node"/>
+            <xsl:with-param name="toc-context" select="$toc-context"/>
           </xsl:call-template>
         </xsl:attribute>
         <xsl:apply-templates select="$node" mode="titleabbrev.markup"/>
     </xsl:if>
     <a>
       <xsl:attribute name="href">
-        <xsl:call-template name="href.target"/>
+        <xsl:call-template name="href.target">
+          <xsl:with-param name="toc-context" select="$toc-context"/>
+        </xsl:call-template>
       </xsl:attribute>
       <xsl:apply-templates select="." mode="titleabbrev.markup"/>
     </a>
index a6669e33b7fdc77c683b2cb94c35fac090d58c94..f368af134b1719faf3e9b8697b1403b5225a56dd 100644 (file)
 <xsl:template name="href.target">
   <xsl:param name="context" select="."/>
   <xsl:param name="object" select="."/>
-
+  <xsl:param name="toc-context" select="."/>
+  <!-- * If $toc-context contains some node other than the current node, -->
+  <!-- * it means we're processing a link in a TOC. In that case, to -->
+  <!-- * ensure the link will work correctly, we need to take a look at -->
+  <!-- * where the file containing the TOC will get written, and where -->
+  <!-- * the file that's being linked to will get written. -->
+  <xsl:variable name="toc-output-dir">
+    <xsl:if test="not($toc-context = .)">
+      <!-- * Get the $toc-context node and all its ancestors, look down -->
+      <!-- * through them to find the last/closest node to the -->
+      <!-- * toc-context node that has a "dbhtml dir" PI, and get the -->
+      <!-- * directory name from that. That's the name of the directory -->
+      <!-- * to which the current toc output file will get written. -->
+      <xsl:call-template name="dbhtml-dir">
+        <xsl:with-param name="context"
+          select="$toc-context/ancestor-or-self::*[processing-instruction('dbhtml')[contains(.,'dir')]][last()]"/>
+      </xsl:call-template>
+    </xsl:if>
+  </xsl:variable>
+  <xsl:variable name="linked-file-output-dir">
+    <xsl:if test="not($toc-context = .)">
+      <!-- * Get the current node and all its ancestors, look down -->
+      <!-- * through them to find the last/closest node to the current -->
+      <!-- * node that has a "dbhtml dir" PI, and get the directory name -->
+      <!-- * from that.  That's the name of the directory to which the -->
+      <!-- * file that's being linked to will get written. -->
+      <xsl:call-template name="dbhtml-dir">
+        <xsl:with-param name="context"
+          select="ancestor-or-self::*[processing-instruction('dbhtml')[contains(.,'dir')]][last()]"/>
+      </xsl:call-template>
+    </xsl:if>
+  </xsl:variable>
   <xsl:variable name="href.to.uri">
     <xsl:call-template name="href.target.uri">
       <xsl:with-param name="object" select="$object"/>
     </xsl:call-template>
   </xsl:variable>
-
   <xsl:variable name="href.from.uri">
     <xsl:call-template name="href.target.uri">
       <xsl:with-param name="object" select="$context"/>
     </xsl:call-template>
   </xsl:variable>
-  
-  <!--
-  <xsl:message>href.to.uri: <xsl:value-of select="$href.to.uri"/></xsl:message>
-  <xsl:message>href.from.uri: <xsl:value-of select="$href.from.uri"/></xsl:message>
-  -->
-
+  <!-- * <xsl:message>toc-context: <xsl:value-of select="local-name($toc-context)"/></xsl:message> -->
+  <!-- * <xsl:message>node: <xsl:value-of select="local-name(.)"/></xsl:message> -->
+  <!-- * <xsl:message>context: <xsl:value-of select="local-name($context)"/></xsl:message> -->
+  <!-- * <xsl:message>object: <xsl:value-of select="local-name($object)"/></xsl:message> -->
+  <!-- * <xsl:message>toc-output-dir: <xsl:value-of select="$toc-output-dir"/></xsl:message> -->
+  <!-- * <xsl:message>linked-file-output-dir: <xsl:value-of select="$linked-file-output-dir"/></xsl:message> -->
+  <!-- * <xsl:message>href.to.uri: <xsl:value-of select="$href.to.uri"/></xsl:message> -->
+  <!-- * <xsl:message>href.from.uri: <xsl:value-of select="$href.from.uri"/></xsl:message> -->
   <xsl:variable name="href.to">
-    <xsl:call-template name="trim.common.uri.paths">
-      <xsl:with-param name="uriA" select="$href.to.uri"/>
-      <xsl:with-param name="uriB" select="$href.from.uri"/>
-      <xsl:with-param name="return" select="'A'"/>
-    </xsl:call-template>
+    <xsl:choose>
+      <!-- * 2007-07-19, MikeSmith: Added the following conditional to -->
+      <!-- * deal with a problem case for links in TOCs. It checks to see -->
+      <!-- * if the output dir that a TOC will get written to is -->
+      <!-- * different from the output dir of the file being linked to. -->
+      <!-- * If it is different, we do not call trim.common.uri.paths. -->
+      <!-- *  -->
+      <!-- * Reason why I added that conditional is: I ran into a bug for -->
+      <!-- * this case: -->
+      <!-- *  -->
+      <!-- * 1. we are chunking into separate dirs -->
+      <!-- *  -->
+      <!-- * 2. output for the TOC is written to current dir, but the file -->
+      <!-- *    being linked to is written to some subdir "foo". -->
+      <!-- *  -->
+      <!-- * For that case, links to that file in that TOC did not show -->
+      <!-- * the correct path - they omitted the "foo". -->
+      <!-- *  -->
+      <!-- * The cause of that problem was that the trim.common.uri.paths -->
+      <!-- * template[1] was being called under all conditions. But it's -->
+      <!-- * apparent that we don't want to call trim.common.uri.paths in -->
+      <!-- * the case where a linked file is being written to a different -->
+      <!-- * directory than the TOC that contains the link, because doing -->
+      <!-- * so will cause a necessary (not redundant) directory-name -->
+      <!-- * part of the link to get inadvertently trimmed, resulting in -->
+      <!-- * a broken link to that file. Thus, added the conditional. -->
+      <!-- *  -->
+      <!-- * [1] The purpose of the trim.common.uri.paths template is to -->
+      <!-- * prevent cases where, if we didn't call it, we end up with -->
+      <!-- * unnecessary, redundant directory names getting output; for -->
+      <!-- * example, "foo/foo/refname.html". -->
+      <xsl:when test="not($toc-output-dir = $linked-file-output-dir)">
+        <xsl:value-of select="$href.to.uri"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="trim.common.uri.paths">
+          <xsl:with-param name="uriA" select="$href.to.uri"/>
+          <xsl:with-param name="uriB" select="$href.from.uri"/>
+          <xsl:with-param name="return" select="'A'"/>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
   </xsl:variable>
-
   <xsl:variable name="href.from">
     <xsl:call-template name="trim.common.uri.paths">
       <xsl:with-param name="uriA" select="$href.to.uri"/>
       <xsl:with-param name="return" select="'B'"/>
     </xsl:call-template>
   </xsl:variable>
-
   <xsl:variable name="depth">
     <xsl:call-template name="count.uri.path.depth">
       <xsl:with-param name="filename" select="$href.from"/>
     </xsl:call-template>
   </xsl:variable>
-
   <xsl:variable name="href">
     <xsl:call-template name="copy-string">
       <xsl:with-param name="string" select="'../'"/>
     </xsl:call-template>
     <xsl:value-of select="$href.to"/>
   </xsl:variable>
-
   <!--
   <xsl:message>
     <xsl:text>In </xsl:text>
     <xsl:value-of select="$href"/>
   </xsl:message>
   -->
-
   <xsl:value-of select="$href"/>
 </xsl:template>