Edit online

Convert Code Templates to External Author Actions

Contributed by: Alex Jitianu on 26 May 2021

Describes how to bring code templates into a framework as author actions.

Code templates are code fragments that can be inserted quickly at the current editing position. Author actions that are available in the Author mode offer a lot more flexibility. For example, you can decide what fragment to insert based on the current context. If you want to create a new framework or customize an existing framework, then it makes sense to convert code templates to author actions. You can then contribute them to the content completion window. You can also define the framework using a Framework extension script.
  1. Create a framework or extend an existing framework using a Framework extension script.
  2. Go to Options > Preferences > Code Templates and Export the code templates to a file named code-templates.xml.
  3. Create an XSLT file with the following content:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="3.0">
        <xsl:output method="xml"/>
        <xsl:template match="//codeTemplateItem[field[@name='contentType']/String/text() = 'text/xml']">
            <xsl:variable name="actionName" select="field[@name='renderString']/String/text()"/>
            <xsl:result-document href="externalAuthorActions/{$actionName}.xml">
                <a:authorAction xmlns:a="http://www.oxygenxml.com/ns/author/external-action"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://www.oxygenxml.com/ns/author/external-action http://www.oxygenxml.com/ns/author/external-action/authorAction.xsd"
                    id="{$actionName}">
                    <a:name><xsl:value-of select="$actionName"/></a:name>
                    <a:description><xsl:value-of select="field[@name='descriptionString']/String/text()"/></a:description>
                    <a:operations>
                        <a:operation id="InsertFragmentOperation">
                            <a:xpathCondition>true()</a:xpathCondition>
                            <a:arguments>
                                <a:argument name="fragment">
                                    <!-- Try parsing the fragment. if it succeeds, we basically unwrap it from the CDATA. -->
                                    <xsl:try
                                        select="parse-xml-fragment(field[@name='unparsedInsertString']/String/text())">
                                        <xsl:catch>
                                            <!-- Parsing failed. It might have unresolved entities. Keep it in a CDATA. -->
                                            <xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
                                            <xsl:value-of disable-output-escaping="true" select="field[@name='unparsedInsertString']/String/text()" ></xsl:value-of>
                                            <xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
                                        </xsl:catch>
                                    </xsl:try>
                                </a:argument>
                            </a:arguments>
                        </a:operation>
                    </a:operations>
                    <a:accessKey/>
                </a:authorAction>
            </xsl:result-document>
        </xsl:template>
        
        <xsl:template match="text()"/>
    </xsl:stylesheet>
  4. Create an XSLT Transformation scenario and apply the XSLT over the code-templates.xml file.
  5. Go to the directory of code-templates.xml and copy the generated externalAuthorActions to the framework directory (the directory with the framework extension script).
  6. Create another XSLT with the following content, then create an XSLT Transformation scenario and apply it over the code-templates.xml file.
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="3.0">
        <xsl:output method="xml" omit-xml-declaration="yes" indent="true"></xsl:output>
        <xsl:output method="xml"/>
        <xsl:template match="/">
            <contentCompletion>
                <authorActions>
                    <xsl:apply-templates/>
                </authorActions>
            </contentCompletion>
        </xsl:template>
        <xsl:template match="//codeTemplateItem[field[@name='contentType']/String/text() = 'text/xml']">
            <xsl:variable name="actionName" select="field[@name='renderString']/String/text()"/>
            
            <addAction id="{$actionName}" inCCWindow="true"/> 
        </xsl:template>
        
        <xsl:template match="text()"/>
    </xsl:stylesheet>
  7. Copy the resulting <contentCompletion> into the Framework extension script root element.
There is a new external author action for each initial code template. All actions are contributed to the content completion window.