]> git.stg.codes - stg.git/blob - doc/xslt/html/html.xsl
[NY] Code deduplication.
[stg.git] / doc / xslt / html / html.xsl
1 <?xml version='1.0'?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3                 version='1.0'>
4
5 <!-- ********************************************************************
6      $Id: html.xsl 8556 2009-12-11 00:05:45Z bobstayton $
7      ********************************************************************
8
9      This file is part of the XSL DocBook Stylesheet distribution.
10      See ../README or http://docbook.sf.net/release/xsl/current/ for
11      copyright and other information.
12
13      ******************************************************************** -->
14
15 <!-- These variables set the align attribute value for HTML output based on
16      the writing-mode specified in the gentext file for the document's lang. -->
17
18 <xsl:variable name="direction.align.start">
19   <xsl:choose>
20     <xsl:when test="starts-with($writing.mode, 'lr')">left</xsl:when>
21     <xsl:when test="starts-with($writing.mode, 'rl')">right</xsl:when>
22     <xsl:otherwise>left</xsl:otherwise>
23   </xsl:choose>
24 </xsl:variable>
25
26 <xsl:variable name="direction.align.end">
27   <xsl:choose>
28     <xsl:when test="starts-with($writing.mode, 'lr')">right</xsl:when>
29     <xsl:when test="starts-with($writing.mode, 'rl')">left</xsl:when>
30     <xsl:otherwise>right</xsl:otherwise>
31   </xsl:choose>
32 </xsl:variable>
33
34 <xsl:variable name="direction.mode">
35   <xsl:choose>
36     <xsl:when test="starts-with($writing.mode, 'lr')">ltr</xsl:when>
37     <xsl:when test="starts-with($writing.mode, 'rl')">rtl</xsl:when>
38     <xsl:otherwise>ltr</xsl:otherwise>
39   </xsl:choose>
40 </xsl:variable>
41
42 <!-- The generate.html.title template is currently used for generating HTML -->
43 <!-- "title" attributes for some inline elements only, but not for any -->
44 <!-- block elements. It is called in eleven places in the inline.xsl -->
45 <!-- file. But it's called by all the inline.* templates (e.g., -->
46 <!-- inline.boldseq), which in turn are called by other (element) -->
47 <!-- templates, so it results, currently, in supporting generation of the -->
48 <!-- HTML "title" attribute for a total of about 92 elements. -->
49 <!-- You can use mode="html.title.attribute" to get a title for -->
50 <!-- an element specified by a param, including targets of cross references. -->
51 <xsl:template name="generate.html.title">
52   <xsl:apply-templates select="." mode="html.title.attribute"/>
53 </xsl:template>
54
55 <!-- Generate a title attribute for the context node -->
56 <xsl:template match="*" mode="html.title.attribute">
57   <xsl:variable name="is.title">
58     <xsl:call-template name="gentext.template.exists">
59       <xsl:with-param name="context" select="'title'"/>
60       <xsl:with-param name="name" select="local-name(.)"/>
61       <xsl:with-param name="lang">
62         <xsl:call-template name="l10n.language"/>
63       </xsl:with-param>
64     </xsl:call-template>
65   </xsl:variable>
66
67   <xsl:variable name="is.title-numbered">
68     <xsl:call-template name="gentext.template.exists">
69       <xsl:with-param name="context" select="'title-numbered'"/>
70       <xsl:with-param name="name" select="local-name(.)"/>
71       <xsl:with-param name="lang">
72         <xsl:call-template name="l10n.language"/>
73       </xsl:with-param>
74     </xsl:call-template>
75   </xsl:variable>
76
77   <xsl:variable name="is.title-unnumbered">
78     <xsl:call-template name="gentext.template.exists">
79       <xsl:with-param name="context" select="'title-unnumbered'"/>
80       <xsl:with-param name="name" select="local-name(.)"/>
81       <xsl:with-param name="lang">
82         <xsl:call-template name="l10n.language"/>
83       </xsl:with-param>
84     </xsl:call-template>
85   </xsl:variable>
86
87   <xsl:variable name="has.title.markup">
88     <xsl:apply-templates select="." mode="title.markup">
89       <xsl:with-param name="verbose" select="0"/>
90     </xsl:apply-templates>
91   </xsl:variable>
92
93   <xsl:variable name="gentext.title">
94     <xsl:if test="$has.title.markup != '???TITLE???' and
95                   ($is.title != 0 or
96                   $is.title-numbered != 0 or
97                   $is.title-unnumbered != 0)">
98       <xsl:apply-templates select="."
99                            mode="object.title.markup.textonly"/>
100     </xsl:if>
101   </xsl:variable>
102
103   <xsl:choose>
104     <xsl:when test="string-length($gentext.title) != 0">
105       <xsl:attribute name="title">
106         <xsl:value-of select="$gentext.title"/>
107       </xsl:attribute>
108     </xsl:when>
109     <!-- Fall back to alt if available -->
110     <xsl:when test="alt">
111       <xsl:attribute name="title">
112         <xsl:value-of select="normalize-space(alt)"/>
113       </xsl:attribute>
114     </xsl:when>
115   </xsl:choose>
116 </xsl:template>
117
118 <xsl:template match="qandaentry" mode="html.title.attribute">
119   <xsl:apply-templates select="question" mode="html.title.attribute"/>
120 </xsl:template>
121
122 <xsl:template match="question" mode="html.title.attribute">
123   <xsl:variable name="label.text">
124     <xsl:apply-templates select="." mode="qanda.label"/>
125   </xsl:variable>
126
127   <xsl:choose>
128     <xsl:when test="string-length($label.text) != 0">
129       <xsl:attribute name="title">
130         <xsl:value-of select="$label.text"/>
131       </xsl:attribute>
132     </xsl:when>
133     <!-- Fall back to alt if available -->
134     <xsl:when test="alt">
135       <xsl:attribute name="title">
136         <xsl:value-of select="normalize-space(alt)"/>
137       </xsl:attribute>
138     </xsl:when>
139   </xsl:choose>
140 </xsl:template>
141
142 <xsl:template name="dir">
143   <xsl:param name="inherit" select="0"/>
144
145   <xsl:variable name="dir">
146     <xsl:choose>
147       <xsl:when test="@dir">
148         <xsl:value-of select="@dir"/>
149       </xsl:when>
150       <xsl:when test="$inherit != 0">
151         <xsl:value-of select="ancestor::*/@dir[1]"/>
152       </xsl:when>
153     </xsl:choose>
154   </xsl:variable>
155
156   <xsl:if test="$dir != ''">
157     <xsl:attribute name="dir">
158       <xsl:value-of select="$dir"/>
159     </xsl:attribute>
160   </xsl:if>
161 </xsl:template>
162
163 <xsl:template name="anchor">
164   <xsl:param name="node" select="."/>
165   <xsl:param name="conditional" select="1"/>
166   <xsl:variable name="id">
167     <xsl:call-template name="object.id">
168       <xsl:with-param name="object" select="$node"/>
169     </xsl:call-template>
170   </xsl:variable>
171   <xsl:if test="$conditional = 0 or $node/@id or $node/@xml:id">
172     <a name="{$id}"/>
173   </xsl:if>
174 </xsl:template>
175
176 <xsl:template name="href.target.uri">
177   <xsl:param name="context" select="."/>
178   <xsl:param name="object" select="."/>
179   <xsl:text>#</xsl:text>
180   <xsl:call-template name="object.id">
181     <xsl:with-param name="object" select="$object"/>
182   </xsl:call-template>
183 </xsl:template>
184
185 <xsl:template name="href.target">
186   <xsl:param name="context" select="."/>
187   <xsl:param name="object" select="."/>
188   <xsl:text>#</xsl:text>
189   <xsl:call-template name="object.id">
190     <xsl:with-param name="object" select="$object"/>
191   </xsl:call-template>
192 </xsl:template>
193
194 <xsl:template name="href.target.with.base.dir">
195   <xsl:param name="context" select="."/>
196   <xsl:param name="object" select="."/>
197   <xsl:if test="$manifest.in.base.dir = 0">
198     <xsl:value-of select="$base.dir"/>
199   </xsl:if>
200   <xsl:call-template name="href.target">
201     <xsl:with-param name="context" select="$context"/>
202     <xsl:with-param name="object" select="$object"/>
203   </xsl:call-template>
204 </xsl:template>
205
206 <xsl:template name="dingbat">
207   <xsl:param name="dingbat">bullet</xsl:param>
208   <xsl:call-template name="dingbat.characters">
209     <xsl:with-param name="dingbat" select="$dingbat"/>
210   </xsl:call-template>
211 </xsl:template>
212
213 <xsl:template name="dingbat.characters">
214   <!-- now that I'm using the real serializer, all that dingbat malarky -->
215   <!-- isn't necessary anymore... -->
216   <xsl:param name="dingbat">bullet</xsl:param>
217   <xsl:choose>
218     <xsl:when test="$dingbat='bullet'">&#x2022;</xsl:when>
219     <xsl:when test="$dingbat='copyright'">&#x00A9;</xsl:when>
220     <xsl:when test="$dingbat='trademark'">&#x2122;</xsl:when>
221     <xsl:when test="$dingbat='trade'">&#x2122;</xsl:when>
222     <xsl:when test="$dingbat='registered'">&#x00AE;</xsl:when>
223     <xsl:when test="$dingbat='service'">(SM)</xsl:when>
224     <xsl:when test="$dingbat='nbsp'">&#x00A0;</xsl:when>
225     <xsl:when test="$dingbat='ldquo'">&#x201C;</xsl:when>
226     <xsl:when test="$dingbat='rdquo'">&#x201D;</xsl:when>
227     <xsl:when test="$dingbat='lsquo'">&#x2018;</xsl:when>
228     <xsl:when test="$dingbat='rsquo'">&#x2019;</xsl:when>
229     <xsl:when test="$dingbat='em-dash'">&#x2014;</xsl:when>
230     <xsl:when test="$dingbat='mdash'">&#x2014;</xsl:when>
231     <xsl:when test="$dingbat='en-dash'">&#x2013;</xsl:when>
232     <xsl:when test="$dingbat='ndash'">&#x2013;</xsl:when>
233     <xsl:otherwise>
234       <xsl:text>&#x2022;</xsl:text>
235     </xsl:otherwise>
236   </xsl:choose>
237 </xsl:template>
238
239 <xsl:template name="id.warning">
240   <xsl:if test="$id.warnings != 0 and not(@id) and not(@xml:id) and parent::*">
241     <xsl:variable name="title">
242       <xsl:choose>
243         <xsl:when test="title">
244           <xsl:value-of select="title[1]"/>
245         </xsl:when>
246         <xsl:when test="substring(local-name(*[1]),
247                                   string-length(local-name(*[1])-3) = 'info')
248                         and *[1]/title">
249           <xsl:value-of select="*[1]/title[1]"/>
250         </xsl:when>
251         <xsl:when test="refmeta/refentrytitle">
252           <xsl:value-of select="refmeta/refentrytitle"/>
253         </xsl:when>
254         <xsl:when test="refnamediv/refname">
255           <xsl:value-of select="refnamediv/refname[1]"/>
256         </xsl:when>
257       </xsl:choose>
258     </xsl:variable>
259
260     <xsl:message>
261       <xsl:text>ID recommended on </xsl:text>
262       <xsl:value-of select="local-name(.)"/>
263       <xsl:if test="$title != ''">
264         <xsl:text>: </xsl:text>
265         <xsl:choose>
266           <xsl:when test="string-length($title) &gt; 40">
267             <xsl:value-of select="substring($title,1,40)"/>
268             <xsl:text>...</xsl:text>
269           </xsl:when>
270           <xsl:otherwise>
271             <xsl:value-of select="$title"/>
272           </xsl:otherwise>
273         </xsl:choose>
274       </xsl:if>
275     </xsl:message>
276   </xsl:if>
277 </xsl:template>
278
279 <xsl:template name="generate.class.attribute">
280   <xsl:param name="class" select="local-name(.)"/>
281   <xsl:apply-templates select="." mode="class.attribute">
282     <xsl:with-param name="class" select="$class"/>
283   </xsl:apply-templates>
284 </xsl:template>
285
286 <xsl:template match="*" mode="class.attribute">
287   <xsl:param name="class" select="local-name(.)"/>
288   <!-- permit customization of class attributes -->
289   <!-- Use element name by default -->
290   <xsl:attribute name="class">
291     <xsl:apply-templates select="." mode="class.value">
292       <xsl:with-param name="class" select="$class"/>
293     </xsl:apply-templates>
294   </xsl:attribute>
295 </xsl:template>
296
297 <xsl:template match="*" mode="class.value">
298   <xsl:param name="class" select="local-name(.)"/>
299   <!-- permit customization of class value only -->
300   <!-- Use element name by default -->
301   <xsl:value-of select="$class"/>
302 </xsl:template>
303
304 <!-- Apply common attributes such as class, lang, dir -->
305 <xsl:template name="common.html.attributes">
306   <xsl:param name="inherit" select="0"/>
307   <xsl:param name="class" select="local-name(.)"/>
308   <xsl:apply-templates select="." mode="common.html.attributes">
309     <xsl:with-param name="class" select="$class"/>
310     <xsl:with-param name="inherit" select="$inherit"/>
311   </xsl:apply-templates>
312 </xsl:template>
313
314 <xsl:template match="*" mode="common.html.attributes">
315   <xsl:param name="class" select="local-name(.)"/>
316   <xsl:param name="inherit" select="0"/>
317   <xsl:call-template name="generate.html.lang"/>
318   <xsl:call-template name="dir">
319     <xsl:with-param name="inherit" select="$inherit"/>
320   </xsl:call-template>
321   <xsl:apply-templates select="." mode="class.attribute">
322     <xsl:with-param name="class" select="$class"/>
323   </xsl:apply-templates>
324   <xsl:call-template name="generate.html.title"/>
325 </xsl:template>
326
327 <!-- Apply common attributes not including class -->
328 <xsl:template name="locale.html.attributes">
329   <xsl:apply-templates select="." mode="locale.html.attributes"/>
330 </xsl:template>
331
332 <xsl:template match="*" mode="locale.html.attributes">
333   <xsl:call-template name="generate.html.lang"/>
334   <xsl:call-template name="dir"/>
335   <xsl:call-template name="generate.html.title"/>
336 </xsl:template>
337
338 <!-- Pass through any lang attributes -->
339 <xsl:template name="generate.html.lang">
340   <xsl:apply-templates select="." mode="html.lang.attribute"/>
341 </xsl:template>
342
343 <xsl:template match="*" mode="html.lang.attribute">
344   <!-- match the attribute name to the output type -->
345   <xsl:choose>
346     <xsl:when test="@lang and $stylesheet.result.type = 'html'">
347       <xsl:attribute name="lang">
348         <xsl:value-of select="@lang"/>
349       </xsl:attribute>
350     </xsl:when>
351     <xsl:when test="@lang and $stylesheet.result.type = 'xhtml'">
352       <xsl:attribute name="xml:lang">
353         <xsl:value-of select="@lang"/>
354       </xsl:attribute>
355     </xsl:when>
356     <xsl:when test="@xml:lang and $stylesheet.result.type = 'html'">
357       <xsl:attribute name="lang">
358         <xsl:value-of select="@xml:lang"/>
359       </xsl:attribute>
360     </xsl:when>
361     <xsl:when test="@xml:lang and $stylesheet.result.type = 'xhtml'">
362       <xsl:attribute name="xml:lang">
363         <xsl:value-of select="@xml:lang"/>
364       </xsl:attribute>
365     </xsl:when>
366   </xsl:choose>
367 </xsl:template>
368
369 <!-- ==================================================================== -->
370 <!-- Insert link to css or insert literal CSS in head element -->
371 <xsl:template name="generate.css">
372   <xsl:choose>
373     <xsl:when test="$generate.css.header = 0">
374       <xsl:call-template name="generate.css.links"/>
375     </xsl:when>
376     <xsl:otherwise>
377       <xsl:call-template name="generate.css.headers"/>
378     </xsl:otherwise>
379   </xsl:choose>
380 </xsl:template>
381
382 <xsl:template name="generate.css.headers">
383   <xsl:call-template name="generate.default.css.header"/>
384   <xsl:call-template name="generate.custom.css.header"/>
385 </xsl:template>
386
387 <xsl:template name="generate.default.css.header">
388   <xsl:if test="$make.clean.html != 0 and 
389                 $docbook.css.source != ''">
390     <!-- Select default file relative to stylesheet -->
391     <xsl:variable name="css.node" select="document($docbook.css.source)/*[1]"/>
392
393     <xsl:call-template name="output.css.header">
394       <xsl:with-param name="css.node" select="$css.node"/>
395     </xsl:call-template>
396   </xsl:if>
397 </xsl:template>
398
399 <xsl:template name="generate.custom.css.header">
400   <xsl:if test="$custom.css.source != ''">
401     <!-- Select custom file relative to document -->
402     <xsl:variable name="css.node" select="document($custom.css.source,.)/*[1]"/>
403
404     <xsl:call-template name="output.css.header">
405       <xsl:with-param name="css.node" select="$css.node"/>
406     </xsl:call-template>
407   </xsl:if>
408 </xsl:template>
409
410 <xsl:template name="output.css.header">
411   <xsl:param name="css.node"/> 
412
413   <xsl:choose>
414     <xsl:when test="count($css.node) = 0">
415     </xsl:when>
416     <xsl:otherwise>
417       <style type="text/css">
418         <xsl:copy-of select="$css.node/text()"/>
419       </style>
420     </xsl:otherwise>
421   </xsl:choose>
422 </xsl:template>
423
424 <!-- ==================================================================== -->
425 <xsl:template name="generate.css.links">
426   <xsl:call-template name="generate.default.css.link"/>
427   <xsl:call-template name="generate.custom.css.link"/>
428 </xsl:template>
429
430 <xsl:template name="generate.default.css.link">
431   <xsl:if test="$make.clean.html != 0 and 
432                 $docbook.css.link != 0 and
433                 $docbook.css.source != ''">
434     <xsl:variable name="filename">
435       <xsl:call-template name="css.output.filename">
436         <xsl:with-param name="src" select="$docbook.css.source"/>
437       </xsl:call-template>
438     </xsl:variable>
439
440     <xsl:call-template name="make.css.link">
441       <xsl:with-param name="css.filename" select="$filename"/>
442     </xsl:call-template>
443   </xsl:if>
444 </xsl:template>
445
446 <xsl:template name="generate.custom.css.link">
447   <xsl:if test="$custom.css.source != ''">
448     <xsl:variable name="filename">
449       <xsl:call-template name="css.output.filename">
450         <xsl:with-param name="src" select="$custom.css.source"/>
451       </xsl:call-template>
452     </xsl:variable>
453
454     <xsl:call-template name="make.css.link">
455       <xsl:with-param name="css.filename" select="$filename"/>
456     </xsl:call-template>
457   </xsl:if>
458 </xsl:template>
459
460 <!-- a CSS link reference must take into account the relative
461      path to a CSS file when chunked HTML is output to more than one directory -->
462 <xsl:template name="make.css.link">
463   <xsl:param name="css.filename" select="''"/>
464
465   <xsl:variable name="href.to.uri" select="$css.filename"/>
466
467   <xsl:variable name="href.from.uri">
468     <xsl:call-template name="href.target.uri">
469       <xsl:with-param name="object" select="."/>
470     </xsl:call-template>
471   </xsl:variable>
472
473   <xsl:variable name="href.to">
474     <xsl:call-template name="trim.common.uri.paths">
475       <xsl:with-param name="uriA" select="$href.to.uri"/>
476       <xsl:with-param name="uriB" select="$href.from.uri"/>
477       <xsl:with-param name="return" select="'A'"/>
478     </xsl:call-template>
479   </xsl:variable>
480
481   <xsl:variable name="href.from">
482     <xsl:call-template name="trim.common.uri.paths">
483       <xsl:with-param name="uriA" select="$href.to.uri"/>
484       <xsl:with-param name="uriB" select="$href.from.uri"/>
485       <xsl:with-param name="return" select="'B'"/>
486     </xsl:call-template>
487   </xsl:variable>
488   <xsl:variable name="depth">
489     <xsl:call-template name="count.uri.path.depth">
490       <xsl:with-param name="filename" select="$href.from"/>
491     </xsl:call-template>
492   </xsl:variable>
493   <xsl:variable name="href">
494     <xsl:call-template name="copy-string">
495       <xsl:with-param name="string" select="'../'"/>
496       <xsl:with-param name="count" select="$depth"/>
497     </xsl:call-template>
498     <xsl:value-of select="$href.to"/>
499   </xsl:variable>
500
501   <xsl:if test="string-length($css.filename) != 0">
502     <link rel="stylesheet" 
503           type="text/css"
504           href="{$href}"/>
505   </xsl:if>
506 </xsl:template>
507
508 <!-- ==================================================================== -->
509
510 <xsl:template name="generate.css.files">
511   <xsl:call-template name="generate.default.css.file"/>
512   <xsl:call-template name="generate.custom.css.file"/>
513 </xsl:template>
514
515 <xsl:template name="generate.default.css.file">
516   <xsl:if test="$make.clean.html != 0 and 
517                 $generate.css.header = 0 and
518                 $docbook.css.source != ''">
519     <!-- Select default file relative to stylesheet -->
520     <xsl:variable name="css.node" select="document($docbook.css.source)/*[1]"/>
521
522     <xsl:call-template name="generate.css.file">
523       <xsl:with-param name="src" select="$docbook.css.source"/>
524       <xsl:with-param name="css.node" select="$css.node"/>
525     </xsl:call-template>
526   </xsl:if>
527 </xsl:template>
528
529 <xsl:template name="generate.custom.css.file">
530   <xsl:if test="$custom.css.source != '' and
531                 $generate.css.header = 0">
532     <!-- Select custom file relative to document -->
533     <xsl:variable name="css.node" select="document($custom.css.source,.)/*[1]"/>
534
535     <xsl:call-template name="generate.css.file">
536       <xsl:with-param name="src" select="$custom.css.source"/>
537       <xsl:with-param name="css.node" select="$css.node"/>
538     </xsl:call-template>
539   </xsl:if>
540 </xsl:template>
541
542 <xsl:template name="generate.css.file">
543   <xsl:param name="css.node"/> 
544   <xsl:param name="src" select="''"/> 
545
546   <xsl:variable name="css.text" select="$css.node/text()"/>
547
548   <xsl:choose>
549     <xsl:when test="count($css.node) = 0">
550       <xsl:message>
551         <xsl:text>ERROR: no root element for CSS source file'</xsl:text>
552         <xsl:value-of select="$src"/>
553         <xsl:text>'.</xsl:text>
554       </xsl:message>
555     </xsl:when>
556     <xsl:otherwise>
557       <xsl:variable name="filename">
558         <xsl:call-template name="css.output.pathname">
559           <xsl:with-param name="src" select="$src"/>
560           <xsl:with-param name="content" select="$css.node"/>
561         </xsl:call-template>
562       </xsl:variable>
563
564       <xsl:call-template name="write.text.chunk">
565         <xsl:with-param name="filename" select="$filename"/>
566         <xsl:with-param name="content" select="$css.text"/>
567       </xsl:call-template>
568
569     </xsl:otherwise>
570   </xsl:choose>
571 </xsl:template>
572
573 <xsl:template name="css.output.filename">
574   <xsl:param name="content"/>
575   <xsl:param name="src" select="''"/>
576   
577   <xsl:variable name="candidate">
578     <xsl:choose>
579       <xsl:when test="string-length($src) = 0">
580         <xsl:message>
581           <xsl:text>ERROR: missing CSS input filename.</xsl:text>
582         </xsl:message>
583       </xsl:when>
584       <xsl:when test="substring($src,string-length($src)-3) = '.xml'">
585         <xsl:value-of select="substring($src, 1, string-length($src) - 4)"/>
586       </xsl:when>
587       <xsl:otherwise>
588         <xsl:value-of select="$src"/>
589       </xsl:otherwise>
590     </xsl:choose>
591   </xsl:variable>
592   <xsl:value-of select="$candidate"/>
593 </xsl:template>
594
595 <xsl:template name="css.output.pathname">
596   <xsl:param name="content"/>
597   <xsl:param name="src" select="''"/>
598
599   <xsl:variable name="file">
600     <xsl:call-template name="css.output.filename">
601       <xsl:with-param name="content" select="$content"/>
602       <xsl:with-param name="src" select="$src"/>
603     </xsl:call-template>
604   </xsl:variable>
605
606   <xsl:variable name="path" select="concat($base.dir, $file)"/>
607   <xsl:value-of select="$path"/>
608   
609 </xsl:template>
610
611 </xsl:stylesheet>
612