Rendering Macros

Last modified by Eleni Cojocariu on 2026/10/06 18:27

Explanation

A rendering macro is a component implementing the Macro role, registered under the name it is called by in wiki syntax. Rendering Macros describes what a macro is to the person reading the page; this one describes what a macro is in the code.

A Macro Is a Component

The name a macro is called by in the syntax is its component hint, and nothing registers it separately. The class below is what makes {{useravatar/}} work, declared in its module's META-INF/components.txt like any other component:

@Component
@Named("useravatar")
@Singleton
public class UserAvatarMacro extends AbstractMacro<UserAvatarMacroParameters>
{
    public UserAvatarMacro()
    {
        super("User Avatar", DESCRIPTION, UserAvatarMacroParameters.class);
        setDefaultCategories(Set.of(DEFAULT_CATEGORY_CONTENT));
    }

    @Override
    public List<Block> execute(UserAvatarMacroParameters parameters, String content,
        MacroTransformationContext context) throws MacroExecutionException
    {
        // Build and return the blocks the macro call is replaced by.
    }

    @Override
    public boolean supportsInlineMode()
    {
        return true;
    }
}

Changing the @Named value renames the macro. Two components declared on the same hint are resolved by component priority, which is how an extension replaces a bundled macro without touching it.

A Macro Returns Blocks, Not Text

execute returns a list of Blocks, and the macro transformation substitutes them for the macro call in the XDOM, the tree the parser produced from the page. A renderer only ever sees that tree, once every macro in it has run.

Two things follow, and they are what a first macro usually gets wrong:

  • The output is syntax-independent. A macro returning an ImageBlock renders in HTML, in a PDF export and in LaTeX alike, while one returning raw HTML renders in none of the others.
  • A macro may emit another macro call, and that call is executed in turn, because what the macro returned went back into the tree rather than into the output.

Macros are also not run in the order they are written. The transformation runs them by priority, lowest first, and AbstractMacro defaults to 1000. A macro that has to act before the ones its own content holds lowers it, as the container macro does:

@Override
public int getPriority()
{
    return 750;
}

The Parameters Bean Is What the Editors Show

A macro declares its parameters as a bean, and the descriptor the editors read is built from it. The annotations on each setter are the whole of the parameter metadata, so a parameter is described once, in the code:

public class UserAvatarMacroParameters
{
    private String username;

    @PropertyMandatory
    @PropertyDescription("the name of the user whose avatar is to be displayed")
    @PropertyDisplayType(UserReference.class)
    public void setUsername(String username)
    {
        this.username = username;
    }
}

@PropertyDescription is the help text beside the field, @PropertyMandatory makes the editor refuse an empty value, and @PropertyDisplayType replaces the plain text field by a picker, here the user picker. The categories the macro is listed under come from setDefaultCategories; AbstractMacro defines the bundled ones, Formatting, Content, Navigation, Development, Layout, Internal and Deprecated.

Java Macro or Wiki Macro

A macro can also be written as a wiki page carrying an XWiki.WikiMacroClass object, with no Java and no build. That object holds the same metadata the Java descriptor does, the id, name, description, default categories, inline support and content availability, plus the macro code itself and a visibility, Current User, Current Wiki or Global, that decides which component manager the macro is registered in.

CharacteristicJava macroWiki macro
Easy to debug, and to write an automated test foracceptcancel
Optimized for performanceacceptcancel
Advanced parameter metadata, such as pickers and deprecationacceptcancel
Needs no development skills and no buildcancelaccept
Fast to write, and easy for a user to customize afterwardscancelaccept

Writing a Macro is the Java tutorial, and Writing XWiki Rendering Macros in wiki pages the wiki one.

Executing Content Is a Rights Decision

A macro that renders or executes the content it is handed runs what a page author wrote, so it also needs a required-rights analyzer. The analyzer does not enforce anything; it reports what the macro's content will need, and without one nothing tells the author to declare those rights or shows a reviewer what the page will run.

A macro whose result may be reused across requests extends AbstractExecutedContentMacro rather than driving the asynchronous renderer by hand; it then takes the standard async, cached and context parameters.

Where the Macros Are Documented

A macro is documented in the topic of the feature it belongs to, such as the "async" macro under Async Rendering. All Bundled Rendering Macros (Developer Documentation) lists them all in one place.

FAQ

Can a macro be used inside a sentence?

Only if its supportsInlineMode returns true. A macro that produces a paragraph or a group cannot, and using it inline is reported as an error instead.

Can an extension replace a bundled macro?

Yes. The macro name is the component hint, so a component declared on that hint at a stronger priority takes over, which is how the platform replaces the engine's toc macro with one that resolves a document reference.

How does a macro become asynchronous or cached?

By extending AbstractExecutedContentMacro. Whatever the macro reads while rendering has to be declared to AsyncContext, or the cached result survives the change that should have evicted it.

More

To find more about the current topic, you can search or use the table below and filter the columns to narrow your choices.

Related

Get Connected