can you include all child pages automatically?

Nate Simpson October 27, 2015

This question is in reference to Atlassian Documentation: Include Page Macro

Is it possible to use this or another macro to automatically include the content of all child pages in the parent automatically?

8 answers

6 votes
Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 28, 2015

Here is a user macro that I wrote for this a while back.

 

Macro Name:
include_children

Macro Title:
Include Children 

Macro Body Processing:
No macro body

Template:

## Macro Name: include_children
## Visibility: 
## Macro Title: Include Children
## Description: This will include the content from from the child pages onto the parent page that this macro is placed on.
## Categories: Confluence content
## Icon URL: 
## Documentation URL: https://bitbucket.org/fredclown/confluence-user-macros
## Macro Body Processing: No macro body

##############################
##       Template:          ##
##############################
## Developed By: Davin Studer
## Date Created: 12/4/2014
## Updated by: Milo Grika
## Added: show/hide title, link/unlink title.
## Updated by: Gregor Mirai
## Date updated: 26/1/2016
## Added: page separator, PDF split page marker options.
## Updated by: Davin Studer
## Date updated: 4/13/2018
## Added: Include Descendants checkbox
## Updated by: Davin Studer
## Date updated: 12/3/2018
## Added: Added an option to specify the parent page.

## @param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false
## @param IncludeDescendants:title=Include Descendants|type=boolean|desc=Select to include descendants.|default=false
## @param PageSeparator:title=Page Separator|type=boolean|desc=Separate pages with horizontal ruler.|default=false
## @param SplitPages:title=Split Pages|type=boolean|desc=Split pages marker for PDF export will be inserted.|default=false
## @param Collapsible:title=Collapsible|type=boolean|desc=Should the included pages be collapsible?|default=false
## @param FilterLabel:title=Filter on Page Label|type=string|desc=Include only subpages with the specified label.
## @param Page:title=Page title|type=confluence-content|required=false|desc=If not specified, the current page is used.
## @param Order:title=Order|type=enum|enumValues=Nav Order,Reverse Nav Order,Alphabetical,Reverse Alphabetical,Create Date,Reverse Create Date|default=nav order|desc=In what order should the child pages be displayed? Nav Order refers to the order of the child pages in the page tree. Reverse Nav Order simply reverses that.

#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )

#if( $paramPage && $paramPage != "" )
    ##########################
    ## Find the page        ##
    ##########################
    #set( $parts = $paramPage.split(":") )
    #set( $i = 0 )
    #set ( $len = 0 )
    #set( $key = "" )
    #set( $name = "" )

    ##Having trouble finding out the length/size of $parts ... brute force it
    #foreach ( $part in $parts )
        #set ( $len = $len + 1 )
    #end
    
    #if ( $len == 1 )
        #set ( $key = $content.spaceKey )
        #set ( $name = $paramPage )
    #else
        #foreach ( $part in $parts )
            #if ( $i == 0 )
              #set ( $key = $part )
              #set ( $i = $i + 1 )
           #else
              #set ( $name = $part )
           #end
        #end
    #end

    #set ( $tempcontent = "" )
    #if ( $pageManager )
        #set ( $tempcontent = $pageManager.getPage($key, $name) )
    #end
    #if ( $tempcontent && $tempcontent != "" )
        #set ( $content = $tempcontent )
    #else
        The page "$paramPage" was not found in this space.
        #set ( $content = "" )
    #end
#end

#set( $data = "" )
#childPages ( $content.id )

