root/docs/docbook-xsl/manpages/links.xsl

Revision 23dea7e00df87480acb58bb3398283c2bb227949, 16.4 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

pull docs into master

  • Property mode set to 100644
Line 
1 <?xml version='1.0'?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3                 xmlns:exsl="http://exslt.org/common"
4                 version='1.0'>
5
6 <!-- ********************************************************************
7      $Id: links.xsl,v 1.4 2005/07/14 11:38:18 xmldoc Exp $
8      ********************************************************************
9
10      This file is part of the XSL DocBook Stylesheet distribution.
11      See ../README or http://docbook.sf.net/release/xsl/current/ for
12      copyright and other information.
13
14      ******************************************************************** -->
15
16 <!-- ==================================================================== -->
17
18 <!-- * Make per-Refentry sets of all links in each Refentry which do not -->
19 <!-- * have the same URL as any preceding link in that same Refentry -->
20 <!-- * -->
21 <!-- * We need this in order to have inline numbering match the -->
22 <!-- * numbering of the link list. In both places, for any link whose -->
23 <!-- * URL is a duplicate of that of a preceding link in the same -->
24 <!-- * Refentry, we assign it the number of that previous link. -->
25 <!-- * -->
26 <!-- * Note that we don't get links in *info sections or Refmeta or -->
27 <!-- * Refnamediv or Indexterm, because, in manpages output, contents -->
28 <!-- * of those are either suppressed or are displayed out of document -->
29 <!-- * order - for example, the Info/Author content gets moved to the -->
30 <!-- * end of the page. So, if we were to number links in the Author -->
31 <!-- * content, it would "throw off" the numbering at the beginning of -->
32 <!-- * the main text flow. -->
33 <!-- * -->
34 <!-- * And note especially that the reason we don't use xsl:key here -->
35 <!-- * is that the "match" value is an XSLT _pattern_, not an XSLT -->
36 <!-- * _expression_; XSLT patterns can't contain function calls, but -->
37 <!-- * XSLT expressions can. We need the calls to the generate-id() -->
38 <!-- * function in order to determine whether or not two links have -->
39 <!-- * the same Refentry parent -->
40 <xsl:variable name="get.all.links.with.unique.urls">
41   <xsl:if test="$man.links.are.numbered != 0">
42     <xsl:for-each select="//refentry">
43       <refentry.link.set>
44         <xsl:attribute name="idref">
45           <xsl:value-of select="generate-id()"/>
46         </xsl:attribute>
47         <xsl:for-each
48             select=".//ulink[node()
49                     and not(ancestor::refentryinfo)
50                     and not(ancestor::info)
51                     and not(ancestor::docinfo)
52                     and not(ancestor::refmeta)
53                     and not(ancestor::refnamediv)
54                     and not(ancestor::indexterm)
55                     and not(@url =
56                     preceding::ulink[node()
57                     and not(ancestor::refentryinfo)
58                     and not(ancestor::info)
59                     and not(ancestor::docinfo)
60                     and not(ancestor::refmeta)
61                     and not(ancestor::refnamediv)
62                     and not(ancestor::indexterm)
63                     and (generate-id(ancestor::refentry)
64                     = generate-id(current()))]/@url)]">
65           <link>
66             <xsl:attribute name="url">
67               <xsl:value-of select="@url"/>
68             </xsl:attribute>
69             <xsl:copy>
70               <xsl:copy-of select="node()"/>
71             </xsl:copy>
72           </link>
73         </xsl:for-each>
74       </refentry.link.set>
75     </xsl:for-each>
76   </xsl:if>
77 </xsl:variable>
78
79 <xsl:variable name="all.links.with.unique.urls"
80               select="exsl:node-set($get.all.links.with.unique.urls)"/>
81
82 <!-- ==================================================================== -->
83
84 <!-- * We first find out if the link is empty; if it is, we just -->
85 <!-- * display the contents of its URL (that is, the value of its "Url" -->
86 <!-- * attribute), and stop there. -->
87 <!-- * -->
88 <!-- * On the other hand, if it is NON-empty, we need to display its -->
89 <!-- * contents AND (optionally) display its URL. We could display the -->
90 <!-- * URL inline, after the contents (as we did previously), but that -->
91 <!-- * ends up looking horrible if you have a lot of links. -->
92 <!-- * -->
93 <!-- * So, we instead need to display the URL out-of-line, in a way -->
94 <!-- * that associates it with the content. How to do that in a -->
95 <!-- * text-based output format that lacks hyperlinks? -->
96 <!-- * -->
97 <!-- * Here's how: Do it the way that most text/curses-based browsers -->
98 <!-- * (e.g., w3m and lynx) do in the "-dump" output: Put a number -->
99 <!-- * (in brackets) before the contents, and then put the URL, with -->
100 <!-- * the corresponding number, in a generated section -->
101 <!-- * at the end of the page. -->
102 <!-- * -->
103 <!-- * For any link whose URL is a duplicate of that of a preceding -->
104 <!-- * link in the same Refentry, we assign it the number of that -->
105 <!-- * previous link. -->
106 <xsl:template match="ulink">
107   <xsl:variable name="get.links.with.unique.urls">
108     <!-- * get the set of all unique links in the ancestor Refentry of -->
109     <!-- * this Ulink -->
110     <xsl:copy-of
111         select="$all.links.with.unique.urls/refentry.link.set
112                 [@idref = generate-id(current()/ancestor::refentry)]/link"/>
113   </xsl:variable>
114   <xsl:variable name="links.with.unique.urls"
115                 select="exsl:node-set($get.links.with.unique.urls)"/>
116   <!-- * store link URL in variable because we check it multiple times -->
117   <xsl:variable name="url">
118     <xsl:value-of select="@url"/>
119   </xsl:variable>
120   <!-- * $link is either the link contents (if the link is non-empty) or -->
121   <!-- * the URL (if the link is empty -->
122   <xsl:variable name="link">
123     <xsl:choose>
124       <!-- * check to see if the element is empty or not; if it's non-empty, -->
125       <!-- * get the content -->
126       <xsl:when test="node()">
127         <xsl:apply-templates/>
128       </xsl:when>
129       <xsl:otherwise>
130         <!-- * The element is empty, so we just get the value of the URL; -->
131         <!-- * note that we don't number empty links -->
132         <!-- * -->
133         <!-- * Add hyphenation suppression in URL output only if -->
134         <!-- * break.after.slash is also non-zero -->
135         <xsl:if test="$man.hyphenate.urls = 0 and
136                       $man.break.after.slash = 0">
137           <xsl:call-template name="suppress.hyphenation"/>
138           <xsl:text>\%</xsl:text>
139         </xsl:if>
140         <xsl:value-of select="$url"/>
141       </xsl:otherwise>
142     </xsl:choose>
143   </xsl:variable>
144   <!-- * if link is non-empty AND user wants links numbered, output -->
145   <!-- * a number for it -->
146   <xsl:if test="node() and $man.links.are.numbered != 0">
147     <!-- * We number links by checking the $links.with.unique.urls set -->
148     <!-- * and finding the link whose URL matches the URL for this -->
149     <!-- * link. If this is the only instance in this Refentry of a link -->
150     <!-- * with this URL, then it gets a unique number. But if this is a -->
151     <!-- * link for which there are multiple instances of links in this -->
152     <!-- * Refentry that have the same URL as this link, then the number -->
153     <!-- * assigned is the number of the _first_ instance of a link in -->
154     <!-- * this Refentry with the URL for this link (which be the number -->
155     <!-- * of this link itself, if it happens to be the first instance). -->
156     <xsl:variable name="link.number">
157       <xsl:apply-templates
158           select="$links.with.unique.urls/link[@url = $url][1]"
159           mode="link.number"/>
160     </xsl:variable>
161     <!-- * format the number by placing it in square brackets. This -->
162     <!-- * formatting could be made user-configurable - something -->
163     <!-- * other than square brackets. But what else would work? -->
164     <!-- * <10> Angle brackets? {10} Braces? -->
165     <xsl:text>[</xsl:text>
166     <xsl:value-of select="$link.number"/>
167     <xsl:text>]\&amp;</xsl:text>
168     <!-- * Note that the reason for the \& after the closing bracket -->
169     <!-- * is to prevent a hyphen character from being rendered -->
170     <!-- * between the closing bracket and the following text - even -->
171     <!-- * when the following text is preceded by a "hyphenation -->
172     <!-- * character"; for example: -->
173     <!-- * -->
174     <!-- *  [26]\&\fI\%COUNTRY\fR\fR -->
175     <!-- * -->
176     <!-- * Where COUNTRY is marked up with as <envar>COUNTRY</envar> -->
177     <!-- * in the source (we generate \% before all Envar output (and -->
178     <!-- * all other "computer inlines") to prevent it from being -->
179     <!-- * broken across lines. -->
180     <!-- * -->
181     <!-- * Without the \& after the closing bracket, if the -->
182     <!-- * [26]\fI\%COUNTRY\fR\fR instance fell at the end of a line, -->
183     <!-- * a hyphen could end up being inserted; for example: -->
184     <!-- * -->
185     <!-- *   if you are uncertain, check the value of the [26]- -->
186     <!-- *   COUNTRY environment variable -->
187     <!-- * -->
188     <!-- * The \& causes [26]COUNTRY to be treated as a unit, -->
189     <!-- * preventing insertion of the stray hyphen. -->
190   </xsl:if>
191   <xsl:choose>
192     <!-- * if user wants links underlined, underline (ital) it -->
193     <xsl:when test="$man.links.are.underlined != 0">
194       <xsl:variable name="link.wrapper">
195         <italic><xsl:value-of select="$link"/></italic>
196       </xsl:variable>
197       <xsl:apply-templates mode="italic" select="exsl:node-set($link.wrapper)"/>
198     </xsl:when>
199     <xsl:otherwise>
200       <!-- * user doesn't want links underlined, so just display content -->
201       <xsl:value-of select="$link"/>
202     </xsl:otherwise>
203   </xsl:choose>
204 </xsl:template>
205
206 <!-- ==================================================================== -->
207
208 <xsl:template match="*" mode="link.number">
209   <!-- * Count all links in this Refentry which do not have the same -->
210   <!-- * URL as any preceding link in this same Refentry -->
211   <!-- * -->
212   <!-- * Note that we don't get links in *info sections or Refmeta or -->
213   <!-- * Refnamediv or Indexterm, because, in manpages output, -->
214   <!-- * contents of those are either suppressed or are displayed out -->
215   <!-- * of document order -->
216   <!-- * -->
217   <!-- * And note that the reason we don't just use xsl:number here -->
218   <!-- * is that the "match" value is an XSLT _pattern_, not an XSLT -->
219   <!-- * _expression_; XSLT patterns can't contain function calls, but -->
220   <!-- * XSLT expressions can. We need the calls to the generate-id() -->
221   <!-- * function in order to determine whether or not two links have -->
222   <!-- * the same Refentry parent -->
223   <xsl:value-of select="count(preceding::ulink[node()
224                         and not(ancestor::refentryinfo)
225                         and not(ancestor::info)
226                         and not(ancestor::docinfo)
227                         and not(ancestor::refmeta)
228                         and not(ancestor::refnamediv)
229                         and not(ancestor::indexterm)
230                         and not(@url =
231                         preceding::ulink[node()
232                         and not(ancestor::refentryinfo)
233                         and not(ancestor::info)
234                         and not(ancestor::docinfo)
235                         and not(ancestor::refmeta)
236                         and not(ancestor::refnamediv)
237                         and not(ancestor::indexterm)
238                         and (generate-id(ancestor::refentry)
239                         = generate-id(current()/ancestor::refentry))]/@url)]
240                         [generate-id(ancestor::refentry)
241                         = generate-id(current()/ancestor::refentry)]) + 1"/>
242 </xsl:template>
243
244 <!-- ==================================================================== -->
245
246 <xsl:template name="links.list">
247   <!-- * Get all links in this Refentry which do not have the same URL -->
248   <!-- * as any preceding link in this same Refentry -->
249   <!-- * -->
250   <!-- * Note that we don't get links in *info sections or Refmeta or -->
251   <!-- * Refnamediv or Indexterm, because, in manpages output, -->
252   <!-- * contents of those are either suppressed or are displayed out -->
253   <!-- * of document order -->
254   <xsl:variable name="links"
255                 select=".//ulink[node()
256                   and not(ancestor::refentryinfo)
257                   and not(ancestor::info)
258                   and not(ancestor::docinfo)
259                   and not(ancestor::refmeta)
260                   and not(ancestor::refnamediv)
261                   and not(ancestor::indexterm)
262                   and not(@url =
263                   preceding::ulink[node()
264                   and not(ancestor::refentryinfo)
265                   and not(ancestor::info)
266                   and not(ancestor::docinfo)
267                   and not(ancestor::refmeta)
268                   and not(ancestor::refnamediv)
269                   and not(ancestor::indexterm)
270                   and (generate-id(ancestor::refentry)
271                   = generate-id(current()))]/@url)]"/>
272   <!-- * check to see if we have actually found any links; if we have, -->
273   <!-- * we generate the links list, if not, we do nothing -->
274   <xsl:if test="$links/node()">
275     <xsl:call-template name="format.links.list">
276       <xsl:with-param name="links" select="$links"/>
277     </xsl:call-template>
278   </xsl:if>
279 </xsl:template>
280
281 <!-- ==================================================================== -->
282
283 <xsl:template name="format.links.list">
284   <xsl:param name="links"/>
285   <!-- * The value of $padding.length is used for determining how much -->
286   <!-- * to right-pad numbers in the LINKS list. So, for $length, we -->
287   <!-- * count how many links there are, then take the number of digits -->
288   <!-- * in that count, and add 2 to it. The reason we add 2 is that we -->
289   <!-- * also prepend a dot and no-break space to each link number in -->
290   <!-- * the list, so we need to consider what length to pad out to. -->
291   <xsl:param name="padding.length">
292     <xsl:choose>
293       <xsl:when test="$man.links.are.numbered != 0">
294         <xsl:value-of select="string-length(count($links)) + 2"/>
295       </xsl:when>
296       <xsl:otherwise>
297         <!-- * if links aren't numbered, just set padding to zero -->
298         <xsl:value-of select="0"/>
299       </xsl:otherwise>
300     </xsl:choose>
301   </xsl:param>
302   <xsl:call-template name="mark.subheading"/>
303   <!-- * make the link-list section heading (REFERENCES) -->
304   <xsl:text>.SH "</xsl:text>
305   <xsl:call-template name="string.upper">
306     <xsl:with-param name="string">
307       <xsl:choose>
308         <!-- * if user has specified a heading, use that -->
309         <xsl:when test="$man.links.list.heading != ''">
310           <xsl:value-of select="$man.links.list.heading"/>
311         </xsl:when>
312         <xsl:otherwise>
313           <!-- * otherwise, get localized heading from gentext -->
314           <xsl:call-template name="gentext">
315             <xsl:with-param name="key" select="'References'"/>
316           </xsl:call-template>
317         </xsl:otherwise>
318       </xsl:choose>
319     </xsl:with-param>
320   </xsl:call-template>
321   <xsl:text>"&#10;</xsl:text>
322   <xsl:for-each select="$links">
323     <!-- * number the link, in the form " 1." followed by a -->
324     <!-- * non-breaking space; -->
325     <xsl:variable name="link.number">
326       <xsl:apply-templates select="." mode="link.number"/>
327       <xsl:text>.&#160;</xsl:text>
328     </xsl:variable>
329     <!-- * make paragraph with hanging indent; length of indent is -->
330     <!-- * same as value of $padding.length -->
331     <xsl:text>.TP </xsl:text>
332     <xsl:value-of select="$padding.length"/>
333     <xsl:text>&#10;</xsl:text>
334     <!-- * right-pad each number out to the correct length -->
335     <!-- * So, if there are 10 or more links, numbers -->
336     <!-- * 1 through 9 will have a space in front of them; if -->
337     <!-- * there are 100 or more, 1 through 9 will have two -->
338     <!-- * spaces, 10 through 99 will have one space, etc. -->
339     <xsl:call-template name="prepend-pad">
340       <xsl:with-param name="padVar" select="$link.number"/>
341       <xsl:with-param name="length" select="$padding.length"/>
342     </xsl:call-template>
343     <!-- * Print the links contents -->
344     <!-- * IMPORTANT: If there are multiple links in this Refentry -->
345     <!-- * with the same URL, this gets the contents of the _first -->
346     <!-- * instance_ of the link in this Refentry with that URL -->
347     <xsl:variable name="link.contents">
348       <xsl:value-of select="."/>
349     </xsl:variable>
350     <xsl:value-of select="normalize-space($link.contents)"/>
351     <xsl:text>&#10;</xsl:text>
352     <!-- * Print the link's URL -->
353     <!-- * Add hyphenation suppression in URL output only if -->
354     <!-- * break.after.slash is also non-zero -->
355     <xsl:if test="$man.hyphenate.urls = 0 and
356                   $man.break.after.slash = 0">
357       <xsl:call-template name="suppress.hyphenation"/>
358       <xsl:text>\%</xsl:text>
359     </xsl:if>
360     <xsl:value-of select="@url"/>
361     <xsl:text>&#10;</xsl:text>
362   </xsl:for-each>
363 </xsl:template>
364
365 </xsl:stylesheet>
Note: See TracBrowser for help on using the browser.