1 <?xml version=
"1.0" encoding=
"utf-8"?>
2 <!DOCTYPE xsl:stylesheet [
4 <!-- "xml:space='preserve'" is needed for use with libxslt -->
5 <!-- "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" is needed for
7 <!-- Used to create a blank line -->
8 <!ENTITY tCR
"<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xml:space='preserve'>&CR;</xsl:text>">
9 <!-- Used when the line before must be ended -->
10 <!ENTITY tEOL
"<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xml:space='preserve'>&CR;</xsl:text>">
11 <!ENTITY tSP
"<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xml:space='preserve'> </xsl:text>">
15 Copyright (C) 2005, 2006 Stefan Merten, David Priest
16 Copyright (C) 2009, 2010, 2011 Stefan Merten
18 xml2rst.xsl is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published
20 by the Free Software Foundation; either version 2 of the License,
21 or (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34 <!-- ********************************************************************** -->
35 <!-- ********************************************************************** -->
37 <!-- These elements in the DTD need support:
39 - ``colspec`` has attribute "stub %yesorno; #IMPLIED"
41 - ``document`` has attribute "title CDATA #IMPLIED"
43 Probably rendered by the `.. title::` directive
48 Set namespace extensions. These are used as [shortname]:[tag] throughout the
50 xsl: eXtensible Stylesheet Language
51 u: user extensions (indicates utility 'call-template' routines defined in
53 data: Data elements used by the stylesheet
57 xmlns:
xsl=
"http://www.w3.org/1999/XSL/Transform"
60 exclude-result-prefixes=
"data"
61 xmlns:
str=
"http://exslt.org/strings"
62 xmlns:
dyn=
"http://exslt.org/dynamic"
63 xmlns:
math=
"http://exslt.org/math"
64 xmlns:
rst=
"http://www.merten-home.de/xml2rst"
65 extension-element-prefixes=
"str dyn math rst">
67 <!-- xmlns:regexp="http://exslt.org/regular-expressions" not supported :-( -->
71 omit-xml-declaration=
"yes"
74 <!-- ******************************************************************** -->
75 <!-- ******************************************************************** -->
77 <!-- Parameter to configure title markup; see manual page for description -->
80 select=
"'o=o-u=u-u~u`u,u.'"/>
82 <!-- Parameter for folding long lines; see manual page for description -->
87 <!-- ******************************************************************** -->
88 <!-- ******************************************************************** -->
95 name=
"structural_elements"
96 select=
"'*document*section*topic*sidebar*'"/>
99 name=
"structural_subelements"
100 select=
"'*title*subtitle*docinfo*decoration*transition*'"/>
103 name=
"bibliographic_elements"
104 select=
"'*address*author*authors*contact*copyright*date*field*organization*revision*status*version*'"/>
107 name=
"decorative_elements"
108 select=
"'*footer*header*'"/>
111 name=
"simple_body_elements_no_substitution"
112 select=
"'*comment*doctest_block*image*literal_block*paragraph*pending*raw*rubric*target*'"/>
115 name=
"folding_elements"
116 select=
"concat('*comment*paragraph*rubric*attribution*caption*line*', substring-after($bibliographic_elements, '*'))"/>
119 name=
"simple_body_elements"
120 select=
"concat($simple_body_elements_no_substitution, 'substitution_definition*')"/>
123 name=
"compound_body_elements"
124 select=
"'*admonition*attention*block_quote*bullet_list*caution*citation*compound*danger*definition_list*enumerated_list*error*field_list*figure*footnote*hint*important*line_block*note*option_list*system_message*table*tip*warning*container*'"/>
128 select=
"concat($simple_body_elements, substring-after($compound_body_elements, '*'))"/>
132 select=
"'*admonition*attention*caution*danger*error*hint*important*note*tip*warning*'"/>
135 name=
"simple_body_subelements"
136 select=
"'*attribution*caption*classifier*colspec*field_name*label*line*option_argument*option_string*term*'"/>
139 name=
"compound_body_subelements"
140 select=
"'*definition*definition_list_item*description*entry*field*field_body*legend*list_item*option*option_group*option_list_item*row*tbody*tgroup*thead*'"/>
143 name=
"inline_elements"
144 select=
"'*abbreviation*acronym*citation_reference*emphasis*footnote_reference*generated*image*inline*literal*problematic*reference*strong*subscript*substitution_reference*superscript*target*title_reference*raw*'"/>
147 name=
"inline_containers"
148 select=
"concat($simple_body_elements_no_substitution, substring-after($inline_elements, '*'))"/>
152 select=
"'*admonition*attention*caution*comment*danger*error*footnote*hint*important*note*tip*warning*image*figure*topic*sidebar*rubric*meta*raw*citation*compound*substitution_definition*container*'"/>
155 name=
"titled_elements"
156 select=
"'*sidebar*topic*admonition*'"/>
160 select=
"concat($structural_elements, substring-after($structural_subelements, '*'), substring-after($body_elements, '*'))"/>
163 name=
"adornment_characters"
164 select=
"concat($apos, '!"#$%&()*+,-./:;<=>?@[\]^_`{|}~')"/>
166 <!-- ******************************************************************** -->
167 <!-- ******************************************************************** -->
170 Content Model: ((title, subtitle?)?, docinfo?, decoration?,
173 Attributes: The document element contains only the common attributes: ids,
174 names, dupnames, source, and classes.
176 Depending on the source of the data and the stage of processing, the
177 "document" may not initially contain a "title". A document title is not
178 directly representable in reStructuredText. Instead, a lone top-level section
179 may have its title promoted to become the document title, and similarly for a
180 lone second-level (sub)section's title to become the document subtitle. The
181 "docinfo" may be transformed from an initial field_list, and "decoration" is
182 usually constructed programmatically.
184 <!-- == structural_element -->
188 test=
"//generated[@classes = 'sectnum']">
189 <xsl:text>.. section-numbering::
</xsl:text>
194 name=
"u:outputClass">
199 <xsl:apply-templates/>
202 <!-- ******************************************************************** -->
205 Content Model: (title, %structure.model;)
206 Attributes: The section element contains only the common attributes: ids,
207 names, dupnames, source, and classes.
209 <!-- == structural_element -->
213 name=
"u:outputClass"/>
216 <xsl:apply-templates/>
219 <!-- == structural_element -->
221 match=
"section[@classes = 'system-messages']"/>
222 <!-- Ignore system messages completely -->
223 <!-- This should be really in `generated' -->
225 <!-- ******************************************************************** -->
228 Content Model: (title, subtitle?, (%body.elements;)+)
229 Attributes: The sidebar element contains only the common attributes: ids,
230 names, dupnames, source, and classes.
232 <!-- == structural_element == directive -->
237 <xsl:text>.. sidebar::
</xsl:text>
247 select=
"'subtitle'"/>
253 select=
"ancestor-or-self::*"/>
258 <!-- Always blank line after parameter block -->
261 select=
"*[not(self::title) and not(self::subtitle)]"/>
264 <!-- ******************************************************************** -->
267 Content Model: (title?, (%body.elements;)+)
268 Attributes: The topic element contains only the common attributes: ids,
269 names, dupnames, source, and classes.
271 <!-- == structural_element == directive -->
276 <xsl:text>.. topic::
</xsl:text>
283 select=
"*[not(self::title)]"/>
286 <!-- == structural_element == directive -->
288 match=
"topic[starts-with(@classes, 'contents')]">
291 <xsl:text>.. contents::
</xsl:text>
299 select=
"@*[name() != 'ids' and name() != 'names' and name() != 'classes']"/>
303 select=
"substring-before(@classes, ' local')"/>
305 name=
"realClassesLocal"
306 select=
"normalize-space(substring-after(@classes, 'contents'))"/>
308 name=
"realClassesNode">
313 select=
"normalize-space(substring-before($realClassesLocal, 'local'))"/>
317 select=
"$realClassesLocal"/>
323 select=
"string($realClassesNode)"/>
336 select=
"ancestor-or-self::*"/>
348 select=
"$realClasses"/>
351 select=
"ancestor-or-self::*"/>
354 <!-- Autogenerated content is discarded -->
358 <!-- == structural_element == directive -->
360 match=
"topic[@classes='dedication' or @classes='abstract']">
363 <xsl:text>:
</xsl:text>
366 <xsl:text>:
</xsl:text>
369 select=
"*[not(self::title)]"/>
372 <!-- ******************************************************************** -->
375 Content Model: (title, (%body.elements;)+)
376 Attributes: The admonition element contains only the common attributes:
377 ids, names, dupnames, source, and classes.
379 <!-- == compound_body_element == directive -->
384 <xsl:text>.. admonition::
</xsl:text>
392 select=
"@*[name() != 'classes' or not(starts-with(., 'admonition-'))]"/>
397 select=
"*[not(self::title)]"/>
400 <!-- ******************************************************************** -->
403 Content Model: (%body.elements;)+
404 Attributes: The note element contains only the common attributes: ids,
405 names, dupnames, source, and classes.
407 <!-- == compound_body_element == directive -->
409 match=
"attention | caution | danger | error | hint | important | note | tip | warning">
411 name=
"u:outputClass"/>
414 <xsl:text>..
</xsl:text>
417 <xsl:text>::
</xsl:text>
422 select=
"@*[name() != 'classes']"/>
424 <xsl:apply-templates/>
427 <!-- ******************************************************************** -->
430 Content Model: (header?, footer?)
431 Attributes: The decoration element contains only the common attributes:
432 ids, names, dupnames, source, and classes.
434 Although the content model doesn't specifically require contents, no empty
435 decoration elements are ever created.
437 <!-- == structural_subelement -->
439 match=
"//document/decoration">
440 <xsl:apply-templates/>
443 <!-- TODO To be rendered as `.. header::` directive -->
444 <!-- == decorative_element -->
446 match=
"//document/decoration/header">
447 <xsl:apply-templates/>
450 <!-- TODO To be rendered as `.. footer::` directive -->
451 <!-- == decorative_element -->
453 match=
"//document/decoration/footer">
454 <xsl:apply-templates/>
457 <!-- ******************************************************************** -->
460 Content Model: (%bibliographic.elements;)+
461 Attributes: The docinfo element contains only the common attributes: ids,
462 names, dupnames, source, and classes.
464 <!-- == structural_subelement -->
468 name=
"u:outputClass"/>
471 <xsl:apply-templates/>
476 <!-- ******************************************************************** -->
479 Content Model: ((author, organization?, address?, contact?)+)
480 Attributes: The authors element contains only the common attributes: ids,
481 names, dupnames, source, and classes.
483 In reStructuredText, multiple author's names are separated with semicolons
484 (";") or commas (","); semicolons take precedence. There is currently no way
485 to represent the author's organization, address, or contact in a
486 reStructuredText "Authors" field.
488 <!-- == bibliographic_element == folding_element -->
490 match=
"docinfo/authors">
492 name=
"u:outputFolding">
495 <xsl:text>:
</xsl:text>
498 <xsl:text>:
</xsl:text>
504 Content Model: %text.model;
505 Attributes: All docinfo elements contains the common attributes (ids,
506 names, dupnames, source, and classes)
507 Some docinfo elements also have xml:space.
510 match=
"docinfo/authors/*">
511 <xsl:apply-templates/>
512 <!-- no semicolon after final author -->
514 test=
"generate-id(current()) != generate-id(../*[last()])">
515 <xsl:text>;
</xsl:text>
520 Content Model: (field_name, field_body)
521 Attributes: The field element contains only the common attributes: ids,
522 names, dupnames, source, and classes.
524 <!-- == bibliographic_element -->
526 match=
"docinfo/field">
527 <!-- contents handled by ordinary field lists -->
528 <xsl:apply-templates/>
529 <!-- Supply an EOL because following elements do not recognize this -->
534 Content Model: %text.model;
535 Attributes: All docinfo elements contains the common attributes (ids,
536 names, dupnames, source, and classes)
537 Some docinfo elements also have xml:space.
539 <!-- == bibliographic_element == folding_element -->
541 match=
"docinfo/*[name()!='authors' and name()!='field']">
543 name=
"u:outputFolding">
546 <xsl:text>:
</xsl:text>
549 <xsl:text>:
</xsl:text>
554 <!-- ******************************************************************** -->
558 Attributes: The transition element contains only the common attributes:
559 ids, names, dupnames, source, and classes.
561 <!-- == structural_subelement -->
565 name=
"u:outputClass"/>
566 &tCR; <!-- req: blank line before -->
567 <xsl:text>-----
</xsl:text>
569 <!-- Add a required blank line after unless class follows immediately -->
571 test=
"not(following-sibling::*[1]/@classes)">
576 <!-- ******************************************************************** -->
577 <!-- ******************************************************************** -->
580 IFF there is a /document/title element, it is the publication's title. All
581 other titles will appear within sections.
583 Content Model: %text.model;
584 Attributes: The title element contains the common attributes (ids, names,
585 dupnames, source, and classes), plus refid and auto.
586 refid is used as a backlink to a table of contents entry.
587 auto is used to indicate (with value "1") that the title has been
588 numbered automatically.
590 <!-- == structural_subelement -->
592 match=
"//document/title">
594 name=
"u:outputClass"/>
597 <!-- Catch the title text as it is rendered so its length can be
599 <xsl:apply-templates/>
603 select=
"normalize-space($textWS)"/>
606 select=
"string-length($text)"/>
630 <!-- ******************************************************************** -->
633 Title Underlines are defined by their position within the tree.
635 Content Model: %text.model;
636 Attributes: The title element contains the common attributes (ids, names,
637 dupnames, source, and classes), plus refid and auto.
638 refid is used as a backlink to a table of contents entry.
639 auto is used to indicate (with value "1") that the title has been
640 numbered automatically.
642 <!-- == structural_subelement -->
644 match=
"section/title">
646 name=
"u:outputClass"/>
649 <!-- catch the title text as it is rendered -->
650 <xsl:apply-templates/>
654 select=
"normalize-space($textWS)"/>
657 select=
"string-length($text)"/>
660 select=
"count(ancestor::section)"/>
668 select=
"$depth + 2"/>
680 select=
"$depth + 2"/>
682 <!-- Add a blank line after unless structure follows immediately -->
684 test=
"not(contains(concat($structural_elements, $compound_body_elements), concat('*', name(following-sibling::*[1]), '*')) or following-sibling::*[1]/@classes)">
689 <!-- ******************************************************************** -->
692 Content Model: %text.model;
693 Attributes: The title element contains the common attributes (ids, names,
694 dupnames, source, and classes), plus refid and auto.
695 refid is used as a backlink to a table of contents entry.
696 auto is used to indicate (with value "1") that the title has been
697 numbered automatically.
699 <!-- == structural_subelement -->
703 name=
"u:outputClass">
705 name=
"alreadyBlanked"
708 <!-- blank line provided by parent -->
709 <xsl:apply-templates/>
710 <!-- no EOL: provided by parent -->
713 <!-- ******************************************************************** -->
716 IFF there is a /document/title element, it is the publication's title. All
717 other titles will appear within sections.
719 Content Model: %text.model;
720 Attributes: The subtitle element contains only the common attributes:
721 ids, names, dupnames, source, and classes.
723 <!-- == structural_subelement -->
725 match=
"//document/subtitle">
727 name=
"u:outputClass"/>
730 <!-- Catch the title text as it is rendered -->
731 <xsl:apply-templates/>
735 select=
"normalize-space($textWS)"/>
738 select=
"string-length($text)"/>
740 <!-- always a blank line above -->
765 <!-- ******************************************************************** -->
768 Content Model: %text.model;
769 Attributes: The subtitle element contains only the common attributes: ids,
770 names, dupnames, source, and classes.
772 <!-- == structural_subelement -->
774 match=
"sidebar/subtitle">
776 name=
"u:outputClass"/>
779 <xsl:apply-templates/>
784 <!-- ******************************************************************** -->
785 <!-- ******************************************************************** -->
788 Content Model: %text.model;
789 Attributes: The comment element contains only the common attributes: ids,
790 names, dupnames, source, and classes.
792 <!-- == simple_body_element == folding_element == directive -->
798 name=
"u:outputFolding">
801 <xsl:text>..
</xsl:text>
806 <!-- ******************************************************************** -->
809 Content Model: %text.model;
810 Attributes: The doctest_block element contains the common attributes (ids,
811 names, dupnames, source, and classes), plus xml:space.
813 <!-- == simple_body_element -->
815 match=
"doctest_block">
817 name=
"u:outputClass"/>
820 <xsl:apply-templates/>
824 <!-- ******************************************************************** -->
826 <!-- An image element can have various roles; they are all covered here -->
827 <!-- == simple_body_element == inline_element == directive -->
832 test=
"contains($inline_containers, concat('*', name(..), '*')) and @alt">
833 <!-- An inline image with an `@alt' - must be a substitution
835 <xsl:text>|
</xsl:text>
836 <!-- Original text is lost - use what we have -->
839 <xsl:text>|
</xsl:text>
844 test=
"not(parent::figure)">
846 test=
"not(parent::substitution_definition)">
849 <xsl:text>..
</xsl:text>
851 <xsl:text>image::
</xsl:text>
858 test=
"parent::figure">
859 <!-- `@classes' is special because it is in the parent -->
866 select=
"'figclass'"/>
869 select=
"../@classes"/>
872 select=
"ancestor::*"/>
875 <!-- `@align' is special because it is in the parent -->
888 select=
"ancestor::*"/>
893 <!-- `figure' would add one level of indentation -->
896 select=
"ancestor::*"/>
900 test=
"parent::substitution_definition">
903 <!-- `@alt' only for the real images -->
906 select=
"@*[name() != 'alt']"/>
914 select=
"@*[name() != 'ids' and name() != 'names']"/>
919 test=
"parent::reference">
920 <!-- A clickable image -->
931 <!-- An internal link -->
933 name=
"u:inlineReference">
940 <!-- An external link -->
942 select=
"../@refuri"/>
948 select=
"ancestor-or-self::*"/>
951 <!-- Always blank line after parameter block -->
957 <!-- ******************************************************************** -->
960 Content Model: (line_block | line)+
961 Attributes: The line_block element contains the common attributes (ids,
962 names, dupnames, source, and classes), plus xml:space.
964 <!-- == compound_body_element -->
968 name=
"u:outputClass"/>
971 select=
"name(..) = 'line_block'"/>
973 test=
"not($isEmbedded)">
977 <xsl:apply-templates/>
980 <!-- ******************************************************************** -->
983 Content Model: %text.model;
984 Attributes: The line element contains the common attributes (ids,
985 names, dupnames, source, and classes).
987 <!-- == simple_body_subelement == folding_element -->
991 name=
"u:outputClass"/>
1002 <!-- Only for non-empty lines -->
1004 name=
"lineBlockIndent">
1005 <!-- Very special indendation for nested `line_block's -->
1007 select=
"ancestor::line_block[position() > 1]">
1009 select=
"str:padding(4)"/>
1013 name=
"u:outputFolding">
1016 <xsl:text>|
</xsl:text>
1018 select=
"$lineBlockIndent"/>
1022 select=
"concat($indent, ' ', $lineBlockIndent)"/>
1023 </xsl:call-template>
1026 <xsl:text>|
</xsl:text>
1032 <!-- ******************************************************************** -->
1035 Content Model: %text.model;
1036 Attributes: The literal_block element contains the common attributes (ids,
1037 names, dupnames, source, and classes), plus xml:space.
1039 <!-- == simple_body_element == directive -->
1041 match=
"literal_block">
1042 <!-- If it contains inline elements this is a parsed-literal -->
1044 name=
"isParsedLiteral"
1045 select=
".//*[contains($inline_elements, concat('*', name(), '*'))]"/>
1048 test=
"$isParsedLiteral">
1051 <xsl:text>.. parsed-literal::
</xsl:text>
1059 name=
"u:outputClass"/>
1060 <!-- TODO Support for the (fully) minimized style would be nice but
1061 is difficult to accomplish because there is a linefeed
1062 already when we arrive here :-( -->
1065 <xsl:text>::
</xsl:text>
1071 name=
"isQuotedLiteral">
1073 name=
"u:isQuotedLiteral"/>
1075 <!-- Indent correctly depending on quoted literal or not -->
1078 test=
"string-length($isQuotedLiteral)">
1083 select=
"ancestor::*"/>
1084 </xsl:call-template>
1085 <xsl:apply-templates
1086 mode=
"quotedLiteral"/>
1093 select=
"ancestor-or-self::*"/>
1094 </xsl:call-template>
1097 test=
"$isParsedLiteral">
1098 <xsl:apply-templates/>
1101 <xsl:apply-templates
1110 <!-- Indent a text of a quoted literal containing line feeds correctly -->
1113 mode=
"quotedLiteral">
1122 select=
"ancestor::*[position() > 1]"/>
1123 </xsl:call-template>
1128 </xsl:call-template>
1131 <!-- Determine whether `$text' is a quoted literal and return the quote
1134 name=
"u:isQuotedLiteral">
1140 select=
"substring($text, 1, 1)"/>
1142 test=
"contains($adornment_characters, $quote) and substring($text, 1, 1) = $quote">
1143 <!-- Given quote is an adornment character and first character is this
1147 test=
"contains($text, '
')">
1148 <!-- Test the remaining lines -->
1150 name=
"u:isQuotedLiteral">
1153 select=
"substring-after($text, '
')"/>
1157 </xsl:call-template>
1160 <!-- No more lines to test so this is a quoted literal -->
1168 <!-- ******************************************************************** -->
1171 Content Model: %text.model;
1172 Attributes: The paragraph element contains only the common attributes:
1173 ids, names, dupnames, source, and classes.
1175 <!-- == simple_body_element == folding_element -->
1180 select=
"preceding-sibling::*[1]"/>
1181 <!-- Do indent except first element in some compound elements -->
1184 select=
"($previous or not(parent::list_item or parent::field_body or contains($admonitions, concat('*', name(..), '*')))) and name($previous) != 'label'"/>
1185 <!-- Blank line in front if following a body element, except first
1186 elements in some compound elements -->
1189 select=
"($previous or not(parent::list_item or ../parent::option_list_item or parent::field_body or parent::document or contains($admonitions, concat('*', name(..), '*')))) and (not($previous) or contains($body_elements, concat('*', name($previous), '*')) or name($previous) = 'title' and contains($titled_elements, concat('*', name(..), '*')) or name($previous) = 'docinfo')"/>
1195 test=
"$needsIndent">
1201 <!-- This paragraph has a classes attribute - always needs newline and
1204 name=
"u:outputClass">
1206 name=
"alreadyBlanked"
1207 select=
"$needsBlank"/>
1209 name=
"alreadyIndented"
1210 select=
"$needsIndent"/>
1211 </xsl:call-template>
1216 name=
"u:outputFolding"/>
1219 <!-- ******************************************************************** -->
1221 <!-- == simple_body_element -->
1225 name=
"u:notSupported"/>
1228 <!-- ******************************************************************** -->
1230 <!-- == simple_body_element == inline_element == directive -->
1235 test=
"contains($inline_containers, concat('*', name(..), '*'))">
1236 <!-- Used as a custom role -->
1237 <!-- TODO `role' directives must be generated for user-defined raw
1239 <!-- The name of the custom role is not contained in the input -->
1240 <xsl:text>:RAW-ROLE:`
</xsl:text>
1241 <xsl:apply-templates/>
1242 <xsl:text>`
</xsl:text>
1245 <!-- A directive -->
1247 name=
"u:outputClass"/>
1250 <xsl:text>.. raw::
</xsl:text>
1258 select=
"@*[name() != 'format' and name() != 'classes']"/>
1259 </xsl:call-template>
1265 select=
"ancestor-or-self::*"/>
1266 </xsl:call-template>
1267 <xsl:apply-templates
1274 <!-- ******************************************************************** -->
1276 <!-- == simple_body_element == folding_element == directive -->
1282 name=
"u:outputFolding">
1285 <xsl:text>.. rubric::
</xsl:text>
1287 </xsl:call-template>
1292 <!-- ******************************************************************** -->
1294 <!-- == compound_body_element == directive -->
1299 <xsl:text>.. compound::
</xsl:text>
1303 <xsl:apply-templates/>
1306 <!-- ******************************************************************** -->
1308 <!-- == compound_body_element == directive -->
1313 <xsl:text>.. container::
</xsl:text>
1321 <xsl:apply-templates/>
1324 <!-- ******************************************************************** -->
1326 <!-- == simple_body_element == directive -->
1328 match=
"substitution_definition">
1329 <!-- More than one child or not a directive is a replacement text -->
1332 select=
"not(* and count(node()) = 1 and contains($directives, concat('*', name(*[1]), '*')))"/>
1337 <xsl:text>.. |
</xsl:text>
1339 name=
"u:outputNames"/>
1340 <xsl:text>|
</xsl:text>
1345 <!-- TODO Substitution references for replace can not be found because
1346 they are not marked as such; embedding them in `generated'
1349 name=
"u:outputFolding">
1354 <xsl:text>replace::
</xsl:text>
1356 </xsl:call-template>
1361 <xsl:apply-templates/>
1366 <!-- ******************************************************************** -->
1369 Content Model: ((%body.elements;)+, attribution?)
1370 Attributes: The block_quote element contains only the common attributes:
1371 ids, names, dupnames, source, and classes.
1373 <!-- == compound_body_element -->
1375 match=
"block_quote">
1377 test=
"@classes = 'epigraph' or @classes = 'highlights' or @classes = 'pull-quote'">
1380 <xsl:text>..
</xsl:text>
1383 <xsl:text>::
</xsl:text>
1388 <xsl:apply-templates/>
1391 <!-- ******************************************************************** -->
1393 <!-- == simple_body_subelement == folding_element -->
1395 match=
"attribution">
1397 name=
"u:outputClass"/>
1398 <!-- blank line between quote and attribution -->
1403 name=
"u:outputFolding">
1406 <xsl:text>--
</xsl:text>
1408 </xsl:call-template>
1411 <!-- ******************************************************************** -->
1413 <!-- == compound_body_element == directive -->
1417 name=
"u:outputClass"/>
1420 <xsl:text>.. [
</xsl:text>
1423 <xsl:text>]
</xsl:text>
1424 <xsl:apply-templates
1425 select=
"*[not(self::label)]"/>
1428 <!-- == simple_body_subelement -->
1430 match=
"citation/label">
1431 <xsl:apply-templates/>
1434 <!-- ******************************************************************** -->
1436 <!-- == compound_body_element == directive -->
1441 <xsl:text>.. figure::
</xsl:text>
1442 <xsl:apply-templates/>
1445 <!-- ******************************************************************** -->
1447 <!-- == simple_body_subelement == folding_element -->
1453 name=
"u:outputFolding"/>
1456 <!-- ******************************************************************** -->
1458 <!-- == compound_body_subelement -->
1461 <xsl:apply-templates/>
1464 <!-- ******************************************************************** -->
1466 <!-- TODO Footnotes should continue on line of definition -->
1468 <!-- user-numbered footnotes lack @auto -->
1469 <!-- == compound_body_element == directive -->
1471 match=
"footnote[not(@auto)]">
1473 name=
"u:outputClass"/>
1476 <xsl:text>.. [
</xsl:text>
1477 <xsl:apply-templates
1479 <xsl:text>]
</xsl:text>
1480 <xsl:apply-templates
1481 select=
"*[not(self::label)]"/>
1484 <!-- autonumbered footnotes have @auto -->
1485 <!-- if the target footnote_reference@names matches its label, it was not a
1486 numbered-name footnote -->
1487 <!-- == compound_body_element == directive -->
1489 match=
"footnote[@auto='1']">
1491 name=
"u:outputClass"/>
1494 <xsl:text>.. [#
</xsl:text>
1496 test=
"@names = @ids">
1498 name=
"u:outputNames"/>
1500 <xsl:text>]
</xsl:text>
1501 <xsl:apply-templates
1502 select=
"*[not(self::label)]"/>
1505 <!-- autosymboled footnotes have @auto -->
1506 <!-- == compound_body_element == directive -->
1508 match=
"footnote[@auto='*']">
1510 name=
"u:outputClass"/>
1513 <xsl:text>.. [*]
</xsl:text>
1514 <xsl:apply-templates
1515 select=
"*[not(self::label)]"/>
1518 <!-- == compound_body_element == directive -->
1520 match=
"footnote[starts-with(@names, 'TARGET_NOTE:\ ')]">
1521 <!-- This is not a footnote but a hint for a directive -->
1523 test=
"generate-id(//footnote[starts-with(@names, 'TARGET_NOTE:\ ')][1]) = generate-id(.)">
1524 <!-- Only for the first one -->
1527 <!-- TODO May have a `classes` attribute -->
1528 <xsl:text>.. target-notes::
</xsl:text>
1533 <!-- == simple_body_subelement -->
1535 match=
"footnote/label">
1536 <xsl:apply-templates/>
1539 <!-- ******************************************************************** -->
1542 Content Model: (list_item +)
1543 Attributes: The bullet_list element contains the common attributes (ids,
1544 names, dupnames, source, and classes), plus bullet.
1545 bullet is used to record the style of bullet from the input data.
1546 In documents processed from reStructuredText, it contains one of "-",
1547 "+", or "*". It may be ignored in processing.
1549 <!-- == compound_body_element -->
1551 match=
"bullet_list">
1553 name=
"u:outputClass"/>
1554 <xsl:apply-templates
1555 mode=
"bullet_list"/>
1558 <!-- ******************************************************************** -->
1561 Content Model: (definition_list_item +)
1562 Attributes: The definition_list element contains only the common
1563 attributes: ids, names, dupnames, source, and classes.
1565 <!-- == compound_body_element -->
1567 match=
"definition_list">
1569 name=
"u:outputClass"/>
1570 <xsl:apply-templates/>
1573 <!-- ******************************************************************** -->
1576 Content Model: (term, classifier?, definition)
1577 Attributes: The definition_list_item element contains only the common
1578 attributes: ids, names, dupnames, source, and classes.
1580 <!-- == compound_body_subelement -->
1582 match=
"definition_list_item">
1584 name=
"u:outputClass"/>
1587 <xsl:apply-templates/>
1590 <!-- ******************************************************************** -->
1593 Content Model: %text.model;
1594 Attributes: The term element contains only the common attributes: ids,
1595 names, dupnames, source, and classes.
1597 <!-- == simple_body_subelement -->
1600 <xsl:apply-templates/>
1603 <!-- ******************************************************************** -->
1606 Content Model: %text.model;
1607 Attributes: The classifier element contains only the common attributes:
1608 ids, names, dupnames, source, and classes.
1610 <!-- == simple_body_subelement -->
1613 <xsl:text> :
</xsl:text>
1614 <xsl:apply-templates/>
1617 <!-- ******************************************************************** -->
1620 Content Model: (%body.elements;)+
1621 Attributes: The definition element contains only the common attributes:
1622 ids, names, dupnames, source, and classes.
1624 <!-- == compound_body_subelement -->
1628 name=
"u:outputClass"/>
1629 <xsl:apply-templates/>
1632 <!-- ******************************************************************** -->
1635 Content Model: (list_item +)
1636 Attributes: The enumerated_list element contains the common attributes
1637 (ids, names, dupnames, source, and classes), plus enumtype, prefix, suffix, and
1639 enumtype is used to record the intended enumeration sequence, one
1640 of "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A,
1641 B, C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1642 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1643 prefix stores the formatting characters used before the enumerator. In
1644 documents originating from reStructuredText data, it will contain either ""
1645 (empty string) or "(" (left parenthesis). It may or may not affect
1647 suffix stores the formatting characters used after the enumerator. In
1648 documents originating from reStructuredText data, it will contain either "."
1649 (period) or ")" (right parenthesis). Depending on the capabilities of the
1650 output format, this attribute may or may not affect processing.
1651 start contains the ordinal value of the first item in the list, in
1652 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1653 attribute may be omitted.
1655 <!-- == compound_body_element -->
1657 match=
"enumerated_list">
1659 name=
"u:outputClass"/>
1660 <xsl:apply-templates
1661 mode=
"enumerated_list"/>
1664 <!-- ******************************************************************** -->
1667 Content Model: (field +)
1668 Attributes: The field_list element contains only the common attributes:
1669 ids, names, dupnames, source, and classes.
1671 <!-- == compound_body_element -->
1675 name=
"u:outputClass"/>
1676 <xsl:apply-templates/>
1679 <!-- ******************************************************************** -->
1682 Content Model: (field_name, field_body)
1683 Attributes: The field element contains only the common attributes: ids,
1684 names, dupnames, source, and classes.
1686 <!-- == compound_body_subelement -->
1690 name=
"u:outputClass"/>
1693 <xsl:apply-templates/>
1696 <!-- ********************************************************************** -->
1699 Content Model: %text.model;
1700 Attributes: The field_name element contains only the common attributes:
1701 ids, names, dupnames, source, and classes.
1703 <!-- == simple_body_subelement -->
1706 <xsl:text>:
</xsl:text>
1707 <xsl:apply-templates/>
1708 <xsl:text>:
</xsl:text>
1709 <!-- no EOL: field_body starts on same line -->
1712 <!-- ******************************************************************** -->
1715 Content Model: (%body.elements;)*
1716 Attributes: The field_body element contains only the common attributes:
1717 ids, names, dupnames, source, and classes.
1719 <!-- == compound_body_subelement -->
1723 name=
"u:outputClass"/>
1724 <xsl:apply-templates/>
1727 <!-- ******************************************************************** -->
1730 Content Model: (option_list_item +)
1731 Attributes: The option_list element contains only the common attributes:
1732 ids, names, dupnames, source, and classes.
1734 <!-- == compound_body_element -->
1736 match=
"option_list">
1738 name=
"u:outputClass"/>
1741 <xsl:apply-templates/>
1744 <!-- ******************************************************************** -->
1747 Content Model: (option_group, description)
1748 Attributes: The option_list_item element contains only the common
1749 attributes: ids, names, dupnames, source, and classes.
1751 <!-- == compound_body_subelement -->
1753 match=
"option_list_item">
1755 name=
"u:outputClass"/>
1758 <xsl:apply-templates/>
1761 <!-- ******************************************************************** -->
1764 Content Model: (option_group, description)
1765 Attributes: The option_group element contains only the common attributes:
1766 ids, names, dupnames, source, and classes.
1768 <!-- == compound_body_subelement -->
1770 match=
"option_group">
1771 <xsl:apply-templates/>
1775 <!-- ******************************************************************** -->
1778 Content Model: (option_string, option_argument *)
1779 Attributes: The option element contains only the common attributes: ids,
1780 names, dupnames, source, and classes.
1782 <!-- == compound_body_subelement -->
1786 name=
"u:outputClass"/>
1787 <xsl:apply-templates/>
1789 test=
"generate-id(current()) != generate-id(../*[last()])">
1790 <!-- No comma after final option -->
1791 <xsl:text>,
</xsl:text>
1793 <!-- no EOL: description on same line -->
1796 <!-- ******************************************************************** -->
1799 Content Model: (#PCDATA)
1800 Attributes: The option_string element contains only the common attributes:
1801 ids, names, dupnames, source, and classes.
1803 <!-- == simple_body_subelement -->
1805 match=
"option_string">
1806 <xsl:apply-templates/>
1809 <!-- ******************************************************************** -->
1812 Content Model: (#PCDATA)
1813 Attributes: The option_argument element contains the common attributes
1814 (ids, names, dupnames, source, and classes), plus delimiter.
1815 delimiter contains the text preceding the option_argument:
1816 either the text separating it from the option_string (typically
1818 or the text between option arguments (typically either "," or " ").
1820 <!-- == simple_body_subelement -->
1822 match=
"option_argument">
1824 select=
"@delimiter"/>
1825 <xsl:apply-templates/>
1828 <!-- ******************************************************************** -->
1831 Content Model: (%body.elements;)+
1832 Attributes: The description element contains only the common attributes:
1833 ids, names, dupnames, source, and classes.
1835 <!-- == compound_body_subelement -->
1837 match=
"description">
1839 name=
"u:outputClass"/>
1840 <xsl:apply-templates/>
1844 <!-- ******************************************************************** -->
1847 Content Model: (%body.elements;)+
1848 Attributes: The list_item element contains only the common attributes:
1849 ids, names, dupnames, source, and classes
1852 bullet is used to record the style of bullet from the input data.
1853 In documents processed from reStructuredText, it contains one of "-",
1854 "+", or "*". It may be ignored in processing.
1856 <!-- == compound_body_subelement -->
1861 name=
"u:outputClass"/>
1865 select=
"../@bullet"/>
1866 &tSP; <!-- space after bullet -->
1867 <xsl:apply-templates/>
1870 <!-- ******************************************************************** -->
1874 enumtype is used to record the intended enumeration sequence, one of
1875 "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A, B,
1876 C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1877 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1878 prefix stores the formatting characters used before the enumerator. In
1879 documents originating from reStructuredText data, it will contain either ""
1880 (empty string) or "(" (left parenthesis). It may or may not affect
1882 suffix stores the formatting characters used after the enumerator. In
1883 documents originating from reStructuredText data, it will contain either "."
1884 (period) or ")" (right parenthesis). Depending on the capabilities of the
1885 output format, this attribute may or may not affect processing.
1886 start contains the ordinal value of the first item in the list, in
1887 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1888 attribute may be omitted.
1891 <!-- == compound_body_subelement -->
1894 mode=
"enumerated_list">
1896 name=
"u:outputClass"/>
1900 name=
"u:outputEnumerator"/>
1901 <xsl:apply-templates/>
1904 <!-- Outputs a complete enumerator when called in an
1905 enumerated_list/list_item -->
1907 name=
"u:outputEnumerator">
1908 <!-- Use parent's numeration attribute -->
1911 select=
"../@enumtype"/>
1912 <!-- Determine starting point -->
1919 select=
"../@start"/>
1927 <!-- Determine position of this item in its real context -->
1932 select=
"generate-id()"/>
1933 <!-- Generate the right current node list -->
1935 select=
"../list_item">
1937 test=
"generate-id() = $wanted">
1939 select=
"position()"/>
1943 <!-- Determine encoding of the number for the given numeration -->
1947 name=
"u:position2Enumerator">
1950 select=
"$enumType"/>
1953 select=
"$position"/>
1957 </xsl:call-template>
1959 <!-- Determine encoding of the maximum number -->
1963 name=
"u:position2Enumerator">
1966 select=
"$enumType"/>
1969 select=
"count(../list_item)"/>
1973 </xsl:call-template>
1975 <!-- Output complete enumerator -->
1977 select=
"../@prefix"/>
1981 select=
"../@suffix"/>
1982 <!-- Output at least one trailing space -->
1984 <!-- Output more whitespace to align with the maximum enumerator -->
1986 test=
"$enumType != 'lowerroman' and $enumType != 'upperroman'">
1987 <!-- Assumes that the maximum number has maximum string length -->
1989 select=
"str:padding(string-length($max) - string-length($cur))"/>
1993 <!-- Determine the right ordinal enumerator based on the parameters -->
1995 name=
"u:position2Enumerator">
2002 <!-- Determine logical number -->
2005 select=
"$start - 1 + $position"/>
2008 test=
"$enumType = 'arabic'">
2013 test=
"$enumType = 'loweralpha'">
2015 select=
"substring('abcdefghijklmnopqrstzuvwxyz', $ordinal, 1)"/>
2018 test=
"$enumType = 'upperalpha'">
2020 select=
"substring('ABCDEFGHIJKLMNOPQRSTZUVWXYZ', $ordinal, 1)"/>
2022 <!-- TODO Support for counting roman numbers -->
2024 test=
"$enumType = 'lowerroman'">
2025 <xsl:text>i
</xsl:text>
2028 test=
"$enumType = 'upperroman'">
2029 <xsl:text>I
</xsl:text>
2034 <!-- ******************************************************************** -->
2035 <!-- ******************************************************************** -->
2038 Content Model: (title?, tgroup+)
2039 Attributes: The table element contains the common attributes and:
2040 frame, colsep, rowsep, pgwide
2042 <!-- == compound_body_element -->
2046 name=
"u:outputClass"/>
2049 <xsl:apply-templates
2053 <!-- TODO A table title must be rendered by using the `.. table::'
2057 <xsl:apply-templates
2063 <!-- ******************************************************************** -->
2066 Content Model: (colspec*, thead?, tbody)
2067 Attributes: The tgroup element contains the common attributes and:
2068 cols, colsep, rowsep, align
2070 <!-- == compound_body_subelement -->
2073 <xsl:apply-templates/>
2076 <!-- ******************************************************************** -->
2079 Content Model: EMPTY
2080 Attributes: The colspec element contains the common attributes and:
2081 colnum, colname, colwidth, colsep, rowsep, align, char, charoff
2083 The colwidth attribute gives the width of the respective column in characters
2084 including padding whitespace but no separator markup.
2086 <!-- == simple_body_subelement -->
2087 <!-- @colwidth needed by children but element has no own output -->
2091 <!-- ******************************************************************** -->
2094 Content Model: (row+)
2095 Attributes: The thead element contains the common attributes and:
2098 <!-- == compound_body_subelement -->
2101 <xsl:apply-templates/>
2105 Content Model: (row+)
2106 Attributes: The tbody element contains the common attributes and:
2109 <!-- == compound_body_subelement -->
2112 <xsl:apply-templates/>
2115 <!-- ******************************************************************** -->
2118 Content Model: (entry+)
2119 Attributes: The row element contains the common attributes and:
2122 <!-- == compound_body_subelement -->
2125 <!-- Separator line above unless first row of a tbody with no previous
2126 thead (in this case the separator line is output already as the
2127 closing separator line of thead) -->
2129 test=
"position() > 1 or parent::thead or parent::tbody and not(../../thead)">
2131 name=
"u:rowSeparatorLine"/>
2133 <!-- Determine heights in physical lines of all entries -->
2140 <!-- Catch the text of all entries -->
2141 <xsl:apply-templates/>
2143 <!-- Compute height of this entry; leading and trailing EOL must be
2146 select=
"string-length($text) - string-length(translate($text, '
', '')) - 1"/>
2147 &tSP; <!-- A space as a list separator -->
2150 <!-- Determine maximum height so every entry must be this high -->
2153 select=
"math:max(str:tokenize(normalize-space($heights)))"/>
2154 <!-- Output all the physical lines of this row -->
2162 select=
"$maxHeight"/>
2163 </xsl:call-template>
2164 <!-- Output final separator line if this is the last row -->
2166 test=
"position() = last()">
2168 name=
"u:rowSeparatorLine">
2171 <!-- Determine correct character for the separator line -->
2174 test=
"parent::thead">
2184 </xsl:call-template>
2188 <!-- Output physical line $currentLine of a row and continue until
2189 line $maxLine is output -->
2193 name=
"currentLine"/>
2197 test=
"$currentLine <= $maxLine">
2198 <!-- If there are still physical lines to output do it -->
2201 <!-- Leading bar -->
2202 <xsl:text>|
</xsl:text>
2203 <xsl:apply-templates>
2206 select=
"$currentLine"/>
2207 </xsl:apply-templates>
2208 <!-- End of this physical line -->
2210 <!-- Continue with the next physical line -->
2215 select=
"$currentLine + 1"/>
2219 </xsl:call-template>
2223 <!-- Output a separator line with all the right characters -->
2225 name=
"u:rowSeparatorLine">
2231 <xsl:text>+
</xsl:text>
2233 select=
"../../colspec">
2235 select=
"str:padding(@colwidth, $char)"/>
2236 <xsl:text>+
</xsl:text>
2241 <!-- ******************************************************************** -->
2244 Content Model: (%body.elements;)*
2245 Attributes: The entry element contains the common attributes and:
2246 colname, namest, morerows, colsep, rowsep, align, char, charoff, valign and
2249 <!-- == compound_body_subelement -->
2252 <!-- TODO `classes` attribute needs support -->
2253 <!-- This is called in two ways; if $currentLine = 0 all physical lines
2254 of this entry must be output; if $currentLine > 0 the physical line
2255 with exactly this number shall be output -->
2261 select=
"position() + sum(preceding-sibling::entry/@morecols)"/>
2262 <!-- Determine width in characters needed for this entry -->
2266 name=
"u:computeEntryWidth">
2269 select=
"../../../colspec"/>
2275 select=
"@morecols"/>
2276 </xsl:call-template>
2278 <!-- Output the entry completely or a certain physical line -->
2280 name=
"u:outputEntry">
2283 <!-- Capture physical lines of the entry in a variable -->
2284 <xsl:apply-templates/>
2290 name=
"expectedIndent">
2291 <!-- Capture indent for the entry generated by the normal template
2292 rules to remove it later -->
2298 select=
"$currentLine"/>
2299 </xsl:call-template>
2300 <!-- Final bar after the entry -->
2301 <xsl:text>|
</xsl:text>
2304 <!-- Compute width of the entry -->
2306 name=
"u:computeEntryWidth">
2307 <!-- The colspec elements of all columns -->
2310 <!-- Column of this entry -->
2313 <!-- Number of columns this entry spans -->
2323 <!-- If entry spans multiple columns compute their width -->
2325 name=
"u:computeEntryWidth">
2328 select=
"$colspecs"/>
2331 select=
"$column + 1"/>
2334 select=
"$span - 1"/>
2335 <!-- Add the separator character and the following column width -->
2338 select=
"$sum + 1 + $colspecs[$column]/@colwidth"/>
2339 </xsl:call-template>
2342 <!-- Does not span more columns so return sum and width of this
2345 select=
"$sum + $colspecs[$column]/@colwidth"/>
2350 <!-- Outputs one or all lines of a table entry as a string trimmed left and
2353 name=
"u:outputEntry">
2354 <!-- Width of the entry; there is no provision for actual physical lines
2355 longer than this width -->
2358 <!-- The string containing the remaining physical lines; may be an empty
2363 <!-- The indendation which is expected to be prefixed before every
2366 name=
"expectedIndent"
2368 <!-- Is this the first call to this template -->
2372 <!-- Number of physical line to output or 0 to output all lines -->
2376 <!-- Output is wanted if all or the first physical line are to be
2380 select=
"$outputLine = 0 or $outputLine = 1"/>
2382 name=
"stringLFHalfTrimmed">
2385 test=
"$isFirst and substring($string, 1, 1) = '
'">
2386 <!-- Remove leading linefeed if this is the first time -->
2388 select=
"substring($string, 2)"/>
2397 name=
"stringLFTrimmed">
2400 test=
"$isFirst and substring($stringLFHalfTrimmed, string-length($stringLFHalfTrimmed), 1) = '
'">
2401 <!-- Remove trailing linefeed if this is the first time -->
2403 select=
"substring($stringLFHalfTrimmed, 1, string-length($stringLFHalfTrimmed) - 1)"/>
2407 select=
"$stringLFHalfTrimmed"/>
2411 <!-- Determine remaining lines after the first one -->
2413 name=
"remainingLines">
2415 test=
"contains($stringLFTrimmed, '
')">
2417 select=
"substring-after($stringLFTrimmed, '
')"/>
2422 <!-- If this physical line must be output determine the first physical
2428 test=
"string-length($remainingLines)">
2430 select=
"substring-before($stringLFTrimmed, '
')"/>
2434 select=
"$stringLFTrimmed"/>
2438 <!-- Remove the leading indentation from the physical line which is
2439 brought there by the normal templates -->
2443 test=
"string-length($firstLine)">
2444 <!-- Trim only non-empty lines -->
2446 select=
"substring-after($firstLine, $expectedIndent)"/>
2449 <!-- Pad the line with a leading and a trailing space -->
2452 select=
"concat(' ', $trimmed, ' ')"/>
2453 <!-- Output the padded value -->
2456 <!-- Fill up the width of the entry with spaces -->
2458 test=
"$width - string-length($padded) < 0">
2460 <xsl:text>WARNING: Table column too narrow (minimum:
</xsl:text>
2462 select=
"string-length($padded)"/>
2463 <xsl:text>)
</xsl:text>
2468 select=
"str:padding($width - string-length($padded))"/>
2471 test=
"$outputLine > 1 or $outputLine = 0 and string-length($remainingLines)">
2472 <!-- If a following physical line must be output or if all physical
2473 lines shall be output and there are remaining physical lines -->
2475 test=
"$outputLine = 0">
2476 <!-- Output linefeed only if we output all the lines -->
2479 <!-- Output the remaining lines -->
2481 name=
"u:outputEntry">
2487 select=
"$remainingLines"/>
2489 name=
"expectedIndent"
2490 select=
"$expectedIndent"/>
2498 test=
"$outputLine = 0">
2504 select=
"$outputLine - 1"/>
2508 </xsl:call-template>
2512 <!-- ******************************************************************** -->
2513 <!-- ******************************************************************** -->
2515 <!-- == inline_element -->
2517 match=
"citation_reference">
2519 name=
"u:bkslshEscPre"/>
2520 <xsl:text>[
</xsl:text>
2521 <xsl:apply-templates/>
2522 <xsl:text>]_
</xsl:text>
2524 name=
"u:bkslshEscSuf"/>
2527 <!-- ******************************************************************** -->
2529 <!-- == inline_element -->
2533 name=
"u:bkslshEscPre"/>
2534 <xsl:text>*
</xsl:text>
2535 <xsl:apply-templates/>
2536 <xsl:text>*
</xsl:text>
2538 name=
"u:bkslshEscSuf"/>
2541 <!-- ******************************************************************** -->
2543 <!-- user-numbered footnotes lack @auto -->
2544 <!-- == inline_element -->
2546 match=
"footnote_reference[not(@auto)]">
2548 name=
"u:bkslshEscPre"/>
2549 <xsl:text>[
</xsl:text>
2552 <xsl:text>]_
</xsl:text>
2554 name=
"u:bkslshEscSuf"/>
2555 <!-- child paragraph provides blank line -->
2558 <!-- automatically numbered footnotes have @auto -->
2559 <!-- if @names is different from label content, it is a named footnote -->
2560 <!-- == inline_element -->
2562 match=
"footnote_reference[@auto='1']">
2567 test=
"not(starts-with(//footnote[@ids=$ref]/@names, 'TARGET_NOTE:\ '))">
2568 <!-- Not a generated footnote reference for a `.. target-notes::';
2569 such footnote reference and the preceding space should be
2570 embedded in `generated'! -->
2572 name=
"u:bkslshEscPre"/>
2573 <xsl:text>[#
</xsl:text>
2575 test=
"//footnote[@ids=$ref]/@names != //footnote[@ids=$ref]/label">
2577 name=
"u:outputNames">
2580 select=
"//footnote[@ids=$ref]/@names"/>
2581 </xsl:call-template>
2583 <xsl:text>]_
</xsl:text>
2585 name=
"u:bkslshEscSuf"/>
2589 <!-- automatically symboled footnotes have @auto=* -->
2590 <!-- == inline_element -->
2592 match=
"footnote_reference[@auto='*']">
2594 name=
"u:bkslshEscPre"/>
2595 <xsl:text>[*]_
</xsl:text>
2597 name=
"u:bkslshEscSuf"/>
2600 <!-- ******************************************************************** -->
2603 Content Model: %text.model;
2605 <!-- == inline_element -->
2609 name=
"u:bkslshEscPre"/>
2610 <xsl:text>``
</xsl:text>
2611 <xsl:apply-templates/>
2612 <xsl:text>``
</xsl:text>
2614 name=
"u:bkslshEscSuf"/>
2617 <!-- ******************************************************************** -->
2619 <!-- Attribute combinations found in `standard' text and other examples:
2620 @refuri = standalone hyperlink
2621 @ids @refid = TOC, probably all in <generated>
2622 @name @refuri with matching <target> in document = named external hyperlink _
2623 @name @refuri immediately followed by matching <target> = named embedded URI _
2624 @name @refuri with no matching <target> in document = anonymous embedded URI __
2625 @anonymous @name @refuri with no matching <target> in document = anonymous explicit URI __
2626 @name @refid = internal cross-reference _
2627 @anonymous @name @refid = anonymous implicit internal reference __
2628 @name @refid image = clickable image to internal reference _
2629 @refuri image = clickable image to standalone hyperlink
2631 A target matches if target/@names contains the lower cased, whitespace
2632 quoted reference/@name
2635 <!-- Standalone hyperlink -->
2636 <!-- == inline_element -->
2638 match=
"reference[not(@name or @anonymous)]">
2640 name=
"u:bkslshEscPre"/>
2643 test=
"starts-with(., 'PEP ')">
2644 <xsl:text>:PEP:`
</xsl:text>
2646 select=
"substring-after(., 'PEP ')"/>
2647 <xsl:text>`
</xsl:text>
2650 test=
"starts-with(., 'RFC ')">
2651 <xsl:text>:RFC:`
</xsl:text>
2653 select=
"substring-after(., 'RFC ')"/>
2654 <xsl:text>`
</xsl:text>
2657 <xsl:apply-templates/>
2661 name=
"u:bkslshEscSuf"/>
2664 <!-- External references -->
2665 <!-- == inline_element -->
2667 match=
"reference[@name and @refuri]">
2668 <!-- Determine normalized name by downcasing it -->
2671 select=
"translate(normalize-space(@name), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
2674 select=
"str:replace($normalized, ' ', '\ ')"/>
2677 select=
"//target[contains(@names, $quoted)]"/>
2679 name=
"u:inlineReference">
2682 select=
"not($matching) or @anonymous"/>
2685 select=
"not(@anonymous) and (not($matching) or generate-id(following-sibling::node()[1]) = generate-id($matching))"/>
2686 </xsl:call-template>
2689 <!-- Internal references -->
2690 <!-- == inline_element -->
2692 match=
"reference[@name and @refid]">
2694 name=
"u:inlineReference">
2697 select=
"@anonymous"/>
2698 </xsl:call-template>
2701 <!-- Image references -->
2702 <!-- == inline_element -->
2704 match=
"reference[image]">
2705 <!-- All done by the `image' tag -->
2706 <xsl:apply-templates/>
2709 <!-- ******************************************************************** -->
2712 Content Model: %text.model;
2714 <!-- == inline_element -->
2718 name=
"u:bkslshEscPre"/>
2719 <xsl:text>**
</xsl:text>
2720 <xsl:apply-templates/>
2721 <xsl:text>**
</xsl:text>
2723 name=
"u:bkslshEscSuf"/>
2726 <!-- ******************************************************************** -->
2728 <!-- == inline_element -->
2732 name=
"u:bkslshEscPre"/>
2733 <xsl:text>:sub:`
</xsl:text>
2734 <xsl:apply-templates/>
2735 <xsl:text>`
</xsl:text>
2737 name=
"u:bkslshEscSuf"/>
2740 <!-- ******************************************************************** -->
2742 <!-- == inline_element -->
2744 match=
"superscript">
2746 name=
"u:bkslshEscPre"/>
2747 <xsl:text>:sup:`
</xsl:text>
2748 <xsl:apply-templates/>
2749 <xsl:text>`
</xsl:text>
2751 name=
"u:bkslshEscSuf"/>
2754 <!-- ******************************************************************** -->
2756 <!-- The target element has various roles depending on context; they are
2757 all handled here -->
2758 <!-- == simple_body_element == inline_element == directive -->
2763 test=
"name(preceding-sibling::*[1]) = 'reference'">
2764 <!-- An embedded inline target - handled by the reference itself -->
2767 test=
"contains($inline_containers, concat('*', name(..), '*'))">
2768 <!-- An inline target of some sort -->
2770 name=
"u:inlineReference">
2774 </xsl:call-template>
2778 <!-- An anonymous target directive -->
2780 name=
"u:outputClass"/>
2783 <xsl:text>__
</xsl:text>
2788 name=
"u:outputNamesRefid"/>
2789 <xsl:text>_
</xsl:text>
2800 test=
"@names | @refid">
2801 <!-- A target directive -->
2803 name=
"u:outputClass"/>
2806 <xsl:text>.. _
</xsl:text>
2811 name=
"u:outputNamesRefid"/>
2816 select=
"contains(@names, ':')"/>
2818 test=
"$quoteNeeded">
2819 <xsl:text>`
</xsl:text>
2822 name=
"u:outputNames"/>
2824 test=
"$quoteNeeded">
2825 <xsl:text>`
</xsl:text>
2829 <xsl:text>:
</xsl:text>
2832 <xsl:text> </xsl:text>
2839 <!-- Should not happen -->
2841 name=
"u:notSupported"/>
2846 <!-- ******************************************************************** -->
2849 Content Model: %text.model;
2851 <!-- == inline_element -->
2853 match=
"title_reference">
2855 name=
"u:bkslshEscPre"/>
2856 <xsl:text>`
</xsl:text>
2857 <xsl:apply-templates/>
2858 <xsl:text>`
</xsl:text>
2860 name=
"u:bkslshEscSuf"/>
2863 <!-- ******************************************************************** -->
2866 Content Model: %text.model;
2868 <!-- == inline_element -->
2871 <!-- TODO `role' directives must be generated for plain and derived
2872 user-defined roles. -->
2874 name=
"u:bkslshEscPre"/>
2875 <xsl:text>:
</xsl:text>
2878 <xsl:text>:`
</xsl:text>
2879 <xsl:apply-templates/>
2880 <xsl:text>`
</xsl:text>
2882 name=
"u:bkslshEscSuf"/>
2885 <!-- ******************************************************************** -->
2887 <!-- TODO `meta` directive must be implemented. -->
2889 <!-- ******************************************************************** -->
2892 Docutils wraps generated elements around text that is inserted (generated) by
2893 Docutils; i.e., text that was not in the document, like section numbers
2894 inserted by the "sectnum" directive.
2896 <!-- == inline_element -->
2900 <!-- == inline_element -->
2902 match=
"problematic">
2903 <!-- Simply output the contained text because this is probably the
2909 <!-- == compound_body_element -->
2911 match=
"system_message"/>
2913 <!-- ******************************************************************** -->
2914 <!-- ******************************************************************** -->
2917 When a block of text contains linefeeds, it was indented relative to a marker
2934 </xsl:call-template>
2937 <!-- ******************************************************************** -->
2938 <!-- ******************************************************************** -->
2940 <!-- Add a blank line if necessary and indent -->
2949 <!-- ******************************************************************** -->
2951 <!-- Add a blank line in certain contexts -->
2954 <xsl:apply-templates
2955 mode=
"blankSkipInline"
2956 select=
"preceding::*[1]"/>
2959 <!-- Find the preceding element we are really interested in and act
2960 according to this element -->
2962 mode=
"blankSkipInline"
2965 <!-- Skip all inline elements and body subelements and check their
2968 test=
"contains(concat($inline_elements, $simple_body_subelements, $compound_body_subelements), concat('*', name(.), '*'))">
2969 <xsl:apply-templates
2970 mode=
"blankSkipInline"
2974 <!-- Reached the type of element we decide on -->
2976 test=
"contains($blank_after, concat('*', name(.), '*'))">
2983 <!-- ******************************************************************** -->
2986 Indent a block if it's a child of...
3019 <!-- This is only for `bullet_list/list_item';
3020 `enumerated_list/list_item' is handled special -->
3025 name=
"definition_list_item"
3031 name=
"option_list_item"
3033 <!-- This is also the indentation if block_quote comes as one of the
3034 special directives -->
3039 name=
"literal_block"
3049 <!-- Do indent according to ancestor -->
3052 <!-- In some cases the ancestors to indent for need to be determined
3053 by the calling template -->
3056 select=
"ancestor::*"/>
3058 select=
"$ancestors">
3064 test=
"contains($directives, concat('*', $this, '*'))">
3065 <!-- TODO Indentation of lines after some directives must be
3066 indented to align with the directive instead of a
3067 fixed indentation; however, this is rather complicated
3068 since identation for parameters should be fixed -->
3070 select=
"str:padding(3)"/>
3073 test=
"$this = 'list_item' and parent::enumerated_list">
3074 <!-- Enumerated list items base their indentation on the
3079 name=
"u:outputEnumerator"/>
3082 select=
"str:padding(string-length($enumerator))"/>
3086 select=
"str:padding(document('')//data:lookup/data:node[@name=$this]/@indent)"/>
3092 <!-- ******************************************************************** -->
3094 <!-- Indent a text containing line feeds correctly -->
3100 <!-- A fixed indentation may be given by caller -->
3103 <!-- If not given compute it -->
3111 select=
"rst:plain($string, $indent, $literal)"/>
3114 <!-- ******************************************************************** -->
3116 <!-- Do output for those elements which do fold their inline content -->
3118 name=
"u:outputFolding">
3119 <!-- The prefix text to be output before the body -->
3123 <!-- The indentation for this body -->
3130 select=
"ancestor-or-self::*"/>
3131 </xsl:call-template>
3135 <!-- TODO Whitespace count of inline literals must be preserved -->
3136 <xsl:apply-templates/>
3138 <!-- Always output prefix with all trailing and leading spaces -->
3143 test=
"$fold > 0">
3146 select=
"normalize-space($string)"/>
3149 test=
"$string = ''">
3150 <!-- Empty strings need no output -->
3153 test=
"$normalized = ''">
3154 <!-- Only white-space in string; output a single space here -->
3158 <!-- Output leading white-space here -->
3160 test=
"normalize-space(substring($string, 1, 1)) = ''">
3164 name=
"u:indentFold">
3167 select=
"$normalized"/>
3173 select=
"string-length($indent) + string-length($prefix)"/>
3174 </xsl:call-template>
3175 <!-- Output trailing white-space here -->
3177 test=
"normalize-space(substring($string, string-length($string), 1)) = ''">
3191 <!-- ******************************************************************** -->
3193 <!-- Indent a string with folding -->
3195 name=
"u:indentFold">
3196 <!-- Normalized string to output -->
3199 <!-- Indentation to use for a new line -->
3202 <!-- Current output column -->
3203 <!-- TODO This is not a correct assumption for field definitions where
3204 the field name effectively determines the column of the first
3208 select=
"string-length($indent)"/>
3209 <!-- Do we start on a new (indented) line? -->
3216 <!-- TODO Quoted spaces must not end a word -->
3218 test=
"contains($string, ' ')">
3220 select=
"substring-before($string, ' ')"/>
3230 select=
"substring-after($string, ' ')"/>
3233 test=
"$string = ''"/>
3236 <!-- Output at least first word -->
3238 select=
"$firstWord"/>
3240 name=
"u:indentFold">
3249 select=
"$cursorColumn + string-length($firstWord)"/>
3253 </xsl:call-template>
3256 test=
"$cursorColumn + 1 + string-length($firstWord) > $fold">
3257 <!-- Line would get too long; start new line, indent and continue -->
3262 name=
"u:indentFold">
3271 select=
"string-length($indent)"/>
3275 </xsl:call-template>
3278 <!-- In a line and first word fits; separate and add word -->
3281 select=
"$firstWord"/>
3283 name=
"u:indentFold">
3292 select=
"$cursorColumn + 1 + string-length($firstWord)"/>
3296 </xsl:call-template>
3301 <!-- ******************************************************************** -->
3303 <!-- Output attributes of the current element as a field list -->
3309 <!-- Ancestors are needed for determining indentation; caller may give
3313 select=
"ancestor-or-self::*"/>
3316 <!-- Skip URIs based on parent -->
3318 test=
"name() != 'uri' and name() != 'xml:space'">
3323 select=
"$ancestors"/>
3324 </xsl:call-template>
3329 <!-- Output one attribute of the current element as a field list -->
3338 <!-- Ancestors are needed for determining indentation; caller may give
3342 select=
"ancestor::*"/>
3347 select=
"$ancestors"/>
3348 </xsl:call-template>
3349 <xsl:text>:
</xsl:text>
3352 test=
"$name = 'classes'">
3353 <xsl:text>class
</xsl:text>
3360 <xsl:text>:
</xsl:text>
3363 <xsl:text> </xsl:text>
3370 <!-- ******************************************************************** -->
3372 <!-- Output `\' or `\ ' before some inline element if necessary -->
3374 name=
"u:bkslshEscPre">
3375 <!-- Get the sibling node directly before the current element -->
3378 select=
"preceding-sibling::node()[1]"/>
3380 <!-- No sibling before this node -->
3382 test=
"not($before)"/>
3383 <!-- Element directly before this - must be another inline element -->
3385 test=
"name($before)">
3386 <!-- So separate it by a quoted space -->
3387 <xsl:text>\
</xsl:text>
3389 <!-- Node directly before this is text - check it -->
3391 test=
"not(contains(concat($apos, ' 
	
"([{<-/:'), substring($before, string-length($before), 1)))">
3392 <!-- Does not end in one of the allowed characters so separate it -->
3393 <xsl:text>\
</xsl:text>
3398 <!-- Output `\' after some inline element if necessary -->
3400 name=
"u:bkslshEscSuf">
3401 <!-- Get the sibling node directly after the current element -->
3404 select=
"following-sibling::node()[1]"/>
3406 <!-- No sibling after this node -->
3408 test=
"not($after)"/>
3409 <!-- Element directly after this - must be another inline element
3412 test=
"name($after)"/>
3413 <!-- Node directly after this is text - check it -->
3415 test=
"not(contains(concat($apos, ' 
	
")]}>-/:.,;!?\'), substring($after, 1, 1)))">
3416 <!-- Does not start with one of the allowed characters so separate
3418 <xsl:text>\
</xsl:text>
3423 <!-- ******************************************************************** -->
3426 name=
"u:notSupported">
3429 <xsl:text>######## NOT SUPPORTED: `
</xsl:text>
3432 <xsl:text>' ########
</xsl:text>
3436 <!-- ******************************************************************** -->
3440 <!-- Length of the rendered(!) text -->
3443 <!-- Depth 1 and 2 are document title and subtitle while depths
3444 greater than 2 are normal section titles -->
3447 <!-- Test whether a overline is wanted at all -->
3449 test=
"substring($adornment, 2 * ($depth - 1) + 1, 1) = 'o'">
3451 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3458 <!-- Length of the rendered(!) text -->
3461 <!-- Depth 1 and 2 are document title and subtitle while depths
3462 greater than 2 are normal section titles -->
3466 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3470 <!-- ******************************************************************** -->
3472 <!-- Output a non-standalone reference or target -->
3474 name=
"u:inlineReference">
3481 <!-- Is this a target instead of a reference? -->
3489 name=
"u:bkslshEscPre"/>
3490 <!-- Delimiter only if link contains other than alphanumerics -->
3494 test=
"* or translate($text, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '') or $embedded">
3495 <xsl:text>`
</xsl:text>
3500 <xsl:text>_
</xsl:text>
3503 select=
"$delimiter"/>
3504 <xsl:apply-templates
3508 <xsl:text> <</xsl:text>
3511 <xsl:text>></xsl:text>
3514 select=
"$delimiter"/>
3516 test=
"not($isTarget)">
3517 <xsl:text>_
</xsl:text>
3520 <xsl:text>_
</xsl:text>
3524 name=
"u:bkslshEscSuf"/>
3527 <!-- ******************************************************************** -->
3529 <!-- Output a class directive for the directly following element. -->
3530 <!-- TODO A class directive can also be used as a container putting the
3531 respective attribute to its content; however, this is not
3532 reflected in XML - you'd need to check a sequence of elements
3533 whether they all have the same attribute; furthermore class
3534 settings for block quotes needs to be treated special -->
3536 name=
"u:outputClass">
3537 <!-- Blank line already output? -->
3539 name=
"alreadyBlanked"
3541 <!-- Indentation already output? -->
3543 name=
"alreadyIndented"
3545 <!-- Add a blank line after class directive? -->
3552 test=
"not($alreadyBlanked)">
3557 test=
"not($alreadyIndented)">
3561 <xsl:text>.. class::
</xsl:text>
3572 <!-- ******************************************************************** -->
3574 <!-- Output a names attribute at index considering quoted spaces. -->
3576 name=
"u:outputNames">
3577 <!-- Blank line already output? -->
3585 select=
"str:replace(str:tokenize(normalize-space(str:replace($names, '\ ', '|')))[position() = $index + 1], '|', ' ')"/>
3588 <!-- ******************************************************************** -->
3590 <!-- Output a names attribute for a refid. -->
3592 name=
"u:outputNamesRefid">
3596 <!-- Determine the elements which is referred -->
3599 select=
"//*[@ids and math:max(dyn:map(str:tokenize(normalize-space(@ids)), 'number($refid = .)')) > 0]"/>
3601 name=
"u:outputNames">
3604 select=
"$refElem/@names"/>
3607 select=
"math:max(dyn:map(str:tokenize(normalize-space($refElem/@ids)), 'number($refid = .) * position() - 1'))"/>
3608 </xsl:call-template>
3611 <!-- ******************************************************************** -->
3612 <!-- ******************************************************************** -->
3614 <!-- Report unknown tags -->
3618 <xsl:text>`
</xsl:text>
3621 <xsl:text>' encountered
</xsl:text>
3624 <xsl:text> in `
</xsl:text>
3626 select=
"name(parent::*)"/>
3627 <xsl:text>'
</xsl:text>
3629 <xsl:text>, but no template matches.
</xsl:text>