How to Intercept Confluence Content Before it’s Rendered
Daniel was a bored Atlassian Confluence Administrator. So he hatched up a prank on April fool’s day. He was going to intercept Confluence content before it’s rendered. He was going to intercept all Loremipsum macros and make it an unknown macro. Here’s how he did it.
1. Tools
Daniel used the following tools:
2. Create the Plug-in
Daniel ran the atlas-create-confluence-plugin
command in his terminal. He typed com.javacodegeeks.example
when he was prompted for a groupId. For his artifactId, he placed content-transformer
. In the version and package prompts, he just pressed ENTER to accept the defaults. Finally, he pressed Y to accept everything inputted.
3. Modify the Files
Daniel deleted some of the unnecessary files that were generated. His content-transformer directory contained the following files:
pom.xml
README
LICENSE
- Under “src/main/resources” –
atlassian-plugin.xml
,content-transformer.properties
, css folder, images folder, js folder, and META-INF folder (all folders contained their default files) - Under “src/main/java” –
com.javacodegeeks.example
package and under itMacroTransformer.java
He then executed atlas-mvn eclipse:eclipse
to create .classpath and .project so that he will be able to import his Maven project into Eclipse.
4. Add the Logic
Daniel’s MacroTransformer
class intercepts the storage format and looks for the loremipsum macro and replaces it with an incorrect spelling then passes it to the view. This in effect makes it an unknown macro. His code looks like this:
MacroTransformer.java
package com.javacodegeeks.example; import java.io.IOException; import java.io.Reader; import java.io.StringWriter; import org.apache.commons.io.IOUtils; import com.atlassian.confluence.content.render.xhtml.ConversionContext; import com.atlassian.confluence.content.render.xhtml.XhtmlException; import com.atlassian.confluence.content.render.xhtml.transformers.Transformer; public class MacroTransformer implements Transformer { @Override public String transform(Reader reader, ConversionContext context) throws XhtmlException { String input = readerToString(reader); if (input != null) { return input.replaceAll("loremipsum", "loremepsum"); } return input; } private String readerToString(Reader reader) { StringWriter outputWriter = new StringWriter(); try { reader.reset(); IOUtils.copy(reader, outputWriter); } catch (IOException e) { return null; } return outputWriter.toString(); } }
5. Add the Transformer Module in the Add-on Descriptor
Daniel then added the <transformer>
tag in the plug-in descriptor just before the <atlassian-plugin>
closing tag. The chain attribute can have one of three values, depending on which pipeline you want to intercept:
- storageToView
- storageToEditor
- editorToStorage
The weight attribute indicates what order the transformer will be invoked. A lower weighting gets processed before a higher weighting. The default transformer has a weighting of “0”. His add-on descriptor looks like this:
atlassian-plugin.xml
<atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2"> <plugin-info> <description>${project.description}</description> <version>${project.version}</version> <vendor name="${project.organization.name}" url="${project.organization.url}" /> <param name="plugin-icon">images/pluginIcon.png</param> <param name="plugin-logo">images/pluginLogo.png</param> </plugin-info> <!-- add our i18n resource --> <resource type="i18n" name="i18n" location="content-transformer"/> <!-- add our web resources --> <web-resource key="content-transformer-resources" name="content-transformer Web Resources"> <dependency>com.atlassian.auiplugin:ajs</dependency> <resource type="download" name="content-transformer.css" location="/css/content-transformer.css"/> <resource type="download" name="content-transformer.js" location="/js/content-transformer.js"/> <resource type="download" name="images/" location="/images"/> <context>content-transformer</context> </web-resource> <transformer key="macro-transformer" name="Macro Transformer" class="com.javacodegeeks.example.MacroTransformer" chain="storageToView" weight="-1" /> </atlassian-plugin>
6. Try the Plug-in
Daniel executed atlas-run. He accessed the Confluence Server at http://localhost:1990/confluence. He used admin
as his username and password. He then created a page (click on the “Create” button at the top of the page to create a blank page) with the title loremipsum page and added the Loremipsum Macro (press “Shift + {“ to open the Macro Browser Dialog and type “loremipsum” in the search field to filter and display the Loremipsum Macro) below it. The final output looks like this:
7. Summary
In this example, Daniel was able to build a transformer for the Atlassian Confluence Server by following these steps:
- Tools
- Create the plug-in
- Modify the files
- Add the logic
- Add the Transformer Module in the Add-on Descriptor
- Try the plug-in
8. Download the Source Code
This is an example of building a Transformer Add-on for Atlassian Confluence Server.
You can download the source code of this example here: confluence-content-transformer.zip.