blob: 65391dae060847c0c6e2f82238f353646cb650b9 [file] [log] [blame]
<#ftl nsPrefixes={"D":"http://docbook.org/ns/docbook"}>
<#import "util.ftl" as u>
<#-- Constants: -->
<#assign forProgrammersCss = "programmers-note">
<#-- State variables: -->
<#assign
inHtmlP = false, compactPara = false,
disableAnchors = false, postponedAnchor = [],
inlineMonospacedColorisation=false
>
<#assign footnotes = []>
<#macro @text>${.node}</#macro>
<#macro @element>
<#stop "This DocBook element is not supported by the Docgen transformer, "
+ "or wasn't expected where it occured: "
+ .node?nodeName>
</#macro>
<#-- Attention: Must not produce any white-space! -->
<#macro Anchor node=.node>
<#if !disableAnchors>
<#if postponedAnchor?hasContent>
<#local pa = postponedAnchor>
<#assign postponedAnchor=[]>
<@Anchor pa /><#t>
</#if>
<#if node.@id[0]??>
<a name="${node.@id}"></a><#t>
</#if>
</#if>
</#macro>
<#macro anchor>
<@Anchor/>
</#macro>
<#macro answer>
<dd class="answer">
<#recurse>
</dd>
</#macro>
<#macro emphasis>
<#local role=.node.@role[0]!"none">
<#if role = "term" || role = "bold" || .node?ancestors("programlisting")?hasContent>
<strong><#recurse></strong><#t>
<#else>
<em><#recurse></em><#t>
</#if>
</#macro>
<#macro glossentry><#recurse></#macro>
<#macro glossdef>
<dd><#recurse>
<#local seealsos=.node.glossseealso>
<#if seealsos?hasContent>
<p>See Also
<#list seealsos as also>
<#local otherTermID=also.@otherterm>
<#local otherNode=NodeFromID(otherTermID)>
<#local term=otherNode.glossterm>
<a href="${CreateLinkFromID(also.@otherterm)}">${term}</a><#sep>,</#sep>
</#list>
</p>
</#if>
</dd>
</#macro>
<#macro glosssee>
<dd>See
<#local otherTermID=.node.@otherterm>
<#local otherNode=NodeFromID(otherTermID)>
<#local term=otherNode.glossterm>
<a href="${CreateLinkFromID(otherTermID)}">${term}</a>
</dd>
</#macro>
<#macro glossseealso>
<#-- This is dealt with in the glossdef routine -->
</#macro>
<#macro glossterm>
<dt><@Anchor .node?parent/><#recurse></dt>
</#macro>
<#macro indexterm>
<@Anchor/>
</#macro>
<#macro itemizedlist>
<#local packed=.node.@spacing[0]! = "compact">
<#local prevCompactPara=compactPara>
<#if packed>
<#assign compactPara = true>
</#if>
<@CantBeNestedIntoP>
<@Anchor/>
<#local mark=.node.@mark[0]!>
<#if mark = "bullet">
<ul type="disc"><#t>
<#elseIf mark = "box">
<ul type="square"><#t>
<#elseIf mark = "ring">
<ul type="circle"><#t>
<#elseIf mark = "">
<ul><#t>
<#else>
<ul type="${mark}"><#t>
</#if>
<#recurse>
</ul><#t>
</@CantBeNestedIntoP>
<#assign compactPara = prevCompactPara>
</#macro>
<#macro link>
<#if .node.@linkend?hasContent>
<a href="${CreateLinkFromID(.node.@linkend)}"><#recurse></a><#t>
<#else>
<a href="${.node["@xlink:href"]}"><#recurse></a><#t>
</#if>
</#macro>
<#macro listitem>
<#local mark=.node?parent.@mark[0]!>
<#if mark != "">
<li style="list-style-type: ${mark}"><#t>
<#else>
<li><#t>
</#if>
<#if .node.para?hasContent>
<#-- Because with <li><a ...></a><p>...</p></li> we had a visual empty line before the p. -->
<#assign postponedAnchor = .node>
<#else>
<@Anchor/>
</#if>
<#recurse>
</li><#t>
</#macro>
<#macro _inlineMonospaced>
<#local moreStyle="" color="#A03D10">
<#if .node?ancestors("link")?hasContent>
<#-- If we are within a link, we don't change color, just use the regular link color -->
<code><#recurse></code><#t>
<#else>
<#if fontBgColor! != "">
<#local moreStyle = "; background-color:${fontBgColor}">
</#if>
<#-- @todo: convert 'moreStyle' to class names -->
<code class="inline-code"<#if moreStyle?hasContent> style="${moreStyle}"</#if>><#t>
<#local saved_inlineMonospacedColorisation = inlineMonospacedColorisation>
<#assign inlineMonospacedColorisation = true>
<#recurse><#t>
<#assign inlineMonospacedColorisation = saved_inlineMonospacedColorisation>
</code><#t>
</#if>
</#macro>
<#assign classname = _inlineMonospaced>
<#assign code = _inlineMonospaced>
<#assign command=_inlineMonospaced>
<#assign constant = _inlineMonospaced>
<#assign envar = _inlineMonospaced>
<#assign errorcode = _inlineMonospaced>
<#assign errorname = _inlineMonospaced>
<#assign errortext = _inlineMonospaced>
<#assign errortype = _inlineMonospaced>
<#assign exceptionname = _inlineMonospaced>
<#assign filename = _inlineMonospaced>
<#assign function = _inlineMonospaced>
<#assign interfacename = _inlineMonospaced>
<#assign literal = _inlineMonospaced>
<#assign markup = _inlineMonospaced>
<#assign methodname = _inlineMonospaced>
<#assign package = _inlineMonospaced>
<#assign parameter = _inlineMonospaced>
<#assign prompt = _inlineMonospaced>
<#assign property = _inlineMonospaced>
<#assign returnvalue = _inlineMonospaced>
<#assign sgmltag = _inlineMonospaced>
<#assign structfield = _inlineMonospaced>
<#assign structname = _inlineMonospaced>
<#assign symbol = _inlineMonospaced>
<#assign token = _inlineMonospaced>
<#assign type = _inlineMonospaced>
<#assign uri = _inlineMonospaced>
<#assign varname = _inlineMonospaced>
<#macro note>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<#recurse>
</div>
</#macro>
<#macro warning>
<div class="callout warning">
<strong class="callout-label">Warning!</strong>
<#recurse>
</div>
</#macro>
<#macro olink>
<#if !(olinks[.node.@targetdoc]??)>
<#stop "The olink element refers to an unknown targetdoc: \""
+ .node.@targetdoc?jsString
+ "\". Ensure this target is defined in the docgen.cfg file.">
</#if>
<a href="${olinks[.node.@targetdoc]}"><#recurse></a><#t>
</#macro>
<#macro orderedlist>
<#local packed=(.node.@spacing[0]! = "compact")>
<#local prevCompactPara=compactPara>
<#if packed>
<#assign compactPara = true>
</#if>
<@CantBeNestedIntoP>
<div class="orderedlist"><@Anchor/><ol type="1"><#recurse></ol></div><#t>
</@CantBeNestedIntoP>
<#assign compactPara = prevCompactPara>
</#macro>
<#macro para>
<#if .node.@role[0]! = "forProgrammers">
<#local cssClass = forProgrammersCss>
<#else>
<#local cssClass = "">
</#if>
<#if compactPara!>
<#if cssClass?hasContent>
<span<#if cssClass?hasContent> class="${cssClass}"</#if>><#t>
</#if>
<@Anchor /><#t>
<#recurse>
<#if cssClass?hasContent>
</span><#t>
</#if>
<#else>
<#assign inHtmlP = true>
<p<#if cssClass?hasContent> class="${cssClass}"</#if>><#t>
<#local content><@Anchor /><#recurse></#local><#t>
<#-- Avoid empty p element when closing para directly after orderedlist or itemizedlist. -->
<#if !content?markupString?matches(r".*<p>\s*$", "s")>
${content}</p><#t>
<#else>
${content?markupString[0 ..< content?lastIndexOf("<p>")]?noEsc}<#t>
</#if>
<#assign inHtmlP = false>
</#if>
</#macro>
<#macro CantBeNestedIntoP>
<#if inHtmlP>
</p><#t>
<#assign inHtmlP = false>
<#nested>
<p><#t>
<#assign inHtmlP = true>
<#else>
<#nested>
</#if>
</#macro>
<#function convertRoleClass role>
<#switch role>
<#case "markedComment">
<#return "marked-comment">
<#break>
<#case "markedTemplate">
<#return "marked-template">
<#break>
<#case "markedDataModel">
<#return "marked-data-model">
<#break>
<#case "markedOutput">
<#return "marked-output">
<#break>
<#case "markedText">
<#return "marked-text">
<#break>
<#case "markedInterpolation">
<#return "marked-interpolation">
<#break>
<#case "markedFTLTag">
<#return "marked-ftl-tag">
<#break>
<#case "markedInvisibleText">
<#return "marked-invisible-text">
<#break>
<#case "forProgrammers">
<#return "marked-for-programmers">
<#break>
</#switch>
</#function>
<#macro phrase>
<#local lastFontBgColor = fontBgColor!>
<#local moreStyle = "">
<#local role = .node.@role[0]!>
<#local bgcolors = {
"markedComment": "#6af666",
"markedTemplate": "#D8D8D8",
"markedDataModel": "#99CCFF",
"markedOutput" : "#CCFFCC",
"markedText" : "#8acbfa",
"markedInterpolation" : "#ffb85d",
"markedFTLTag" : "#dbfe5e"
}>
<#if role != "">
<#if role = "homepage">
http://freemarker.org<#t>
<#elseIf role = "markedInvisibleText">
<#if fontBgColor! != "">
<#local moreStyle = "; background-color:${fontBgColor}">
</#if>
<em><span class="${convertRoleClass(role)}"><#recurse></span></em><#t>
<#else>
<span class="${convertRoleClass(role)}"><#recurse></span><#t>
</#if>
</#if>
</#macro>
<#macro programlisting>
<#local role=.node.@role[0]!?string>
<#local dotidx=role?indexOf(".")>
<#if dotidx != -1>
<#local role = role[0..dotidx-1]>
</#if>
<#switch role>
<#case "output">
<#local codeType = "code-output">
<#break>
<#case "dataModel">
<#local codeType = "code-data-model">
<#break>
<#case "template">
<#local codeType = "code-template">
<#break>
<#case "unspecified">
<#local codeType = "code-unspecified">
<#break>
<#case "metaTemplate">
<pre class="metaTemplate"><#t>
<#recurse>
</pre><#lt>
<#return>
<#default>
<#local codeType = "code-default">
</#switch>
<@CantBeNestedIntoP>
<div class="code-wrapper"><#t>
<pre class="code-block ${codeType}"><@Anchor/><#t><#-- XXE and usual FO-stylesheet-compatible interpretation of inital line-breaks -->
<#local content><#recurse></#local><#t>
${content?markupString?chopLinebreak?noEsc}</pre></div><#t>
</@CantBeNestedIntoP>
</#macro>
<#macro qandaset>
<div class="qandaset">
<#local prevCompactPara=compactPara!>
<#assign compactPara = true>
<#assign qaIndex = 1>
<#-- @todo: remove table, fix spacing -->
<ol>
<#list .node.qandaentry as qandaentry>
<li>
<#local prevdisableAnchors=disableAnchors!>
<#assign disableAnchors = true>
<a href="#${qandaentry.@id[0]!("faq_question_" + qaIndex)}">
<#recurse qandaentry.question>
</a>
<#assign disableAnchors = prevdisableAnchors>
<#assign qaIndex++>
</li>
</#list>
</ol>
<#assign compactPara = prevCompactPara>
<#assign qaIndex = 1>
<dl>
<#recurse>
</dl>
</div>
</#macro>
<#macro question>
<#local prevCompactPara=compactPara!>
<#assign compactPara = true>
<#local nodeParent = .node?parent>
<#if nodeParent.@id[0]??>
<#local questionId = nodeParent.@id />
</#if>
<dt class="question" id="${questionId!''}">
${qaIndex}.&nbsp; <#recurse>
</dt>
<#assign qaIndex++>
<#assign compactPara = prevCompactPara>
</#macro>
<#macro qandaentry><#recurse></#macro>
<#macro remark>
<#if showEditoralNotes>
<p style="background-color:#FFFF00">[<#recurse>]</p><#t>
</#if>
</#macro>
<#macro replaceable>
<#local moreStyle="">
<#if inlineMonospacedColorisation>
<#if fontBgColor! != "">
<#local moreStyle = "; background-color:${fontBgColor}">
</#if>
<#-- @todo: check if class name is necessary. probably able to cascade under .inline-code -->
<em class="code-color"<#if moreStyle?hasContent> style="${moreStyle}"</#if>><#recurse></em><#t>
<#else>
<em><#recurse></em><#t>
</#if>
</#macro>
<#macro subtitle>
<#-- We do nothing here because this is dealt with in the title macro -->
</#macro>
<#macro sectionLikeElement>
<#recurse>
</#macro>
<#assign article = sectionLikeElement>
<#assign part = sectionLikeElement>
<#assign chapter = sectionLikeElement>
<#assign appendix = sectionLikeElement>
<#assign preface = sectionLikeElement>
<#assign section = sectionLikeElement>
<#assign simplesect = sectionLikeElement>
<#macro index>
<#-- ABC links -->
<#local lastLetter = "">
<p>
<#list indexEntries as key>
<#local letter = key[0]?upperCase>
<#if lastLetter != letter>
<#if lastLetter != "">&nbsp;| </#if><a href="#${index_safeID(letter)}">${letter}</a><#t>
<#local lastLetter = letter>
</#if>
</#list>
</p>
<#-- Index list -->
<#local lastLetter = "">
<#list indexEntries as key>
<#local letter = key[0]?upperCase>
<#if letter != lastLetter>
<#if lastLetter != "">
</dl></div><#lt>
</#if>
<div class="indexdiv"><#lt>
<a name="${index_safeID(letter)}"></a><#lt>
<h2 class="indexLabel">${letter}</h2><#lt>
<dl><#lt>
<#local lastLetter = letter>
</#if>
<#local entryNodes = primaryIndexTermLookup[key]>
<dt>
${key}<#if entryNodes?hasContent>,&nbsp;&nbsp;</#if><#rt>
<#list entryNodes as entryNode>
<a href="${CreateLinkFromNode(entryNode)}"><#t><@index_entryText entryNode/></a><#t>
<#sep>,</#sep><#lt>
</#list>
</dt>
<#if secondaryIndexTermLookup[key]?hasContent>
<#local secondaryTerms = secondaryIndexTermLookup[key]>
<dd><dl>
<#list secondaryTerms?keys?sort as secondary>
<dt><#rt>
${secondary}, <#t>
<#list secondaryTerms[secondary] as secondaryNode>
<a href="${CreateLinkFromNode(secondaryNode)}"><#t>
<@index_entryText secondaryNode/><#t>
</a><#sep>, </#sep><#t>
</#list>
</dt><#lt>
</#list>
</dl></dd>
</#if>
<#if key?isLast>
</dl></div><#lt>
</#if>
</#list>
</#macro>
<#macro index_entryText node>
<#list 1..100 as i>
<#if node?nodeType != "element">
entry<#t>
<#return>
</#if>
<#if node.title?hasContent>
<#local title=node.title>
<#if !node.@id[0]!?startsWith("autoid_")>
${title?trim}<#t>
<#return>
</#if>
</#if>
<#local node = node?parent>
</#list>
No title<#t>
</#macro>
<#function index_safeID id>
<#return "idx_" + id?url('UTF-8')?replace('%', "x")?replace('+', "_")>
</#function>
<#macro glossary>
<#local ges = .node.glossentry?sortBy("glossterm")>
<#-- Print alphabetical index links: -->
<#local lgtl = "">
<p>
<#list ges as ge>
<#local fullgt = ge.glossterm>
<#if fullgt?size != 0>
<#local gtl = fullgt.@@text[0]?upperCase>
<#if gtl != lgtl>
<#if lgtl != "">&nbsp;| </#if><a href="#${ge.@id}">${gtl}</a><#t>
<#local lgtl = gtl>
</#if>
</#if>
</#list>
</p>
<#-- Print glossentry-es: -->
<dl>
<#list ges as ge>
<#visit ge using nodeHandlers>
</#list>
</dl>
</#macro>
<#assign partintro = simplesect>
<#macro title>
<#local hierarElem = .node?parent>
<#if hierarElem?nodeName == "info">
<#local hierarElem = hierarElem?parent>
</#if>
<#local type = hierarElem?nodeName>
<#local titleInitial = u.getTitlePrefix(hierarElem, false, true)>
<#-- Calculate htmlHLevel: ToC-deeph compared to the enclosing file-element -->
<#local htmlHLevel = 1>
<#local cur = hierarElem>
<#list 1..100000 as _>
<#if cur.@docgen_file_element?size != 0>
<#break>
</#if>
<#if cur.@docgen_rank?size != 0>
<#local htmlHLevel++>
</#if>
<#local cur = cur?parent>
</#list>
<#-- HTML only defines h-s up to h6 -->
<#if htmlHLevel <= 6>
<#local htmlHElem = "h${htmlHLevel}">
<#else>
<#local htmlHElem = "p">
</#if>
<#local classAtt = "">
<${htmlHElem} class="content-header header-${hierarElem.@docgen_rank}" <#if !disableAnchors && hierarElem.@id[0]??>id="${hierarElem.@id[0]}"</#if><#t>
<#if htmlHLevel == 1> itemprop="headline"</#if>><#t>
<#recurse><#t>
<#local subtitleElem = u.getOptionalSubtitleElement(hierarElem)>
<#if subtitleElem?hasContent>
<span class="subtitle"><#recurse subtitleElem></span>
</#if>
<#local prodNameElem = .node?parent.productname>
<#if prodNameElem?hasContent>
<span class="subtitle productname">For <#recurse prodNameElem></span>
</#if>
</${htmlHElem}><#lt>
</#macro>
<#macro subtitle>
<#-- Handled by "title" macro -->
</#macro>
<#macro ulink>
<a href="${.node.@url}"><#recurse></a><#t>
</#macro>
<#macro xref>
<#local xrefID=.node.@linkend>
<#local targetNode = NodeFromID(xrefID)>
<#local targetLink = CreateLinkFromID(xrefID)>
<#local label = targetNode.@xreflabel[0]!>
<#if label?hasContent>
<a href="${targetLink}">${label}</a><#t>
<#else>
<#local labelHTMLs = buildTitleHTMLChain(targetNode)>
<#if labelHTMLs?size == 0>
<#stop "\"xref\" target element with xml:id \"" + targetNode.@id
+ "\" has no \"title\" element in it nor \"xreflabel\" attribute.">
</#if>
<#local ctxLabelHTMLs = buildTitleHTMLChain(.node, true)>
<a href="${targetLink}"><#t>
<#local started = false>
<#list labelHTMLs as labelHTML>
<#if started || !(
labelHTML?hasNext
&& ctxLabelHTMLs[labelHTML?index]??
&& labelHTML?markupString == ctxLabelHTMLs[labelHTML?index]?markupString
)
>
${labelHTML?noEsc}<#sep>/</#sep><#t>
<#local started = true>
</#if>
</#list>
</a><#t>
</#if>
</#macro>
<#function buildTitleHTMLChain targetNode allowFallback=false>
<#local result = []>
<#list 1..1000000 as _>
<#if targetNode.@docgen_root_element?size != 0><#break></#if>
<#local title = u.getOptionalTitleElement(targetNode)>
<#if title?hasContent>
<#local titleHTML><#recurse title></#local>
<#local result = [titleHTML] + result>
<#local allowFallback = true>
<#elseIf !allowFallback>
<#break>
</#if>
<#local targetNode = targetNode?parent>
</#list>
<#return result>
</#function>
<#macro quote>"<#recurse>"</#macro>
<#macro footnote>
${' '}[<a href="#autoid_footnote_${footnotes?size + 1}">${footnotes?size + 1}</a>]${' '}<#t>
<#local capturedContent><#recurse></#local><#t>
<#assign footnotes += [capturedContent]>
</#macro>
<#macro informaltable>
<@Anchor/>
<div class="table-responsive">
<table class="table">
<#recurse>
</table>
</div>
</#macro>
<#-- Re-prints the original tag as is, but restricts the allowed attributes -->
<#macro _HTMLTableElement supportedAtts empty=false>
<#if !supportedAtts??><#stop 'XXX ' + .node?nodeName></#if>
<${.node?nodeName}<#t>
<#list .node.@@ as att>
<#if supportedAtts[att?nodeName]??>
${' '}${att?nodeName}="${att}"<#t>
<#else>
<#stop 'Unimplemented attribute for "${.node?nodeName}": ' + att?nodeName>
</#if>
</#list>
><#t>
<#if !empty>
<#recurse><#t>
</${.node?nodeName}><#t>
</#if>
${'\n'}<#t>
</#macro>
<#assign htmlAlignAtts = {"align":true, "valign":true}>
<#macro tr><@_HTMLTableElement htmlAlignAtts /></#macro>
<#macro td><@_HTMLTableElement htmlAlignAtts + {"colspan":true, "rowspan":true} /></#macro>
<#assign th = td>
<#macro thead><@_HTMLTableElement htmlAlignAtts /></#macro>
<#assign tbody = thead>
<#assign tfoot = thead>
<#macro colgroup>
<#-- This element should be resolved and deleted from the DOM before we get here -->
<#stop 'This element is only supported directly inside tables.'>
</#macro>
<#macro col>
<#-- This element should be resolved and deleted from the DOM before we get here -->
<#stop 'This element is only supported directly inside a "colgroup".'>
</#macro>
<#macro mediaobject>
<#list .node.* as imageobject>
<#if imageobject?nodeName == "imageobject">
<#list imageobject.* as imagedata>
<#if imagedata?nodeName == "imagedata">
<p class="center-img"><@Anchor /><#t>
<#local src = imagedata.@fileref>
<img src="${src}" alt="Figure"<#rt>
<#if src?endsWith(".svg")> onerror="this.src=&quot;${src?keepBeforeLast('.') + '.png'}&quot;; this.onerror=null;"</#if><#t>
><#t>
</p>
<#else>
<#stop "Unexpected element when \"imagedata\" was expected: "
+ imagedata?nodeName>
</#if>
</#list>
<#else>
<#stop "Unexpected element when \"imageobject\" was expected: "
+ imageobject?nodeName>
</#if>
</#list>
</#macro>
<#macro anyNonVisual><#recurse></#macro>
<#assign info=anyNonVisual titleabbrev=anyNonVisual productname=anyNonVisual productnumber=anyNonVisual>