Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

This page describes a way of allowing arbitrary Confluence content, including macros, in the bodies of macros that don't normally allow this.


Confluence macros can be nested within other macros. For instance, the chart macro can take a static table as input:


But the chart macro can also take output from a SQL macro:


In fact chart can take input from any other table-generating macro (e.g. CSV).

Like Unix pipes, you can string together and reuse macros. This plugin composability is one of Confluence's most powerful features.

This is great, but only works when the macro in question was designed to accept the "rich text" XHTML generated by another macro. For example, but the SQL Query macro can't take macro output as its input.


Why would we want to send dynamic content to a macro not expecting it? Here are a few situations:

  • You are using the SQL macro to query a database, but want to use a HTTP parameter from the URL (param macro) in the query to make it dynamic.
  • You want to use SQL results in Javascript in a html macro.

Dynamic Wrapper Macros

The solution is to create a wrapper user macro that accepts rich text input, strips out any XHTML tags, and feeds the resulting plain text to the macro you're interested in.


The first example lets the SQL Query macro take dynamic input. Here is a silly example, with SQL that emits XHTML for a Confluence @user reference, (/) tick and a custom param user macro:

rendering as:


The macro definition looks like this:

With macro body:

## @param dataSource:title=Data source name|type=string|required=true|desc=Type or select a data source configured by your Confluence administrator.
## @param output:title=Output format|type=enum|default=html|enumValues=html,xhtml,wiki,unrenderedWiki
## @param table:title=Show result as a table|type=boolean|default=true
## @param printsql:title=Print SQL after results|type=boolean|default=true
## @param autototal:title=Auto row total|type=boolean|default=false|desc=Adds a row to the end of the table that totals numeric columns.
## @param columnTypes:title=Column Types|type=string|desc=Comma separated list of type indicators. Column type determines sorting and other characteristics. See

## Given rendered macro output (HTML), strips HTML formatting elements, leaving just the content.
#macro(clean $body)
#foreach($i in [1..10])
## (?:..) is a non-capturing group. 
#set($body=$body.replaceAll('(?smi)<span(?: [^>]*)?>(.*?)</span>', '$1'))
#set($body=$body.replaceAll('(?smi)<p(?: [^>]*)?>(.*?)</p>', ' $1'))
#set($body=$body.replaceAll('(?smi)<div(?: [^>]*)?>(.*?)</div>', '$1'))
#set($body=$body.replaceAll('(?smi)<p(?: [^>]*)?>(.*?)</p>', ' $1'))
#set($body=$body.replaceAll('<br ?/>', '
#set($body=$body.replaceAll('&apos;', "'"))
#set($body=$body.replaceAll('&lt;', "<"))
#set($body=$body.replaceAll('&gt;', ">"))
#set($body=$body.replaceAll('&quot;', '"'))
#set($body=$body.replaceAll('&;', '"'))
<ac:structured-macro ac:name="sql-query">
  <ac:parameter ac:name="output">$paramoutput</ac:parameter>
  <ac:parameter ac:name="dataSource">$paramdataSource</ac:parameter>
  <ac:parameter ac:name="atlassian-macro-output-type">INLINE</ac:parameter>
  <ac:parameter ac:name="table">$paramtable</ac:parameter>
  #if($paramcolumnTypes)<ac:parameter ac:name="columnTypes">$paramcolumnTypes</ac:parameter>#end
  <ac:parameter ac:name="rowStyles">border-bottom:black 2px solid;border-top:black 2px solid;,background:#ffffee,background:#fff</ac:parameter>
  <ac:parameter ac:name="autoTotal">$paramautototal</ac:parameter>
  <ac:parameter ac:name="noDataMessage">no results</ac:parameter>

#if($paramprintsql == true)
<small>Rendering SQL: $generalUtil.htmlEncode($body)</small><br>
  • No labels