Merge branch 'master' into ofop
[librarian.git] / librarian / xslt / book2html.xslt
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--
3
4    This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
5    Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
6
7 -->
8 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
9     xmlns:wl="http://wolnelektury.pl/functions"
10     xmlns:dc="http://purl.org/dc/elements/1.1/" >
11
12 <xsl:output encoding="utf-8" indent="yes" omit-xml-declaration = "yes" version="2.0" />
13 <xsl:strip-space  elements="opowiadanie powiesc dramat_wierszowany_l dramat_wierszowany_lp dramat_wspolczesny liryka_l liryka_lp wywiad"/>
14 <xsl:template match="utwor">
15     <xsl:choose>
16         <xsl:when test="@full-page">
17             <html>
18             <head>
19                 <title><xsl:apply-templates mode="inline" select="//nazwa_utworu" /></title>
20                 <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
21             </head>
22             <style>
23                 body {
24                     font-size: 16px;
25                     font: Georgia, "Times New Roman", serif;
26                     line-height: 1.5em;
27                     margin: 0;
28                 }
29
30                 a {
31                     color: blue;
32                     text-decoration: none;
33                 }
34
35                 #book-text {
36                     margin: 3em;
37                     max-width: 36em;
38                 }
39
40                 /* ================================== */
41                 /* = Header with logo and menu      = */
42                 /* ================================== */
43                 #header {
44                     margin: 3.4em 0 0 1.4em;
45                 }
46
47                 img {
48                     border: none;
49                     max-width: 100%;
50                 }
51
52
53                 #menu {
54                     position: fixed;
55                     left: 0em;
56                     top: 0em;
57                     width: 100%;
58                     height: 1.5em;
59                     background: #333;
60                     color: #FFF;
61                     opacity: 0.9;
62                     z-index: 99;
63                 }
64
65                 #menu ul {
66                     list-style: none;
67                     padding: 0;
68                     margin: 0;
69                 }
70
71                 #menu li a {
72                     display: block;
73                     float: left;
74                     width: 7.5em;
75                     height: 1.5em;
76                     margin-left: 0.5em;
77                     text-align: center;
78                     color: #FFF;
79                 }
80
81                 #menu li a:hover, #menu li a:active {
82                     color: #000;
83                     background: #FFF url(/static/img/arrow-down.png) no-repeat center right;
84                 }
85
86                 #menu li a.selected {
87                     color: #000;
88                     background: #FFF url(/static/img/arrow-up.png) no-repeat center right;
89                 }
90                 #menu a.menu-link {
91                     display: block;
92                     float: left;
93                     height: 1.5em;
94                     margin-left: 0.5em;
95                     text-align: center;
96                     color: #FFF;
97                 }
98                 #menu span {
99                     color: #888;
100                     font-style: italic;
101                     font-size: .75em;
102                     margin-right: 0.5em;
103                 }
104
105
106                 #toc, #themes, #nota_red, #info {
107                     position: fixed;
108                     left: 0em;
109                     top: 1.5em;
110                     width: 37em;
111                     padding: 1.5em;
112                     background: #FFF;
113                     border-bottom: 0.25em solid #DDD;
114                     border-right: 0.25em solid #DDD;
115                     display: none;
116                     height: 16em;
117                     overflow-x: hidden;
118                     overflow-y: auto;
119                     opacity: 0.9;
120                     z-index: 99;
121                 }
122
123                 #toc ol, #themes ol {
124                     list-style: none;
125                     padding: 0;
126                     margin: 0;
127                 }
128
129                 #toc ol li {
130                     font-weight: bold;
131                 }
132
133                 #toc ol ol {
134                     padding: 0 0 1.5em 1.5em;
135                     margin: 0;
136                 }
137
138                 #toc ol ol li {
139                     font-weight: normal;
140                 }
141
142                 #toc h2 {
143                     display: none;
144                 }
145
146                 #toc .anchor {
147                     float: none;
148                     margin: 0;
149                     color: blue;
150                     font-size: 16px;
151                     position: inherit;
152                 }
153
154                 #info p {
155                     text-align: justify;
156                     margin: 1.5em 0 0;
157                 }
158
159                 /* =================================================== */
160                 /* = Common elements: headings, paragraphs and lines = */
161                 /* =================================================== */
162                 h1 {
163                     font-size: 3em;
164                     margin: 1.5em 0;
165                     text-align: center;
166                     line-height: 1.5em;
167                     font-weight: bold;
168                 }
169
170                 h2 {
171                     font-size: 2em;
172                     margin: 1.5em 0 0;
173                     font-weight: bold;
174                     line-height: 1.5em;
175                 }
176
177                 h3 {
178                     font-size: 1.5em;
179                     margin: 1.5em 0 0;
180                     font-weight: normal;
181                     line-height: 1.5em;
182                 }
183
184                 h4 {
185                     font-size: 1em;
186                     margin: 1.5em 0 0;
187                     line-height: 1.5em;
188                 }
189
190                 p {
191                     margin: 0;
192                 }
193
194                 /* ======================== */
195                 /* = Footnotes and themes = */
196                 /* ======================== */
197                 .theme-begin {
198                     border-left: 0.1em solid #DDDDDD;
199                     color: #777;
200                     padding: 0 0.5em;
201                     width: 7.5em;
202
203                     font-style: normal;
204                     font-weight: normal;
205                     font-variant: normal;
206                     letter-spacing: 0;
207                     text-transform: none;
208                     text-decoration: none;
209
210                     font-size: 16px;
211                     float: right;
212                     margin-right: -9.5em;
213                     margin-bottom: 0.5em;
214                     clear: both;
215                     left: 40em;
216                     line-height: 1.5em;
217                     text-align: left;
218                 }
219
220                 .annotation {
221                     font-style: normal;
222                     font-weight: normal;
223                     font-size: 12px;
224                     padding-left: 2px;
225                     position: relative;
226                     top: -4px;
227                 }
228
229                 #footnotes .annotation {
230                     display: block;
231                     float: left;
232                     width: 2.5em;
233                     clear: both;
234                 }
235
236                 #footnotes div {
237                     margin: 1.5em 0 0 0;
238                 }
239
240                 #footnotes p {
241                     margin-left: 2.5em;
242                     font-size: 0.875em;
243                 }
244
245                 blockquote {
246                     font-size: 0.875em;
247                 }
248
249                 /* ============= */
250                 /* = Numbering = */
251                 /* ============= */
252                 .verse, .paragraph {
253                     position:relative;
254                 }
255                 .anchor {
256                     position: absolute;
257                     margin: -0.25em -0.5em;
258                     left: -3em;
259                     color: #777;
260                     font-size: 12px;
261                     width: 2em;
262                     text-align: center;
263                     padding: 0.25em 0.5em;
264                     line-height: 1.5em;
265                 }
266
267                 .anchor:hover, #book-text .anchor:active {
268                     color: #FFF;
269                     background-color: #CCC;
270                 }
271
272                 /* =================== */
273                 /* = Custom elements = */
274                 /* =================== */
275                 span.author {
276                     font-size: 0.5em;
277                     display: block;
278                     line-height: 1.5em;
279                     margin-bottom: 0.25em;
280                 }
281
282                 span.collection {
283                     font-size: 0.375em;
284                     display: block;
285                     line-height: 1.5em;
286                     margin-bottom: -0.25em;
287                 }
288
289                 span.subtitle {
290                     font-size: 0.5em;
291                     display: block;
292                     line-height: 1.5em;
293                     margin-top: -0.25em;
294                 }
295
296                 span.translator {
297                     font-size: 0.375em;
298                     display: block;
299                     line-height: 1.5em;
300                     margin-top: 0.25em;
301                 }
302
303                 div.didaskalia {
304                     font-style: italic;
305                     margin: 0.5em 0 0 1.5em;
306                 }
307
308                 div.kwestia {
309                     margin: 0.5em 0 0;
310                 }
311
312                 div.stanza {
313                     margin: 1.5em 0 0;
314                 }
315
316                 div.kwestia div.stanza {
317                     margin: 0;
318                 }
319
320                 p.paragraph {
321                     text-align: justify;
322                     margin: 1.5em 0 0;
323                 }
324
325                 p.motto {
326                     text-align: justify;
327                     font-style: italic;
328                     margin: 1.5em 0 0;
329                 }
330
331                 p.motto_podpis {
332                     font-size: 0.875em;
333                     text-align: right;
334                 }
335
336                 div.fragment {
337                     border-bottom: 0.1em solid #999;
338                     padding-bottom: 1.5em;
339                 }
340
341                 div.note p, div.dedication p, div.note p.paragraph, div.dedication p.paragraph {
342                     text-align: right;
343                     font-style: italic;
344                 }
345
346                 hr.spacer {
347                     height: 3em;
348                     visibility: hidden;
349                 }
350
351                 hr.spacer-line {
352                     margin: 1.5em 0;
353                     border: none;
354                     border-bottom: 0.1em solid #000;
355                 }
356
357                 p.spacer-asterisk {
358                     padding: 0;
359                     margin: 1.5em 0;
360                     text-align: center;
361                 }
362
363                 div.person-list ol {
364                     list-style: none;
365                     padding: 0 0 0 1.5em;
366                 }
367
368                 p.place-and-time {
369                     font-style: italic;
370                 }
371
372                 em.math, em.foreign-word, em.book-title, em.didaskalia {
373                     font-style: italic;
374                 }
375
376                 em.author-emphasis {
377                     letter-spacing: 0.1em;
378                 }
379
380                 em.person {
381                     font-style: normal;
382                     font-variant: small-caps;
383                 }
384
385                 .verse:after {
386                     content: "\feff";
387                 }
388
389
390                 /* =================================== */
391                 /* = Hide some elements for printing = */
392                 /* =================================== */
393
394                 @media print {
395                     #menu {display: none;}
396                 }
397             </style>
398             <body>
399                 <xsl:call-template name="book-text" />
400             </body>
401             </html>
402         </xsl:when>
403         <xsl:otherwise>
404             <xsl:call-template name="book-text" />
405         </xsl:otherwise>
406     </xsl:choose>
407 </xsl:template>
408
409 <xsl:template name="book-text">
410     <div id="book-text">
411         <xsl:apply-templates select="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny" />
412         <xsl:if test="count(descendant::*[self::pe or self::pa or self::pr or self::pt][not(parent::extra)])">
413             <div id="footnotes">
414                 <h3>Przypisy</h3>
415                 <xsl:for-each select="descendant::*[self::pe or self::pa or self::pr or self::pt][not(parent::extra)]">
416                     <div>
417                         <a name="{concat('footnote-', generate-id(.))}" />
418                         <a href="{concat('#anchor-', generate-id(.))}" class="annotation">[<xsl:number value="count(preceding::*[self::pa or self::pe or self::pr or self::pt]) + 1" />]</a>
419                         <xsl:choose>
420                             <xsl:when test="count(akap|akap_cd|strofa) = 0">
421                                 <p><xsl:apply-templates select="text()|*" mode="inline" />
422                                 <xsl:if test="name()='pa'"> [przypis autorski]</xsl:if>
423                                 </p>
424                             </xsl:when>
425                             <xsl:otherwise>
426                                 <xsl:apply-templates select="text()|*" mode="inline" />
427                             </xsl:otherwise>
428                         </xsl:choose>
429                     </div>
430                 </xsl:for-each>
431             </div>
432         </xsl:if>
433     </div>
434 </xsl:template>
435
436
437 <!-- ============================================================================== -->
438 <!-- = MASTER TAG                                                                 = -->
439 <!-- = (can contain block tags, paragraph tags, standalone tags and special tags) = -->
440 <!-- ============================================================================== -->
441 <xsl:template match="powiesc|opowiadanie|liryka_l|liryka_lp|dramat_wierszowany_l|dramat_wierszowany_lp|dramat_wspolczesny">
442     <xsl:apply-templates select="nota_red" mode="special" />
443     <xsl:if test="nazwa_utworu">
444         <h1>
445             <xsl:apply-templates select="autor_utworu|dzielo_nadrzedne|nazwa_utworu|podtytul" mode="header" />
446             <xsl:call-template name="translators" />
447         </h1>
448     </xsl:if>
449     <xsl:apply-templates />
450 </xsl:template>
451
452
453 <!-- ==================================================================================== -->
454 <!-- = BLOCK TAGS                                                                       = -->
455 <!-- = (can contain other block tags, paragraph tags, standalone tags and special tags) = -->
456 <!-- ==================================================================================== -->
457 <xsl:template match="nota">
458     <div class="note"><xsl:apply-templates /></div>
459 </xsl:template>
460
461 <xsl:template match="lista_osob">
462     <div class="person-list">
463         <h3><xsl:value-of select="naglowek_listy" /></h3>
464         <ol>
465             <xsl:apply-templates select="lista_osoba" />
466         </ol>
467     </div>
468 </xsl:template>
469
470 <xsl:template match="dedykacja">
471     <div class="dedication"><xsl:apply-templates /></div>
472 </xsl:template>
473
474 <xsl:template match="kwestia">
475     <div class="kwestia">
476         <xsl:apply-templates select="strofa|akap|didaskalia" />
477     </div>
478 </xsl:template>
479
480 <xsl:template match="dlugi_cytat|poezja_cyt">
481     <blockquote><xsl:apply-templates /></blockquote>
482 </xsl:template>
483
484 <xsl:template match="motto">
485     <div class="motto"><xsl:apply-templates mode="inline" /></div>
486 </xsl:template>
487
488
489 <!-- ========================================== -->
490 <!-- = PARAGRAPH TAGS                         = -->
491 <!-- = (can contain inline and special tags)  = -->
492 <!-- ========================================== -->
493 <!-- Title page -->
494 <xsl:template match="autor_utworu" mode="header">
495     <span class="author"><xsl:apply-templates mode="inline" /></span>
496 </xsl:template>
497
498 <xsl:template match="nazwa_utworu" mode="header">
499     <span class="title"><xsl:apply-templates mode="inline" /></span>
500 </xsl:template>
501
502 <xsl:template match="dzielo_nadrzedne" mode="header">
503     <span class="collection"><xsl:apply-templates mode="inline" /></span>
504 </xsl:template>
505
506 <xsl:template match="podtytul" mode="header">
507     <span class="subtitle"><xsl:apply-templates mode="inline" /></span>
508 </xsl:template>
509
510 <!-- Section headers (included in index)-->
511 <xsl:template match="naglowek_akt|naglowek_czesc|srodtytul">
512   <xsl:call-template name="section-anchor"/>
513     <h2><xsl:apply-templates mode="inline" /></h2>
514 </xsl:template>
515
516 <xsl:template match="naglowek_scena|naglowek_rozdzial">
517     <xsl:call-template name="section-anchor"/>
518     <h3><xsl:apply-templates mode="inline" /></h3>
519 </xsl:template>
520
521 <xsl:template match="naglowek_osoba|naglowek_podrozdzial">
522       <xsl:call-template name="section-anchor"/>
523     <h4><xsl:apply-templates mode="inline" /></h4>
524 </xsl:template>
525
526 <!-- Other paragraph tags -->
527 <xsl:template match="miejsce_czas">
528       <xsl:call-template name="section-anchor"/>
529     <p class="place-and-time"><xsl:apply-templates mode="inline" /></p>
530 </xsl:template>
531
532 <xsl:template match="didaskalia">
533       <xsl:call-template name="section-anchor"/>
534     <div class="didaskalia"><xsl:apply-templates mode="inline" /></div>
535 </xsl:template>
536
537 <xsl:template match="lista_osoba">
538     <li><xsl:apply-templates mode="inline" /></li>
539 </xsl:template>
540
541 <xsl:template match="akap|akap_dialog|akap_cd">
542     <p class="paragraph">
543       <xsl:call-template name="section-anchor"/>
544         <xsl:apply-templates mode="inline" />
545     </p>
546 </xsl:template>
547
548 <xsl:template match="strofa">
549     <div class="stanza">
550       <xsl:call-template name="section-anchor"/>
551         <xsl:choose>
552             <xsl:when test="count(br) > 0">
553                 <xsl:call-template name="verse">
554                     <xsl:with-param name="verse-content" select="br[1]/preceding-sibling::text() | br[1]/preceding-sibling::node()" />
555                     <xsl:with-param name="verse-type" select="br[1]/preceding-sibling::*[name() = 'wers_wciety' or name() = 'wers_akap' or name() = 'wers_cd'][1]" />
556                 </xsl:call-template>
557                 <xsl:for-each select="br">              
558                                 <!-- Each BR tag "consumes" text after it -->
559                     <xsl:variable name="lnum" select="count(preceding-sibling::br)" />
560                     <xsl:call-template name="verse">
561                         <xsl:with-param name="verse-content"
562                             select="following-sibling::text()[count(preceding-sibling::br) = $lnum+1] | following-sibling::node()[count(preceding-sibling::br) = $lnum+1]" />
563                         <xsl:with-param name="verse-type" select="following-sibling::*[count(preceding-sibling::br) = $lnum+1 and (name() = 'wers_wciety' or name() = 'wers_akap' or name() = 'wers_cd')][1]" />
564                     </xsl:call-template>
565                 </xsl:for-each>
566             </xsl:when>
567             <xsl:otherwise>
568                 <xsl:call-template name="verse">
569                     <xsl:with-param name="verse-content" select="text() | node()" />
570                     <xsl:with-param name="verse-type" select="wers_wciety|wers_akap|wers_cd[1]" />
571                  </xsl:call-template>
572             </xsl:otherwise>
573         </xsl:choose>
574     </div>
575 </xsl:template>
576
577 <xsl:template name="verse">
578     <xsl:param name="verse-content" />
579     <xsl:param name="verse-type" />
580     <p class="verse">
581         <xsl:choose>
582             <xsl:when test="name($verse-type) = 'wers_akap'">
583                 <xsl:attribute name="style">padding-left: 1em</xsl:attribute>
584             </xsl:when>
585             <xsl:when test="name($verse-type) = 'wers_wciety'">
586                 <xsl:choose>
587                     <xsl:when test="$verse-content/@typ">
588                         <xsl:attribute name="style">padding-left: <xsl:value-of select="$verse-content/@typ" />em</xsl:attribute>
589                     </xsl:when>
590                     <xsl:otherwise>
591                         <xsl:attribute name="style">padding-left: 1em</xsl:attribute>
592                     </xsl:otherwise>
593                 </xsl:choose>
594             </xsl:when>
595             <xsl:when test="name($verse-type) = 'wers_cd'">
596                 <xsl:attribute name="style">padding-left: 12em</xsl:attribute>
597             </xsl:when>
598         </xsl:choose>
599         <xsl:apply-templates select="$verse-content" mode="inline" />
600     </p>
601 </xsl:template>
602
603 <xsl:template match="motto_podpis">
604     <p class="motto_podpis"><xsl:apply-templates mode="inline" /></p>
605 </xsl:template>
606
607
608 <!-- ================================================ -->
609 <!-- = INLINE TAGS                                  = -->
610 <!-- = (contain other inline tags and special tags) = -->
611 <!-- ================================================ -->
612 <!-- Annotations -->
613 <xsl:template match="pa|pe|pr|pt" mode="inline">
614     <a name="{concat('anchor-', generate-id(.))}" />
615     <a href="{concat('#footnote-', generate-id(.))}" class="annotation">[<xsl:number value="count(preceding::*[self::pa or self::pe or self::pr or self::pt]) + 1" />]</a>
616 </xsl:template>
617
618 <!-- Other inline tags -->
619 <xsl:template match="mat" mode="inline">
620     <em class="math"><xsl:apply-templates mode="inline" /></em>
621 </xsl:template>
622
623 <xsl:template match="didask_tekst" mode="inline">
624     <em class="didaskalia"><xsl:apply-templates mode="inline" /></em>
625 </xsl:template>
626
627 <xsl:template match="slowo_obce" mode="inline">
628     <em class="foreign-word"><xsl:apply-templates mode="inline" /></em>
629 </xsl:template>
630
631 <xsl:template match="tytul_dziela" mode="inline">
632     <em class="book-title">
633         <xsl:if test="@typ = '1'">„</xsl:if><xsl:apply-templates mode="inline" /><xsl:if test="@typ = '1'">”</xsl:if>
634     </em>
635 </xsl:template>
636
637 <xsl:template match="wyroznienie" mode="inline">
638     <em class="author-emphasis"><xsl:apply-templates mode="inline" /></em>
639 </xsl:template>
640
641 <xsl:template match="osoba" mode="inline">
642     <em class="person"><xsl:apply-templates mode="inline" /></em>
643 </xsl:template>
644
645
646 <!-- ============================================== -->
647 <!-- = STANDALONE TAGS                            = -->
648 <!-- = (cannot contain any other tags)            = -->
649 <!-- ============================================== -->
650 <xsl:template match="sekcja_swiatlo">
651     <hr class="spacer" />
652 </xsl:template>
653
654 <xsl:template match="sekcja_asterysk">
655     <p class="spacer-asterisk">*</p>
656 </xsl:template>
657
658 <xsl:template match="separator_linia">
659     <hr class="spacer-line" />
660 </xsl:template>
661
662 <xsl:template match="ilustr">
663     <div xmlns="http://www.w3.org/1999/xhtml" class="ilustr">
664       <img xmlns="http://www.w3.org/1999/xhtml" alt="ilustracja">
665         <xsl:attribute name="src">
666           <xsl:value-of select="@src" />
667         </xsl:attribute>
668         <xsl:attribute name="alt">
669           <xsl:apply-templates mode="inline" />
670         </xsl:attribute>
671         <xsl:attribute name="title">
672           <xsl:apply-templates mode="inline" />
673         </xsl:attribute>
674       </img>
675     </div>
676 </xsl:template>
677
678
679 <!-- ================ -->
680 <!-- = SPECIAL TAGS = -->
681 <!-- ================ -->
682 <!-- Themes -->
683 <xsl:template match="begin" mode="inline">
684     <xsl:variable name="mnum" select="concat('m', substring(@id, 2))" />
685     <a name="m{substring(@id, 2)}" class="theme-begin" fid="{substring(@id, 2)}">
686         <xsl:value-of select="string(following::motyw[@id=$mnum]/text())" />
687     </a>
688 </xsl:template>
689
690 <xsl:template match="end" mode="inline">
691     <span class="theme-end" fid="{substring(@id, 2)}"> </span>
692 </xsl:template>
693
694 <xsl:template match="begin|end">
695     <xsl:apply-templates select='.' mode="inline" />
696 </xsl:template>
697
698 <xsl:template match="motyw" mode="inline" />
699
700
701 <xsl:template match="nota_red" mode="special">
702     <div id="nota_red">
703         <xsl:apply-templates />
704     </div>
705 </xsl:template>
706
707
708 <xsl:template name="translators">
709     <xsl:if test="//dc:contributor.translator">
710         <span class="translator">
711             <xsl:text>tłum. </xsl:text>
712             <xsl:for-each select="//dc:contributor.translator">
713                 <xsl:if test="position() != 1">, </xsl:if>
714                 <xsl:apply-templates mode="person" />
715             </xsl:for-each>
716         </span>
717     </xsl:if>
718 </xsl:template>
719
720 <xsl:template match="text()" mode="person">
721     <xsl:value-of select="wl:person_name(.)" />
722 </xsl:template>
723
724
725 <!-- ================ -->
726 <!-- = IGNORED TAGS = -->
727 <!-- ================ -->
728 <xsl:template match="extra|uwaga" />
729 <xsl:template match="extra|uwaga" mode="inline" />
730
731 <xsl:template match="nota_red" />
732
733 <!-- ======== -->
734 <!-- = TEXT = -->
735 <!-- ======== -->
736 <xsl:template match="text()" />
737 <xsl:template match="text()" mode="inline">
738     <xsl:value-of select="wl:substitute_entities(.)" />
739 </xsl:template>
740
741 <!-- ========= -->
742 <!-- = utils = -->
743 <!-- ========= -->
744 <xsl:template name="section-anchor">
745   <!-- 
746        this formula works as follows:
747        - get all ancestors including self
748        - choose the header (third one from root): utwor/book-type/header
749        - get all preceding siblings
750        - count them
751        - create an <a name="sec123"/> tag.
752   -->
753         <a name="{concat('sec', count(ancestor-or-self::*[last()-2]/preceding-sibling::*) + 1)}" />
754 </xsl:template>
755
756 </xsl:stylesheet>