#macro ( childPages $pageid )
    ## Find the array of (sorted) child pages.
    #if( $paramOrder == "Nav Order" || $paramOrder == "Reverse Nav Order" )
        #set( $children =  $pageManager.getPage($pageid).getSortedChildren() )
    #elseif( $paramOrder == "Alphabetical" || $paramOrder == "Reverse Alphabetical" )
        #set( $array =  $pageManager.getPage($pageid).getChildren() )
        ###############################################################
        ## Could not find a method to get them in Alphabetical order ##
        ## Must sort them myself ... Bubble sort                     ##
        ###############################################################
        #set( $size = $array.size() )
        #foreach( $junk in $array )
            #set( $count = -1 )
            #foreach( $line in $array )
                #set( $count = $count + 1 )
                #if( $velocityCount < $size )
                    #if( $line.getTitle().compareToIgnoreCase($array.get($velocityCount).getTitle()) > 0 )
                        #set( $tmp = $array.get($velocityCount) )
                        #set( $junk = $array.set($velocityCount, $line) )
                        #set( $junk = $array.set($count, $tmp) )
                    #end
                #end
            #end
        #end
        #set( $children = $array )
    #elseif( $paramOrder == "Create Date" || $paramOrder == "Reverse Create Date" )
        #set( $children =  $pageManager.getPage($pageid).getChildren() )
    #end
    
    ## Prepare children data. 
    #foreach( $child in $children )
        ## Create the map of labels for the page.
        #set( $labelsMap = {} )
        #foreach( $label in $child.getLabels() )
            #set( $dummy = $labelsMap.put($label.toString(), 1) )
        #end
    
        ## Include all pages (when no filter label is specified) or pages with a specific label.
        #if( !$paramFilterLabel || $paramFilterLabel && $labelsMap.containsKey($paramFilterLabel) )
            #set( $include = "" )
            #if ( $paramCollapsible == true )
                #set( $include = $include + '<ac:structured-macro ac:name="expand">' )
                #set( $include = $include + '<ac:parameter ac:name="title">' + $child.getTitle() + '</ac:parameter>' )
                #set( $include = $include + '<ac:rich-text-body>' )
                #set( $include = $include + '<p>' )
            #end
            #set( $include = $include + '<div class="included-child-page">' )
    
            ## Show title and links.
            #if( $paramShowTitle == true )
                #if( $paramLinkTitle == true )
                    #set( $include = $include + '<h1 class="included-child-page-title"><a href="' + $child.getUrlPath() + '">' + $child.getTitle() + '</a></h1>' )
                #else
                    #set( $include = $include + '<h1 class="included-child-page-title">' + $child.getTitle() + '</h1>' )
                #end
            #end
    
            ## Include sub page.
            #set( $include = $include + '<div class="included-child-page-body">' )
                #set( $include = $include + '<ac:structured-macro ac:name="include">' )
                    #set( $include = $include + '<ac:parameter ac:name="">' )
                        #set( $include = $include + '<ac:link>' )
                            #set( $include = $include + '<ri:page ri:content-title="' + $child.getTitle() + '" ri:space-key="' + $content.spaceKey + '"/>' )
                        #set( $include = $include + '</ac:link>' )
                    #set( $include = $include + '</ac:parameter>' )
                #set( $include = $include + '</ac:structured-macro>' )
            #set( $include = $include + '</div>' )
            #set( $include = $include + '</div>' )

            #if ( $paramCollapsible == true )
                #set( $include = $include + '</p>' )
                #set( $include = $include + '</ac:rich-text-body>' )
                #set( $include = $include + '</ac:structured-macro>' )
            #end
    
            ## Define sorting order.
            #set( $inOrder = false )
            #if( $paramOrder == "Nav Order" || $paramOrder == "Alphabetical" || $paramOrder == "Create Date" )
                #set( $inOrder = true )
            #end
    
            ## Include page separator or include page split marker used for PDF exports.
            #if( $paramPageSeparator == true )
                #set( $include = $include + '<hr/><br/>' )
            #end
            #if( $paramSplitPages == true )
                #set( $include = $include + '<div style="page-break-before:always;"></div>' )
            #end

            ## Add page content in order or in reverse order.
            #if( $inOrder == true )
                #set( $data = $data + $include )
            #else
                #set( $data = $include + $data)
            #end
        #end
        
        #if($paramIncludeDescendants == true)
            #childPages( $child.id )
        #end
    #end
#end

$data
 
<style type="text/css">
    .included-child-page {
        margin-bottom: 30px;
        overflow: hidden;
    }
</style>

 

David Joy January 9, 2019

Thanks for sharing, Davin.

I'm not seeing any child page content (I'm starting by testing all in the same space, ultimately I need to Include from a separate space).

  • I wrapped the content of each desired child pages in a Confluence Excerpt macro
  • On the target page, I added a standard Confluence Include macro, pointing to the parent page.
  • Directly under the Include macro, I added your <include Children macro.

The first macro renders the content of the parent page, but nothing appears below.

Can you give some pointers?

Appreciated,

DJ

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 9, 2019

I updated the macro last month to add an option to specify the parent page. I updated the code above just now. Probably the reason you are not seeing anything is because it is currently pulling the children of the current page. If your page has no children you won't see anything. Anyway, with the new code above you can specify the parent page (it does not have to be the page the macro is on).

Like Marcus Netz likes this
Jason Green March 26, 2019

Great Macro, thanks. Any suggestions for making this work with Scroll versioning? With multiple versions of my site, the code pulls in multiple copies of the same exact content (for each version).... Trying to find a way around this....

Jeff Tillett
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 25, 2019

Excellent macro! One of my teammates pointed out that inline comments don't show up when viewing the included pages. Do you think there is a way to add that in?

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2019

Thanks. Glad it helps. Basically, the user macro just dynamically adds in the built-in page include macro for each of the sub pages. That macro does not pull in the inline comments. So, unfortunately it not possible.

Jamil Rahimov
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 1, 2020

@Davin Studer 
I need do some changes on it.

I know I can test it adding it to user macros list.

But is there any script console or any IDE which I can test it?

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 3, 2020

Not sure what exactly you mean by that. There is an app in the market place called Enhanced User Macro Editor that enhances the macro editor to give you things such as syntax highlighting, line numbers, asynchronous save, and user macro history. To be up front I wrote the app. It doesn't give you anything like a preview functionality or anything like that ... yet. : )

If you are wanting to try the user macro out without others being able to see it you can select who can see the user macro in the macro browser when you create it. Or better yet if you have a non-production Confluence instance you could create it there and test it out before putting it into your production system.

Like Jamil Rahimov likes this
Guy Rouillard July 28, 2020

There's actually a critical issue with the macro.

Confluence lets users input HTML tags in the title of pages, and the macro does not escape them, leading to a number of rendering and security issues.

I had a page named "IO :: <script>" to describe a XML tag for one of our specifications (unrelated to HTML) and I noticed the macro would not render the link and the children pages properly. And worse, that the tags in the title were actually interpreted without any escaping.

I managed to fix it, replacing all calls like:

$child.getTitle()

by:

$generalUtil.escapeXMLCharacters($child.getTitle())

Please consider fixing it. 

Guy Rouillard July 28, 2020

Hi,

Here is my version with the fix and two added features:

  1. The headings can follow the level of the page tree (H1 for 1st level, H2 for 2nd level, and so on).
  2. Whatever is collapsible can be set to be expanded initially.
