Can I create macros within an HTML macro?

Willy Case February 1, 2018

Hi,

I am just a user, and not an admin of my team's Confluence server. However, I frequently use the HTML macro to include snippets of Javascript to generate dynamic content of some sort. What I'd really like to do is to include an excerpt-include macro within that dynamic content. So, my javascript would generate/edit some html that could include 1 to several excerpt include macros based on some criteria.

Is this possible with Confluence?

Thanks

1 answer

2 votes
Stephen Deutsch
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 2, 2018

Hi Willy,

It's a bit hackish, but not impossible:

<script>
function renderAndInsertMarkup(markup, containingElement) {
var dataObj = {};
dataObj.representation = "storage";
dataObj.content = {};
dataObj.content.id = AJS.params.pageId;
dataObj.value = markup;

jQuery.ajax({dataType: 'json',
contentType: 'application/json',
type: 'POST',
url: contextPath + '/rest/api/contentbody/convert/view',
data: JSON.stringify(dataObj),
success: function(response) {
jQuery(containingElement).append(response.value);
}
});
}
renderAndInsertMarkup(`<ac:structured-macro ac:name="cheese" />`, "#output-markup");
</script>
<div id="output-markup"></div>
Willy Case February 7, 2018

This works perfectly. Thank you!

EwingLin April 24, 2019

Thanks! This solution is what I'm looking for!

Stefan Mueller April 30, 2019

Hello,
@Stephen Deutsch could you explain the code in more detail?

I'm trying to do the same with the Popular Labels Macro what works basically. I'm trying to refine by means of its parameters but no clue how to get them into the code. 
Could you explain the purposes of the \ and / ?  I tried several approached inspired by using macros inside user macrosPossible to Call User Macro inside another User Macro?using macros inside user macros and Using confluence macro code inside user macro (entity names were exchanged) but nothing worked out. Could you help out?

Stefan Mueller April 30, 2019

it took me a while but I figured it out based on the description of Section Macro

\"your string\" is to mark a string including the quotation marks

var arg1 = "<ac:structured-macro ac:name=\"popular-labels\" > "+ 
				"<ac:parameter ac:name=\"style\">heatmap</ac:parameter> "+
				"<ac:parameter ac:name=\"spaceKey\">MANMECOSWIKI</ac:parameter> "+
			"</ac:structured-macro>"
renderAndInsertMarkup(arg1 , "#output-markup");

 

Stefan Mueller April 30, 2019

I still need some help here as I try the same with Contet By Label Macro, what was my original intention.  

By using the in browsers dev tools I figure out the macro name, what is contentbylabel. I did the same to give me an idea about the right parameters to be used in the code. 
The inspector gives me

data-macro-parameters="cql=label \= "amb" and label \= "glossary" and label \= "glossary_b"

but I how to work with the quotation marks around the label name in the code?
I tried without success:

  • <ac:parameter ac:name=\"cql=label\\">amb</ac:parameter> "
  • <ac:parameter ac:name=\"cql=label\\">"amb"</ac:parameter> "
  • <ac:parameter ac:name=\"cql=label\\">\"amb\"</ac:parameter> "
  • <ac:parameter ac:name=\"cql=label\\">\""amb"\"</ac:parameter> "
  • <ac:parameter ac:name=\"cql=label\\">&quot;glossary&quot</ac:parameter> "
  • <ac:parameter ac:name=\"cql=label\\">\"&quot;glossary&quot\"</ac:parameter> "

get macro name.png

Stephen Deutsch
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.
May 1, 2019

Hi Stefan, sorry for not getting back to you sooner.

Instead of trying to figure out how to do the quotes, it might just be easier to use backticks: `` which are now supported by most modern browsers. Then just put the code inside and it should work OK.

Stefan Mueller May 6, 2019

Hoi Stephen,
no worries, I was on vacation anyway :).

