1<xsl:stylesheet version="3.0" 2 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 3 xmlns:xs="http://www.w3.org/2001/XMLSchema" 4 xmlns:d="http://github.com/vinniefalco/docca" 5 exclude-result-prefixes="xs d" 6 expand-text="yes"> 7 8 <!-- TODO: make sure this doesn't screw up any formatting --> 9 <!-- NEW TODO: verify we don't need/want this --> 10 <!-- 11 <xsl:output indent="yes"/> 12 --> 13 14 <xsl:include href="common.xsl"/> 15 16 <xsl:key name="visible-memberdefs-by-id" 17 match="memberdef[$include-private-members or not(@prot eq 'private')]" 18 use="@id"/> 19 20 <xsl:key name="elements-by-refid" match="compound | member" use="@refid"/> 21 22 <xsl:variable name="index-xml" select="/"/> 23 24 <xsl:template match="/"> 25 <index> 26 <xsl:apply-templates select="/doxygenindex/compound"/> 27 </index> 28 <!-- Testing the ID-related functions 29 <xsl:value-of select="replace(d:extract-ns('put'), '::$', '')"/> 30 <xsl:text>
</xsl:text> 31 <xsl:value-of select="replace(d:extract-ns('foobar::parser::put'), '::$', '')"/> 32 <xsl:text>
</xsl:text> 33 <xsl:value-of select="d:extract-ns('foobar::parser::put<foo::bar, bat::bang>')"/> 34 <xsl:text>
</xsl:text> 35 <xsl:value-of select="d:strip-ns('boost::beast::http::parser::basic_parser< foo::isRequest, bar::parser >')"/> 36 <xsl:text>
</xsl:text> 37 <xsl:value-of select="d:strip-doc-ns('boost::beast::http::parser::basic_parser< foo::isRequest, bar::parser >')"/> 38 <xsl:text>
</xsl:text> 39 <xsl:text>
</xsl:text> 40 <xsl:value-of select="d:make-id('boost::beast::http::parser::basic_parser< foo::isRequest, bar::parser >')"/> 41 --> 42 </xsl:template> 43 44 <!-- Default implementation; can be customized/overridden --> 45 <xsl:function name="d:should-ignore-compound"> 46 <xsl:param name="compound" as="element(compound)"/> 47 <xsl:sequence select="false()"/> 48 </xsl:function> 49 50 <xsl:template match="compound[d:should-ignore-compound(.)]"/> 51 <xsl:template match="compound"> 52 <!-- Load each input file only once --> 53 <xsl:variable name="source-doc" select="d:get-source-doc(.)"/> 54 <!-- Ignore private classes unless private members are enabled --> 55 <xsl:if test="$include-private-members or not($source-doc/doxygen/compounddef/@prot eq 'private')"> 56 <!-- Look up memberdefs (and constrain by visibility) only once --> 57 <xsl:variable name="memberdefs" select="key('visible-memberdefs-by-id', member/@refid, $source-doc)"/> 58 <!-- Create a filtered copy of members within their minimal context, listing only the visible ones --> 59 <xsl:variable name="visible-members" as="element(member)*"> 60 <xsl:variable name="compound" as="element()"> 61 <compound kind="{@kind}" refid="{@refid}"> 62 <name>{name}</name> 63 <xsl:copy-of select="member[@refid = $memberdefs/@id]"/> 64 </compound> 65 </xsl:variable> 66 <xsl:sequence select="$compound/member"/> 67 </xsl:variable> 68 <xsl:apply-templates mode="create-page" select="."> 69 <xsl:with-param name="source-doc" select="$source-doc" tunnel="yes"/> 70 <xsl:with-param name="memberdefs" select="$memberdefs" tunnel="yes"/> 71 <xsl:with-param name="visible-members" select="$visible-members" tunnel="yes"/> 72 </xsl:apply-templates> 73 </xsl:if> 74 </xsl:template> 75 76 <xsl:function name="d:get-source-doc" as="document-node()"> 77 <xsl:param name="compound" as="element(compound)"/> 78 <xsl:sequence select="document($compound/@refid||'.xml', $index-xml)"/> 79 </xsl:function> 80 81 <!-- Split up the content into class, struct, and member pages --> 82 <xsl:template mode="create-page" match="*"/> 83 <xsl:template mode="create-page" match="compound[@kind = 'namespace']"> 84 <xsl:apply-templates mode="child-pages" select="."/> 85 </xsl:template> 86 <xsl:template mode="create-page" match="compound[@kind = ('class','struct')] 87 | compound/member"> 88 <xsl:variable name="page-id" as="xs:string"> 89 <xsl:apply-templates mode="page-id" select="."/> 90 </xsl:variable> 91 <page id="{$page-id}" href="{$page-id}.xml"> 92 <xsl:result-document href="xml-pages/{$page-id}.xml"> 93 <xsl:apply-templates mode="page-content" select="."> 94 <xsl:with-param name="page-id" select="$page-id" tunnel="yes"/> 95 </xsl:apply-templates> 96 </xsl:result-document> 97 <xsl:apply-templates mode="child-pages" select="."/> 98 </page> 99 </xsl:template> 100 101 <!-- Create the member page for each child (or, if overloaded, the overload-list page) --> 102 <xsl:template mode="child-pages" match="compound"> 103 <xsl:param name="visible-members" tunnel="yes"/> 104 <!-- Create a page for each unique member name --> 105 <xsl:for-each select="$visible-members[not(name = preceding-sibling::member/name)]"> 106 <xsl:apply-templates mode="create-page" select="."> 107 <xsl:with-param name="is-overload-list-page" select="d:is-overloaded(.)" tunnel="yes"/> 108 </xsl:apply-templates> 109 </xsl:for-each> 110 </xsl:template> 111 112 <!-- A member page doesn't have children, unless it is an overload-list page --> 113 <xsl:template mode="child-pages" match="compound/member"> 114 <xsl:param name="is-overload-list-page" tunnel="yes"/> 115 <xsl:if test="$is-overload-list-page"> 116 <xsl:apply-templates mode="create-page" select="d:overloaded-members(.)"> 117 <xsl:with-param name="is-overload-list-page" select="false()" tunnel="yes"/> 118 </xsl:apply-templates> 119 </xsl:if> 120 </xsl:template> 121 122 123 <xsl:template mode="page-id" match="compound">{d:make-id(name)}</xsl:template> 124 <xsl:template mode="page-id" match="member"> 125 <xsl:param name="is-overload-list-page" tunnel="yes"/> 126 <xsl:value-of> 127 <xsl:apply-templates mode="base-member-page-id" select="."/> 128 <!-- Append the overload-specific suffix, if applicable --> 129 <xsl:if test="d:is-overloaded(.) and not($is-overload-list-page)"> 130 <xsl:value-of select="d:make-id('.overload'||d:overload-position(.))"/> 131 </xsl:if> 132 </xsl:value-of> 133 </xsl:template> 134 135 <xsl:function name="d:is-overloaded" as="xs:boolean"> 136 <xsl:param name="member" as="element(member)"/> 137 <xsl:sequence select="exists(d:overloaded-members($member)[2])"/> 138 </xsl:function> 139 140 <xsl:function name="d:overload-position" as="xs:integer"> 141 <xsl:param name="member" as="element(member)"/> 142 <xsl:sequence select="1 + count($member/preceding-sibling::member[name eq $member/name])"/> 143 </xsl:function> 144 145 <xsl:function name="d:overloaded-members" as="element(member)+"> 146 <xsl:param name="member" as="element(member)"/> 147 <xsl:sequence select="$member/../member[name eq $member/name]"/> 148 </xsl:function> 149 150 151 <xsl:template mode="base-member-page-id" priority="1" 152 match="compound[@kind eq 'namespace'] 153 /member">{d:make-id(../name||'::'||name)}</xsl:template> 154 <xsl:template mode="base-member-page-id" match="compound/member">{d:make-id(../name||'.' ||name)}</xsl:template> 155 156 157 <!-- The content for a class or struct is the original source document, pared down some --> 158 <xsl:template mode="page-content" match="compound"> 159 <xsl:param name="source-doc" tunnel="yes"/> 160 <xsl:apply-templates mode="compound-page" select="$source-doc"/> 161 </xsl:template> 162 163 <!-- By default, copy everything --> 164 <xsl:template mode="compound-page" match="@* | node()" name="copy-in-compound-page"> 165 <xsl:copy> 166 <xsl:apply-templates mode="#current" select="@*"/> 167 <xsl:apply-templates mode="compound-page-insert" select="."/> 168 <xsl:apply-templates mode="#current"/> 169 </xsl:copy> 170 </xsl:template> 171 172 <!-- By default, don't insert anything --> 173 <xsl:template mode="compound-page-insert" match="*"/> 174 175 <xsl:template mode="compound-page" match="listofallmembers"/> 176 177 <xsl:template mode="compound-page" match="memberdef/@*"/> 178 179 <!-- But directly inside <memberdef>, don't copy anything... --> 180 <xsl:template mode="compound-page" match="memberdef/node()"/> 181 182 <!-- ...except for <name>, <briefdescription>, and <type> --> 183 <xsl:template mode="compound-page" match="memberdef/name 184 | memberdef/briefdescription 185 | memberdef/type" priority="1"> 186 <xsl:call-template name="copy-in-compound-page"/> 187 </xsl:template> 188 189 <!-- Insert a reference to each child member's page ID --> 190 <xsl:template mode="compound-page-insert" match="memberdef"> 191 <xsl:attribute name="d:page-refid" select="d:make-id(/doxygen/compounddef/compoundname||'.'||name)"/> 192 </xsl:template> 193 194 <!-- Alternative implementation in case we need to start controlling whitespace more 195 <xsl:template mode="compound-page" match="memberdef"> 196 <memberdef> 197 <xsl:text>
</xsl:text> 198 <xsl:copy-of select="name"/> 199 <xsl:text>
</xsl:text> 200 <xsl:copy-of select="briefdescription"/> 201 </memberdef> 202 </xsl:template> 203 --> 204 205 <!-- The content for a member page is a subset of the source document --> 206 <xsl:template mode="page-content" match="compound/member"> 207 <xsl:param name="is-overload-list-page" tunnel="yes"/> 208 <xsl:choose> 209 <xsl:when test="$is-overload-list-page"> 210 <!-- For the overload list page, include the content for every like-named member --> 211 <xsl:apply-templates mode="list-page" select="."> 212 <xsl:with-param name="applicable-members" select="d:overloaded-members(.)" tunnel="yes"/> 213 </xsl:apply-templates> 214 </xsl:when> 215 <xsl:otherwise> 216 <!-- Otherwise, this page is just for one implementation (whether overloaded or not) --> 217 <xsl:apply-templates mode="member-page" select="."/> 218 </xsl:otherwise> 219 </xsl:choose> 220 </xsl:template> 221 222 <xsl:template mode="list-page member-page" match="member" priority="2"> 223 <xsl:param name="applicable-members" as="element(member)+" select="." tunnel="yes"/> 224 <xsl:param name="source-doc" tunnel="yes"/> 225 <xsl:param name="memberdefs" tunnel="yes"/> 226 <xsl:apply-templates mode="#current" select="$source-doc"> 227 <xsl:with-param name="target-memberdefs" 228 select="$memberdefs[@id = $applicable-members/@refid]" 229 tunnel="yes"/> 230 <xsl:with-param name="member" select="." tunnel="yes"/> 231 </xsl:apply-templates> 232 </xsl:template> 233 234 <!-- Always copy the name of the parent compound --> 235 <xsl:template mode="list-page member-page" match="compoundname" priority="2"> 236 <xsl:copy-of select="."/> 237 </xsl:template> 238 239 <!-- Otherwise, only copy an element if it's the target member or one of its ancestors --> 240 <xsl:template mode="list-page member-page" match="*" priority="1"> 241 <xsl:param name="target-memberdefs" tunnel="yes"/> 242 <xsl:if test=". intersect $target-memberdefs/ancestor-or-self::*"> 243 <xsl:next-match/> 244 </xsl:if> 245 </xsl:template> 246 247 <!-- By default, copy everything --> 248 <xsl:template mode="list-page" match="@* | node()"> 249 <xsl:copy> 250 <xsl:apply-templates mode="#current" select="@*"/> 251 <xsl:apply-templates mode="list-page-insert" select="."/> 252 <xsl:apply-templates mode="#current"/> 253 </xsl:copy> 254 </xsl:template> 255 256 <!-- By default, don't insert anything --> 257 <xsl:template mode="list-page-insert" match="*"/> 258 259 260 <!-- By default, copy everything --> 261 <xsl:template mode="member-page 262 copy-member-content" match="@* | node()"> 263 <xsl:copy> 264 <xsl:apply-templates mode="#current" select="@*"/> 265 <xsl:apply-templates mode="member-page-insert" select="."/> 266 <xsl:apply-templates mode="#current"/> 267 <xsl:apply-templates mode="member-page-append" select="."/> 268 </xsl:copy> 269 </xsl:template> 270 271 <!-- By default, don't insert or append anything --> 272 <xsl:template mode="member-page-insert 273 member-page-append" match="*"/> 274 275 <!-- Strip out extraneous whitespace --> 276 <xsl:template mode="list-page member-page" match="compounddef/text() | sectiondef/text()"/> 277 278 <!-- Switch to an unfiltered copy once we're done filtering out the undesired elements --> 279 <xsl:template mode="list-page member-page" match="memberdef/node()" priority="2"> 280 <xsl:apply-templates mode="copy-member-content" select="."/> 281 </xsl:template> 282 283 <!-- Add the page ID to the top of all page types --> 284 <xsl:template mode="compound-page-insert 285 member-page-insert 286 list-page-insert" match="/doxygen" priority="2"> 287 <xsl:param name="page-id" tunnel="yes"/> 288 <xsl:attribute name="d:page-id" select="$page-id"/> 289 <xsl:next-match/> 290 </xsl:template> 291 292 <!-- Also, if applicable, insert the overload position and/or base compound reference of this member --> 293 <xsl:template mode="member-page-insert" match="/doxygen" priority="1"> 294 <xsl:param name="member" tunnel="yes"/> 295 <xsl:if test="d:is-overloaded($member)"> 296 <xsl:attribute name="d:overload-position" select="d:overload-position($member)"/> 297 <xsl:attribute name="d:overload-size" select="count(d:overloaded-members($member))"/> 298 </xsl:if> 299 <xsl:if test="$member[not(starts-with(@refid, ../@refid))]"> 300 <xsl:variable name="base-compound" select="$index-xml/*/compound[starts-with($member/@refid, @refid)] 301 [not(d:should-ignore-compound(.))]"/> 302 <xsl:apply-templates mode="base-compound-atts" select="$base-compound"/> 303 </xsl:if> 304 <xsl:next-match/> 305 </xsl:template> 306 307 <xsl:template mode="base-compound-atts" match="compound"> 308 <xsl:attribute name="d:base-compound-name" select="d:strip-doc-ns(name)"/> 309 <xsl:attribute name="d:base-compound-refid"> 310 <xsl:apply-templates mode="page-id" select="."/> 311 </xsl:attribute> 312 </xsl:template> 313 314 <!-- Make data available for the typedef tables, if applicable --> 315 <xsl:template mode="member-page-append" match="memberdef[@kind eq 'typedef'] 316 [type/ref] 317 [not(contains(type, '*'))]"> 318 <xsl:for-each select="type/ref"> 319 <d:referenced-typedef-class> 320 <xsl:variable name="compound" select="d:get-target-element(.)[self::compound]"/> 321 <xsl:apply-templates mode="compound-page" select="$compound ! d:get-source-doc(.)/*/compounddef"/> 322 </d:referenced-typedef-class> 323 </xsl:for-each> 324 </xsl:template> 325 326 <!-- Finally, add the page type --> 327 <xsl:template mode="compound-page-insert" match="/doxygen"> 328 <xsl:attribute name="d:page-type" select="'compound'"/> 329 </xsl:template> 330 <xsl:template mode="member-page-insert" match="/doxygen"> 331 <xsl:attribute name="d:page-type" select="'member'"/> 332 </xsl:template> 333 <xsl:template mode="list-page-insert" match="/doxygen"> 334 <xsl:attribute name="d:page-type" select="'overload-list'"/> 335 </xsl:template> 336 337 <!-- For overload-list pages, include the page id for each member --> 338 <xsl:template mode="list-page-insert" match="memberdef"> 339 <xsl:param name="applicable-members" tunnel="yes"/> 340 <xsl:variable name="this-id" select="@id"/> 341 <xsl:variable name="original-member" select="$applicable-members[@refid eq $this-id]"/> 342 <xsl:attribute name="d:page-refid"> 343 <xsl:apply-templates mode="page-id" select="$original-member"> 344 <xsl:with-param name="is-overload-list-page" select="false()" tunnel="yes"/> 345 </xsl:apply-templates> 346 </xsl:attribute> 347 </xsl:template> 348 349 <!-- For public innerclasses, insert the referenced class inline --> 350 <xsl:template mode="compound-page-insert" match="innerclass[@prot eq 'public']"> 351 <xsl:attribute name="d:page-refid" select="d:make-id(.)"/> 352 <d:referenced-inner-class> 353 <xsl:variable name="compound" select="d:get-target-element(.)" as="element(compound)"/> 354 <xsl:apply-templates mode="compound-page" select="d:get-source-doc($compound)/*/compounddef"/> 355 </d:referenced-inner-class> 356 </xsl:template> 357 358 <!-- Resolve the referenced page IDs for later link generation --> 359 <xsl:template mode="compound-page-insert member-page-insert" match="ref"> 360 <xsl:attribute name="d:refid"> 361 <xsl:apply-templates mode="page-id" select="d:get-target-element(.)"> 362 <!-- For inline links to member pages, only link to the base page id (no overloads) --> 363 <xsl:with-param name="is-overload-list-page" select="true()" tunnel="yes"/> 364 </xsl:apply-templates> 365 </xsl:attribute> 366 </xsl:template> 367 368 <xsl:function name="d:get-target-element" as="element()?"> <!-- to allow for partial builds --> 369 <!-- 370 <xsl:function name="d:get-target-element" as="element()"> 371 --> 372 <xsl:param name="ref" as="element()"/> <!-- <ref> or <innerclass> or... --> 373 <xsl:variable name="referenced-elements" select="key('elements-by-refid', $ref/@refid, $index-xml)"/> 374 <xsl:variable name="result" as="element()?"> 375 <xsl:choose> 376 <!-- Handle the case where the referenced element appears two or more times in index.xml --> 377 <!-- If there's no ambiguity, we're done! --> 378 <xsl:when test="count($referenced-elements) eq 1"> 379 <xsl:apply-templates mode="find-target-element" select="$referenced-elements"/> 380 </xsl:when> 381 <xsl:otherwise> 382 <!-- Otherwise, see if a namespace in the link text successfully disambiguates --> 383 <xsl:variable name="qualified-reference" as="element()*"> 384 <xsl:variable name="parent-in-link-text" 385 select="if (contains($ref,'::')) 386 then d:extract-ns-without-suffix($ref) 387 else ''"/> 388 <xsl:sequence select="$referenced-elements[ends-with(parent::compound/name, '::'||$parent-in-link-text)]"/> 389 </xsl:variable> 390 <xsl:choose> 391 <xsl:when test="count($qualified-reference) eq 1"> 392 <xsl:apply-templates mode="find-target-element" select="$qualified-reference"/> 393 </xsl:when> 394 <xsl:otherwise> 395 <!-- Otherwise, favor the member that's in the same class or namespace as the current page --> 396 <xsl:variable name="sibling-reference" as="element()*"> 397 <xsl:variable name="compound-for-current-page" select="root($ref)/doxygen/compounddef/compoundname/string()"/> 398 <xsl:sequence select="$referenced-elements[parent::compound/name eq $compound-for-current-page]"/> 399 </xsl:variable> 400 <xsl:choose> 401 <xsl:when test="count($sibling-reference) eq 1"> 402 <xsl:apply-templates mode="find-target-element" select="$sibling-reference"/> 403 </xsl:when> 404 <!-- If all else fails, give up and just use the first one --> 405 <xsl:otherwise> 406 <xsl:apply-templates mode="find-target-element" select="$referenced-elements[1]"/> 407 </xsl:otherwise> 408 </xsl:choose> 409 </xsl:otherwise> 410 </xsl:choose> 411 </xsl:otherwise> 412 </xsl:choose> 413 </xsl:variable> 414 <xsl:if test="not($result)"> 415 <xsl:message>Unable to find referenced ID: <xsl:value-of select="$ref/@refid"/></xsl:message> 416 </xsl:if> 417 <xsl:sequence select="$result"/> 418 </xsl:function> 419 420 <xsl:template mode="find-target-element" match="compound | member"> 421 <xsl:sequence select="."/> 422 </xsl:template> 423 424 <!-- In the index XML, enumvalue "members" immediately follow the corresponding enum member --> 425 <xsl:template mode="find-target-element" match="member[@kind eq 'enumvalue']"> 426 <xsl:sequence select="preceding-sibling::member[@kind eq 'enum'][1]"/> 427 </xsl:template> 428 429</xsl:stylesheet> 430