## Macro Name: include_children
## Visibility:
## Macro Title: Include Children
## Description: This will include the content from from the child pages onto the parent page that this macro is placed on.
## Categories: Confluence content
## Icon URL:
## Documentation URL: https://bitbucket.org/fredclown/confluence-user-macros
## Macro Body Processing: No macro body

##############################
## Template: ##
##############################
## Developed By: Davin Studer
## Date Created: 12/4/2014
## Updated by: Milo Grika
## Added: show/hide title, link/unlink title.
## Updated by: Gregor Mirai
## Date updated: 26/1/2016
## Added: page separator, PDF split page marker options.
## Updated by: Davin Studer
## Date updated: 4/13/2018
## Added: Include Descendants checkbox
## Updated by: Davin Studer
## Date updated: 12/3/2018
## Added: Added an option to specify the parent page.
## Updated by: Guy Rouillard
## Date updated: 28/7/2020
## Added: HeadingIncreasingLevels checkbox, CollapsedInitially checkbox
## Fixed: Page title XML character escaping
## Updated by: Guy Rouillard
## Date updated: 3/8/2020
## Fixed: HeadingIncreasingLevels implementation

## @param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false
## @param HeadingIncreasingLevels:title=Title as increasing level headings|type=boolean|desc=Select to turn the titles of the child pages into increasing level headings to those pages (Show Title must be selected).|default=false
## @param IncludeDescendants:title=Include Descendants|type=boolean|desc=Select to include descendants.|default=false
## @param PageSeparator:title=Page Separator|type=boolean|desc=Separate pages with horizontal ruler.|default=false
## @param SplitPages:title=Split Pages|type=boolean|desc=Split pages marker for PDF export will be inserted.|default=false
## @param Collapsible:title=Collapsible|type=boolean|desc=Should the included pages be collapsible?|default=false
## @param CollapsedInitially:title=Collapsed Initially|type=boolean|desc=Should the included pages be initially collapsed? (Collapsible should be selected).|default=false
## @param FilterLabel:title=Filter on Page Label|type=string|desc=Include only subpages with the specified label.
## @param Page:title=Page title|type=confluence-content|required=false|desc=If not specified, the current page is used.
## @param Order:title=Order|type=enum|enumValues=Nav Order,Reverse Nav Order,Alphabetical,Reverse Alphabetical,Create Date,Reverse Create Date|default=nav order|desc=In what order should the child pages be displayed? Nav Order refers to the order of the child pages in the page tree. Reverse Nav Order simply reverses that.

#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )

#if( $paramPage && $paramPage != "" )
##########################
## Find the page ##
##########################
#set( $parts = $paramPage.split(":") )
#set( $i = 0 )
#set ( $len = 0 )
#set( $key = "" )
#set( $name = "" )

##Having trouble finding out the length/size of $parts ... brute force it
#foreach ( $part in $parts )
#set ( $len = $len + 1 )
#end

#if ( $len == 1 )
#set ( $key = $content.spaceKey )
#set ( $name = $paramPage )
#else
#foreach ( $part in $parts )
#if ( $i == 0 )
#set ( $key = $part )
#set ( $i = $i + 1 )
#else
#set ( $name = $part )
#end
#end
#end

#set ( $tempcontent = "" )
#if ( $pageManager )
#set ( $tempcontent = $pageManager.getPage($key, $name) )
#end
#if ( $tempcontent && $tempcontent != "" )
#set ( $content = $tempcontent )
#else
The page "$paramPage" was not found in this space.
#set ( $content = "" )
#end
#end

#set( $data = "" )
#set( $counter = 0 )

##
## Used to enable the CSS/JavaScript that handle "expand" feature.
#if ( $paramCollapsible == true )
#set( $data = '<div style="display: none"><ac:structured-macro ac:name="expand"></ac:structured-macro></div>' )
#end


#set( $mainContentId = $content.id )


#childPages ( $content.id )


#macro ( childPages $pageid )
## Initialize collapsible counter
#set( $counter = $counter + 1 )

## Find the array of (sorted) child pages.
#if( $paramOrder == "Nav Order" || $paramOrder == "Reverse Nav Order" )
#set( $children = $pageManager.getPage($pageid).getSortedChildren() )
#elseif( $paramOrder == "Alphabetical" || $paramOrder == "Reverse Alphabetical" )
#set( $array = $pageManager.getPage($pageid).getChildren() )
###############################################################
## Could not find a method to get them in Alphabetical order ##
## Must sort them myself ... Bubble sort ##
###############################################################
#set( $size = $array.size() )
#foreach( $junk in $array )
#set( $count = -1 )
#foreach( $line in $array )
#set( $count = $count + 1 )
#if( $velocityCount < $size )
#if( $line.getTitle().compareToIgnoreCase($array.get($velocityCount).getTitle()) > 0 )
#set( $tmp = $array.get($velocityCount) )
#set( $junk = $array.set($velocityCount, $line) )
#set( $junk = $array.set($count, $tmp) )
#end
#end
#end
#end
#set( $children = $array )
#elseif( $paramOrder == "Create Date" || $paramOrder == "Reverse Create Date" )
#set( $children = $pageManager.getPage($pageid).getChildren() )
#end

## Prepare children data.
#foreach( $child in $children )
## Detect position in hierarchy
#set( $distToAncestor = 0 )
#set( $ancestorFound = false )
#if( $child.id == $mainContentId )
#set( $ancestorFound = true )
#end
#set( $maxIndex = $child.getAncestors().size() - 1 )
#foreach ( $index in [ $maxIndex .. 0 ] )
#set( $ancestor = $child.getAncestors().get($index) )
#if ( $ancestorFound == false )
#set ( $distToAncestor = $distToAncestor + 1 )
#if ( $ancestor.id == $mainContentId )
#set( $ancestorFound = true )
#end
#end
#end
#set( $hlevel = $distToAncestor + 1 )

## Create the map of labels for the page.
#set( $labelsMap = {} )
#foreach( $label in $child.getLabels() )
#set( $dummy = $labelsMap.put($label.toString(), 1) )
#end

## Include all pages (when no filter label is specified) or pages with a specific label.
#if( !$paramFilterLabel || $paramFilterLabel && $labelsMap.containsKey($paramFilterLabel) )
#set( $include = "" )
#if ( $paramCollapsible == true )
#set( $toggleId = $counter + 1234567890123 )
#set( $controlIconClasses = 'expand-control-icon icon' )
#set( $expanderContentClasses = 'expand-content expand-hidden' )
#if ( $paramCollapsedInitially == true )
#set( $controlIconClasses = $controlIconClasses + ' expanded' )
#set( $expanderContentClasses = 'expand-content' )
#end
#set( $include = $include + '<div id="expander-' + $toggleId + '" class="expand-container">' )
#set( $include = $include + '<div id="expander-control-' + $toggleId + '" class="expand-control">' )
#set( $include = $include + ' <span class="' + $controlIconClasses + '">&nbsp;</span>' )
#set( $include = $include + '<span class="expand-control-text">' + $generalUtil.escapeXMLCharacters($child.getTitle()) + '</span>' )
#set( $include = $include + '</div>' )
#set( $include = $include + '<div id="expander-content-' + $toggleId + '" class="' + $expanderContentClasses + '">' )
#set( $include = $include + '<p>' )
#end
#set( $include = $include + '<div class="included-child-page">' )

## Show title and links.
#if( $paramShowTitle == true )
#if( $paramHeadingIncreasingLevels != true )
#set( $hlevel = 1 )
#end
#if( $paramLinkTitle == true )
#set( $include = $include + '<h' + $hlevel + ' class="included-child-page-title"><a href="' + $child.getUrlPath() + '">' + $generalUtil.escapeXMLCharacters($child.getTitle()) + '</a></h' + $hlevel + '>' )
#else
#set( $include = $include + '<h' + $hlevel + ' class="included-child-page-title">' + $generalUtil.escapeXMLCharacters($child.getTitle()) + '</h' + $hlevel + '>' )
#end
#end

## Include sub page.
#set( $include = $include + '<div class="included-child-page-body">' )
#set( $include = $include + '<ac:structured-macro ac:name="include">' )
#set( $include = $include + '<ac:parameter ac:name="">' )
#set( $include = $include + '<ac:link>' )
#set( $include = $include + '<ri:page ri:content-title="' + $generalUtil.escapeXMLCharacters($child.getTitle()) + '" ri:space-key="' + $content.spaceKey + '"/>' )
#set( $include = $include + '</ac:link>' )
#set( $include = $include + '</ac:parameter>' )
#set( $include = $include + '</ac:structured-macro>' )
#set( $include = $include + '</div>' )
#set( $include = $include + '</div>' )

#if ( $paramCollapsible == true )
#set( $include = $include + '</p>' )
#set( $include = $include + '</div>' )
#set( $include = $include + '</div>' )
#end

## Define sorting order.
#set( $inOrder = false )
#if( $paramOrder == "Nav Order" || $paramOrder == "Alphabetical" || $paramOrder == "Create Date" )
#set( $inOrder = true )
#end

## Include page separator or include page split marker used for PDF exports.
#if( $paramPageSeparator == true )
#set( $include = $include + '<hr/><br/>' )
#end
#if( $paramSplitPages == true )
#set( $include = $include + '<div style="page-break-before:always;"></div>' )
#end

## Add page content in order or in reverse order.
#if( $inOrder == true )
#set( $data = $data + $include )
#else
#set( $data = $include + $data )
#end
#end

#if($paramIncludeDescendants == true)
#childPages( $child.id )
#end
#end
#end

$data

<style type="text/css">
.included-child-page {
margin-bottom: 30px;
overflow: hidden;
}
</style>
Like # people like this
DIGIT CITnet October 19, 2020

Thanks for this great macro and the latest update!

We just upgraded to 7.8.1 and the macro stopped to work. The output is now HTML and css codes instead of the list of child pages.

Can you have a look in to it if you have some free time? :)

Cheers,

Guy Rouillard October 19, 2020

I'm sorry, but I won't be able to help here.

My employer is still using the 5.6.5 version of Confluence, since the cost of extended support is considered too high to be justifiable (security holes are being patched by ourselves) and will upgrade about each 5-7 years.

The issue may be that the macro configuration is incorrect. There are settings that tell how the macro will be interpreted and behave. Per example, the macro we're talking about requires a Macro Body Processing of No macro body type.

Of course, the macro produces both HTML and CSS, but they should be returned in the page HTML flow (and not be interpreted as text).

Orhan Ugurlu December 7, 2020

For others that experience problem on 7.8, I have been able to have it working by following changes:

  • Seems default values became case sensitive, therefore, updated default value of Order parameter from 'nav order' to 'Nav Order'
  • For the rendering of the data, instead of '$data', used '#evaluate($data)'
Like # people like this
2 votes
Robert Reiner _smartics_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 30, 2015

There is a commercial add-on (projectdoc - biased alert! I'm one of the authors  smile) that allows to transclude fragments of a document query result set. In the documentation there is an example on how to transclude child documents. The macro takes care of heading level adjustments and allows to filter on the transcluded sections.

The downside is that you need to define sections in the child documents (or any document you want to transclude), since only content of sections is transcluded. This is very similar to the Excerpt Macro provided by Atlassian.

0 votes
Jochen Berdi March 29, 2021

we have added it under confluence 7.5 but macro is not displayed

Orhan Ugurlu March 29, 2021

We are using 7.8 and it is working as is. Maybe you need to revert #evaluate($data) back to $data on 7.5.

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 29, 2021

I can't remember which version it was, but Atlassian removed the ability to to do this...

#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )

You can add it back, but you need to edit some files on the server to do it. You need to edit the Confluence install directory/Confluence/confluence/WEB-INF/classes/velocity.properties file. You need to change this ...

introspector.restrict.packages = java.lang.reflect,\

to 

introspector.restrict.packages = \ 

and this ..

introspector.restrict.classes = java.lang.Class,\
java.lang.ClassLoader,\
 

to

introspector.restrict.classes = \

I'm on 7.6 and I know I had to do that. If this is working in 7.8 maybe Atlassian put that ability back in for user macros.

Jochen Berdi May 10, 2021

Also under 7.11.2 it does not run on our system (Confluence Server). Is there any way to get it to work without customizing the properties?
In the macro text there are still two or three $data entries, is that correct?
I am a complete newbie and our IT would like if budget or ready macros.

Alexander Poryvkin September 13, 2021

On 7.13.0 it also does not work( 

Orhan Ugurlu September 13, 2021

As mentioned before, I am using the following without any problems, also now on 7.13.0. I am not able to figure out how to retain spaces while pasting here.

## Updated version of macro retrieved from https://community.atlassian.com/t5/Confluence-questions/can-you-include-all-child-pages-automatically/qaq-p/86946
## Added same level page including except itself
## Added support for multiple labels for filtering and excluding

## Macro Name: include_children
## Visibility:
## Macro Title: Include Children
## Description: This will include the content from from the child pages onto the parent page that this macro is placed on.
## Categories: Confluence content
## Icon URL:
## Documentation URL: https://bitbucket.org/fredclown/confluence-user-macros
## Macro Body Processing: No macro body

##############################
## Template: ##
##############################
## Developed By: Davin Studer
## Date Created: 12/4/2014
## Updated by: Milo Grika
## Added: show/hide title, link/unlink title.
## Updated by: Gregor Mirai
## Date updated: 26/1/2016
## Added: page separator, PDF split page marker options.
## Updated by: Davin Studer
## Date updated: 4/13/2018
## Added: Include Descendants checkbox
## Updated by: Davin Studer
## Date updated: 12/3/2018
## Added: Added an option to specify the parent page.

## @param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false
## @param IncludeDescendants:title=Include Descendants|type=boolean|desc=Select to include descendants.|default=false
## @param IncludeSameLevel:title=Include Same Level|type=boolean|desc=Select to include same level pages.|default=false
## @param PageSeparator:title=Page Separator|type=boolean|desc=Separate pages with horizontal ruler.|default=false
## @param SplitPages:title=Split Pages|type=boolean|desc=Split pages marker for PDF export will be inserted.|default=false
## @param Collapsible:title=Collapsible|type=boolean|desc=Should the included pages be collapsible?|default=false
## @param FilterLabel:title=Filter on Page Label|type=string|desc=Include only subpages with the specified label(s).
## @param ExcludeLabel:title=Exclude on Page Label|type=string|desc=Exclude subpages with the specified label(s).
## @param Page:title=Page title|type=confluence-content|required=false|desc=If not specified, the current page is used.
## @param Order:title=Order|type=enum|enumValues=Nav Order,Reverse Nav Order,Alphabetical,Reverse Alphabetical,Create Date,Reverse Create Date|default=Nav Order|desc=In what order should the child pages be displayed? Nav Order refers to the order of the child pages in the page tree. Reverse Nav Order simply reverses that.

#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )

#if( $paramPage && $paramPage != "" )
##########################
## Find the page ##
##########################
#set( $parts = $paramPage.split(":") )
#set( $i = 0 )
#set ( $len = 0 )
#set( $key = "" )
#set( $name = "" )

##Having trouble finding out the length/size of $parts ... brute force it
#foreach ( $part in $parts )
#set ( $len = $len + 1 )
#end

#if ( $len == 1 )
#set ( $key = $content.spaceKey )
#set ( $name = $paramPage )
#else
#foreach ( $part in $parts )
#if ( $i == 0 )
#set ( $key = $part )
#set ( $i = $i + 1 )
#else
#set ( $name = $part )
#end
#end
#end

#set ( $tempcontent = "" )
#if ( $pageManager )
#set ( $tempcontent = $pageManager.getPage($key, $name) )
#end
#if ( $tempcontent && $tempcontent != "" )
#set ( $content = $tempcontent )
#else
The page "$paramPage" was not found in this space.
#set ( $content = "" )
#end
#end

#set( $data = "" )
#if( $paramIncludeSameLevel == true )
#childPages ( $$pageManager.getPage($content.id).getParent().id, $content.id)
#else
#childPages ( $content.id, "" )
#end

#macro ( childPages $pageid $excludePageId)
## Find the array of (sorted) child pages.
#if( $paramOrder == "Nav Order" || $paramOrder == "Reverse Nav Order" )
#set( $children = $pageManager.getPage($pageid).getSortedChildren() )
#elseif( $paramOrder == "Alphabetical" || $paramOrder == "Reverse Alphabetical" )
#set( $array = $pageManager.getPage($pageid).getChildren() )
###############################################################
## Could not find a method to get them in Alphabetical order ##
## Must sort them myself ... Bubble sort ##
###############################################################
#set( $size = $array.size() )
#foreach( $junk in $array )
#set( $count = -1 )
#foreach( $line in $array )
#set( $count = $count + 1 )
#if( $velocityCount < $size )
#if( $line.getTitle().compareToIgnoreCase($array.get($velocityCount).getTitle()) > 0 )
#set( $tmp = $array.get($velocityCount) )
#set( $junk = $array.set($velocityCount, $line) )
#set( $junk = $array.set($count, $tmp) )
#end
#end
#end
#end
#set( $children = $array )
#elseif( $paramOrder == "Create Date" || $paramOrder == "Reverse Create Date" )
#set( $children = $pageManager.getPage($pageid).getChildren() )
#end

## Prepare children data.
#foreach( $child in $children )
## Create the map of labels for the page.
#set( $labelsMap = {} )
#foreach( $label in $child.getLabels() )
#set( $dummy = $labelsMap.put($label.toString(), 1) )
#end

#set( $filterLabelMatched = false )
#if ( $paramFilterLabel && $paramFilterLabel.trim().length() > 0 )
#set( $labelsToFilter = $paramFilterLabel.split("\W+") )
#foreach( $label in $labelsToFilter )
#if ( $labelsMap.containsKey($label) == true )
#set( $filterLabelMatched = true )
#end
#end
#else
#set( $filterLabelMatched = true )
#end

#set( $excludeLabelMatched = false )
#if ( $paramExcludeLabel && $paramExcludeLabel.trim().length() > 0 )
#set( $labelsToExclude = $paramExcludeLabel.split("\W+") )
#foreach( $label in $labelsToExclude )
#if ( $labelsMap.containsKey($label) == true )
#set( $excludeLabelMatched = true )
#end
#end
#end

## Include all pages (when no filter label is specified) or pages with a specific label.
#if( $child.id != $excludePageId && $filterLabelMatched == true && $excludeLabelMatched == false )
#set( $include = "" )
#if ( $paramCollapsible == true )
#set( $include = $include + '<ac:structured-macro ac:name="expand">' )
#set( $include = $include + '<ac:parameter ac:name="title">' + $child.getTitle() + '</ac:parameter>' )
#set( $include = $include + '<ac:rich-text-body>' )
#set( $include = $include + '<p>' )
#end
#set( $include = $include + '<div class="included-child-page">' )

## Show title and links.
#if( $paramShowTitle == true )
#if( $paramLinkTitle == true )
#set( $include = $include + '<h1 class="included-child-page-title"><a href="' + $req.contextPath + $child.getUrlPath() + '">' + $child.getTitle() + '</a></h1>' )
#else
#set( $include = $include + '<h1 class="included-child-page-title">' + $child.getTitle() + '</h1>' )
#end
#end

## Include sub page.
#set( $include = $include + '<div class="included-child-page-body">' )
#set( $include = $include + '<ac:structured-macro ac:name="include">' )
#set( $include = $include + '<ac:parameter ac:name="">' )
#set( $include = $include + '<ac:link>' )
#set( $include = $include + '<ri:page ri:content-title="' + $child.getTitle() + '" ri:space-key="' + $content.spaceKey + '"/>' )
#set( $include = $include + '</ac:link>' )
#set( $include = $include + '</ac:parameter>' )
#set( $include = $include + '</ac:structured-macro>' )
#set( $include = $include + '</div>' )
#set( $include = $include + '</div>' )

#if ( $paramCollapsible == true )
#set( $include = $include + '</p>' )
#set( $include = $include + '</ac:rich-text-body>' )
#set( $include = $include + '</ac:structured-macro>' )
#end

## Define sorting order.
#set( $inOrder = false )
#if( $paramOrder == "Nav Order" || $paramOrder == "Alphabetical" || $paramOrder == "Create Date" )
#set( $inOrder = true )
#end

## Include page separator or include page split marker used for PDF exports.
#if( $paramPageSeparator == true )
#set( $include = $include + '<hr/><br/>' )
#end
#if( $paramSplitPages == true )
#set( $include = $include + '<div style="page-break-before:always;"></div>' )
#end

## Add page content in order or in reverse order.
#if( $inOrder == true )
#set( $data = $data + $include )
#else
#set( $data = $include + $data)
#end
#end

#if($paramIncludeDescendants == true)
#childPages( $child.id )
#end
#end
#end

#evaluate($data)

<style type="text/css">
.included-child-page {
margin-bottom: 30px;
overflow: hidden;
}
</style>
Like # people like this
Alexander Pucher November 10, 2021

@Orhan Ugurlu- thanks so much for pasting the macro.

It works perfectly in Confluence Data Center 7.13.2!

Alexander Poryvkin April 13, 2023

We updated our Confluence to 7.19.7 and it started to show:
The page "page name" was not found in this space.

Does anyone know how to fix it?

0 votes
Jochen Berdi March 26, 2021

I would like to ask if it is possible to specify a parent page and then display the contents of this parent page with all the contents of the child pages.

Orhan Ugurlu March 26, 2021

Version that I updated has that capability:


## Macro Name: include_children
## Visibility:
## Macro Title: Include Children
## Description: This will include the content from from the child pages onto the parent page that this macro is placed on.
## Categories: Confluence content
## Icon URL:
## Documentation URL: https://bitbucket.org/fredclown/confluence-user-macros
## Macro Body Processing: No macro body

##############################
## Template: ##
##############################
## Developed By: Davin Studer
## Date Created: 12/4/2014
## Updated by: Milo Grika
## Added: show/hide title, link/unlink title.
## Updated by: Gregor Mirai
## Date updated: 26/1/2016
## Added: page separator, PDF split page marker options.
## Updated by: Davin Studer
## Date updated: 4/13/2018
## Added: Include Descendants checkbox
## Updated by: Davin Studer
## Date updated: 12/3/2018
## Added: Added an option to specify the parent page.
## Added/Updated by: Orhan ugurlu
## Date updated: 26/3/2021
## Added: IncludeSameLevel and ExcludeLabel capability
## Updated: Updated for version 7.8: default value of Order parameter from 'nav order' to 'Nav Order', instead of '$data', used '#evaluate($data)'

## @Param ShowTitle:title=Show Title|type=boolean|desc=Deselect to remove the title of the child page.|default=true
## @Param LinkTitle:title=Link Title|type=boolean|desc=Select to turn the titles of the child pages into links to those pages (Show Title must be selected).|default=false
## @Param IncludeDescendants:title=Include Descendants|type=boolean|desc=Select to include descendants.|default=false
## @Param IncludeSameLevel:title=Include Same Level|type=boolean|desc=Select to include same level pages.|default=false
## @Param PageSeparator:title=Page Separator|type=boolean|desc=Separate pages with horizontal ruler.|default=false
## @Param SplitPages:title=Split Pages|type=boolean|desc=Split pages marker for PDF export will be inserted.|default=false
## @Param Collapsible:title=Collapsible|type=boolean|desc=Should the included pages be collapsible?|default=false
## @Param FilterLabel:title=Filter on Page Label|type=string|desc=Include only subpages with the specified label.
## @Param ExcludeLabel:title=Exclude on Page Label|type=string|desc=Exclude subpages with the specified label.
## @Param Page:title=Page title|type=confluence-content|required=false|desc=If not specified, the current page is used.
## @Param Order:title=Order|type=enum|enumValues=Nav Order,Reverse Nav Order,Alphabetical,Reverse Alphabetical,Create Date,Reverse Create Date|default=Nav Order|desc=In what order should the child pages be displayed? Nav Order refers to the order of the child pages in the page tree. Reverse Nav Order simply reverses that.

#set( $containerManagerClass=$content.class.forName('com.atlassian.spring.container.ContainerManager') )
#set( $getInstanceMethod=$containerManagerClass.getDeclaredMethod('getInstance',null) )
#set( $containerManager=$getInstanceMethod.invoke(null,null) )
#set( $containerContext=$containerManager.containerContext )
#set( $pageManager=$containerContext.getComponent('pageManager') )

#if( $paramPage && $paramPage != "" )
##########################
## Find the page ##
##########################
#set( $parts = $paramPage.split(":") )
#set( $i = 0 )
#set ( $len = 0 )
#set( $key = "" )
#set( $name = "" )

##Having trouble finding out the length/size of $parts ... brute force it
#foreach ( $part in $parts )
#set ( $len = $len + 1 )
#end

#if ( $len == 1 )
#set ( $key = $content.spaceKey )
#set ( $name = $paramPage )
#else
#foreach ( $part in $parts )
#if ( $i == 0 )
#set ( $key = $part )
#set ( $i = $i + 1 )
#else
#set ( $name = $part )
#end
#end
#end

#set ( $tempcontent = "" )
#if ( $pageManager )
#set ( $tempcontent = $pageManager.getPage($key, $name) )
#end
#if ( $tempcontent && $tempcontent != "" )
#set ( $content = $tempcontent )
#else
The page "$paramPage" was not found in this space.
#set ( $content = "" )
#end
#end

#set( $data = "" )
#if( $paramIncludeSameLevel == true )
#childPages ( $$pageManager.getPage($content.id).getParent().id, $content.id)
#else
#childPages ( $content.id, "" )
#end

#macro ( childPages $pageid $excludePageId)
## Find the array of (sorted) child pages.
#if( $paramOrder == "Nav Order" || $paramOrder == "Reverse Nav Order" )
#set( $children = $pageManager.getPage($pageid).getSortedChildren() )
#elseif( $paramOrder == "Alphabetical" || $paramOrder == "Reverse Alphabetical" )
#set( $array = $pageManager.getPage($pageid).getChildren() )
###############################################################
## Could not find a method to get them in Alphabetical order ##
## Must sort them myself ... Bubble sort ##
###############################################################
#set( $size = $array.size() )
#foreach( $junk in $array )
#set( $count = -1 )
#foreach( $line in $array )
#set( $count = $count + 1 )
#if( $velocityCount < $size )
#if( $line.getTitle().compareToIgnoreCase($array.get($velocityCount).getTitle()) > 0 )
#set( $tmp = $array.get($velocityCount) )
#set( $junk = $array.set($velocityCount, $line) )
#set( $junk = $array.set($count, $tmp) )
#end
#end
#end
#end
#set( $children = $array )
#elseif( $paramOrder == "Create Date" || $paramOrder == "Reverse Create Date" )
#set( $children = $pageManager.getPage($pageid).getChildren() )
#end

## Prepare children data.
#foreach( $child in $children )
## Create the map of labels for the page.
#set( $labelsMap = {} )
#foreach( $label in $child.getLabels() )
#set( $dummy = $labelsMap.put($label.toString(), 1) )
#end

## Include all pages (when no filter label is specified) or pages with a specific label.
#if( $child.id != $excludePageId && (!$paramFilterLabel || $paramFilterLabel && $labelsMap.containsKey($paramFilterLabel)) && (!$paramExcludeLabel || $paramExcludeLabel && !$labelsMap.containsKey($paramExcludeLabel)))
#set( $include = "" )
#if ( $paramCollapsible == true )
#set( $include = $include + '<ac:structured-macro ac:name="expand">' )
#set( $include = $include + '<ac:parameter ac:name="title">' + $child.getTitle() + '</ac:parameter>' )
#set( $include = $include + '<ac:rich-text-body>' )
#set( $include = $include + '<p>' )
#end
#set( $include = $include + '<div class="included-child-page">' )

## Show title and links.
#if( $paramShowTitle == true )
#if( $paramLinkTitle == true )
#set( $include = $include + '<h1 class="included-child-page-title"><a href="' + $req.contextPath + $child.getUrlPath() + '">' + $child.getTitle() + '</a></h1>' )
#else
#set( $include = $include + '<h1 class="included-child-page-title">' + $child.getTitle() + '</h1>' )
#end
#end

## Include sub page.
#set( $include = $include + '<div class="included-child-page-body">' )
#set( $include = $include + '<ac:structured-macro ac:name="include">' )
#set( $include = $include + '<ac:parameter ac:name="">' )
#set( $include = $include + '<ac:link>' )
#set( $include = $include + '<ri:page ri:content-title="' + $child.getTitle() + '" ri:space-key="' + $content.spaceKey + '"/>' )
#set( $include = $include + '</ac:link>' )
#set( $include = $include + '</ac:parameter>' )
#set( $include = $include + '</ac:structured-macro>' )
#set( $include = $include + '</div>' )
#set( $include = $include + '</div>' )

#if ( $paramCollapsible == true )
#set( $include = $include + '</p>' )
#set( $include = $include + '</ac:rich-text-body>' )
#set( $include = $include + '</ac:structured-macro>' )
#end

## Define sorting order.
#set( $inOrder = false )
#if( $paramOrder == "Nav Order" || $paramOrder == "Alphabetical" || $paramOrder == "Create Date" )
#set( $inOrder = true )
#end

## Include page separator or include page split marker used for PDF exports.
#if( $paramPageSeparator == true )
#set( $include = $include + '<hr/><br/>' )
#end
#if( $paramSplitPages == true )
#set( $include = $include + '<div style="page-break-before:always;"></div>' )
#end

## Add page content in order or in reverse order.
#if( $inOrder == true )
#set( $data = $data + $include )
#else
#set( $data = $include + $data)
#end
#end

#if($paramIncludeDescendants == true)
#childPages( $child.id )
#end
#end
#end

#evaluate($data)

<style type="text/css">
.included-child-page {
margin-bottom: 30px;
overflow: hidden;
}
</style>

 

Michael Scholze June 4, 2021

On this version I get a "Missing Metadata" Macro error in our Confluence Server 7.8.1 version. 

Aside from that this macro works with version  3/8/2020 by @Guy Rouillard  above, but only when I use ...

#evaluate($data)

 at the end instead of $data.

---- 

As an request: Since we have a lot of "smaller" subpages with little content acting as "Infocards", would it be possible to render the output in a way that breaks over horizontally (e.g. like a 2-3 column layout)?

It would be fantastic to have since our colleagues have a lot of "small" info pages (e.g. with properties) that could be displayed on wider screens like a sort of dashboard.

Alexander Poryvkin April 7, 2023

We updated our Confluence to 7.19.7 and it started to show:
The page "page name" was not found in this space.

Does anyone know how to fix it?

0 votes
Andrea Striesova August 28, 2020

Hello all!

Is there any way how to use this function on cloud?

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 28, 2020

Unfortunately no. User macros are not enabled in Confluence Cloud.

Andrea Striesova September 2, 2020

I actually found solution for myself on Confluence Cloud. Not sure if it belongs to this community space but here it is:

There is the macro "Children Display". In the macro settings Excerpt Display choose "rich content" and all the child pages will be displayed on the parent page, however without attachments (e.g.pictures), only text.

BUT, if all the content of the child page is placed inside of an Excerpt macro, all the content including attachments will be displayed via the Children Display macro! 

Obviously I have to have this in mind when creating new child pages, but it works for me well right now since I'm just starting to create a whole new page structure.

0 votes
Alexander Poryvkin March 12, 2020

@Davin StuderHi! thank you for the macro.

I want to ask, is it possible to modify it to add an ability to specify the parent page? For example, if i want to place the macro to one page but render children from another parent page.

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 16, 2020

That parameter is already in the user macro. It is the "Page title" parameter.

Like Alexander Poryvkin likes this
0 votes
Josef Bayer Gmail August 29, 2017

1. No, you can not.

2. There might be some free or non-free add-ons or macros, but in a corporate Jira it is an impossible mission to achieve, that sys admins would install them.

Josef Bayer Gmail August 29, 2017

And please let me know, if a new release would bring the feature.

Davin Studer
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 5, 2017

The above user macro works well.

0 votes
Kay Brown
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 27, 2015

Hi Nate,

You can use the Children Display macro.  It is located in the macro browser.

 

Regards,

Kay

Ben November 26, 2015

I believe they want the content of the pages. Not just the links to the pages.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events