Rendering Macro Transformation

Last modified by Admin on 2024/04/19 01:17

cogTransform Macro blocks by executing Macros
TypeJAR
CategoryRendering Transformation
Developed by

XWiki Development Team

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Installable with the Extension Manager

Description

Execution Flow

This Rendering Transformation works as follows:

  • Macros can be registered for a given syntax or for all syntaxes.
  • Macros also have a priority which allows some macros to be executed before or after other macros. For example the "Include" macro runs first and the "Table Of Content" macro executes last (so that it can take into account all headers created by other macros).
  • The Macro Transformation finds all macro blocks defined in the passed XDOM object. For each macro block found it verifies if there's a macro registered for that macro block and for the target syntax. It then sorts all macros by priority and execute them one by one, replacing the macro block with the list of blocks generated by the macro, until there are no macro blocks left in the XDOM. Note that a macro can generate macro blocks.
  • The Macro Transformation uses a MacroTransformationContext which augments the TransformationContext by holding additional information such as the current XDOM block being processed or whether the macro is called inline or not.

Transformation Context

Starting with XWiki 6.0, it's now possible to access the context of the rendering in progress from any components. The information, initially provided by the org.xwiki.rendering.transformation.TransformationContext and org.xwiki.rendering.transformation.MacroTransformationContext (for Transformations and for Macros) are now available to any component using the org.xwiki.rendering.transformation.RenderingContext role.

For this context to be properly actuated, any process that initiate a transformation without using the default implementation of org.xwiki.rendering.transformation.TransformationManager role (or implement it) should take care of it. At the moment, there is no public API for this (internally we use org.xwiki.rendering.internal.transformation.MutableRenderingContext for this purpose), so it is highly recommended to use the Transformation Manager when possible.

Macro Components

The most important class is the Macro role class which is implemented by all Macro components.

See the Writing a Macro tutorial to learn how to write macros.

You'll find below some reference information about Macros.

public interface Macro<P> extends Comparable<Macro<?>>
{
   /**
     * The priority of execution relative to the other Macros. The lowest values have the highest priorities and execute
     * first. For example a Macro with a priority of 100 will execute before one with a priority of 500.
     *
     * @return the execution priority
     */

   int getPriority();

   /**
     * @return the macro descriptor
     */

    MacroDescriptor getDescriptor();

   /**
     * @return true if the macro can be inserted in some existing content such as a paragraph, a list item etc. For
     *         example if I have <code>== hello {{velocity}}world{{/velocity}}</code> then the Velocity macro must
     *         support the inline mode and not generate a paragraph.
     */

   boolean supportsInlineMode();

   /**
     * Executes the macro.
     *
     * @param parameters the macro parameters in the form of a bean defined by the {@link Macro} implementation
     * @param content the content of the macro
     * @param context the context of the macros transformation process
     * @return the result of the macro execution as a list of Block elements
     * @throws MacroExecutionException error when executing the macro
     */

    List<Block> execute(P parameters, String content, MacroTransformationContext context)
       throws MacroExecutionException;
}

A Macro provides a MacroDescriptor that indicates all the metadata of the macro: its parameters, their types, whether they are mandatory or not, whether the macro in inline or standalone mode, etc.

In order to make it simpler to implement Macros, it's highly recommended that you extend AbstractMacro which can generate this descriptor for you, based on a macro parameter bean class that you pass in its constructor. This macro parameter bean can have its methods annotated with all property annotation provided by the Properties API (see MacroDescriptor which uses ContentDescriptor and ParameterDescriptor for more details).

Other Components

