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"/>
1863 test=
"name(*[1]) != 'bullet_list'">
1864 <!-- Start the list item only if the first child is not another list -->
1868 select=
"../@bullet"/>
1869 &tSP; <!-- space after bullet -->
1871 <xsl:apply-templates/>
1874 <!-- ******************************************************************** -->
1878 enumtype is used to record the intended enumeration sequence, one of
1879 "arabic" (1, 2, 3, ...), "loweralpha" (a, b, c, ..., z), "upperalpha" (A, B,
1880 C, ..., Z), "lowerroman" (i, ii, iii, iv, ..., mmmmcmxcix [4999]), or
1881 "upperroman" (I, II, III, IV, ..., MMMMCMXCIX [4999]).
1882 prefix stores the formatting characters used before the enumerator. In
1883 documents originating from reStructuredText data, it will contain either ""
1884 (empty string) or "(" (left parenthesis). It may or may not affect
1886 suffix stores the formatting characters used after the enumerator. In
1887 documents originating from reStructuredText data, it will contain either "."
1888 (period) or ")" (right parenthesis). Depending on the capabilities of the
1889 output format, this attribute may or may not affect processing.
1890 start contains the ordinal value of the first item in the list, in
1891 decimal. For lists beginning at value 1 ("1", "a", "A", "i", or "I"), this
1892 attribute may be omitted.
1895 <!-- == compound_body_subelement -->
1898 mode=
"enumerated_list">
1900 name=
"u:outputClass"/>
1904 name=
"u:outputEnumerator"/>
1905 <xsl:apply-templates/>
1908 <!-- Outputs a complete enumerator when called in an
1909 enumerated_list/list_item -->
1911 name=
"u:outputEnumerator">
1912 <!-- Use parent's numeration attribute -->
1915 select=
"../@enumtype"/>
1916 <!-- Determine starting point -->
1923 select=
"../@start"/>
1931 <!-- Determine position of this item in its real context -->
1936 select=
"generate-id()"/>
1937 <!-- Generate the right current node list -->
1939 select=
"../list_item">
1941 test=
"generate-id() = $wanted">
1943 select=
"position()"/>
1947 <!-- Determine encoding of the number for the given numeration -->
1951 name=
"u:position2Enumerator">
1954 select=
"$enumType"/>
1957 select=
"$position"/>
1961 </xsl:call-template>
1963 <!-- Determine encoding of the maximum number -->
1967 name=
"u:position2Enumerator">
1970 select=
"$enumType"/>
1973 select=
"count(../list_item)"/>
1977 </xsl:call-template>
1979 <!-- Output complete enumerator -->
1981 select=
"../@prefix"/>
1985 select=
"../@suffix"/>
1986 <!-- Output at least one trailing space -->
1988 <!-- Output more whitespace to align with the maximum enumerator -->
1990 test=
"$enumType != 'lowerroman' and $enumType != 'upperroman'">
1991 <!-- Assumes that the maximum number has maximum string length -->
1993 select=
"str:padding(string-length($max) - string-length($cur))"/>
1997 <!-- Determine the right ordinal enumerator based on the parameters -->
1999 name=
"u:position2Enumerator">
2006 <!-- Determine logical number -->
2009 select=
"$start - 1 + $position"/>
2012 test=
"$enumType = 'arabic'">
2017 test=
"$enumType = 'loweralpha'">
2019 select=
"substring('abcdefghijklmnopqrstzuvwxyz', $ordinal, 1)"/>
2022 test=
"$enumType = 'upperalpha'">
2024 select=
"substring('ABCDEFGHIJKLMNOPQRSTZUVWXYZ', $ordinal, 1)"/>
2026 <!-- TODO Support for counting roman numbers -->
2028 test=
"$enumType = 'lowerroman'">
2029 <xsl:text>i
</xsl:text>
2032 test=
"$enumType = 'upperroman'">
2033 <xsl:text>I
</xsl:text>
2038 <!-- ******************************************************************** -->
2039 <!-- ******************************************************************** -->
2042 Content Model: (title?, tgroup+)
2043 Attributes: The table element contains the common attributes and:
2044 frame, colsep, rowsep, pgwide
2046 <!-- == compound_body_element -->
2050 name=
"u:outputClass"/>
2053 <xsl:apply-templates
2057 <!-- TODO A table title must be rendered by using the `.. table::'
2061 <xsl:apply-templates
2067 <!-- ******************************************************************** -->
2070 Content Model: (colspec*, thead?, tbody)
2071 Attributes: The tgroup element contains the common attributes and:
2072 cols, colsep, rowsep, align
2074 <!-- == compound_body_subelement -->
2077 <xsl:apply-templates/>
2080 <!-- ******************************************************************** -->
2083 Content Model: EMPTY
2084 Attributes: The colspec element contains the common attributes and:
2085 colnum, colname, colwidth, colsep, rowsep, align, char, charoff
2087 The colwidth attribute gives the width of the respective column in characters
2088 including padding whitespace but no separator markup.
2090 <!-- == simple_body_subelement -->
2091 <!-- @colwidth needed by children but element has no own output -->
2095 <!-- ******************************************************************** -->
2098 Content Model: (row+)
2099 Attributes: The thead element contains the common attributes and:
2102 <!-- == compound_body_subelement -->
2105 <xsl:apply-templates/>
2109 Content Model: (row+)
2110 Attributes: The tbody element contains the common attributes and:
2113 <!-- == compound_body_subelement -->
2116 <xsl:apply-templates/>
2119 <!-- ******************************************************************** -->
2122 Content Model: (entry+)
2123 Attributes: The row element contains the common attributes and:
2126 <!-- == compound_body_subelement -->
2129 <!-- Separator line above unless first row of a tbody with no previous
2130 thead (in this case the separator line is output already as the
2131 closing separator line of thead) -->
2133 test=
"position() > 1 or parent::thead or parent::tbody and not(../../thead)">
2135 name=
"u:rowSeparatorLine"/>
2137 <!-- Determine heights in physical lines of all entries -->
2144 <!-- Catch the text of all entries -->
2145 <xsl:apply-templates/>
2147 <!-- Compute height of this entry; leading and trailing EOL must be
2150 select=
"string-length($text) - string-length(translate($text, '
', '')) - 1"/>
2151 &tSP; <!-- A space as a list separator -->
2154 <!-- Determine maximum height so every entry must be this high -->
2157 select=
"math:max(str:tokenize(normalize-space($heights)))"/>
2158 <!-- Output all the physical lines of this row -->
2166 select=
"$maxHeight"/>
2167 </xsl:call-template>
2168 <!-- Output final separator line if this is the last row -->
2170 test=
"position() = last()">
2172 name=
"u:rowSeparatorLine">
2175 <!-- Determine correct character for the separator line -->
2178 test=
"parent::thead">
2188 </xsl:call-template>
2192 <!-- Output physical line $currentLine of a row and continue until
2193 line $maxLine is output -->
2197 name=
"currentLine"/>
2201 test=
"$currentLine <= $maxLine">
2202 <!-- If there are still physical lines to output do it -->
2205 <!-- Leading bar -->
2206 <xsl:text>|
</xsl:text>
2207 <xsl:apply-templates>
2210 select=
"$currentLine"/>
2211 </xsl:apply-templates>
2212 <!-- End of this physical line -->
2214 <!-- Continue with the next physical line -->
2219 select=
"$currentLine + 1"/>
2223 </xsl:call-template>
2227 <!-- Output a separator line with all the right characters -->
2229 name=
"u:rowSeparatorLine">
2235 <xsl:text>+
</xsl:text>
2237 select=
"../../colspec">
2239 select=
"str:padding(@colwidth, $char)"/>
2240 <xsl:text>+
</xsl:text>
2245 <!-- ******************************************************************** -->
2248 Content Model: (%body.elements;)*
2249 Attributes: The entry element contains the common attributes and:
2250 colname, namest, morerows, colsep, rowsep, align, char, charoff, valign and
2253 <!-- == compound_body_subelement -->
2256 <!-- TODO `classes` attribute needs support -->
2257 <!-- This is called in two ways; if $currentLine = 0 all physical lines
2258 of this entry must be output; if $currentLine > 0 the physical line
2259 with exactly this number shall be output -->
2265 select=
"position() + sum(preceding-sibling::entry/@morecols)"/>
2266 <!-- Determine width in characters needed for this entry -->
2270 name=
"u:computeEntryWidth">
2273 select=
"../../../colspec"/>
2279 select=
"@morecols"/>
2280 </xsl:call-template>
2282 <!-- Output the entry completely or a certain physical line -->
2284 name=
"u:outputEntry">
2287 <!-- Capture physical lines of the entry in a variable -->
2288 <xsl:apply-templates/>
2294 name=
"expectedIndent">
2295 <!-- Capture indent for the entry generated by the normal template
2296 rules to remove it later -->
2302 select=
"$currentLine"/>
2303 </xsl:call-template>
2304 <!-- Final bar after the entry -->
2305 <xsl:text>|
</xsl:text>
2308 <!-- Compute width of the entry -->
2310 name=
"u:computeEntryWidth">
2311 <!-- The colspec elements of all columns -->
2314 <!-- Column of this entry -->
2317 <!-- Number of columns this entry spans -->
2327 <!-- If entry spans multiple columns compute their width -->
2329 name=
"u:computeEntryWidth">
2332 select=
"$colspecs"/>
2335 select=
"$column + 1"/>
2338 select=
"$span - 1"/>
2339 <!-- Add the separator character and the following column width -->
2342 select=
"$sum + 1 + $colspecs[$column]/@colwidth"/>
2343 </xsl:call-template>
2346 <!-- Does not span more columns so return sum and width of this
2349 select=
"$sum + $colspecs[$column]/@colwidth"/>
2354 <!-- Outputs one or all lines of a table entry as a string trimmed left and
2357 name=
"u:outputEntry">
2358 <!-- Width of the entry; there is no provision for actual physical lines
2359 longer than this width -->
2362 <!-- The string containing the remaining physical lines; may be an empty
2367 <!-- The indendation which is expected to be prefixed before every
2370 name=
"expectedIndent"
2372 <!-- Is this the first call to this template -->
2376 <!-- Number of physical line to output or 0 to output all lines -->
2380 <!-- Output is wanted if all or the first physical line are to be
2384 select=
"$outputLine = 0 or $outputLine = 1"/>
2386 name=
"stringLFHalfTrimmed">
2389 test=
"$isFirst and substring($string, 1, 1) = '
'">
2390 <!-- Remove leading linefeed if this is the first time -->
2392 select=
"substring($string, 2)"/>
2401 name=
"stringLFTrimmed">
2404 test=
"$isFirst and substring($stringLFHalfTrimmed, string-length($stringLFHalfTrimmed), 1) = '
'">
2405 <!-- Remove trailing linefeed if this is the first time -->
2407 select=
"substring($stringLFHalfTrimmed, 1, string-length($stringLFHalfTrimmed) - 1)"/>
2411 select=
"$stringLFHalfTrimmed"/>
2415 <!-- Determine remaining lines after the first one -->
2417 name=
"remainingLines">
2419 test=
"contains($stringLFTrimmed, '
')">
2421 select=
"substring-after($stringLFTrimmed, '
')"/>
2426 <!-- If this physical line must be output determine the first physical
2432 test=
"string-length($remainingLines)">
2434 select=
"substring-before($stringLFTrimmed, '
')"/>
2438 select=
"$stringLFTrimmed"/>
2442 <!-- Remove the leading indentation from the physical line which is
2443 brought there by the normal templates -->
2447 test=
"string-length($firstLine)">
2448 <!-- Trim only non-empty lines -->
2450 select=
"substring-after($firstLine, $expectedIndent)"/>
2453 <!-- Pad the line with a leading and a trailing space -->
2456 select=
"concat(' ', $trimmed, ' ')"/>
2457 <!-- Output the padded value -->
2460 <!-- Fill up the width of the entry with spaces -->
2462 test=
"$width - string-length($padded) < 0">
2464 <xsl:text>WARNING: Table column too narrow (minimum:
</xsl:text>
2466 select=
"string-length($padded)"/>
2467 <xsl:text>)
</xsl:text>
2472 select=
"str:padding($width - string-length($padded))"/>
2475 test=
"$outputLine > 1 or $outputLine = 0 and string-length($remainingLines)">
2476 <!-- If a following physical line must be output or if all physical
2477 lines shall be output and there are remaining physical lines -->
2479 test=
"$outputLine = 0">
2480 <!-- Output linefeed only if we output all the lines -->
2483 <!-- Output the remaining lines -->
2485 name=
"u:outputEntry">
2491 select=
"$remainingLines"/>
2493 name=
"expectedIndent"
2494 select=
"$expectedIndent"/>
2502 test=
"$outputLine = 0">
2508 select=
"$outputLine - 1"/>
2512 </xsl:call-template>
2516 <!-- ******************************************************************** -->
2517 <!-- ******************************************************************** -->
2519 <!-- == inline_element -->
2521 match=
"citation_reference">
2523 name=
"u:bkslshEscPre"/>
2524 <xsl:text>[
</xsl:text>
2525 <xsl:apply-templates/>
2526 <xsl:text>]_
</xsl:text>
2528 name=
"u:bkslshEscSuf"/>
2531 <!-- ******************************************************************** -->
2533 <!-- == inline_element -->
2535 match=
"substitution_reference">
2537 name=
"u:bkslshEscPre"/>
2538 <xsl:text>|
</xsl:text>
2539 <xsl:apply-templates/>
2540 <xsl:text>|
</xsl:text>
2542 name=
"u:bkslshEscSuf"/>
2545 <!-- ******************************************************************** -->
2547 <!-- == inline_element -->
2551 name=
"u:bkslshEscPre"/>
2552 <xsl:text>*
</xsl:text>
2553 <xsl:apply-templates/>
2554 <xsl:text>*
</xsl:text>
2556 name=
"u:bkslshEscSuf"/>
2559 <!-- ******************************************************************** -->
2561 <!-- user-numbered footnotes lack @auto -->
2562 <!-- == inline_element -->
2564 match=
"footnote_reference[not(@auto)]">
2566 name=
"u:bkslshEscPre"/>
2567 <xsl:text>[
</xsl:text>
2570 <xsl:text>]_
</xsl:text>
2572 name=
"u:bkslshEscSuf"/>
2573 <!-- child paragraph provides blank line -->
2576 <!-- automatically numbered footnotes have @auto -->
2577 <!-- if @names is different from label content, it is a named footnote -->
2578 <!-- == inline_element -->
2580 match=
"footnote_reference[@auto='1']">
2585 test=
"not(starts-with(//footnote[@ids=$ref]/@names, 'TARGET_NOTE:\ '))">
2586 <!-- Not a generated footnote reference for a `.. target-notes::';
2587 such footnote reference and the preceding space should be
2588 embedded in `generated'! -->
2590 name=
"u:bkslshEscPre"/>
2591 <xsl:text>[#
</xsl:text>
2593 test=
"//footnote[@ids=$ref]/@names != //footnote[@ids=$ref]/label">
2595 name=
"u:outputNames">
2598 select=
"//footnote[@ids=$ref]/@names"/>
2599 </xsl:call-template>
2601 <xsl:text>]_
</xsl:text>
2603 name=
"u:bkslshEscSuf"/>
2607 <!-- automatically symboled footnotes have @auto=* -->
2608 <!-- == inline_element -->
2610 match=
"footnote_reference[@auto='*']">
2612 name=
"u:bkslshEscPre"/>
2613 <xsl:text>[*]_
</xsl:text>
2615 name=
"u:bkslshEscSuf"/>
2618 <!-- ******************************************************************** -->
2621 Content Model: %text.model;
2623 <!-- == inline_element -->
2627 name=
"u:bkslshEscPre"/>
2628 <xsl:text>``
</xsl:text>
2629 <xsl:apply-templates/>
2630 <xsl:text>``
</xsl:text>
2632 name=
"u:bkslshEscSuf"/>
2635 <!-- ******************************************************************** -->
2637 <!-- Attribute combinations found in `standard' text and other examples:
2638 @refuri = standalone hyperlink
2639 @ids @refid = TOC, probably all in <generated>
2640 @name @refuri with matching <target> in document = named external hyperlink _
2641 @name @refuri immediately followed by matching <target> = named embedded URI _
2642 @name @refuri with no matching <target> in document = anonymous embedded URI __
2643 @anonymous @name @refuri with no matching <target> in document = anonymous explicit URI __
2644 @name @refid = internal cross-reference _
2645 @anonymous @name @refid = anonymous implicit internal reference __
2646 @name @refid image = clickable image to internal reference _
2647 @refuri image = clickable image to standalone hyperlink
2649 A target matches if target/@names contains the lower cased, whitespace
2650 quoted reference/@name
2653 <!-- Standalone hyperlink -->
2654 <!-- == inline_element -->
2656 match=
"reference[not(@name or @anonymous)]">
2658 name=
"u:bkslshEscPre"/>
2661 test=
"starts-with(., 'PEP ')">
2662 <xsl:text>:PEP:`
</xsl:text>
2664 select=
"substring-after(., 'PEP ')"/>
2665 <xsl:text>`
</xsl:text>
2668 test=
"starts-with(., 'RFC ')">
2669 <xsl:text>:RFC:`
</xsl:text>
2671 select=
"substring-after(., 'RFC ')"/>
2672 <xsl:text>`
</xsl:text>
2675 <xsl:apply-templates/>
2679 name=
"u:bkslshEscSuf"/>
2682 <!-- External references -->
2683 <!-- == inline_element -->
2685 match=
"reference[@name and @refuri]">
2686 <!-- Determine normalized name by downcasing it -->
2689 select=
"translate(normalize-space(@name), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
2692 select=
"str:replace($normalized, ' ', '\ ')"/>
2695 select=
"//target[contains(@names, $quoted)]"/>
2697 name=
"u:inlineReference">
2700 select=
"not($matching) or @anonymous"/>
2703 select=
"not(@anonymous) and (not($matching) or generate-id(following-sibling::node()[1]) = generate-id($matching))"/>
2704 </xsl:call-template>
2707 <!-- Internal references -->
2708 <!-- == inline_element -->
2710 match=
"reference[@name and @refid]">
2712 name=
"u:inlineReference">
2715 select=
"@anonymous"/>
2716 </xsl:call-template>
2719 <!-- Image references -->
2720 <!-- == inline_element -->
2722 match=
"reference[image]">
2723 <!-- All done by the `image' tag -->
2724 <xsl:apply-templates/>
2727 <!-- ******************************************************************** -->
2730 Content Model: %text.model;
2732 <!-- == inline_element -->
2736 name=
"u:bkslshEscPre"/>
2737 <xsl:text>**
</xsl:text>
2738 <xsl:apply-templates/>
2739 <xsl:text>**
</xsl:text>
2741 name=
"u:bkslshEscSuf"/>
2744 <!-- ******************************************************************** -->
2746 <!-- == inline_element -->
2750 name=
"u:bkslshEscPre"/>
2751 <xsl:text>:sub:`
</xsl:text>
2752 <xsl:apply-templates/>
2753 <xsl:text>`
</xsl:text>
2755 name=
"u:bkslshEscSuf"/>
2758 <!-- ******************************************************************** -->
2760 <!-- == inline_element -->
2762 match=
"superscript">
2764 name=
"u:bkslshEscPre"/>
2765 <xsl:text>:sup:`
</xsl:text>
2766 <xsl:apply-templates/>
2767 <xsl:text>`
</xsl:text>
2769 name=
"u:bkslshEscSuf"/>
2772 <!-- ******************************************************************** -->
2774 <!-- The target element has various roles depending on context; they are
2775 all handled here -->
2776 <!-- == simple_body_element == inline_element == directive -->
2781 test=
"name(preceding-sibling::*[1]) = 'reference'">
2782 <!-- An embedded inline target - handled by the reference itself -->
2785 test=
"contains($inline_containers, concat('*', name(..), '*'))">
2786 <!-- An inline target of some sort -->
2788 name=
"u:inlineReference">
2792 </xsl:call-template>
2796 <!-- An anonymous target directive -->
2798 name=
"u:outputClass"/>
2801 <xsl:text>__
</xsl:text>
2806 name=
"u:outputNamesRefid"/>
2807 <xsl:text>_
</xsl:text>
2818 test=
"@names | @refid">
2819 <!-- A target directive -->
2821 name=
"u:outputClass"/>
2824 <xsl:text>.. _
</xsl:text>
2829 name=
"u:outputNamesRefid"/>
2834 select=
"contains(@names, ':')"/>
2836 test=
"$quoteNeeded">
2837 <xsl:text>`
</xsl:text>
2840 name=
"u:outputNames"/>
2842 test=
"$quoteNeeded">
2843 <xsl:text>`
</xsl:text>
2847 <xsl:text>:
</xsl:text>
2850 <xsl:text> </xsl:text>
2857 <!-- Should not happen -->
2859 name=
"u:notSupported"/>
2864 <!-- ******************************************************************** -->
2867 Content Model: %text.model;
2869 <!-- == inline_element -->
2871 match=
"title_reference">
2873 name=
"u:bkslshEscPre"/>
2874 <xsl:text>`
</xsl:text>
2875 <xsl:apply-templates/>
2876 <xsl:text>`
</xsl:text>
2878 name=
"u:bkslshEscSuf"/>
2881 <!-- ******************************************************************** -->
2884 Content Model: %text.model;
2886 <!-- == inline_element -->
2889 <!-- TODO `role' directives must be generated for plain and derived
2890 user-defined roles. -->
2892 name=
"u:bkslshEscPre"/>
2893 <xsl:text>:
</xsl:text>
2896 <xsl:text>:`
</xsl:text>
2897 <xsl:apply-templates/>
2898 <xsl:text>`
</xsl:text>
2900 name=
"u:bkslshEscSuf"/>
2903 <!-- ******************************************************************** -->
2905 <!-- TODO `meta` directive must be implemented. -->
2907 <!-- ******************************************************************** -->
2910 Docutils wraps generated elements around text that is inserted (generated) by
2911 Docutils; i.e., text that was not in the document, like section numbers
2912 inserted by the "sectnum" directive.
2914 <!-- == inline_element -->
2918 <!-- == inline_element -->
2920 match=
"problematic">
2921 <!-- Simply output the contained text because this is probably the
2927 <!-- == compound_body_element -->
2929 match=
"system_message"/>
2931 <!-- ******************************************************************** -->
2932 <!-- ******************************************************************** -->
2935 When a block of text contains linefeeds, it was indented relative to a marker
2952 </xsl:call-template>
2955 <!-- ******************************************************************** -->
2956 <!-- ******************************************************************** -->
2958 <!-- Add a blank line if necessary and indent -->
2967 <!-- ******************************************************************** -->
2969 <!-- Add a blank line in certain contexts -->
2972 <xsl:apply-templates
2973 mode=
"blankSkipInline"
2974 select=
"preceding::*[1]"/>
2977 <!-- Find the preceding element we are really interested in and act
2978 according to this element -->
2980 mode=
"blankSkipInline"
2983 <!-- Skip all inline elements and body subelements and check their
2986 test=
"contains(concat($inline_elements, $simple_body_subelements, $compound_body_subelements), concat('*', name(.), '*'))">
2987 <xsl:apply-templates
2988 mode=
"blankSkipInline"
2992 <!-- Reached the type of element we decide on -->
2994 test=
"contains($blank_after, concat('*', name(.), '*'))">
3001 <!-- ******************************************************************** -->
3004 Indent a block if it's a child of...
3037 <!-- This is only for `bullet_list/list_item';
3038 `enumerated_list/list_item' is handled special -->
3043 name=
"definition_list_item"
3049 name=
"option_list_item"
3051 <!-- This is also the indentation if block_quote comes as one of the
3052 special directives -->
3057 name=
"literal_block"
3067 <!-- Do indent according to ancestor -->
3070 <!-- In some cases the ancestors to indent for need to be determined
3071 by the calling template -->
3074 select=
"ancestor::*"/>
3076 select=
"$ancestors">
3082 test=
"contains($directives, concat('*', $this, '*'))">
3083 <!-- TODO Indentation of lines after some directives must be
3084 indented to align with the directive instead of a
3085 fixed indentation; however, this is rather complicated
3086 since identation for parameters should be fixed -->
3088 select=
"str:padding(3)"/>
3091 test=
"$this = 'list_item' and parent::enumerated_list">
3092 <!-- Enumerated list items base their indentation on the
3097 name=
"u:outputEnumerator"/>
3100 select=
"str:padding(string-length($enumerator))"/>
3104 select=
"str:padding(document('')//data:lookup/data:node[@name=$this]/@indent)"/>
3110 <!-- ******************************************************************** -->
3112 <!-- Indent a text containing line feeds correctly -->
3118 <!-- A fixed indentation may be given by caller -->
3121 <!-- If not given compute it -->
3129 select=
"rst:plain($string, $indent, $literal)"/>
3132 <!-- ******************************************************************** -->
3134 <!-- Do output for those elements which do fold their inline content -->
3136 name=
"u:outputFolding">
3137 <!-- The prefix text to be output before the body -->
3141 <!-- The indentation for this body -->
3148 select=
"ancestor-or-self::*"/>
3149 </xsl:call-template>
3153 <!-- TODO Whitespace count of inline literals must be preserved -->
3154 <xsl:apply-templates/>
3156 <!-- Always output prefix with all trailing and leading spaces -->
3161 test=
"$fold > 0">
3164 select=
"normalize-space($string)"/>
3167 test=
"$string = ''">
3168 <!-- Empty strings need no output -->
3171 test=
"$normalized = ''">
3172 <!-- Only white-space in string; output a single space here -->
3176 <!-- Output leading white-space here -->
3178 test=
"normalize-space(substring($string, 1, 1)) = ''">
3182 name=
"u:indentFold">
3185 select=
"$normalized"/>
3191 select=
"string-length($indent) + string-length($prefix)"/>
3192 </xsl:call-template>
3193 <!-- Output trailing white-space here -->
3195 test=
"normalize-space(substring($string, string-length($string), 1)) = ''">
3209 <!-- ******************************************************************** -->
3211 <!-- Indent a string with folding -->
3213 name=
"u:indentFold">
3214 <!-- Normalized string to output -->
3217 <!-- Indentation to use for a new line -->
3220 <!-- Current output column -->
3221 <!-- TODO This is not a correct assumption for field definitions where
3222 the field name effectively determines the column of the first
3226 select=
"string-length($indent)"/>
3227 <!-- Do we start on a new (indented) line? -->
3234 <!-- TODO Quoted spaces must not end a word -->
3236 test=
"contains($string, ' ')">
3238 select=
"substring-before($string, ' ')"/>
3248 select=
"substring-after($string, ' ')"/>
3251 test=
"$string = ''"/>
3254 <!-- Output at least first word -->
3256 select=
"$firstWord"/>
3258 name=
"u:indentFold">
3267 select=
"$cursorColumn + string-length($firstWord)"/>
3271 </xsl:call-template>
3274 test=
"$cursorColumn + 1 + string-length($firstWord) > $fold">
3275 <!-- Line would get too long; start new line, indent and continue -->
3280 name=
"u:indentFold">
3289 select=
"string-length($indent)"/>
3293 </xsl:call-template>
3296 <!-- In a line and first word fits; separate and add word -->
3299 select=
"$firstWord"/>
3301 name=
"u:indentFold">
3310 select=
"$cursorColumn + 1 + string-length($firstWord)"/>
3314 </xsl:call-template>
3319 <!-- ******************************************************************** -->
3321 <!-- Output attributes of the current element as a field list -->
3327 <!-- Ancestors are needed for determining indentation; caller may give
3331 select=
"ancestor-or-self::*"/>
3334 <!-- Skip URIs based on parent -->
3336 test=
"name() != 'uri' and name() != 'xml:space'">
3341 select=
"$ancestors"/>
3342 </xsl:call-template>
3347 <!-- Output one attribute of the current element as a field list -->
3356 <!-- Ancestors are needed for determining indentation; caller may give
3360 select=
"ancestor::*"/>
3365 select=
"$ancestors"/>
3366 </xsl:call-template>
3367 <xsl:text>:
</xsl:text>
3370 test=
"$name = 'classes'">
3371 <xsl:text>class
</xsl:text>
3378 <xsl:text>:
</xsl:text>
3381 <xsl:text> </xsl:text>
3388 <!-- ******************************************************************** -->
3390 <!-- Output `\' or `\ ' before some inline element if necessary -->
3392 name=
"u:bkslshEscPre">
3393 <!-- Get the sibling node directly before the current element -->
3396 select=
"preceding-sibling::node()[1]"/>
3398 <!-- No sibling before this node -->
3400 test=
"not($before)"/>
3401 <!-- Element directly before this - must be another inline element -->
3403 test=
"name($before)">
3404 <!-- So separate it by a quoted space -->
3405 <xsl:text>\
</xsl:text>
3407 <!-- Node directly before this is text - check it -->
3409 test=
"not(contains(concat($apos, ' 
	
"([{<-/:'), substring($before, string-length($before), 1)))">
3410 <!-- Does not end in one of the allowed characters so separate it -->
3411 <xsl:text>\
</xsl:text>
3416 <!-- Output `\' after some inline element if necessary -->
3418 name=
"u:bkslshEscSuf">
3419 <!-- Get the sibling node directly after the current element -->
3422 select=
"following-sibling::node()[1]"/>
3424 <!-- No sibling after this node -->
3426 test=
"not($after)"/>
3427 <!-- Element directly after this - must be another inline element
3430 test=
"name($after)"/>
3431 <!-- Node directly after this is text - check it -->
3433 test=
"not(contains(concat($apos, ' 
	
")]}>-/:.,;!?\'), substring($after, 1, 1)))">
3434 <!-- Does not start with one of the allowed characters so separate
3436 <xsl:text>\
</xsl:text>
3441 <!-- ******************************************************************** -->
3444 name=
"u:notSupported">
3447 <xsl:text>######## NOT SUPPORTED: `
</xsl:text>
3450 <xsl:text>' ########
</xsl:text>
3454 <!-- ******************************************************************** -->
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 -->
3465 <!-- Test whether a overline is wanted at all -->
3467 test=
"substring($adornment, 2 * ($depth - 1) + 1, 1) = 'o'">
3469 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3476 <!-- Length of the rendered(!) text -->
3479 <!-- Depth 1 and 2 are document title and subtitle while depths
3480 greater than 2 are normal section titles -->
3484 select=
"str:padding($length, substring($adornment, 2 * ($depth - 1) + 2, 1))"/>
3488 <!-- ******************************************************************** -->
3490 <!-- Output a non-standalone reference or target -->
3492 name=
"u:inlineReference">
3499 <!-- Is this a target instead of a reference? -->
3507 name=
"u:bkslshEscPre"/>
3508 <!-- Delimiter only if link contains other than alphanumerics -->
3512 test=
"* or translate($text, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '') or $embedded">
3513 <xsl:text>`
</xsl:text>
3518 <xsl:text>_
</xsl:text>
3521 select=
"$delimiter"/>
3522 <xsl:apply-templates
3526 <xsl:text> <</xsl:text>
3529 <xsl:text>></xsl:text>
3532 select=
"$delimiter"/>
3534 test=
"not($isTarget)">
3535 <xsl:text>_
</xsl:text>
3538 <xsl:text>_
</xsl:text>
3542 name=
"u:bkslshEscSuf"/>
3545 <!-- ******************************************************************** -->
3547 <!-- Output a class directive for the directly following element. -->
3548 <!-- TODO A class directive can also be used as a container putting the
3549 respective attribute to its content; however, this is not
3550 reflected in XML - you'd need to check a sequence of elements
3551 whether they all have the same attribute; furthermore class
3552 settings for block quotes needs to be treated special -->
3554 name=
"u:outputClass">
3555 <!-- Blank line already output? -->
3557 name=
"alreadyBlanked"
3559 <!-- Indentation already output? -->
3561 name=
"alreadyIndented"
3563 <!-- Add a blank line after class directive? -->
3570 test=
"not($alreadyBlanked)">
3575 test=
"not($alreadyIndented)">
3579 <xsl:text>.. class::
</xsl:text>
3590 <!-- ******************************************************************** -->
3592 <!-- Output a names attribute at index considering quoted spaces. -->
3594 name=
"u:outputNames">
3595 <!-- Blank line already output? -->
3603 select=
"str:replace(str:tokenize(normalize-space(str:replace($names, '\ ', '|')))[position() = $index + 1], '|', ' ')"/>
3606 <!-- ******************************************************************** -->
3608 <!-- Output a names attribute for a refid. -->
3610 name=
"u:outputNamesRefid">
3614 <!-- Determine the elements which is referred -->
3617 select=
"//*[@ids and math:max(dyn:map(str:tokenize(normalize-space(@ids)), 'number($refid = .)')) > 0]"/>
3619 name=
"u:outputNames">
3622 select=
"$refElem/@names"/>
3625 select=
"math:max(dyn:map(str:tokenize(normalize-space($refElem/@ids)), 'number($refid = .) * position() - 1'))"/>
3626 </xsl:call-template>
3629 <!-- ******************************************************************** -->
3630 <!-- ******************************************************************** -->
3632 <!-- Report unknown tags -->
3636 <xsl:text>`
</xsl:text>
3639 <xsl:text>' encountered
</xsl:text>
3642 <xsl:text> in `
</xsl:text>
3644 select=
"name(parent::*)"/>
3645 <xsl:text>'
</xsl:text>
3647 <xsl:text>, but no template matches.
</xsl:text>