Macro Bodies in Forge

Hi @ccurti ,

Thanks for answering here. As Dennis Fischer already wrote in
https://ecosystem.atlassian.net/browse/FRGE-216

There is no macroBody on Forge. And yes I know you can have parameters and all other fancy things, but there is no compatibility between (Server <-> Connect) <-> Forge Macros.

This will be a long post, since I think there is no common understanding what the problem is :slight_smile:

(1) Confluence Server Macro with Macro Body

  • As server macro has
  • (a) a macroKey that is unique and the app installed which has registered that macroKey will be rendered for the ac:structrured-macro with that key
  • (b) a macroBody that is stored inside the confluence page (see storage format of page) and is editable when editing the page
  • (c) macroParameters that are stored within the page as well and can be edited in edit mode
  • (d) macroId that can be used to extract the contentBody and Parameters via REST API from the page

The storage format looks like so:

<ac:structured-macro 
   ac:name="advanced-single-codeblock-macro" 
   ac:schema-version="1" 
   ac:macro-id="cc2655f2-3d33-48ff-a17f-f6eb3d7aa5a6"
>
  <ac:parameter ac:name="theme">light-spring</ac:parameter>
  <ac:parameter ac:name="lang">JSON</ac:parameter>
  <ac:parameter ac:name="globaltitle">My Codeblock</ac:parameter>
  <ac:plain-text-body><![CDATA[{
  "foo": "bar"
}]]></ac:plain-text-body>
</ac:structured-macro>

(2) Cloud Connect Macro

You can provide a 100% exact same macro with Connect Cloud dynamicContentMacro

https://developer.atlassian.com/cloud/confluence/modules/dynamic-content-macro/

You will also have:

  • (a) a macroKey
  • (b) a macroBody that is stored inside the confluence page (see storage format of page) and is editable when editing the page
  • (c) macroParameters that are stored within the page as well and can be edited in edit mode
  • (d) macroId that can be used to extract the contentBody and Parameters via REST API from the page

You will have the same storage format and a customer can export its confluence space via XML and import it in cloud and your macro will work 100%.

A atlassian-connect.json snippet of such looks like this:

"modules": {
  "dynamicContentMacros": [
    {
      "name": { "value": "Advanced Codeblocks Single" },
      "description": { "value": "Visualize a single codeblock without replacements" },
      "key": "advanced-single-codeblock-macro",
      "url": "/advanced-single-codeblock-macro?pageId={page.id}&macroId={macro.id}&spaceKey={space.key}&pageVersion={page.version}",
      "categories": ["development"],
      "outputType": "block",
      "bodyType": "plain-text",
      "icon": { ... },
      "alias": "advanced-single-codeblock-macro",
      "parameters": [
        { ... }
      ]
    }
  ]
}
  • See the bodyType=plain-text.
  • Server and Cloud Connect both have
    • macroKey
    • macroBody
    • macroParams
    • macroId
    • same storage format as ac:structured-macro
  • => Server to Cloud Connect migration works out of the box!

(3) Forge Macro

A Forge macro has:

  • a completely different storage format
  • no macroKey in the form of CloudConnect and Server (some uuid thing that might be different on each installation)
  • no macroBody
  • params that are stored differently

Storage format of forge macro

<ac:adf-extension>
  <ac:adf-node type="extension">
    <ac:adf-attribute key="extension-type">com.atlassian.ecosystem</ac:adf-attribute>
    <ac:adf-attribute key="extension-key">889977.../static/advanced-codeblocks-hello-world</ac:adf-attribute>
    <ac:adf-attribute key="parameters">
      <ac:adf-parameter key="local-id">e31a0637-...</ac:adf-parameter>
      <ac:adf-parameter key="extension-id">ari:cloud:ecosystem::extension/889977.../static/advanced-codeblocks-hello-world</ac:adf-parameter>
      <ac:adf-parameter key="extension-title">advanced-codeblocks (Development)</ac:adf-parameter>
      <ac:adf-parameter key="guest-params">
        <ac:adf-parameter key="macro-body">// my code block
const foo = &quot;bar&quot;;</ac:adf-parameter>
      </ac:adf-parameter>
    </ac:adf-attribute>
    <ac:adf-attribute key="text">advanced-codeblocks (Development)</ac:adf-attribute>
    <ac:adf-attribute key="layout">full-width</ac:adf-attribute>
    <ac:adf-attribute key="local-id">648062b5-....</ac:adf-attribute>
  </ac:adf-node>
  <ac:adf-fallback>
    <ac:adf-node type="extension">
      <ac:adf-attribute key="extension-type">com.atlassian.ecosystem</ac:adf-attribute>
      <ac:adf-attribute key="extension-key">889977.../static/advanced-codeblocks-hello-world</ac:adf-attribute>
      <ac:adf-attribute key="parameters">
        <ac:adf-parameter key="local-id">e31a0637-...</ac:adf-parameter>
        <ac:adf-parameter key="extension-id">ari:cloud:ecosystem::extension/889977.../static/advanced-codeblocks-hello-world</ac:adf-parameter>
        <ac:adf-parameter key="extension-title">advanced-codeblocks (Development)</ac:adf-parameter>
        <ac:adf-parameter key="guest-params">
          <ac:adf-parameter key="macro-body">// my code block
const foo = &quot;bar&quot;;</ac:adf-parameter>
        </ac:adf-parameter>
      </ac:adf-attribute>
      <ac:adf-attribute key="text">advanced-codeblocks (Development)</ac:adf-attribute>
      <ac:adf-attribute key="layout">full-width</ac:adf-attribute>
      <ac:adf-attribute key="local-id">648062b5-....</ac:adf-attribute>
    </ac:adf-node>
  </ac:adf-fallback>
</ac:adf-extension>

Problems with Server to Cloud Forge XOR Cloud Connect to Cloud Forge migration:

Situation:

  • Customer imports Confluence Export as XML in his cloud space.
  • Pages contain ac:structured-macro storage format with server macro
  • Pages render “unknown macro” (because forge macro reacts to its ac:adf-extension storage format)

What needs a solution:

  • When importing a Server Confluence Space to Cloud (XOR When customer has already Cloud Connect app and App Vendor wants to switch to forge)
  • (I) Then how is the ac:structured-macro storage format migrated to the new ac:adf-extension storage format?
  • (II) Then how is the plainText macroBody made available to a forge macro that has no plainText macroBody? (At best you make it available as it is available in Cloud Connect)
  • (III) Then how is the macroParams made available to a forge macro?

I suggest that you really develop a tiny confluence Server macro with plainText macroBody and some params and actually test how to provide an automated migration path to a forge macro.
I think there are a lot of macros in the Marketplace that use macroBody and have currently no way to migrate to forge.

I hope that makes things clearer :slight_smile:


UPDATE: My Suggestions:

  • (I) automatically convert ac:structured-macro storage format to ac:adf-extension storage format with the following conversions:
  • (II) convert the ac:storage-format macroBody to an ac:adf-extension guest parameters with special name like macroBody. e.g.:
    <ac:adf-attribute key="parameters">
      <ac:adf-parameter key="guest-params">
        <ac:adf-parameter key="macro-body">// my code block
const foo = &quot;bar&quot;;</ac:adf-parameter>
      </ac:adf-parameter>
    </ac:adf-attribute>
  • (III) convert ac:storage-format macro params to equally named ac:adf-extension guest parameters.
    <ac:adf-attribute key="parameters">
      <ac:adf-parameter key="guest-params">
        <ac:adf-parameter key="macro-body">...</ac:adf-parameter>
        <ac:adf-parameter key="theme">light-spring</ac:adf-parameter>
        <ac:adf-parameter key="lang">JSON</ac:adf-parameter>
      </ac:adf-parameter>
    </ac:adf-attribute>

Cheers,

Bernhard

28 Likes