The following useful components are provided by this Macro Transformation API:

  • MacroManager: Allows retrieving Macros by id
    public interface MacroManager
    {
       /**
         * @return all the available macros whether they are registered for a given syntax or for all syntaxes
         * @throws MacroLookupException error when lookup macros
         * @since 2.03M
         */

        Set<MacroId> getMacroIds() throws MacroLookupException;

       /**
         * @param syntax the desired syntax
         * @return the available macro ids for the desired syntax (this includes macros registered for all syntaxes and
         *         macros registered only for a given syntax)
         * @throws MacroLookupException error when lookup macros
         * @since 2.03M
         */

        Set<MacroId> getMacroIds(Syntax syntax) throws MacroLookupException;

       /**
         * @param macroId the id of the macro to lookup
         * @return the macro, looked-up first as a macro for the desired syntax identifier (if any is specified in the
         *         MacroId) and then as a macro registered for all syntaxes if not found
         * @throws MacroLookupException when no macro with such id was found in both the list of macro for the specified
         *             syntax identifier and for all syntaxes
         * @since 2.03M
         */

        Macro<?> getMacro(MacroId macroId) throws MacroLookupException;

       /**
         * @param macroId the id of the macro to lookup
         * @return true if a macro with the given id and for the given syntax can be found (if any is specified in the
         *         MacroId), false otherwise. Returns false if a macro with the given id exists but has been registered only
         *         for all syntaxes
         * @since 2.03M
         */

       boolean exists(MacroId macroId);
    }
  • MacroIdFactory: Convert a string representing a macro id into a typed MacroId object.
    public interface MacroIdFactory
    {
       /**
         * @param macroIdAsString the string representing the macro id in the format "id/syntaxtype/syntaxversion".
         *        Example: html/confluence/1.0
         * @return the typed representation of a macro Id
         * @throws ParseException if the passed string has an invalid format
         */

        MacroId createMacroId(String macroIdAsString) throws ParseException;
    }
  • MacroContentParser: Parses content of a macro field (parameter, macro content) in a given syntax.
    public interface MacroContentParser
    {
       /**
         * Parses content of a macro field (parameter, macro content) in a given syntax and optionally remove the top level
         * paragraph.
         *
         * @param content the content to parse
         * @param macroContext the executing Macro context (from which to get the current syntax, etc)
         * @param transform if true then executes transformations
         * @param inline whether the content should be parsed as inline content (not top level paragraph, etc)
         * @return the result as a {@link org.xwiki.rendering.block.Block}s
         * @throws MacroExecutionException in case of a parsing error
         */

        XDOM parse(String content, MacroTransformationContext macroContext, boolean transform, boolean inline)
           throws MacroExecutionException;

       /**
         * Parses content of a macro field (parameter, macro content) in a given syntax and optionally remove the top level
         * paragraph.
         *
         * @param content the content to parse
         * @param macroContext the executing Macro context (from which to get the current syntax, etc)
         * @param transform if true then executes transformations
         * @param metadata the metadata to add to the XDOM before executing transformations
         * @param inline whether the content should be parsed as inline content (not top level paragraph, etc)
         * @return the result as a {@link org.xwiki.rendering.block.Block}s
         * @throws MacroExecutionException in case of a parsing error
         * @since 6.4
         */

        XDOM parse(String content, MacroTransformationContext macroContext, boolean transform, MetaData metadata,
           boolean inline) throws MacroExecutionException;

       /**
         * Find the current syntax to use for macro supporting wiki content/parameters/whatever.
         *
         * @param context the macro execution context containing the default syntax and the current macro block
         * @return the current syntax
         */

        Syntax getCurrentSyntax(MacroTransformationContext context);
    }
  • MacroCategoryManager: Component interface for managing macro categories information. Each rendering macro defines a set of default categories under which it falls, but these categories may be overwritten by xwiki configuration mechanism. This component will handle such overwriting operations and make sure latest macro categories information is presented to client code.
    @Role
    public interface MacroCategoryManager
    {
       /**
         * Returns all the macro categories currently available in the system. Macros that don't have default or overridden
         * categories are not included and thus clients should be aware that there can be macros in the system which do
         * not belong to any category.
         *
         * @return the macro categories available in the system.
         * @throws MacroLookupException error when looking up macros
         */

        Set<String> getMacroCategories() throws MacroLookupException;

       /**
         * Returns all the macro categories currently available in the system for macros registered for a given syntax
         * and for all syntaxes. Macros that don't have default or overridden categories are not included and thus clients
         * should be aware that there can be macros in the system which do not belong to any category.
         *
         * @param syntax the syntax to filter the macros by syntax.
         * @return the macro categories available for the given syntax
         * @throws MacroLookupException error when looking up macros
         */

        Set<String> getMacroCategories(Syntax syntax) throws MacroLookupException;

       /**
         * @param category name of the category or null.
         * @return ids of all the macros belonging to the given category or if the category parameter is null, ids of
         *         all the macros which do not belong to any category.
         * @throws MacroLookupException error when lookup macros
         */

        Set<MacroId> getMacroIds(String category) throws MacroLookupException;

       /**
         * @param category name of the category or null.
         * @param syntax the syntax to filter the macros by syntax.
         * @return ids of all the macros belonging to the given category (and registered for the given syntax) or if the
         *         category parameter is null, ids of all the macros which do not belong to any category (and registered
         *         for the given syntax).
         * @throws MacroLookupException error when lookup macros
         */

        Set<MacroId> getMacroIds(String category, Syntax syntax) throws MacroLookupException;

       /**
         * Return the set of categories of a given macro.
         *
         * @param macroId the id of the macro to get the categories for
         * @return the list of categories of the macro
         * @since 14.6RC1
         */

       @Unstable
       default Set<String> getMacroCategories(MacroId macroId)
       {
           return Set.of();
       }

       /**
         * @return the set of hidden categories (e.g., "Deprecated, Internal")
         * @since 14.8RC1
         */

       @Unstable
       default Set<String> getHiddenCategories()
       {
           return Set.of();
       }
    }

    XWiki <14.6 XWiki 13.10.8+, 14.4.3+ 

        /**
         * Return the set of category of a given macro.
         *
         * @param macroId the id of the macro to get the category for
         * @return the category of the macro
         * @since 13.10.8
         * @since 14.4.3
         */

        String getMacroCategory(MacroId macroId)

XWiki 14.8+ A RawBlockFilter component role is provided to allow macros to perform some custom filtering operations over the raw blocks in some macros where the user input is used to create the raw blocks, for security reasons.
The first implementation of those RawBlockFilter has been provided mainly for html raw blocks. 

Configuration

The Macro Transformation is enabled by default in xwiki.properties under the rendering.transformations key:

rendering.transformations = macro, icon

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager).

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Dependencies

Dependencies for this extension (org.xwiki.rendering:xwiki-rendering-transformation-macro 16.2.0):

Get Connected