The Admin's tale - Lost in Documentation

lost.png

Once upon a time, there were a lot of people in the admin's kingdom who wanted to get rid of their old Doc2Help and MS Word grimoires. They wanted to have them in their Confluence, but, of course, didn't want to transcribe all the recipes once again. 

Since most of the books were saved in MS Office format, it was easy to import them into Confluence. There is a funtion called "Import Word Document" on every single page's "..." - menu.

The documents were quite large. In these times, people knew a lot of spells, curses and recipes for magic potions, you know. The first attempt to import the documents resulted in pages with thousands of lines. They were not clearly arranged and if you scrolled to line 4815 or 162342 or just to line 108, you were totally lost.

The next attempt was, of course, generating several Confluence pages depending on the heading structure of the Word document. Pages were smaller (fine), but they were not linked to one another (oops). During these times, when the first imports were made, the generated pages were not even sorted in the original order, but in an alphabetical order. Today, this is fixed, the Confluence pages are sorted the way they were in the original document, but it is hard to navigate through a document that is fragmented into dozens of pages. 

So, how can you add some kind of navigational structure to your fragmented documents? Let me tell you, what the admin implemented for his people.

There were three main requirements:

  • Make it easy, so that people have no effort
  • People should have no effort, so make it easy for them
  • No plugins with costs

Always the same requirements, the admin thought. And as so often, he thought of a user macro as an easy solution. Easy for the people, not too bad for the admin.

And this is, what he came out with:

(if you don't know anything about user macros, please have a look at this article first)

In this example we will work with the following page structure

image.png

Most of these pages include some headings (1 and 2).

People wanted to get an easy way to navigate through these pages. So the admin thought, it would be nice to have a header on every page that 

  • shows the headings on the page itself
  • lists the subpages of the page
  • lists the pages on the same page's level (e.g. "Page 1" and "Page 2" are on the same level in our example)
  • links to the parent page

image.png

This header includes two built-in macros on the left side:

  • Table of Contents
  • Children Display

But how do you get the functionality on the right side?

First: Pages on the same level 

If you think about that, you will soon find out that pages on the same level are the children of the parent page. 

On the parent page, there's no problem in listing the children, just use the child pages macro. But how do you get this list on the child pages? 

We will see that later... 

Second: Display a link to the parent page

This can be implemented with a simple user macro:

image.png

 image.png

## @noparams 
#if (!$content.getParent()) <b>No parent page found</b>
#else
#contentLink2($content.getParent() false false)
#end

(thanks to @Stephen Deutsch "img srcxss onerroralert(1)  and  @David Grierson for that solution on https://community.atlassian.com/t5/Confluence-questions/Add-link-to-navigate-to-parent-page/qaq-p/410323)

We will need this macro later, so keep it please. 

Putting that all together

Now we put these pieces together to one single user macro. On the left side, we want to see the first two parts (children and toc), on the right side, the second parts ("sisters and brothers" and link-to-parent).

You can get the basic frame for such a macro quite easy using the Confluence Source Editor plugin. With that plugin, you can see and edit the storage format of your confluence page.

So first, create a page with two columns and the three macros:

image.png

Save the page, edit it again and look at the Source Editor:

image.png

The source looks something like this:

<ac:layout>
<ac:layout-section ac:type="two_equal">
<ac:layout-cell>
<p>
<ac:structured-macro ac:macro-id="81020102-bc75-44ac-bf9e-b0887eacf395" ac:name="children" ac:schema-version="2"/>
</p>
<p>
<ac:structured-macro ac:macro-id="1fd2e4a9-be38-4ed7-bd7c-f8068a6db0a1" ac:name="toc" ac:schema-version="1"/>
</p>
</ac:layout-cell>
<ac:layout-cell>
<p> </p>
<p>
<ac:structured-macro ac:macro-id="66b48c60-e154-4e42-b564-149ffe84429e" ac:name="link-to-parent" ac:schema-version="1"/>
</p>
</ac:layout-cell>
</ac:layout-section>
</ac:layout>

Copy that all and put it as template into your user macro. Then remove all the "ac:macro-id="..."" tags. They are useless and just confusing.

The first line of your macro should look like that:

## @noparams

We don't need any parameter for this macro.

The Admin had to add code for showing the pages on the same level ("Sisters and Brothers"). This is done like that:

 #set($childpages = $content.getParent().getChildren())
<ul>
#foreach($page in $childpages)
<li>
#contentLink2($page false false)
</li>
#end

$content.getParent() is getting the parent of the page.

".getChildren" gets all the children of the parent, these are the page itself and all its "brothers and sisters".

Then, every child is added to the unordered list.

In the end, the whole macro looks like that:

image.png

image.png

## @noparams

<ac:layout>
<ac:layout-section ac:type="two_equal">
<ac:layout-cell>
<p>
<ac:structured-macro ac:name="toc" ac:schema-version="1"/>
<p>
<ac:structured-macro ac:name="children" ac:schema-version="2"/>
</p>
</ac:layout-cell>
<ac:layout-cell>
<p>
#set($childpages = $content.getParent().getChildren())
<ul>
#foreach($page in $childpages)
<li>
#contentLink2($page false false)
</li>
#end
</ul>
</p>
<p>
<ac:structured-macro ac:name="link-to-parent" ac:schema-version="1"/>
</p>
</ac:layout-cell>
</ac:layout-section>
</ac:layout>

 

On the pages, it looks like that:

image.png

 

The Admin's people put the macro on top of their content and were happy to get all the navigational stuff they need with just one little macro.

And because they never got lost in their documents anymore, they all lived happily ever after.  

 

5 comments

Béla Hegyesi June 22, 2023

Hi @Thomas Schlegel

Thank you for sharing this method.
Unfortunately, the #contentLink2($content.getParent() false false) is not working anymore, because the getParent function has been deprecated since 6.13.
Can you provide an updated and working code, for newer Confluence versions, like 7.X?

Thanks,
Bela

Thomas Schlegel
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
June 23, 2023

Hi @Béla Hegyesi 

the macro still works in our Confluence 7.13.7  - I just tested it.

Best,

Thomas

Béla Hegyesi June 26, 2023

Hi @Thomas Schlegel

I tested it on Confluence 7.19.9, and it displays the following for me:

usermacro.png

Before the upgrade, it worked perfectly.

BR.,
Bela

Like D’Ante Barnes likes this
Thomas Schlegel
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
June 26, 2023

Thank you for the information, @Béla Hegyesi .

Since we do not have 7.19.9 yet, I can't test the functionality. Maybe you or someone else can find a working solution for version 7.19.9 or later.

D’Ante Barnes
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
June 28, 2023

@Béla Hegyesi There was a change in confluence 7.19 where you now have to allow htmlUtil (and other velocity macros) in the system properties. 

https://confluence.atlassian.com/doc/recognized-system-properties-190430.html#:~:text=macro.required.velocity.context.keys

So you would need to add a line to your configuration similar to this and restart your server:

CATALINA_OPTS="-Dmacro.required.velocity.context.keys=htmlUtil${CATALINA_OPTS}"

This fixed the issues for me.

Like Béla Hegyesi likes this

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events