Wiki

Clone wiki

confluence-macro-tutorial / Home

Macro Magic

This is a tutorial and code samples to manipulate the display of a macro in the Confluence editor and/or macro browser. The creation of a basic macro is covered by Atlassians Creating a New Confluence Macro.

Editor

Formatting


1. Formatting

WIP: Confluence lets you create a web item to extend the formatting options in the RTE. But how to use it is still unclear to me

src/main/resources/atlassian-plugin.xml

<web-item key="editor-awesome-format" name="AwesomeFormat" section="system.editor.more.formats" weight="10">
    <description>Custom format in editor menu</description>
    <label key="com.example.plugin.confluence.macromagic.customformat" />
    <link linkId="my-awesome-format" />
</web-item>

Insert Menu


2. Insert

To add a macro of your choice into the quick insert menu, just add a web item for it:

src/main/resources/atlassian-plugin.xml

<web-item name="menu-link" key="editor-featured-macro-box-item" section="system.editor.featured.macros.default" weight="11">
    <description>Displays an insert box macro link in the tinymce insert menu </description>
    <label key="com.example.plugin.confluence.macromagic.box.label">Box</label>
    <link linkId="box" />
</web-item>
  • The linkId equals the macro key you want to insert.
  • Note that you can't set the icon with a default icon tag, like in other web items. For the editor you will have to set a background-image with CSS, using the linkId:

src/main/resources/atlassian-plugin.xml

<web-resource name="CSS Resource" key="css-resources">
    <description>CSS resource for all macros</description>
    <context>editor</context>
    <resource type="download" name="macromagic.css" location="css/macromagic.css" />
</web-resource>

src/main/resources/css/macromagic.css

#insert-menu .aui-dropdown #box .icon {
    background: url(images/16x16_package.png) no-repeat scroll left center transparent;
}

Macros

Since Confluence 4.0 the old wiki markup editor was removed and old page contents were migrated to the new XHTML markup, which is edited by a WYSIWYG editor.

Changing the markup means also changing the macros, so since Confluence 4.0 we have the new xhtml-macro:

Here a minimized macro of our hillsite example, src/main/resources/atlassian-plugin.xml

<xhtml-macro name="hillsite" class="com.example.plugin.confluence.HillsiteMacro" key="hillsite-xhtml">
    <description>Nice hillsite to relax</description>
    <parameters />
</xhtml-macro>

Note that you should always set a parameters node even if it's empty.

This should do it, right? Not quite, unfortunately. You know the Welcome Message an administrator can set in General Configuration of Confluence? This is still old wiki markup and if your brand new macro should ever be used in there, you should also register your macro as an old style macro:

src/main/resources/atlassian-plugin.xml

<macro name="hillsite" class="com.example.plugin.confluence.HillsiteMacro" key="hillsite">
    <description>This is the legacy definition for the same macro for Confluence less or equal 3.x. We need it to have the macro work within wiki-markup like {hillsite}</description>
    <parameters />
</macro>

Be sure to set the same name, but a different key.

Icon and documentation URL


The macro browser will try to display a 80x80px logo to represent a macro. You can set an image for your macro by adding the url in the macro definition.

Let's take our hillsite macro and add the icon url src/main/resources/atlassian-plugin.xml

src/main/resources/atlassian-plugin.xml

<xhtml-macro name="hillsite" class="com.example.plugin.confluence.HillsiteMacro" key="hillsite-xhtml" 
    icon="/download/resources/com.example.plugin.confluence.macromagic/images/64x64_image.png"
    documentation-url="/plugins/macromagic/hillsite/documentation.action">
    <description>Nice hillsite to relax</description>
    <parameters />
</xhtml-macro>

In this example we used an image which is served by a resource:

src/main/resources/atlassian-plugin.xml

<resource type="download" name="images/" location="images">
    <description>Image resource</description>
    <param name="content-type" value="image/png" />
</resource>

The same way we can add a documentation URL to a page describing our macro. How to implement such a page is not covered by this tutorial, but you'll find more information in Atlassian documentation.

Categories


4. Macro browser

Select a category for each macro and set it in atlassian-plugin.xml

src/main/resources/atlassian-plugin.xml

<category name="visuals" />

The following categories are available:

  • formatting
  • confluence-content
  • media
  • visuals
  • navigation
  • external-content
  • communication
  • reporting
  • admin
  • development

Macro Parameters


5. Macro parameters

Types

  • boolean - displays a check box.
  • enum - displays a select field.
  • string - displays an input field (this is the default if unknown type).
  • spacekey - displays an autocomplete field for search on space names.
  • attachment - displays an autocomplete field for search on attachment filenames.
  • username - displays an autocomplete field for search on username and full name.
  • confluence-content - displays an autocomplete field for search on page and blog titles.
  • attachment - displays an autocomplete field for search on attachments.

These are optional:

  • required - whether it is a required parameter, defaults to false.
  • multiple - whether it takes multiple values, defaults to false.
  • default - the default value for the parameter.

It can also have the following optional child elements:

  • <alias name="xxx"/> - alias for the macro parameter.
  • <value name="xxx"/> - describes a single enum value - only applicable for enum typed parameters.

Example with enum and string: src/main/resources/atlassian-plugin.xml

<xhtml-macro name="box" class="com.example.plugin.confluence.BoxMacro" key="box-xhtml">
    <description>Little boxes ... or big ones</description>
    <parameters>
        <parameter name="size" type="enum" required="true" default="small">
            <value name="SMALL" />
            <value name="MEDIUM" />
            <value name="LARGE" />
        </parameter>
        <parameter name="title" type="string"/>
    </parameters>
</xhtml-macro>

Example with an attachment from a Confluence page (confluence-content). To make this work, don't change the parameter names:

<xhtml-macro name="plugin-name" class="com.example.plugin.confluence.macro.name" key="macroname-xhtml">
    <parameters>
        <parameter name="page" type="confluence-content" required="false" multiple="false" />
        <parameter name="name" type="attachment" required="false" />
    </parameters>
</xhtml-macro>

If you want to add a filter, then you need the following:

<web-resource key="macro-browser-smart-fields" name="Macro Browser Smart Fields">
    <resource type="download" name="confluence-core-macro-fields.js" location="js/confluence-core-macro-fields.js" />
    <dependency>confluence.editor.actions:editor-macro-browser</dependency>
    <context>macro-browser</context>
</web-resource>

... and in confluence-core-macro-fields.js:

(function($) {
    AJS.MacroBrowser.activateSmartFieldsAttachmentsOnPage("plugin-name", [ "png", "jpg", "gif" ]);
})(AJS.$);

Aliases

You can set aliases for parameters to enable a user to easily guess parameter names. This is not necessary anymore with the new WYSIWYG editor since Confluence 4.x, but why not use it anyways ;)

Be sure to use the empty alias only once at most for each macro!

src/main/resources/atlassian-plugin.xml

<parameter name="title" type="string">
    <alias name="" />
    <alias name="name" />
</parameter>

Name/Value presentation

You can choose how you want to display the key/value of a parameter by configuring the default display or each parameter separately:

src/main/resources/atlassian-plugin.xml

<default>
    <option key="showValueInPlaceholder" value="true" />
</default>
<parameter name="title" type="string">
    <option key="showKeyInPlaceholder" value="false" />
    <option key="showValueInPlaceholder" value="true" />
</parameter>

Compare this configuration with the display in the editor: 5. Macro parameters

Hidden Parameters

The example on [Including Information in your Macro for the Macro Browser didn't work for me. Any hints appreciated or just fix this tutorial ;)

Macro Options


6. Macro options

To enable fast and easy editing of a macro, you can set buttons or options and edit the macro parameters accordingly.

Add the following markup to you macro definition:

src/main/resources/atlassian-plugin.xml

<property-panel>
    <spacer />
    <button id="Small" label="S" />
    <button id="Medium" label="M" />
    <button id="Large" label="L" />
    <spacer />
</property-panel>

You can now assign an action for each button with JS:

src/main/resources/js/editor-box.js

AJS.Confluence.PropertyPanel.Macro.registerButtonHandler("Small", function(e, macroNode) {
    // implement me
});

The macroNode is a JS object, which may look something like that:

macro: {
    name: 'box',
    params: {
        size: 'SMALL',
        title: 'My yellow box'
    },
    defaultParameterValue: "",
    body : 'This is the '
}

All you have to do is setting the parameter(s) you want to change and reassign the object to the editor:

src/main/resources/js/editor-box.js

// create macro request object
var macroRenderRequest = {
    contentId: Confluence.Editor.getContentId(),
    macro: {
        name: macroId,
        params: currentParams,
        defaultParameterValue: "",
        body : macroBody
    }
};

// insert new macro content
tinymce.confluence.MacroUtils.insertMacro(macroRenderRequest);

Insert with custom GUI


You will need to create a JS file to override the call to the macro browser. Here we do that for the hillsite macro

src/main/resources/atlassian-plugin.xml

<web-resource name="Resources - handle macros with JS" key="macroeditor-resources">
    <description>Macro related JS resources</description>
    <context>editor</context>

    <!-- JS for custom macro gui without using macro browser (for hillsite macro) -->
    <resource type="download" name="editor-hillsite.js" location="js/editor-hillsite.js" />
</web-resource>

Than add the wanted GUI to your JS file.

src/main/resources/js/editor-hillsite.js

// bind on initialization of editor
AJS.bind("init.rte", function() { 
    var macroName = 'hillsite';

    // 1. create dialog to add macro
    var dialog = new AJS.Dialog(400, 320);

    // hide dialog
    dialog.addCancel("Cancel", function() {
        dialog.hide();
    });

    // 2. add macro to editor
    dialog.addSubmit("Create Macro", function() {

        // 3. get current selection in editor
        var selection = AJS.Rte.getEditor().selection.getNode();
        var macro = {
            name: macroName
        };

        // 4. convert macro and insert in DOM
        tinymce.plugins.Autoconvert.convertMacroToDom(macro, function(data, textStatus, jqXHR ) {
            AJS.$(selection).html(data + "<p><br/></p>");
        }, function(jqXHR, textStatus, errorThrown ) {
            AJS.log("error converting macro to DOM");
        });
        dialog.hide();
    });

    // 5. bind event to open macro browser
    AJS.MacroBrowser.setMacroJsOverride(macroName, {opener: function(macro) {
        // open custom dialog
        dialog.show();
    }});
});
  1. Create a dialog you want to use

  2. It should have a function to create the expected macro markup

  3. Get the currently selected node from the RTE and create the macro object

  • The macro objects can have further parameters, if wanted:

  • params: Object containing all macro parameters, you want to set

  • body: Content for the macro body

  • defaultParameterValue: Don't know what that is for right now

  1. Create the DOM for the macro object and add it to the selected node in RTE

  2. Actually override the call to the macro browser. This will override

  • click in Insert menu of the editor

  • auto-complete while typing the macro name (see: Autocomplete for a macro)

  • and choosing the macro in macro browser

This may look like this:

7. Custom UI

Image place holder


8. Image placeholder

Define the method public ImagePlaceholder getImagePlaceholder() in your macro code, e.g. like the following for our hillsite macro:

src/main/java/com/example/plugin/confluence/HillsiteMacro.java

public ImagePlaceholder getImagePlaceholder( final Map<String, String> params, final ConversionContext ctx) {
    return new DefaultImagePlaceholder(IMAGE_PATH, new Dimensions(330, 145), true);
}

I18N

  • Description for the macro (Will be displayed in macro browser list)

    [PLUGINKEY].[MACROKEY].desc = macro description
    
  • Name for the macro (Will be displayed in macro browser list)

    [PLUGINKEY].[MACROKEY].label = macro name
    
  • Description for macro body

    [PLUGINKEY].[MACROKEY].body.desc = macro body description
    
  • Name for the macro body

    [PLUGINKEY].[MACROKEY].body.label = macro body name
    
  • Description for the macro parameter (Will be displayed in macro browser in macro view underneath the parameter field in light grey)

    [PLUGINKEY].[MACROKEY].param.[PARAMETER_NAME].desc = macro parameter description
    
  • Name for the macro parameter (Will be displayed in macro browser in macro view)

    [PLUGINKEY].[MACROKEY].param.[PARAMETER_NAME].label = macro parameter name
    

see: 10. I18n

see: 11. I18n

Sample result page

9. Sample result page

Helpful Links

License

All graphics used in this plugin were published under GNU Lesser General Public License on http://www.openwebgraphics.com.


This guide was created during work at //SEIBERT/MEDIA

Updated