May I try to understand your code. You can divide it roughly into four sections.
I try to explain where I can find documentation but that is not given for each line.

  1. creating a JavaScript Object
     var dataObj = {};
    Details e.g. on JavaScript Objects | w3schools. or How To Use Object Methods in JavaScript | DigitalOcean or a more complex application Passing Data as JS Objects | Chart Data | ZingChart
     dataObj.representation = "storage";
    I find only ContentRepresentation (Atlassian Confluence 5.8.8 API) but it is not self-explaining. I found some in Custom Content | developer.atlassian.com and How do you post markdown using confluences rest API? is enlighten me slightly but I'm still a bit clueless. 
     dataObj.content = {};
    dataObj.content.id = AJS.params.pageId;
    dataObj.value = markup;
    cannot find anything explaining their necessity. 

  2. erform an asynchronous HTTP (Ajax) request.

    jQuery.ajax({

    Details e.g. on jQuery ajax() Method | w3schoolsjQuery.ajax() | jQuery API Documentation.

      contentType: 'application/json',
    type: 'POST',
    url: contextPath + '/rest/api/contentbody/convert/view',
    data: JSON.stringify(dataObj),

     

    Can be properly explained well based on jQuery Ajax Post Method | freeCodeCamp Guide and javascript - Returning the response from an Jquery AJAX call - Stack Overflow.

    Confluence Server is asked to process the contentType: 'application/json', what comes as JSON string due to data: JSON.stringify(dataObj) by the API contentbody/convert/view, accessible via
    context path is the path to Confluence
    and the 
    Contentbody API (REST API examplesConfluence REST API Documentation)
    supported by 
    1. Dynamic Content Macro: How to retrieve rendered macro body | The Atlassian Developer Community 
    2. How do the various Confluence document formats differ? - Stack Overflow
    3. Confluence Rest API Maintaining Macros After View | The Atlassian Community.

  3. The append() method inserts specified content at the end of the selected elements.
    This happens when action two is successful

    jQuery(containingElement).append
    Due to the location in the HTML Macro,  the new Macro is added at the same spot where the HTML Macro is located and the pageID as part of the JS Object (see 1).
    More details about append are e.g. on
    1. jQuery append() Method | w3schools
    2. jquery .html() vs .append() - Stack Overflow
    3. append() | jQuery API Documentation

  4. The function call

    renderAndInsertMarkup(
    Based on the wording I assume that uses Confluence Wiki Markup and Confluence Storage Format, respectively, what renders the code but where is this documented?
    Could it be that all that we do here is to edit the underlying markup of a Confluence page, what is XHTML-based format that Confluence uses to store the content of pages, page templates, blueprints, blog posts and comments?

    I do not find anything in regard to structured macro. I find them only in the description of some macros as e.g. the Section Macro and View storage format | The Atlassian Community but in none of them is anything mentioned in regard of the quotation marks, where and how to use them.



@Stephen Deutsch "img srcxss onerroralert(1), any chance that you may enlight me?

 

Stefan

Stefan Mueller May 10, 2019

@Stephen Deutschbefore we may get lost in details could you answer point 4 first?

Stephen Deutsch
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.
May 11, 2019

Hi Stefan,

ac:structured-macro simply refers to a standard macro that is inserted on a page. If you insert any of the macros that are available to you, and then you click on "View Storage Format", then you should be able to see what the code looks like.

renderAndInsertMarkup takes Confluence Storage Format text and converts it to HTML. This is what Confluence does internally, but once the page has been rendered, the only way to convert is to use a REST API call. This is done using jQuery.ajax. You see that there is a div with an id of "output-markup" which is passed to the function as a parameter as well. This is where the HTML is output.

The most important thing to understand is the Confluence Storage Format in the request. You can't look at the HTML in the page to figure out the storage format. You have to choose the menu option "View Storage Format" to be able to figure out what you need. Looking at your original request, I tried to make an example that fulfills your requirements, copied directly from a page where I inserted a contentbylabel macro that looks for the labels amb, glossary, and glossary_b:

<script>
function renderAndInsertMarkup(markup, containingElement) {
var dataObj = {};
dataObj.representation = "storage";
dataObj.content = {};
dataObj.content.id = AJS.params.pageId;
dataObj.value = markup;

jQuery.ajax({dataType: 'json',
contentType: 'application/json',
type: 'POST',
url: contextPath + '/rest/api/contentbody/convert/view',
data: JSON.stringify(dataObj),
success: function(response) {
jQuery(containingElement).append(response.value);
}
});
}
renderAndInsertMarkup(`<ac:structured-macro ac:name="contentbylabel"><ac:parameter ac:name="cql">label in ( &quot;amb&quot; , &quot;glossary&quot; , &quot;glossary_b&quot; )</ac:parameter></ac:structured-macro>`, "#output-markup");
</script>
<div id="output-markup"></div>
Like # people like this
Stefan Mueller May 11, 2019

Thank you for all those information and code, I will try as soon as I have access to our confluence instance and a quiet moment.

What do mean by "View Storage Format" , do you refer to the source editor as mentioned here.

Stephen Deutsch
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.
May 19, 2019

Hi Stefan, the "View Storage Format" menu option is available under the three dots menu (•••) when viewing a page. Otherwise you can use the Confluence Source Editor available on the marketplace. Both will show the underlying code of the page, but the source editor allows you to make changes, too.

Stefan Mueller May 19, 2019

nothing like this in my menu, only "View Source" comes close
page view - three dot menu.png

becki.marsh March 24, 2020

@Stephen Deutsch 

Is there any special considerations when using this in conjunction with the Jira macro? I can get a list to display if the original Jira macro is still on the page. If I remove this to leave the code to do it's thing then it no longer loads the list.

Jira Refreshing.png

Dylan Veide July 22, 2020

The jira macro needs to perform it's own rest queries once inserted into the page. Hence you need to use a different endpoint for it:


url: contextPath + '/rest/api/contentbody/convert/export_view'

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events