Creating a simple DITA Open Toolkit plugin to customize published HTML and PDF content
I recently worked on a DITA Open Toolkit plugin which can be used to provide syntax highlight when publishing DITA codeblock elements to HTML-based or PDF outputs.
- Create a folder for your plugin in the DITA OT plugins folder. The DITA OT bundled with Oxygen can be found here: OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT. In my case I created the following folder: OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT/plugins/com.oxygenxml.highlight.
- Create a plugin.xml file in that folder containing the plugin's extension
points. In my case, the plugin descriptor file contains:
The important extensions in it are the references to the XSLT stylesheets which will be used to style the HTML and the PDF outputs. You can find a bunch of other DITA OT plugin extension points here:https://www.dita-ot.org/dev/extension-points/plugin-extension-points.html.<plugin id="com.oxygenxml.highlight"> <feature extension="package.support.name" value="Oxygen XML Editor Support"/> <feature extension="package.support.email" value="support@oxygenxml.com"/> <feature extension="package.version" value="1.0.0"/> <feature extension="dita.xsl.xhtml" value="xhtmlHighlight.xsl" type="file"/> <feature extension="dita.xsl.xslfo" value="pdfHighlight.xsl" type="file"/> </plugin>
- Create an XSLT stylesheet called xhtmlHighlight.xsl located in the same
plugin folder. As I want to overwrite the creation of the HTML content from a
DITA codeblock element I will first need to find the XSLT template that I
need to overwrite. A DITA codeblock element has the class
attribute value "+ topic/pre pr-d/codeblock ". Usually in such cases I
take part of the class attribute value and search using the "Find/Replace in
Files" Oxygen action in all of the DITA OT XSLT resources. In this case
I searched for topic/preand found this XSLT
stylesheet:OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT/plugins/org.dita.xhtml/xsl/xslhtml/dita2htmlImpl.xsl
containing this XSLT
template:
thus my xhtmlHighlight.xsl will overwrite the content of the template like:<xsl:template match="*[contains(@class, ' topic/pre ')]" name="topic.pre"> <xsl:if test="contains(@frame, 'top')"><hr /></xsl:if> <xsl:apply-templates select="*[contains(@class, ' ditaot-d/ditaval-startprop ')]" mode="out-of-line"/> <xsl:call-template name="spec-title-nospace"/> <pre> <xsl:attribute name="class" select="name()"/> <xsl:call-template name="commonattributes"/> <xsl:call-template name="setscale"/> <xsl:call-template name="setidaname"/> <xsl:apply-templates/> </pre> <xsl:apply-templates select="*[contains(@class, ' ditaot-d/ditaval-endprop ')]" mode="out-of-line"/> <xsl:if test="contains(@frame, 'bot')"><hr /></xsl:if><xsl:value-of select="$newline"/> </xsl:template>
and call another XSLT template which applies as a Java extension the XSLTHL library to style the content.<xsl:template match="*[contains(@class, ' topic/pre ')]" name="topic.pre"> <xsl:if test="contains(@frame, 'top')"><hr /></xsl:if> <xsl:apply-templates select="*[contains(@class, ' ditaot-d/ditaval-startprop ')]" mode="out-of-line"/> <xsl:call-template name="spec-title-nospace"/> <pre> <xsl:attribute name="class" select="name()"/> <xsl:call-template name="commonattributes"/> <xsl:call-template name="setscale"/> <xsl:call-template name="setidaname"/> <!--Here I'm calling the styler of the content inside the codeblock.--> <xsl:call-template name="outputStyling"/> </pre> <xsl:apply-templates select="*[contains(@class, ' ditaot-d/ditaval-endprop ')]" mode="out-of-line"/> <xsl:if test="contains(@frame, 'bot')"><hr /></xsl:if><xsl:value-of select="$newline"/> </xsl:template>
- Create an XSLT stylesheet called pdfHighlight.xsl located in the same
plugin folder which will contain the PDF XSLT customization. In this case I will
overwrite the XSLT template
from:OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT/plugins/org.dita.pdf2/xsl/fo/topic.xsl
which has the
content:
<xsl:template match="*[contains(@class,' topic/pre ')]"> <xsl:call-template name="setSpecTitle"/> <fo:block xsl:use-attribute-sets="pre"> <xsl:call-template name="commonattributes"/> <xsl:call-template name="setFrame"/> <xsl:call-template name="setScale"/> <xsl:call-template name="setExpanse"/> <xsl:apply-templates/> </fo:block> </xsl:template>
-
In order to install your plugin in the DITA OT you need to run the integrator. In the Oxygen Transformation Scenarios view there is a Show all scenarios action available in the drop down settings button. Just check that and execute the transformation scenario called Run DITA OT Integrator. And that's it, your XSLT content will be applied with priority when publishing both to XHTML-based and to PDF-based outputs.
Let's take now a look at what that misterious step (5) - running the integrator to install the plugin - really did:- In the XSLT
stylesheet:OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT/plugins/org.dita.xhtml/xsl/dita2html-base.xsl
a new import automatically
appeared:
This import is placed after all base imports and because of this it has a higher priority. More about imported template precedence can be found in the XSLT specs:http://www.w3.org/TR/xslt#import.<xsl:import href="plugin:com.oxygenxml.highlight:xhtmlHighlight.xsl"/>
- Likewise, in the top-level stylesheets related to PDF publishing
like:OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT/plugins/org.dita.pdf2/xsl/fo/topic2fo_shell.xsl
a new import statement has
appeared:
<xsl:import href="plugin:com.oxygenxml.highlight:pdfHighlight.xsl"/>
This video from the DITA OT Day 2018 in Rotterdam has also steps for implementing a simple DITA OT plugin: https://www.oxygenxml.com/events/2018/dita-ot_day.html#step_by_step_implementation_of_a_DITA.
- In the XSLT
stylesheet:OXYGEN_INSTALL_DIR/frameworks/dita/DITA-OT/plugins/org.dita.xhtml/xsl/dita2html-base.xsl
a new import automatically
appeared: