Macros

Macros are ubiquitous in Confluence and using them liberally is one of its greatest powers. The inability to use macros in other macro-based markdown solutions was one of the primary driving factors for creating Alt Text Editor

Being entirely a Confluence concept, CommonMark has no way to represent macros. Alt Text Editor uses a macro directive

Macros from different Confluence add-ons and plugins come in all shapes and sizes but consist of the same general parts: its name, attributes, parameters, and its body.

With all of these different pieces of data to provide to a macro, it is very common that macros will need to be converted into a def form as described in the directive guide and seen in the below examples.

Examples

The below examples are based on a fictitious macro, pets, that will render something (hopefully useful!) based on various parameters. For the below examples, you can imagine that it renders a count of pets or perhaps an image of some kind.

A simple inline macro with no parameters.

You have :macro[pets] pets!
<p>You have
  <ac:structured-macro ac:name="pets" /> pets!
</p>

A block macro with a single parameter. Note that the Storage Format does not have any paragraph tags wrapping it. This means that it will be treated as its own block when Confluence renders it.

Macro parameters are represented by key & value pairs in a markdown code block, parameterized with a params key.

:::macro[farm]
```params
animal=cat
```
:::
<ac:structured-macro ac:name="pets">
  <ac:parameter ac:name="animal">cat</ac:parameter>
</ac:structured-macro>

The previous example demonstrates how a macro that has the potential to be used inline (if it renders a simple count of pets) needs to be represented by multiple lines of markdown text.

Examine the below Storage Format. Notice how this macro is providing a count visual of some kind that is meant to exist within a paragraph (an inline flow context), presumably to render something like You have 9 pets!

<p>You have <ac:structured-macro ac:name="pets">
  <ac:parameter ac:name="animal">cat</ac:parameter>
</ac:structured-macro> pets!</p>

If Alt Text Editor builds markdown for the above when it is loaded, it needs to maintain that inline flow context. To do so, it uses the inline (single colon) version of the macro directive and puts the multi-line content into an associated macrodef def at the bottom of the document.

You have :macro[pets]{#1} pets!

...the rest of your page's content...

:::macrodef[pets]{defId=1}
```params
animal=cat
```
:::

This allows the You have 9 pets! content to remain correctly in an inline flow, while also allowing the usage of multi-line markdown syntax.

Alt Text Editor takes care of all of this for you, so don't worry about crafting this yourself - but when working with macros you will see this fairly often.

A block macro with a plain text body. The body is represented by the raw body placed inside a markdown code block, parameterized with a body key.

:::macro[pets]
```body
plants are not pets
```
:::
<ac:structured-macro ac:name="pets">
  <ac:plain-text-body>
    <![CDATA[plants are not pets]]>
  </ac:plain-text-body>
</ac:structured-macro>

Macros can have both params and a body.

:::macro[pets]
```params
animals=dog,cat
```

```body
plants are not pets
```
:::
<ac:structured-macro ac:name="pets">
  <ac:parameter ac:name="animals">dog,cat</ac:parameter>
  <ac:plain-text-body>
    <![CDATA[plants are not pets]]>
  </ac:plain-text-body>
</ac:structured-macro>

A block macro with markdown content for a body. Unlike the plain text-bodied macro example above, the markdown content of this type of macro is not placed in a code block and is processed normally.

:::macro[pets]
### Animals
* cat
* dog
:::
<ac:structured-macro ac:name="pets">
  <ac:rich-text-body>
    <h3>Animals</h3>

    <ul>
      <li>
        <p>cat</p>
      </li>
      <li>
        <p>dog</p>
      </li>
    </ul>
  </ac:rich-text-body>
</ac:structured-macro>

Macros with rich markdown content bodies can also have parameters.

:::macro[pets]
```params
ignore=snakes
maxweight=10
```

### Animals
* cat
* dog
:::
<ac:structured-macro ac:name="pets">
  <ac:parameter ac:name="ignore">snakes</ac:parameter>
  <ac:parameter ac:name="maxweight">10</ac:parameter>
  <ac:rich-text-body>
    <h3>Animals</h3>

    <ul>
      <li>
        <p>cat</p>
      </li>
      <li>
        <p>dog</p>
      </li>
    </ul>
  </ac:rich-text-body>
</ac:structured-macro>

Confluence associates internal properties with macros once they are saved. These are stored in the macro directive's attributes ({}).

Certain attributes are so common that they have shortcuts, for example, ac:macro-id and ac:schema-version. Others are treated as literal key & value pairs.

:macro[pets]{#123 v=3 some-conf-attribute=abc}
<ac:structured-macro ac:name="pets" ac:macro-id="123" ac:schema-version="3" some-conf-attribute="abc" />

Macros often expect parameters to have complex types beyond simple numbers and text. Alt Text Editor knows how to handle these correctly. See some examples of complex parameters below

:::macro[pets]
```params
animals=dog,cat
ri:faq=page://dog info
ri:faq=space://cat lovers
ri:address=animal.com
ri:address=farm.com
link:references=[](<page://cat reference material>)
link:references=[](<page://dog reference material>)
```
:::
<ac:structured-macro ac:name="pets">
  <ac:parameter ac:name="animals">dog,cat</ac:parameter>
  <ac:parameter ac:name="faq">
    <ri:page ri:content-title="dog info" />
    <ri:space ri:space-key="cat lovers" />
  </ac:parameter>
  <ac:parameter ac:name="address">
    <ri:url ri:value="animal.com" />
    <ri:url ri:value="farm.com" />
  </ac:parameter>
  <ac:parameter ac:name="references"><ac:link>
      <ri:page ri:content-title="cat reference material" />
    </ac:link>
    <ac:link>
      <ri:page ri:content-title="dog reference material" />
    </ac:link>
  </ac:parameter>
</ac:structured-macro>