Applicable: | This tutorial applies to Confluence 4.3. |
Level of experience: | This is an intermediate tutorial. You should have completed at least one beginner tutorial before working through this tutorial. See the list of developer tutorials. |
Status | LEGACY This tutorial applies to Confluence versions that have reached end of life. |
Related:
This tutorial shows you how to write a Soy template in your plugin to use in JavaScript. The plugin adds a table of metadata to the top of each Confluence page using Soy templates:
In order to do this, you will create a very simple Confluence plugin. Your plugin will consist of the following components:
All these components will be contained within a single JAR file. Each component is further discussed in the examples below.
This plugin is of little practical value, but it is designed to show you a way of templating UI elements in JavaScript for use on Confluence.
Source Code
The source code of the plugin used in this tutorial is available in bitbucket. You can browse the source code here: confluence-tutorial-soy-templates.
Soy templates are a templating system for dynamically generating re-usable HTML and UI elements in both Java and JavaScript. Soy templates are also referred to as Closure templates.
For the client side, Soy templates are precompiled into efficient JavaScript. This tutorial is only concerned with client-side aspect of templating.
Begin by creating a new Confluence plugin. You can use the Atlassian Plugin SDK to do this. (See Set up the Atlassian Plugin SDK and Build a Project for full instructions.)
In a command window, go to the directory where you want to create your plugin project, and type: atlas-create-confluence-plugin
You will be prompted to enter two values, the group ID and artifact ID. For this tutorial, we used the following values:
Accept the default values for version and package.
This will create a basic plugin with some Java code and tests. In the sample code, all Java code including tests have been removed as they are not needed for the plugin.
Create a new Soy template at src/main/resources/template.soy:
1 2{namespace Confluence.Templates.SoyTutorial} /** * Renders a table of selected AJS.params * @param pageId * @param pageTitle * @param parentPageId * @param spaceKey * @param spaceName */ {template .listSelectedAjsParams} <b>{getText('confluence.tutorial.soy.templates.intro')}</b> <table class="aui" id="basic"> <thead> <tr> <th>{getText('confluence.tutorial.soy.templates.name')}</th> <th>{getText('confluence.tutorial.soy.templates.value')}</th> </tr> </thead> <tbody> <tr> <td>pageId</td> <td>{$pageId}</td> </tr> <tr> <td>pageTitle</td> <td>{$pageTitle}</td> </tr> <tr> <td>parentPageId</td> <td>{$parentPageId}</td> </tr> <tr> <td>spaceKey</td> <td>{$spaceKey}</td> </tr> <tr> <td>spaceName</td> <td>{$spaceName}</td> </tr> </tbody> </table> {/template}
Each Soy file needs a namespace declaration at the top of the file. It must be declared before any templates are declared.
In this case, we have created a new Confluence.Templates.SoyTutorial namespace for our templates and added a template which displays an AUI-style table containing a number of attributes that a Confluence page is likely to possess.
Each template must precede with a SoyDoc comment that explains the purpose of the template, in the same style as JavaDoc.
1 2/** * Renders a table of selected AJS.params * @param pageId * @param pageTitle * @param parentPageId * @param spaceKey * @param spaceName */
Parameters use this syntax within the template:
1 2{$pageId}
For internationalisation, use getText()
- a JavaScript internationalisation transformer will take care of the i18n:
1 2<b>{getText('confluence.tutorial.soy.templates.intro')}</b>
Create a new JavaScript resource at src/main/resources/init.js:
1 2AJS.toInit(function () { var $pageMetadata = AJS.$('#content.page.view .page-metadata:first'); if ($pageMetadata.length > 0) { var selectedAjsParams = { pageId: AJS.params.pageId, pageTitle: AJS.params.pageTitle, parentPageId: AJS.params.parentPageId, spaceKey: AJS.params.spaceKey, spaceName: AJS.params.spaceName } var template = Confluence.Templates.SoyTutorial.listSelectedAjsParams(selectedAjsParams); $pageMetadata.after(template); } });
Here we are doing four things:
selectedAjsParams
- into the template - Confluence.Templates.SoyTutorial.listSelectedAjsParams
- to render the template into HTML.You will notice the AUI function, AJS.params
- this contains some useful information about the Confluence installation and the current page. In this case, we are using it for convenience. Take a look at AJS.params
in your browser's JavaScript console:
You must now register the plugin module in your plugin descriptor, atlassian-plugin.xml.
Add the following code to your atlassian-plugin.xml
file between the <atlassian-plugin>
tags, but below the <plugin-info>
tag group.
1 2<web-resource key="view-metadata" name="View metadata from AJS.params"> <!-- transform calls to AJS.getText() inside JS files --> <transformation extension="js"> <transformer key="jsI18n"/> </transformation> <!-- transform Soy templates into JS --> <transformation extension="soy"> <transformer key="soyTransformer"> <functions>com.atlassian.confluence.plugins.soy:soy-core-functions</functions> </transformer> </transformation> <!-- JavaScript resources --> <resource name="init.js" type="download" location="init.js"/> <resource name="template-soy.js" type="download" location="template.soy"/> <context>page</context> </web-resource>
Let's break down that XML code, by looking at the web resource module, transformers and resources in the code.
In the code example, the web-resource module (line) has 2 attributes:
1 2<web-resource key="view-metadata" name="View metadata from AJS.params">
In the code example, there are two transformation code blocks:
1 2<!-- transform calls to AJS.getText() inside JS files --> <transformation extension="js"> <transformer key="jsI18n"/> </transformation> <!-- transform Soy templates into JS --> <transformation extension="soy"> <transformer key="soyTransformer"> <functions>com.atlassian.confluence.plugins.soy:soy-core-functions</functions> </transformer> </transformation>
Lastly, there are Javascript resources for the web resources and the context in which they should be displayed. In this case, the Javascript is only added for Confluence pages, thus the 'page' context.
1 2<!-- JavaScript resources --> <resource name="init.js" type="download" location="init.js"/> <resource name="template-soy.js" type="download" location="template.soy"/> <context>page</context>
To add new resource files and internationalisation, add a new file in the resources directory of your plugin, called confluence-tutorial-soy-templates.properties
, and include these lines of code:
1 2confluence.tutorial.soy.templates.intro = Some metadata extracted from the AJS.params JavaScript object: confluence.tutorial.soy.templates.name = Name confluence.tutorial.soy.templates.value = Value
The above keys are used in the Soy template. For example:
1 2<b>{getText('confluence.tutorial.soy.templates.intro')}</b>
Additionally, add a reference the resource file in the atlassian-plugin.xml
file - add this line of code above the <web-resource>
code block:
1 2<resource type="i18n" name="i18n" location="confluence-tutorial-soy-templates" />
This accesses your confluence-tutorial-soy-templates.properties
file and retrieves the text for our button label.
If you would like to know more about internationalisation, see the Confluence documentation on the topic.
Go to the root directory in your plugin project - this is the directory that contains the pom.xml
file. Type the atlas-run command, to compile the plugin project and then launch a local instance of Confluence.
Once Confluence has loaded:
Go to your web browser and access your local instance with this URL:
1 2http://localhost:1990/confluence/
Each page will now have a table above the page content, containing a selection of metadata - this has been rendered client-side using Soy templates.
Congratulations, you have completed this tutorial.
Rate this page: