Can I create macros within an HTML macro?
Asked by Willy Case:

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


Answers:
author: Stephen Deutsch
body: 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>
```

comments: author: Willy Case
body: This works perfectly. Thank you!


author: EwingLin
body: Thanks! This solution is what I'm looking for!


author: Stefan Mueller
body: Hello,  
[@Stephen Deutsch](/t5/user/viewprofilepage/user-id/781490) could you explain the code in more detail?

I'm trying to do the same with the [Popular Labels Macro](https://confluence.atlassian.com/doc/popular-labels-macro-168003614.html) 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 macros](https://community.atlassian.com/t5/Confluence-questions/using-macros-inside-user-macros/qaq-p/405856), [Possible to Call User Macro inside another User Macro?](https://community.atlassian.com/t5/Answers-Developer-Questions/Possible-to-Call-User-Macro-inside-another-User-Macro/qaq-p/544973), [using macros inside user macros](https://community.atlassian.com/t5/Confluence-questions/using-macros-inside-user-macros/qaq-p/405856) and [Using confluence macro code inside user macro](https://community.atlassian.com/t5/Confluence-questions/Using-confluence-macro-code-inside-user-macro/qaq-p/710754) ([entity names](https://stackoverflow.com/questions/5068951/what-do-lt-and-gt-stand-for) were exchanged) but nothing worked out. Could you help out?


author: Stefan Mueller
body: it took me a while but I figured it out based on the description of [Section Macro](https://confluence.atlassian.com/conf59/section-macro-792499196.html)

\\"*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");
```


author: Stefan Mueller
body: I still need some help here as I try the same with [Contet By Label Macro](https://confluence.atlassian.com/conf65/content-by-label-macro-939701193.html), 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](https://community.atlassian.com/t5/image/serverpage/image-id/53062i17C43F3205D08A0D/image-size/large?v=v2&px=999 "get macro name.png")


author: Stephen Deutsch
body: 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.


author: Stefan Mueller
body: 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.](https://www.w3schools.com/js/js_objects.asp) or [How To Use Object Methods in JavaScript \| DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-use-object-methods-in-javascript) or a more complex application [Passing Data as JS Objects \| Chart Data \| ZingChart](https://www.zingchart.com/docs/tutorials/loading-data/passing-data-js-objects/)  

   ```
    dataObj.representation = "storage";
   ```

   I find only [ContentRepresentation (Atlassian Confluence 5.8.8 API)](https://docs.atlassian.com/atlassian-confluence/5.8.8/com/atlassian/confluence/api/model/content/ContentRepresentation.html) but it is not self-explaining. I found some in [Custom Content \| developer.atlassian.com](https://developer.atlassian.com/cloud/confluence/modules/custom-content/) and [How do you post markdown using confluences rest API?](https://community.atlassian.com/t5/Answers-Developer-Questions/How-do-you-post-markdown-using-confluences-rest-API/qaq-p/492056) 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 \| w3schools](https://www.w3schools.com/jquery/ajax_ajax.asp), [jQuery.ajax() \| jQuery API Documentation](http://api.jquery.com/jquery.ajax/).

   ```
     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](https://guide.freecodecamp.org/jquery/jquery-ajax-post-method/) and [javascript - Returning the response from an Jquery AJAX call - Stack Overflow](https://stackoverflow.com/questions/3880361/returning-the-response-from-an-jquery-ajax-call).
   Confluence Server is asked to process the *contentType:* 'application/json', what comes as [JSON string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) due to *data: JSON.stringify(dataObj)* by the API *contentbody/convert/view* , accessible via  
   [context path is the path to Confluence](https://developer.atlassian.com/server/confluence/how-do-i-get-the-base-url-and-contextpath-of-a-confluence-installation/)  
   and the   
   [Contentbody API](https://developer.atlassian.com/cloud/confluence/rest/#api-content-id-version-versionNumber-delete) ([REST API examples](https://developer.atlassian.com/cloud/confluence/rest-api-examples/), [Confluence REST API Documentation](https://docs.atlassian.com/atlassian-confluence/REST/6.6.0/#contentbody/convert/{to}))  
   supported by
   1. [Dynamic Content Macro: How to retrieve rendered macro body \| The Atlassian Developer Community](https://community.developer.atlassian.com/t/dynamic-content-macro-how-to-retrieve-rendered-macro-body/24515)
   2. [How do the various Confluence document formats differ? - Stack Overflow](https://stackoverflow.com/questions/50926276/how-do-the-various-confluence-document-formats-differ)
   3. [Confluence Rest API Maintaining Macros After View \| The Atlassian Community](https://community.atlassian.com/t5/Confluence-questions/Confluence-Rest-API-Maintaining-Macros-After-View-Conversion/qaq-p/640233).  

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](https://www.w3schools.com/jquery/html_append.asp)
   2. [jquery .html() vs .append() - Stack Overflow](https://stackoverflow.com/questions/3015335/jquery-html-vs-append)
   3. [append() \| jQuery API Documentation](http://api.jquery.com/append/)  

4. The function call

   ```
   renderAndInsertMarkup(
   ```

   Based on the wording I assume that uses [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) and [Confluence Storage Format](https://confluence.atlassian.com/doc/confluence-storage-format-790796544.html), 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](https://confluence.atlassian.com/conf59/section-macro-792499196.html?_ga=2.22291387.1405422545.1557126423-218997814.1526317942) and [View storage format \| The Atlassian Community](https://community.atlassian.com/t5/Confluence-questions/View-storage-format/qaq-p/337485) but in none of them is anything mentioned in regard of the quotation marks, where and how to use them.

<br />

<br />

[@Stephen Deutsch "img srcxss onerroralert(1)](/t5/user/viewprofilepage/user-id/565770), any chance that you may enlight me?

Stefan


author: Stefan Mueller
body: [@Stephen Deutsch](/t5/user/viewprofilepage/user-id/781490)before we may get lost in details could you answer point 4 first?


author: Stephen Deutsch
body: 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>
```


author: Stefan Mueller
body: 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](Https://community.atlassian.com/t5/Confluence-questions/View-storage-format/qaq-p/337485).


author: Stephen Deutsch
body: 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.


author: Stefan Mueller
body: nothing like this in my menu, only "View Source" comes close  
![page view - three dot menu.png](https://community.atlassian.com/t5/image/serverpage/image-id/55037i960F4717F35A95B0/image-size/large?v=v2&px=999 "page view - three dot menu.png")


author: becki.marsh
body: [@Stephen Deutsch](/t5/user/viewprofilepage/user-id/781490)

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](https://community.atlassian.com/t5/image/serverpage/image-id/87717iBE1919952699AD65/image-size/large?v=v2&px=999 "Jira Refreshing.png")


author: Dylan Veide
body: 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'
```