1 <!DOCTYPE xsl:stylesheet [
2 <!-- TODO: complete this list -->
3 <!ENTITY BLOCK_LEVEL_ELEMENT "programlisting
12 <xsl:stylesheet version="3.0"
13 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
14 xmlns:xs="http://www.w3.org/2001/XMLSchema"
15 xmlns:d="http://github.com/vinniefalco/docca"
16 exclude-result-prefixes="xs d"
19 <xsl:include href="common.xsl"/>
21 <xsl:output indent="yes"/>
23 <xsl:template match="/doxygen" priority="1">
24 <page id="{@d:page-id}" type="{@d:page-type}">
25 <xsl:apply-templates mode="index-term-atts" select="."/>
27 <xsl:apply-templates mode="page-title" select="."/>
29 <xsl:apply-templates select="@d:base-compound-refid"/>
34 <xsl:template match="@d:base-compound-refid">
35 <div>(Inherited from <ref d:refid="{.}">{../@d:base-compound-name}</ref>)</div>
38 <!-- Put an index term on every page except class (compound) and overloaded-member pages -->
39 <xsl:template mode="index-term-atts" match="doxygen[@d:page-type eq 'compound' or @d:overload-position]"/>
40 <xsl:template mode="index-term-atts" match="doxygen">
41 <xsl:attribute name="primary-index-term">
42 <xsl:apply-templates mode="primary-index-term" select="."/>
44 <xsl:apply-templates mode="secondary-index-term-att" select="."/>
47 <!-- By default, use the member name as the primary term... -->
48 <xsl:template mode="primary-index-term" match="doxygen">
49 <xsl:apply-templates mode="member-name" select="."/>
51 <!-- ...and the compound name as the secondary term. -->
52 <xsl:template mode="secondary-index-term-att" match="doxygen">
53 <xsl:attribute name="secondary-index-term">
54 <xsl:apply-templates mode="compound-name" select="."/>
58 <!-- But with namespace members, use the fully-qualified name as the primary term... -->
59 <xsl:template mode="primary-index-term" match="doxygen[compounddef/@kind eq 'namespace']">
60 <xsl:apply-templates mode="compound-and-member-name" select="."/>
62 <!-- ...and no secondary term. -->
63 <xsl:template mode="secondary-index-term-att" match="doxygen[compounddef/@kind eq 'namespace']"/>
65 <xsl:template mode="compound-name" match="doxygen"
66 >{d:strip-doc-ns(compounddef/compoundname)}</xsl:template>
68 <xsl:template mode="member-name" match="doxygen"
69 >{(compounddef/sectiondef/memberdef/name)[1]}</xsl:template>
71 <xsl:template mode="compound-and-member-name" match="doxygen">
72 <xsl:variable name="compound-name" as="xs:string">
73 <xsl:apply-templates mode="compound-name" select="."/>
75 <xsl:if test="$compound-name">{$compound-name}::</xsl:if>
76 <xsl:apply-templates mode="member-name" select="."/>
79 <xsl:template mode="page-title" match="doxygen[@d:page-type eq 'compound']">
80 <xsl:apply-templates mode="compound-name" select="."/>
82 <xsl:template mode="page-title" match="doxygen">
83 <xsl:apply-templates mode="compound-and-member-name" select="."/>
84 <xsl:apply-templates mode="overload-qualifier" select="."/>
87 <xsl:template mode="overload-qualifier" match="doxygen"/>
88 <xsl:template mode="overload-qualifier" match="doxygen[@d:overload-position]">
89 <xsl:text> (</xsl:text>
90 <xsl:value-of select="@d:overload-position"/>
91 <xsl:text> of </xsl:text>
92 <xsl:value-of select="@d:overload-size"/>
93 <xsl:text> overloads)</xsl:text>
97 <xsl:template match="/doxygen[@d:page-type eq 'compound']">
98 <xsl:apply-templates select="compounddef"/>
101 <xsl:template match="/doxygen[@d:page-type eq 'member']">
102 <xsl:apply-templates select="compounddef/sectiondef/memberdef"/> <!-- should just be one -->
105 <xsl:template match="/doxygen[@d:page-type eq 'overload-list']">
106 <xsl:apply-templates select="(compounddef/sectiondef/memberdef)[1]"/>
109 <xsl:template match="compounddef | memberdef" priority="2">
111 <xsl:apply-templates mode="includes" select=".">
112 <xsl:with-param name="is-footer" select="true()"/>
113 </xsl:apply-templates>
116 <!-- For convenience, pre-calculate some member sequences and tunnel them through -->
117 <xsl:template match="compounddef" priority="1">
119 <xsl:with-param name="public-types"
120 select="sectiondef[@kind eq 'public-type']/memberdef
121 | innerclass[@prot eq 'public'][not(d:should-ignore-inner-class(.))]"
123 <xsl:with-param name="friends"
124 select="sectiondef[@kind eq 'friend']/memberdef[not(type = ('friend class','friend struct'))]
125 [not(d:should-ignore-friend(.))]"
130 <xsl:template match="compounddef">
131 <xsl:param name="public-types" tunnel="yes"/>
132 <xsl:param name="friends" tunnel="yes"/>
134 <xsl:apply-templates select="briefdescription"/>
136 <xsl:apply-templates mode="section"
139 ( $public-types/self::memberdef/..
140 | $public-types/self::innerclass
143 sectiondef[@kind = ( 'public-func', 'public-static-func')],
144 sectiondef[@kind = ('protected-func','protected-static-func')],
145 sectiondef[@kind = ( 'private-func', 'private-static-func')][$include-private-members],
147 sectiondef[@kind = ( 'public-attrib', 'public-static-attrib')],
148 sectiondef[@kind = ('protected-attrib','protected-static-attrib')],
149 sectiondef[@kind = ( 'private-attrib', 'private-static-attrib')][$include-private-members],
153 sectiondef[@kind eq 'related'],
159 <xsl:template match="memberdef">
160 <xsl:apply-templates select="briefdescription"/>
161 <xsl:apply-templates mode="section" select="., detaileddescription"/>
164 <xsl:template match="memberdef[@kind eq 'enum']">
165 <xsl:apply-templates select="briefdescription"/>
166 <xsl:apply-templates mode="section" select="., parent::sectiondef, detaileddescription"/>
169 <xsl:template match="memberdef[/doxygen/@d:page-type eq 'overload-list']">
170 <xsl:for-each-group select="../../sectiondef/memberdef" group-by="briefdescription">
171 <xsl:apply-templates select="briefdescription"/>
172 <xsl:apply-templates mode="overload-list" select="current-group()"/>
173 </xsl:for-each-group>
176 <xsl:template mode="overload-list" match="memberdef">
178 <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
179 <xsl:apply-templates mode="modifier" select="(@explicit, @friend, @static)[. eq 'yes'],
180 @virt[. eq 'virtual']"/>
181 <xsl:apply-templates select="type"/>
182 <ref d:refid="{@d:page-refid}">{name}</ref>
184 <xsl:apply-templates select="param"/>
186 <xsl:apply-templates mode="modifier" select="@const[. eq 'yes']"/>
190 <xsl:template mode="modifier" match="@*">
191 <modifier>{local-name(.)}</modifier>
193 <xsl:template mode="modifier" match="@virt">
194 <modifier>virtual</modifier>
198 <xsl:template match="type">
200 <xsl:value-of select="d:cleanup-type(normalize-space(.))"/>
204 <!-- d:cleanup-param() may not be needed, and the above may suffice. (TODO: confirm this and remove d:cleanup-param() if so)
205 <xsl:template match="param/type">
207 <xsl:value-of select="d:cleanup-param(.)"/>
212 <!-- TODO: Should this be a custom rule or built-in? -->
213 <xsl:template mode="section" match="simplesect[matches(title,'Concepts:?')]"/>
215 <!-- Omit description section if it has no body -->
216 <xsl:template mode="section" match="detaileddescription[not(normalize-space(.))]" priority="1"/>
218 <xsl:template mode="section" match="*">
221 <xsl:apply-templates mode="section-heading" select="."/>
223 <xsl:apply-templates mode="section-body" select="."/>
227 <xsl:template match="simplesect | parameterlist">
228 <xsl:apply-templates mode="section" select="."/>
231 <xsl:template mode="section-heading" match="memberdef |
232 compounddef ">Synopsis</xsl:template>
233 <xsl:template mode="section-heading" match="detaileddescription">Description</xsl:template>
235 <xsl:template mode="section-heading" match="simplesect[@kind eq 'note' ]">Remarks</xsl:template>
236 <xsl:template mode="section-heading" match="simplesect[@kind eq 'see' ]">See Also</xsl:template>
237 <xsl:template mode="section-heading" match="simplesect[@kind eq 'return']">Return Value</xsl:template>
238 <xsl:template mode="section-heading" match="simplesect" >{title}</xsl:template>
240 <xsl:template mode="section-heading" match="parameterlist[@kind eq 'exception' ]">Exceptions</xsl:template>
241 <xsl:template mode="section-heading" match="parameterlist[@kind eq 'templateparam']">Template Parameters</xsl:template>
242 <xsl:template mode="section-heading" match="parameterlist ">Parameters</xsl:template>
244 <xsl:template mode="section-heading" match="innerclass">Types</xsl:template>
246 <xsl:template mode="section-heading" match="sectiondef[@kind eq 'friend' ]">Friends</xsl:template>
247 <xsl:template mode="section-heading" match="sectiondef[@kind eq 'related']">Related Functions</xsl:template>
248 <xsl:template mode="section-heading" match="sectiondef[@kind eq 'enum' ]">Values</xsl:template>
250 <xsl:template mode="section-heading" match="sectiondef">
251 <xsl:apply-templates mode="access-level" select="@kind"/>
252 <xsl:apply-templates mode="storage-class" select="@kind"/>
253 <xsl:apply-templates mode="member-kind" select="@kind"/>
256 <xsl:template mode="access-level" match="@kind[starts-with(.,'public-' )]"/>
257 <xsl:template mode="access-level" match="@kind[starts-with(.,'protected-')]">Protected </xsl:template>
258 <xsl:template mode="access-level" match="@kind[starts-with(.,'private-' )]">Private </xsl:template>
260 <xsl:template mode="storage-class" match="@*"/>
261 <xsl:template mode="storage-class" match="@kind[contains(.,'-static-')]">Static </xsl:template>
263 <xsl:template mode="member-kind" priority="1"
264 match="@kind[ends-with(.,'-static-attrib')]">Members</xsl:template>
265 <xsl:template mode="member-kind" match="@kind[ends-with(.,'-attrib' )]">Data Members</xsl:template>
266 <xsl:template mode="member-kind" match="@kind[ends-with(.,'-func' )]">Member Functions</xsl:template>
267 <xsl:template mode="member-kind" match="@kind[ends-with(.,'-type' )]">Types</xsl:template>
270 <xsl:template mode="section-body" match="sectiondef | innerclass | parameterlist">
274 <xsl:apply-templates mode="column-1-name" select="."/>
277 <xsl:apply-templates mode="column-2-name" select="."/>
280 <xsl:apply-templates mode="table-body" select="."/>
284 <xsl:template mode="column-1-name" match="*">Name</xsl:template>
285 <xsl:template mode="column-2-name" match="*">Description</xsl:template>
287 <xsl:template mode="column-1-name"
288 match="parameterlist[@kind = ('exception','templateparam')]">Type</xsl:template>
290 <xsl:template mode="column-2-name" match="parameterlist[@kind eq 'exception']">Thrown On</xsl:template>
293 <xsl:template mode="table-body" match="parameterlist">
294 <xsl:apply-templates mode="parameter-row" select="parameteritem"/>
297 <xsl:template mode="parameter-row" match="parameteritem">
301 <!-- ASSUMPTION: <parameternamelist> only ever has one <parametername> child -->
302 <xsl:apply-templates select="parameternamelist/parametername/node()"/>
306 <xsl:apply-templates select="parameterdescription/node()"/>
311 <xsl:template mode="table-body" match="sectiondef[@kind eq 'enum']">
312 <xsl:apply-templates mode="enum-row" select="memberdef/enumvalue"/> <!-- Use input order for enum values -->
315 <xsl:template mode="enum-row" match="enumvalue">
321 <xsl:apply-templates select="briefdescription, detaileddescription"/>
326 <xsl:template mode="table-body" match="sectiondef | innerclass">
327 <xsl:variable name="member-nodes" as="element()*">
328 <xsl:apply-templates mode="member-nodes" select="."/>
330 <xsl:for-each-group select="$member-nodes" group-by="d:member-name(.)">
331 <xsl:sort select="current-grouping-key()"/>
332 <xsl:apply-templates mode="member-row" select="."/>
333 </xsl:for-each-group>
336 <xsl:template mode="member-nodes" match="innerclass | sectiondef[@kind eq 'public-type']">
337 <xsl:param name="public-types" tunnel="yes" select="()"/>
338 <xsl:sequence select="$public-types"/>
341 <xsl:template mode="member-nodes" match="sectiondef[@kind eq 'friend']">
342 <xsl:param name="friends" tunnel="yes"/>
343 <xsl:sequence select="$friends"/>
346 <xsl:template mode="member-nodes" match="sectiondef">
348 ASSUMPTION (for now): At least one member per section (table) must not be in a user-defined group.
349 Also, we may need a more robust mapping between a user-defined group's members and the sections
350 in which they belong. For now, we are using this partial test.
352 <xsl:sequence select="memberdef,
353 ../sectiondef[@kind eq 'user-defined']/memberdef[(@kind||@prot||@static) =
354 current()/memberdef/(@kind||@prot||@static)]"/>
358 <xsl:function name="d:member-name">
359 <xsl:param name="element"/>
360 <xsl:apply-templates mode="member-name" select="$element"/>
363 <xsl:template mode="member-name" match="memberdef">
364 <xsl:sequence select="name"/>
366 <xsl:template mode="member-name" match="innerclass">
367 <xsl:sequence select="d:referenced-inner-class/compounddef/compoundname ! d:strip-ns(.)"/>
371 <xsl:template mode="member-row" match="*">
375 <ref d:refid="{@d:page-refid}">{current-grouping-key()}</ref>
376 <xsl:apply-templates mode="member-annotation" select="."/>
380 <xsl:apply-templates mode="member-description" select="."/>
385 <xsl:template mode="member-annotation" match="*">
386 <xsl:variable name="member-name" select="current-grouping-key()"/>
387 <xsl:variable name="is-destructor" select="starts-with($member-name, '~')"/>
388 <xsl:variable name="is-constructor" select="$member-name = d:strip-ns(/doxygen/compounddef/compoundname)"/>
389 <xsl:if test="$is-destructor or $is-constructor">
390 <xsl:text> </xsl:text>
391 <role class="silver">
393 <xsl:when test="$is-destructor">[destructor]</xsl:when>
394 <xsl:otherwise >[constructor]</xsl:otherwise>
401 <xsl:template mode="member-description" match="innerclass">
402 <xsl:apply-templates select="d:referenced-inner-class/compounddef/briefdescription"/>
404 <xsl:template mode="member-description" match="memberdef">
405 <xsl:variable name="descriptions" select="current-group()/briefdescription"/>
406 <!-- Pull in any overload descriptions but only if they vary -->
407 <xsl:for-each select="distinct-values($descriptions)">
408 <!-- ASSUMPTION: <briefdescription> always contains one <para> -->
409 <xsl:apply-templates select="$descriptions[. eq current()][1]/para/node()"/>
410 <xsl:if test="position() ne last()">
412 <role class="silver">—</role>
419 <xsl:template mode="section-body" match="detaileddescription | simplesect">
420 <xsl:apply-templates/>
423 <xsl:template mode="section-body" match="compounddef | memberdef" priority="1">
424 <xsl:apply-templates mode="includes" select="."/>
428 <xsl:template mode="section-body" match="compounddef">
430 <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
432 <name>{d:strip-ns(compoundname)}</name>
433 <xsl:for-each select="basecompoundref[not(d:should-ignore-base(.))]
434 [not(@prot eq 'private')]">
437 <name>{d:strip-doc-ns(.)}</name>
443 <xsl:template mode="section-body" match="memberdef[@kind eq 'typedef']">
445 <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
446 <xsl:apply-templates select="name, type"/>
448 <!-- Nested compounddefs were derived from refs in the typedef's type -->
449 <xsl:apply-templates select="d:referenced-typedef-class/compounddef"/>
452 <!-- Suppress the display of several aspects of referenced typedef classes -->
454 <!-- Don't show the briefdescription -->
455 <xsl:template match="d:referenced-typedef-class/compounddef/briefdescription"/>
457 <!-- Don't show the Synopsis -->
458 <xsl:template mode="section" match="d:referenced-typedef-class/compounddef"/>
460 <!-- Exclude the "Description" heading (only show the body) -->
461 <xsl:template mode="section" match="d:referenced-typedef-class/compounddef/detaileddescription">
462 <xsl:apply-templates mode="section-body" select="."/>
465 <!-- Don't show the includes header or footer -->
466 <xsl:template mode="includes" match="d:referenced-typedef-class/compounddef"/>
469 <xsl:template mode="section-body" match="memberdef[@kind eq 'enum']">
471 <xsl:apply-templates select="name"/>
475 <xsl:template mode="section-body" match="memberdef[@kind eq 'variable']">
477 <xsl:apply-templates mode="modifier" select="@static[. eq 'yes']"/>
478 <xsl:apply-templates select="type, name"/>
479 <xsl:apply-templates select="initializer[count(../initializer) eq 1]"/>
483 <xsl:template mode="section-body" match="memberdef[@kind = ('function','friend')]">
485 <xsl:apply-templates mode="normalize-params" select="templateparamlist"/>
486 <xsl:apply-templates mode="modifier" select="@static[. eq 'yes'],
487 @virt [. eq 'virtual']"/>
488 <xsl:apply-templates select="type, name"/>
490 <xsl:apply-templates select="param"/>
492 <xsl:apply-templates mode="modifier" select="@const[. eq 'yes']"/>
496 <!-- Extract <declname> when Doxygen hides it in the <type> -->
497 <xsl:template mode="normalize-params" match="templateparamlist/param/type[not(../declname)]
498 [starts-with(.,'class ') or
499 starts-with(.,'typename ')]"
501 <type>{substring-before(.,' ')}</type>
502 <declname>{substring-after(.,' ')}</declname>
505 <!-- Flag as error if no declname value could be found (unless the type is simply "class") -->
506 <xsl:template mode="normalize-params" match="templateparamlist/param/type[not(../declname)]
508 <ERROR message="param neither has a declname nor a 'class ' or 'typename ' prefix in the type"/>
511 <xsl:template mode="normalize-params" match="templateparamlist/param/defname"/>
514 <!-- We only need to keep the @file attribute -->
515 <xsl:template match="location/@*[. except ../@file]"/>
517 <xsl:template match="briefdescription | detaileddescription">
519 <xsl:apply-templates/>
523 <xsl:template match="simplesect/title"/>
525 <!-- TODO: verify we don't need this; it was causing duplicate headings in simplesect sections
526 <xsl:template match="title">
528 <xsl:apply-templates/>
533 <!-- By default, don't output an includes header or footer -->
534 <xsl:template mode="includes" match="*"/>
536 <!-- TODO: Review; this is meant to effect what the previous code did, but I'm not sure it captures the original intentions -->
537 <xsl:template mode="includes" match="compounddef
538 | memberdef[@kind eq 'friend' or ../../@kind eq 'namespace']
539 [not(/doxygen/@d:page-type eq 'overload-list')]">
540 <xsl:param name="is-footer"/>
543 <xsl:when test="$is-footer">
545 <xsl:apply-templates select="location"/>
549 <xsl:apply-templates select="location"/>
555 <!-- Strip the project namespace prefix from link display names
556 (matching the text node so this will still work with the strip-leading-space mode/process below) -->
557 <!-- TODO: figure out if we need anything like this (maybe not).
558 <xsl:template match="ref/text()[starts-with(.,$doc-ns)]">
559 <xsl:value-of select="d:strip-doc-ns(.)"/>
564 <!-- When a <para> directly contains a mix of inline nodes and block-level elements, normalize its content -->
565 <xsl:template match="para[&BLOCK_LEVEL_ELEMENT;]">
567 <xsl:for-each-group select="* | text()" group-adjacent="d:is-inline(.)">
568 <xsl:apply-templates mode="capture-ranges" select="."/>
569 </xsl:for-each-group>
573 <xsl:function name="d:is-inline">
574 <xsl:param name="node"/>
575 <xsl:sequence select="not($node/../(&BLOCK_LEVEL_ELEMENT;)[. is $node])"/>
578 <!-- Process the block-level elements as usual -->
579 <xsl:template mode="capture-ranges" match="node()">
580 <xsl:apply-templates select="current-group()"/>
583 <!-- Wrap contiguous ranges of inline children in a nested <para> -->
584 <xsl:template mode="capture-ranges" match="node()[d:is-inline(.)]">
586 <!-- But only if it has text or if the group has more than one node -->
587 <xsl:when test="normalize-space(.) or current-group()[2]">
589 <xsl:apply-templates mode="strip-leading-space" select="."/>
599 <!-- Strip leading whitespace from the nested paragraphs to prevent eventual interpretation as a code block -->
600 <xsl:template mode="strip-leading-space" match="*">
602 <xsl:apply-templates mode="#current" select="@* | node()[1]"/>
604 <xsl:apply-templates mode="#current" select="following-sibling::node()[1]
605 [ancestor-or-self::node() intersect current-group()]"/>
608 <xsl:template mode="strip-leading-space" match="@*">
612 <xsl:template mode="strip-leading-space" match="text()">
613 <xsl:param name="done-stripping" tunnel="yes" select="false()"/>
615 <xsl:when test="$done-stripping">
616 <xsl:apply-templates select="."/>
619 <xsl:sequence select="replace(.,'^\s+','')"/>
622 <xsl:apply-templates mode="#current" select="following-sibling::node()[1]
623 [ancestor-or-self::node() intersect current-group()]">
624 <xsl:with-param name="done-stripping" select="$done-stripping or normalize-space(.)" tunnel="yes"/>
625 </xsl:apply-templates>
629 <xsl:template mode="#default normalize-params" match="@* | node()">
630 <xsl:copy copy-namespaces="no">
631 <xsl:apply-templates mode="#current" select="@* | node()"/>