Well, it finally happened.  I finally had to start learning JavaScript.

It’s actually not that bad, I probably should have learned a while ago.  My use case for it is writing Confluence Macros and plugins for both Confluence and Jira. I started with the plugins, for simplicity’s sake.  
My inspiration came from a post on the Atlassian Community Forums. Someone had requested a way to essentially mirror the setup of a macro. But they wanted to mirror the most recent child page, of a parent page.
I think that without pretty strong knowledge of Confluence and the REST API, I’d have struggled to complete this.  It enough work to learn JavaScript’s basic tenets as I went.


Digging Into The Problem

Okay so what do we actually need the script to do? We need it to:

  •  Figure out the most recently updated child page of a parent page
  •  Fetch the macro setup of the child page
  • Update the parent page accordingly

These are the three high-level functions that the macro needs to accomplish. 

Figuring out the most recently updated child page wasn’t hard.  You can make a call to baseURL + pageID + “/child/page?limit=1000&expand=history.lastUpdated. This returns a list


In a bid to contribute more to the Atlassian Community, I took a look at the most recent requests and questions on the Forums.  One that caught my eye was a request for a Confluence Macro that would:

“…display on the restricted page exactly who has access (including a breakout of all group members, not just the group name) to create transparency and build confidence in the selected user group that they are posting in the appropriately restricted area.”

I’d never created a Confluence Macro before, and this seemed like a challenge I could meet.

Please note that this isn’t a how-to on creating Macros, but really just an accounting of my experience learning the tool.

Getting Started

The first thing I did was check to see what Atlassian has to say on the subject. Confluence Macros are written in Apache Velocity, which is quite different from the Groovy that I’m used to working with.

All of the functional lines in Velocity start with a #, which makes a Velocity script look like one big page of commented-out code.  The truth is that Velocity is very old and pretty clunky.  The last news update to the project was

This script returns a list of pages in a Confluence instance that use a specified macro.

There are a number of references to “MacroManager” in the Confluence API documentation, but none of the implementations seemed to work for me.

For that reason, our best bet for checking on Macro usage is to examine the body content of each page, and look for a specific reference to the macro in question.

We also need to check that the page in question is the latest version of the page. Otherwise the script checks all versions of all pages.


 import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.confluence.spaces.SpaceManager
import com.atlassian.confluence.pages.PageManager
import com.atlassian.confluence.pages.Page
def pageManager = ComponentLocator.getComponent(PageManager)
def spaceManager = ComponentLocator.getComponent(SpaceManager)
def spaces = spaceManager.getAllSpaces()
def macroRef = 'ac:name="info"'
//Replace "info" with the name of the macro you want to assess
spaces.each{  spaceObj ->
//Get all Spaces in the instance
  def pages = pageManager.getPages(spaceObj, false)
  pages.each{    page ->
//Get all pages in the instances
      if (page.getBodyContent().properties.toString().contains(macroRef) && page.version == page.latestVersion.version) {
      //Check if the page contains the macro, then check to see if it's the most current version of the page
        log.warn("'${page.title}' (version ${page.version}) is the latest version of the page, and contains the target macro")