← all demos
xsl:stylesheet(
    default-mode="m:docbook",
    exclude-result-prefixes="#all",
    version="3.0",
    xmlns="http://www.w3.org/1999/xhtml",
    xmlns:db="http://docbook.org/ns/docbook",
    xmlns:ext="http://docbook.org/extensions/xslt",
    xmlns:f="http://docbook.org/ns/docbook/functions",
    xmlns:fp="http://docbook.org/ns/docbook/functions/private",
    xmlns:h="http://www.w3.org/1999/xhtml",
    xmlns:ls="http://docbook.org/ns/docbook/l10n/source",
    xmlns:m="http://docbook.org/ns/docbook/modes",
    xmlns:v="http://docbook.org/ns/docbook/variables",
    xmlns:vp="http://docbook.org/ns/docbook/variables/private",
    xmlns:xs="http://www.w3.org/2001/XMLSchema",
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform")
  v:as-json := map {'method':'json','indent':true()}
  v:as-xml := map {'method':'xml','indent':true()}
  v:mathml-js-roles as string* := tokenize($mathml-js-role, '\s+')
  v:custom-localizations as document-node()? := ()
  v:localization-base-uri := resolve-uri('../locale/', static-base-uri())
  v:chunk as boolean := not(normalize-space($chunk) = '')
  vp:section-toc-depth as integer :=
    choose:
      when $section-toc-depth instance of xs:integer:
        <-- max((0, $section-toc-depth))
      when $section-toc-depth castable as xs:integer:
        <-- max((0, xs:integer($section-toc-depth)))
      when string($section-toc-depth) = 'unbounded':
        <-- 2147483647
      else:
        <-- 0
  v:debug as string* := tokenize($debug, '[,\s]+') ! normalize-space(.)
  v:verbatim-table-style := tokenize($verbatim-table-style, '\s+')
  v:verbatim-line-style := tokenize($verbatim-line-style, '\s+')
  v:verbatim-plain-style as string* := tokenize($verbatim-plain-style, '\s+')
  v:verbatim-space as node() :=
    <- substring($verbatim-space || ' ', 1, 1)
  v:verbatim-numbered-elements as string* := tokenize($verbatim-numbered-elements, '\s+')
  v:verbatim-number-minlines := xs:integer($verbatim-number-minlines)
  v:verbatim-number-every-nth := xs:integer($verbatim-number-every-nth)
  v:verbatim-number-first-line := f:is-true($verbatim-number-first-line)
  v:verbatim-callouts as string* := tokenize($verbatim-callouts, '\s+')
  v:verbatim-syntax-highlight-languages := tokenize($verbatim-syntax-highlight-languages, '\s+')
  v:verbatim-syntax-highlight-options := map { }
  v:verbatim-syntax-highlight-pygments-options := map { }
  v:mediaobject-output-base-uri as string? :=
    xsl:message(
        select="'Mediaobject out. base URI:',
                       if (empty($mediaobject-output-base-uri))
                       then ()
                       else if (ends-with($mediaobject-output-base-uri, '/'))
                            then $mediaobject-output-base-uri
                            else $mediaobject-output-base-uri || '/'",
        use-when="'mediaobject-uris' = $v:debug")
    <-- if (empty($mediaobject-output-base-uri))
                        then ()
                        else if (ends-with($mediaobject-output-base-uri, '/'))
                             then $mediaobject-output-base-uri
                             else $mediaobject-output-base-uri || '/'
  v:mediaobject-exclude-extensions := tokenize($mediaobject-exclude-extensions, '\s+')
  vp:mediaobject-accessibility := tokenize($mediaobject-accessibility, '\s+')
  vp:table-accessibility := tokenize($table-accessibility, '\s+')
  v:personal-name-styles := ('first-last', 'last-first', 'FAMILY-given')
  v:formal-object-title-placement as map(xs:string,xs:string) := fp:parse-key-value-pairs(
                        tokenize($formal-object-title-placement, '\s+'))
  v:formalgroup-nested-object-title-placement as map(xs:string,xs:string) := fp:parse-key-value-pairs(
                        tokenize($formal-object-title-placement, '\s+'))
  v:mediaobject-details-placement as map(xs:string,xs:string) := fp:parse-key-value-pairs(
                        tokenize($mediaobject-details-placement, '\s+'))
  v:arg-choice-opt-open-str :=
    span(class="cmdpunct") = [
  v:arg-choice-opt-close-str :=
    span(class="cmdpunct") = ]
  v:arg-choice-req-open-str :=
    span(class="cmdpunct") = {
  v:arg-choice-req-close-str :=
    span(class="cmdpunct") = }
  v:arg-choice-plain-open-str :=
  v:arg-choice-plain-close-str :=
  v:arg-choice-def-open-str :=
    span(class="cmdpunct") = [
  v:arg-choice-def-close-str :=
    span(class="cmdpunct") = ]
  v:arg-rep-repeat-str :=
    span(class="cmdpunct") =
  v:arg-rep-norepeat-str :=
  v:arg-rep-def-str :=
  v:arg-or-sep :=
    span(class="cmdpunct") = |
  vp:user-css-links := tokenize(normalize-space($user-css-links), '\s+')
  vp:cos-number-from := tokenize(normalize-space($cos-number-from), '\s+')
  v:chunk-renumber-footnotes as boolean := f:is-true($chunk-renumber-footnotes)
  v:chunk-filter-namespaces as namespace-node()* :=
    xsl:namespace(name="db", select="'http://docbook.org/ns/docbook'")
  vp:chunk-output-base-uri as anyURI? :=
    result as anyURI :=
      choose:
        when not($chunk-output-base-uri) castable as xs:anyURI:
          xsl:message(
              select="'Error: ' || $chunk-output-base-uri || ' is not valid as $chunk-output-base-uri.'")
        when true():
          <-- resolve-uri($chunk-output-base-uri, ext:cwd())
        when $v:chunk:
          <-- xs:anyURI($chunk-output-base-uri)
        else:
          <-- xs:anyURI($chunk-output-base-uri)
    if 'chunks' = $v:debug:
      xsl:message(select="'Chunk output base uri:', f:flatten-path($result)")
    <-- f:flatten-path($result)
  v:admonition-icons :=
    db:tip =
    db:note =
    db:important =
    db:caution =
    db:warning = 🛑
    db:danger =
  v:annotation-close as element() :=
    span =
  v:nominal-page-width := f:parse-length($nominal-page-width)
  v:image-nominal-width := f:parse-length($image-nominal-width)
  v:image-nominal-height := f:parse-length($image-nominal-height)
  v:toc-open as element() :=
    img(
        alt="[toc]",
        src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABYlAAAWJQFJUiTwAAABDklEQVQ4je2UUW3EMAyGv0wDUAhlkDBIyuAYXCEclEJoGZRBUgYOgzJoGHgPW6o7rWq35+2TIkWW9duW7N+oKuM46jiOGGMAaNsW5xzee5xzn8EvRESXZUFEWNcVAFWl73v6vjcGUIAYIyEEANZ1RUSY55lSCo/HA4BhGGiahtvthnOOtm0BSCnRdd1eVAGNMeoR27aptVattbpt22FOjFGrzjsX1I7q/4q3y4xf8i/4FwT3Pcw5Y4zBWvujfQMopZBzJuf8XbCeVyWEgHOO+/2+x0SEaZpIKSEih0X2Wz6jdlxKuezaqL7qpZS0lLKbw/M4ANba3RyapiGE8OJGqOrpizGq916999VATvM/AGFn1sxsVjL5AAAAAElFTkSuQmCC")
  v:toc-close as element() :=
    img(
        alt="X",
        src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAtklEQVQ4jaWT0Q3DIAxEz52AEbyB2cDZhBEY3SNcPyqqBEwqpZaQAHNP5jBCEiJCPAiSIgAeiUe8zoveO9x9e9jd0XtfKwHA1hpHtNY49rO8u59zn4mqMiJSyFkcEVTVFQCAtdYFMotrrXN111JnyA/xCsggN2JeXmGEmaGU8l2XUmBm29fZuh0RW2PTK2SGZcamADPb3nmGmNkKOI7j1rAzJG2kcWhqkstQ1QX+/2ciKU/FJOUN6JFZYWpmK3sAAAAASUVORK5CYII=")
  vp:pagetoc-elements as string* := tokenize($pagetoc-elements, '\s+')
  vp:olinkdb := false()
  v:olink-databases as element(h:targetdb)* :=
    if normalize-space($olink-databases) != '':
      foreach tokenize($olink-databases, ',\s*') ! normalize-space(.):
        db := resolve-uri(., static-base-uri())
        xsl:try
          olinkdb := doc($db)/h:targetdb
          if empty($olinkdb):
            xsl:message(select="'No targets in olinkdb:', $db")
          <-- $olinkdb
          xsl:catch
            xsl:message(select="'Failed to load olinkdb:', $db")
  v:theme-list as element()* :=
    theme(dark="true", id="materials-dark", name="Materials dark")
    theme(dark="false", id="materials-light", name="Materials light")
  vp:random-prefix as string :=
    chars := ('a','b','c','d','e','f','_','_','_','1','2','3','4','5','6')
    <-- string-join(random-number-generator()?permute($chars), '')
  vp:js-controls as element()* :=
    random := $vp:random-prefix
    span(class="controls-open") =
    div(class="js-controls-wrapper")
      if $v:theme-list[@dark='true']:
        @db-dark-theme
      div(class="js-controls-body")
        div(class="js-controls-header")
          div(class="js-controls-close") =
          div(class="js-controls-title")
            "Settings"
        div(class="js-controls-content")
          fieldset(class="js-controls-toggles", db-random="{$random}")
            legend = Select options:
            input(id="db-js-annotations_{$random}", type="checkbox", value="js")
            label(for="db-js-annotations_{$random}") = JavaScript annotations
            br
            input(id="db-js-xlinks_{$random}", type="checkbox", value="js")
            label(for="db-js-xlinks_{$random}") = JavaScript extended links
            br
          div(class="js-controls-reload", id="db-js-controls-reload_{$random}")
          fieldset
            legend = Choose a theme:
            input(id="db-default-theme_{$random}", name="db-theme", type="radio", value="default")
            label(for="db-default-theme_{$random}") = Default
            br
            foreach $v:theme-list:
              input(id="db-theme-{@id}-{$random}", name="db-theme", type="radio", value="{@id}")
              label(for="db-theme-{@id}-{$random}")
                <-- @name/string()
              br
        div(class="js-controls-buttons")
          button(id="js-controls-cancel") =
          button(id="js-controls-ok") =
  v:highlight-js-head-elements as element()* :=
    link(href="{fp:add-resource-base-uri('css/highlight-11.10.0.min.css')}", rel="stylesheet")
    script(src="{fp:add-resource-base-uri('js/highlight-11.10.0.min.js')}")
    choose:
      when f:is-true($verbatim-embellish-linenumbers):
        script(src="{fp:add-resource-base-uri('js/highlightjs-line-numbers-2.9.0.min.js')}")
        script = hljs.configure({languages:[]}); hljs.highlightAll(); hljs.initLineNumbersOnLoad();
      else:
        script = hljs.configure({languages:[]}); hljs.highlightAll();
  v:prism-js-head-elements as element()* :=
    link(href="{fp:add-resource-base-uri('css/prism.css')}", rel="stylesheet")
    script(src="{fp:add-resource-base-uri('js/prism.js')}")
  v:media-type-default as string := 'application/octet-stream'
  v:media-type-map as map(xs:string, xs:string) :=
    xsl:map
      xsl:map-entry(key="'.aac'", select="'audio/aac'")
      xsl:map-entry(key="'.abw'", select="'application/x-abiword'")
      xsl:map-entry(key="'.arc'", select="'application/x-freearc'")
      xsl:map-entry(key="'.avif'", select="'image/avif'")
      xsl:map-entry(key="'.avi'", select="'video/x-msvideo'")
      xsl:map-entry(key="'.azw'", select="'application/vnd.amazon.ebook'")
      xsl:map-entry(key="'.bin'", select="'application/octet-stream'")
      xsl:map-entry(key="'.bmp'", select="'image/bmp'")
      xsl:map-entry(key="'.bz'", select="'application/x-bzip'")
      xsl:map-entry(key="'.bz2'", select="'application/x-bzip2'")
      xsl:map-entry(key="'.cda'", select="'application/x-cdf'")
      xsl:map-entry(key="'.csh'", select="'application/x-csh'")
      xsl:map-entry(key="'.css'", select="'text/css'")
      xsl:map-entry(key="'.csv'", select="'text/csv'")
      xsl:map-entry(key="'.doc'", select="'application/msword'")
      xsl:map-entry(
          key="'.docx'",
          select="'application/vnd.openxmlformats-officedocument.wordprocessingml.document'")
      xsl:map-entry(key="'.eot'", select="'application/vnd.ms-fontobject'")
      xsl:map-entry(key="'.epub'", select="'application/epub+zip'")
      xsl:map-entry(key="'.gz'", select="'application/gzip'")
      xsl:map-entry(key="'.gif'", select="'image/gif'")
      xsl:map-entry(key="'.htm'", select="'text/html'")
      xsl:map-entry(key="'.html'", select="'text/html'")
      xsl:map-entry(key="'.ico'", select="'image/vnd.microsoft.icon'")
      xsl:map-entry(key="'.ics'", select="'text/calendar'")
      xsl:map-entry(key="'.jar'", select="'application/java-archive'")
      xsl:map-entry(key="'.jpeg'", select="'image/jpeg'")
      xsl:map-entry(key="'.jpg'", select="'image/jpeg'")
      xsl:map-entry(key="'.js'", select="'text/javascript'")
      xsl:map-entry(key="'.json'", select="'application/json'")
      xsl:map-entry(key="'.jsonld'", select="'application/ld+json'")
      xsl:map-entry(key="'.mid'", select="'audio/midi'")
      xsl:map-entry(key="'.midi'", select="'audio/midi'")
      xsl:map-entry(key="'.mjs'", select="'text/javascript'")
      xsl:map-entry(key="'.m3u8'", select="'application/x-mpegURL'")
      xsl:map-entry(key="'.mp3'", select="'audio/mpeg'")
      xsl:map-entry(key="'.mp4'", select="'video/mp4'")
      xsl:map-entry(key="'.mpeg'", select="'video/mpeg'")
      xsl:map-entry(key="'.mpkg'", select="'application/vnd.apple.installer+xml'")
      xsl:map-entry(key="'.mov'", select="'video/quicktime'")
      xsl:map-entry(key="'.odp'", select="'application/vnd.oasis.opendocument.presentation'")
      xsl:map-entry(key="'.ods'", select="'application/vnd.oasis.opendocument.spreadsheet'")
      xsl:map-entry(key="'.odt'", select="'application/vnd.oasis.opendocument.text'")
      xsl:map-entry(key="'.oga'", select="'audio/ogg'")
      xsl:map-entry(key="'.ogv'", select="'video/ogg'")
      xsl:map-entry(key="'.ogx'", select="'application/ogg'")
      xsl:map-entry(key="'.opus'", select="'audio/opus'")
      xsl:map-entry(key="'.otf'", select="'font/otf'")
      xsl:map-entry(key="'.png'", select="'image/png'")
      xsl:map-entry(key="'.pdf'", select="'application/pdf'")
      xsl:map-entry(key="'.php'", select="'application/x-httpd-php'")
      xsl:map-entry(key="'.ppt'", select="'application/vnd.ms-powerpoint'")
      xsl:map-entry(
          key="'.pptx'",
          select="'application/vnd.openxmlformats-officedocument.presentationml.presentation'")
      xsl:map-entry(key="'.rar'", select="'application/vnd.rar'")
      xsl:map-entry(key="'.rtf'", select="'application/rtf'")
      xsl:map-entry(key="'.sh'", select="'application/x-sh'")
      xsl:map-entry(key="'.svg'", select="'image/svg'")
      xsl:map-entry(key="'.tar'", select="'application/x-tar'")
      xsl:map-entry(key="'.tif'", select="'image/tiff'")
      xsl:map-entry(key="'.tiff'", select="'image/tiff'")
      xsl:map-entry(key="'.ts'", select="'video/mp2t'")
      xsl:map-entry(key="'.ttf'", select="'font/ttf'")
      xsl:map-entry(key="'.txt'", select="'text/plain'")
      xsl:map-entry(key="'.text'", select="'text/plain'")
      xsl:map-entry(key="'.vsd'", select="'application/vnd.visio'")
      xsl:map-entry(key="'.wav'", select="'audio/wav'")
      xsl:map-entry(key="'.weba'", select="'audio/webm'")
      xsl:map-entry(key="'.webm'", select="'video/webm'")
      xsl:map-entry(key="'.webp'", select="'image/webp'")
      xsl:map-entry(key="'.wmv'", select="'video/x-ms-wmv'")
      xsl:map-entry(key="'.woff'", select="'font/woff'")
      xsl:map-entry(key="'.woff2'", select="'font/woff2'")
      xsl:map-entry(key="'.xhtml'", select="'application/xhtml+xml'")
      xsl:map-entry(key="'.xls'", select="'application/vnd.ms-excel'")
      xsl:map-entry(
          key="'.xlsx'",
          select="'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'")
      xsl:map-entry(key="'.xml'", select="'application/xml'")
      xsl:map-entry(key="'.xul'", select="'application/vnd.mozilla.xul+xml'")
      xsl:map-entry(key="'.zip'", select="'application/zip'")
      xsl:map-entry(key="'.7z'", select="'application/x-7z-compressed'")