Writing a macro for Confluence 4.0 or later?
Please refer to Creating a New Confluence Macro.
Macros are written and deployed into Confluence as macro plugin modules. This page describes how to write a macro (but not how to get the plugin working, refer to the other page for that).
Make sure you have created your first macro plugin using our guide, How to Build an Atlassian Plugin. That will save you a lot of time.
All macros must implement the com.atlassian.renderer.v2.macro.Macro
interface. The best place to start is with the Javadoc for the Confluence version you are developing for, such as:
In Confluence version 3 and earlier, com.atlassian.renderer.v2.macro.Macro was the recommended interface; however, If your macro is to be used exclusively with Confluence 4.0 or later, you should use docs.atlassian.com/atlassian-confluence/latest/com/atlassian/confluence/macro/Macro.html. See Creating a New Confluence Macro and Macro Tutorials for Confluence for more information.
Note about the BaseMacro class: While it's not a requirement, your macro should extend the com.atlassian.renderer.v2.macro.BaseMacro
abstract class. This class does not contain any functionality, but if the Macro
interface changes in the future, the BaseMacro
class will be maintained in order to ensure backwards compatibility with existing macros.
When writing a macro, you will need to override the following methods:
Method | Should return... |
---|---|
hasBody() |
|
getBodyRenderMode() | The |
isInline() |
|
execute() | a fragment of HTML that is the rendered macro contents |
RenderMode
The RenderMode
tells the Confluence wiki renderer which wiki-conversion rules should be applied to a piece of text. Once again, the best place to start is with the Javadoc for the Confluence version you are developing for, such as:
There are a number of pre-defined render modes. The ones that would be useful to macro writers are probably:
Mode | Description |
---|---|
| Render everything |
| Don't render anything: just return the raw wiki text |
| Render things you'd normally find inside a paragraph, like links, text effects and so on |
| Render text made up only of paragraphs, without images or links |
If you want finer control, RenderMode
is implemented as a bit-field. Each constant of RenderMode
starting with F_
is a feature of the renderer that can be turned on or off. You can construct a RenderMode by manipulating these bits through the following methods:
Method | Example |
---|---|
|
Description: Allow only the renderings specified. |
|
Description: Allow all renderings except those specified. |
|
Description: Perform a logical AND on an existing render mode. |
|
Description: Perform a logical OR on an existing render mode. |
Many macros (like this note macro) produce a div
. Often, if there's only one line of text within a div, you don't want it surrounded in paragraph tags. For this reason, the RenderMode.F_FIRST_PARA
flag controls the first line of wiki text that is rendered. If F_FIRST_PARA
is not set, and the first line of text is a paragraph, the paragraph tags will not be rendered.
One of the parameters to the execute() method, the one with type RenderContext, can be used to determine how the macro is being rendered. See the relevant Confluence Developer FAQ entry for the details.
Like all Confluence plugin modules, Macros are autowired by the Spring framework. To obtain a manager object through which you can interact with Confluence itself, all you need to do is provide a Javabeans-style setter method for that component on your Macro
class. See Accessing Confluence Components from Plugin Modules
Macros are often most powerful when combined with other plugin modules. For example, the {livesearch} macro uses a Struts module to perform its server-side duties, and the {userlister} plugin uses a listener plugin module to listen for login events and determine who is online. You may also consider using a component plugin module to share common code or state between macros.
If you want to know exactly what happens when a macro is processed, the following (slightly overly-detailed) description should help:
Consider the following code in a Wiki page:
1 2{mymacro:blah|width=10|height=20}This _is_ my macro body{mymacro}
MacroRendererComponent
finds the first {mymacro:blah|width=10|height=20
} tag, and asks the MacroManager
if a macro is currently active with the name "mymacro". The MacroManager
returns a singleton instance of your Macro
.MacroRendererComponent
calls hasBody()
on the Macro
.
hasBody()
returns false, the macro is processed with a 'null' body, and the next {mymacro} tag will be processed as a separate macro.hasBody()
returns true, the MacroRendererComponent
looks for the closing {mymacro}. Anything between the two becomes the macro body.
MacroRendererComponent
then calls getRenderMode()
on the macro to determine how that body should be renderedMacroRendererComponent
calls execute
on the macro, passing in the macro parameters, the (processed) body, and the current RenderMode
execute
method should return an HTML string. No further wiki processing is performed on macro output.Map
of {{String}}s, keyed by parameter name.
parameters.get("0")
would return "blah"
.parameters.get(Macro.RAW_PARAMS_KEY)
will return the raw parameter string, in this case: "blah|width=10|height=20"
MacroRendererComponent
calls isInline()
on the macro to determine if its results should be inserted into the surrounding page as an inline (i.e. part of a surrounding paragraph) or a block element.Rate this page: