Confluence XHTML Syntax Documentation
Reference
The Confluence XHTML Syntax is what Confluence currently uses to store the content of its pages. It is what you can see:
- when using the "View Storage Format" feature of Confluence
- in BodyContent objects with a bodyType equal to 2.
The Confluence XHTML Syntax is basically XHTML (the XML variant of HTML), with a few additional, Confluence-specific tags and attributes, and a few oddities.
Confluence-specific tags
ac:caption
<ac:image ac:align="left" ac:layout="align-start" ac:original-height="1200" ac:original-width="1200"
ac:custom-width="true" ac:alt="some alt text" ac:width="50">
<ri:attachment ri:filename="rock.jpg" ri:version-at-save="1" />
<ac:caption>
<p>sos<em>asdas</em>ame ca<strong>sasd</strong>ion</p>
</ac:caption>
<ac:adf-mark key="border" size="2" color="#091e4224" />
</ac:image>The caption of an image, in the node's body.
ac:default-parameter
<ac:macro ac:name="anchor">
<ac:default-parameter>value1</ac:default-parameter>
</ac:macro>Gives the value of the parameter of a macro that doesn't have a name, in its body. Sometimes, <ac:parameter name=""> is used instead, likely with ac:structured-macro. We haven't seen it used several times per macro, rather, at most once.
ac:emoticon
<p>My emoticon: <ac:emoticon ac:name="smile" ac:emoji-shortname=":slight_smile:" ac:emoji-id="1f642" ac:emoji-fallback="(here an emoji, but xwiki.org cannot handle them in documents)" /></p>
<p>New Confluence Cloud emoticon: <ac:emoticon ac:name="cross" ac:emoji-shortname=":cross_mark:" ac:emoji-id="atlassian-cross_mark" ac:emoji-fallback=":cross_mark:" /></p>An emoticon, that hopefully but doesn't necessarily map well to an emoji. Formerly, Confluence emoticons where a bit like MSN smileys, ancestors of the emojis that are widespread now.
The tag is self-closing. The tag's attributes seem to have changed quite a bit over time, we can't rely on any attribute to be there. Here is an attempt to explain the parameters anyway.
| Attribute | Meaning |
|---|---|
| ac:name | The name of the emoticon |
| ac:emoji-short-name | the name of the emoji on which one would fallback to render this emoticon |
| ac:emoji-id | the hexadecimal code of the corresponding emoji character, OR some Confluence-specific name |
| ac:emoji-fallback | The emoji itself, OR the emoji short name |
Or with an ac:image tag like in the following:
<ac:image ac:class="emoticon emoticon-smile" ac:title="(Lächeln)" ac:alt="(Lächeln)"><ri:url ri:value="http://confluence.atlatian.net/s/de_DE/7901/4635873c8e185dc5df37b4e2487dfbef570b5e2c/_/images/icons/emoticons/smile.svg" /></ac:image>ac:image
<p>
<ac:image ac:align="left" ac:layout="align-start" ac:original-height="1200" ac:original-width="1200"
ac:custom-width="true" ac:alt="some alt text" ac:width="50">
<ri:attachment ri:filename="rock.jpg" ri:version-at-save="1" />
<ac:caption>
<p>sos<em>asdas</em>ame ca<strong>sasd</strong>ion</p>
</ac:caption>
<ac:adf-mark key="border" size="2" color="#091e4224" />
</ac:image>
<ac:image ac:border="true" ac:height="217" ac:width="524">
<ri:attachment ri:filename="image.png">
<ri:page ri:content-title="pagetovalidate" ri:space-key="spacetovalidate"/>
</ri:attachment>
</ac:image>
</p>An image. If the image displays an attachment, it is given using a ri:url tag, possibly with a relative value, or a ri:attachment tag. A caption can be given with the ac:caption tag. Some styling can be given with an ac:adf-mark key.
| Attribute | Meaning |
|---|---|
| ac:align | How the image is aligned (we know about these values: "left", "right", "center") |
| ac:layout | How the image is organised (we know about these values: "align-start", "align-end", "center", "wrap-left", "wrap-right") |
| ac:original-width | The original width of the image |
| ac:original-height | The original height of the image |
| ac:custom-width | Whether a custom width is applied to the image. Note: supposedly, an ac:custom-height attribute exists but we've not seen it yet. |
| ac:width | The custom width (optional) |
| ac:height | The custom height (optional) |
| ac:alt | The alternative text (same as the standard HTML alt attribute of the standard HTML img element) |
| ac:border | Whether the image has a border (but also note the ac:adf-mark key="border" element present in the first example which doesn't have an ac:border attribute) |
ac:inline-comment-marker
<p>before<ac:inline-comment-marker ac:ref="21641e47-9393-4d3c-890f-0994b2181443">annotation</ac:inline-comment-marker>after</p>Surrounds a text commented in an inline comment.
ac:layout
<ac:layout>
<ac:layout-section ac:type="two_equal" ac:breakout-mode="default">
<ac:layout-cell><p>Test1</p></ac:layout-cell>
<ac:layout-cell><p>Test2</p></ac:layout-cell>
</ac:layout-section>
<ac:layout-section ac:type="fixed-width" ac:breakout-mode="default">
<ac:layout-cell><p /></ac:layout-cell>
</ac:layout-section>
</ac:layout>Defines a layout.
ac:layout-cell
Defines a cell in a layout. See ac:layout.
ac:layout-section
Defines a section in a layout. See ac:layout.
ac:link
<p><ac:link ac:card-appearance="inline"><ri:page ri:content-title="Under Page A" ri:version-at-save="2" /><ac:link-body>Under Page A</ac:link-body></ac:link></p>
<p><ac:link><ri:user ri:username="UserName" /></ac:link></p>
<p><ac:link><ri:user ri:userkey="ff80808156e241950156e468e9510003" /></ac:link></p>
<p><ac:link ac:anchor="myanchor"><ac:plain-text-link-body><![CDATA[correctly migrated label]] ></ac:plain-text-link-body></ac:link></p>
<p><ac:link ac:tooltip="an empty link"><ac:plain-text-link-body><![CDATA[this page]] ></ac:plain-text-link-body></ac:link></p>
<ac:structured-macro ac:name="pagetree" ac:schema-version="1" ac:local-id="7725dd30-f42e-4a74-babd-e3ce084d7398" ac:macro-id="67ee8bead41558eb6e8678e51d4d95665af4b328f23ae8d4b567c27a480b59a6">
<ac:parameter ac:name="root">
<ac:link><ri:page ri:content-title="@self" /></ac:link>
</ac:parameter>
<ac:parameter ac:name="startDepth">1</ac:parameter>
</ac:structured-macro>Defines a link to a page or to a user. Appears directly in a paragraph or in a macro parameter.
| Attribute | Meaning |
|---|---|
| ac:card-appearance | How the link is rendered in Confluence |
| ac:anchor | The target anchor |
| ac:tooltip | The link's tooltip |
- The target of the link (anchor excluded: it is defined as an attribute) is defined in a child ri:* element (ri:url, ri:page, ri:blog-post, ri:space, ri:user).
- The body is defined using either:
- an ac:plain-text-link-body element, which defines a plain text body
- an ac:link-body element, which defines a (potentially rich) text body
If no child element defines any target, the target is by default the current page. It is also possible that a link doesn't have a body. Thus, <ac:link /> is a link to the current page.
ac:link-body
An element which content defines the body of the surrounding ac:link element. See ac:link.
ac:macro
<ac:macro ac:name="anchor"><ac:default-parameter>anchorintitle</ac:default-parameter></ac:macro>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[code block text]]></ac:plain-text-body></ac:macro>An element that marks the usage of a macro. Probably an older way of doing this, see also ac:structured-macro.
| Attribute | Meaning |
|---|---|
| ac:name | The name of the macro |
The macro parameters are given as child elements (ac:default-parameter [a nameless parameter], and ac:parameter). The body of the macro is given using an ac:plain-text-body or an ac:rich-text-body element.
ac:parameter
<ac:structured-macro ac:name="panel" ac:schema-version="1" ac:macro-id="bc82cb0f-6564-4928-a24c-f325fc29da0f">
<ac:parameter ac:name="bgColor">#E3FCEF</ac:parameter>
<ac:rich-text-body>
<h2><strong>Welcome to your new space!</strong></h2>
<p>Spaces help your team structure, organize, and share work, so every team member has visibility into institutional knowledge and access to the information they need to do their best work.</p>
</ac:rich-text-body>
</ac:structured-macro>Specifies the value of the parameter of the given name for the macro in which the node is. The value is in the body of the node.
| Attribute | Meaning | |
|---|---|---|
| ac:name | The name of the parameter |
ac:placeholder
<h2>Discussion items</h2><table><tbody><tr><th>Item</th><th>Notes</th></tr><tr><td><ac:placeholder>Agenda item</ac:placeholder></td><td><ul><li><ac:placeholder>Notes for this agenda item</ac:placeholder></li></ul></td></tr><tr><td> </td><td> </td></tr></tbody></table><h2>Action items</h2><ac:task-list>
<ac:task>
<ac:task-id>1</ac:task-id>
<ac:task-status>incomplete</ac:task-status>
<ac:task-body><ac:placeholder ac:type="mention">Type your task here. Use "@" to assign a user and "//" to select a due date.</ac:placeholder><p> </p></ac:task-body>
</ac:task>
</ac:task-list>Defines a placeholder in a space template. Its content is intended for a user to be replaced in when creating a page from a template, and describes what it should be replaced with.
| Attribute | Meaning |
|---|---|
| ac:type | We don't really know. |
ac:plain-text-body
The plain text body of a macro. From what we have seen, the content is inside a CDATA section.
ac:plain-text-link-body
An element which content defines the plain text body of the surrounding ac:link element. See ac:link.
ac:rich-text-body
The rich-text body of a macro. From what we have seen, the content is not inside a CDATA section.
ac:structured-macro
<p>
<ac:structured-macro ac:name="livesearch" ac:schema-version="1" ac:local-id="1b06a399-a2ea-4e7f-8605-644926a58266" ac:macro-id="6b3a5eca5933839827ef50a69a6723f4acac920ca178daa759820b3c376858c2">
<ac:parameter ac:name="spaceKey">
<ri:space ri:space-key="currentSpace()" />
</ac:parameter>
<ac:parameter ac:name="size">large</ac:parameter>
<ac:parameter ac:name="additional">none</ac:parameter>
</ac:structured-macro>
</p>An element that marks the usage of a macro. Formerly
ac:macro.
| Attribute | Meaning |
|---|---|
| ac:name | The name of the macro |
| ac:local-id | An id for the macro. Not always there. |
| ac:macro-id | An id for the macro. From what we have seen, it is always present, and unique per Confluence site |
| ac:schema-version | We are not sure, we have seen "1" or "2" as values for this attribute |
| data-layout | We are not sure. it's not always there but we've always ever seen "default" for this attribute |
ac:task
<ac:task-list>
<ac:task>
<ac:task-id>1</ac:task-id>
<ac:task-status>incomplete</ac:task-status>
<ac:task-body><ac:placeholder ac:type="mention">Type your task here. Use "@" to assign a user and "//" to select a due date.</ac:placeholder><p> </p></ac:task-body>
</ac:task>
</ac:task-list>A task inside a task list, which has an id, a status and a body defined as child elements.
ac:task-body
The rich text body of a task, not inside a CDATA section. Can contain block elements like paragraphs.
ac:task-id
The identifier of a task, defined as an integer given as a child text node.
ac:task-list
A list of tasks containing ac:task elements.
ac:task-status
The status of a task, defined as a child text node. We've seen complete and incomplete.
at:declarations
<at:declarations>
<at:string at:name="currentDateLozenge" />
</at:declarations>A template declaration block, inside which space template variables are defined. Variables are fields that are filled by the user when creating a page from a template. Uses of these variables with the at:var element will be replaced with the filled values.
at:string
Defines a string template parameter. This is a self-closing tag.
| Attribute | Meaning |
|---|---|
| at:name | The name of the template variable |
at:var
<at:declarations>
<at:string at:name="currentDateLozenge" />
</at:declarations>
<h2>Date</h2>
<p>
<at:var at:name="currentDateLozenge" at:rawxhtml="true" />
</p>
| Attribute | Meaning |
|---|---|
| at:name | The name of the template variable |
| at:rawxhtml | We don't know what this boolean does |
ri:* elements
ri:* elements define targets. They appear in the content of ac:link elements, ac:image elements or macro parameters (sometimes inside an ac:link element which is inside an ac:parameter element, we've not found a definitive, consistent rule about this).
They are usually self-closing tags, from what we've seen.
ri:attachment
<ac:image><ri:attachment ri:filename="image.png"><ri:page ri:content-title="page" ri:space-key="SPACE" /></ri:attachment></ac:image>
<ri:attachment ri:filename="[email protected]" ri:version-at-save="1" />Targets an attachment. This one is *not* a self-closing tag. Its content further refines where to find the attachment, with an ri:page or ri:space element. If absent, the attachment is on the current page. If the ri:space element is used, the attachment is to be found in the home page.
| Attribute | Meaning |
|---|---|
| ri:filename | The filename of the attachment |
| ri:version-at-save | Not always there, supposedly the version of the attachment when the content was edited (an integer corresponding to the version parameter of the Attachment object) |
ri:url
<ri:url ri:value="image.png" />
<ri:url ri:value="https://twitter.com/XWiki/status/1808056434883502509"/>Defines a relative URL (usually to an attachment), or an absolute URL
| Attribute | Meaning |
|---|---|
| ri:value | the relative or absolute URL |
ri:page
<ri:attachment ri:filename="file.png">
<ri:page ri:content-title="My Page" ri:space-key="SPACE" />
</ri:attachment>| Attribute | Meaning |
|---|---|
| ri:content-title | The content title of the targeted page. Can be a special "@" value like @self (the current page) or @home (the home page of the given space) |
| ri:space-key | The space in which to find the content type. If not present, the current space is to be used, unless the space is given separately (e.g. in another macro parameter - for example, the view-file macro is like this) |
| ri:version-at-save | Not always there, supposedly the version of the page when the link was added (an integer corresponding to the version parameter of the Page object) |
ri:blog-post
<ac:link><ri:blog-post ri:content-title="Blog post" ri:posting-day="2023/09/27" /></ac:link>
Targets a blog post. Otherwise similar to ri:page.
| Attribute | Meaning |
|---|---|
| ri:content-title | The content title of the targeted page. Supposedly, can be a special "@" value like @self (the current page) |
| ri:posting-day | An YYYY/MM/DD date of when the target blog post was posted |
| ri:space-key | Supposedly possibly present. The space in which to find the content type. If not present, the current space is to be used, unless the space is given separately (e.g. in another macro parameter - for example, the view-file macro is like this) |
| ri:version-at-save | Supposedly possibly present. Supposedly the version of the page when the link was added (an integer corresponding to the version parameter of the BlogPost object) |
ri:space
<ri:space ri:space-key="DEMO" />
<ac:structured-macro ac:name="livesearch" ac:schema-version="1" ac:local-id="1b06a399-a2ea-4e7f-8605-644926a58266" ac:macro-id="6b3a5eca5933839827ef50a69a6723f4acac920ca178daa759820b3c376858c2">
<ac:parameter ac:name="spaceKey">
<ri:space ri:space-key="currentSpace()" />
</ac:parameter>
<ac:parameter ac:name="size">large</ac:parameter>
<ac:parameter ac:name="additional">none</ac:parameter>
</ac:structured-macro>Targets a space.
| Attribute | Meaning |
|---|---|
| ri:space-key | The space in which to find the content type. Can be a special value like currentSpace() |
ri:user
<ac:link><ri:user ri:username="UserName" /></ac:link>
<ac:link><ri:user ri:account-id="ff80808156e241950156e468e9510003" /></ac:link>
<ac:link><ri:user ri:userkey="ff80808156e241950156e468e9510003" /></ac:link>Targets a user. We describe three parameters we've seen to specify the users and only one is present at a time from what we've seen.
| Attribute | Meaning |
|---|---|
| ri:username | The username of the target user |
| ri:account-id | The account id of the target user |
| ri:userkey | The user key of the target user |
ac:adf-extension
<ac:adf-extension>
<ac:adf-node type="panel">
<ac:adf-attribute key="panel-type">note</ac:adf-attribute>
<ac:adf-content>
<p>This is a note (woaw)</p>
</ac:adf-content>
</ac:adf-node>
<ac:adf-fallback>
<div class="panel conf-macro output-block" style="background-color: rgb(234,230,255);border-color: rgb(153,141,217);border-width: 1.0px;">
<div class="panelContent" style="background-color: rgb(234,230,255);">
<p>This is a note (woaw)</p>
</div>
</div>
</ac:adf-fallback>
</ac:adf-extension>
Some sort of macro (which we will call ADF macro) with a fallback.
ac:adf-fallback
The XHML fallback to use (given in the content of the node) if the macro is not supported.
ac:adf-node
The non-fallback definition of the ADF macro.
| Attribute | Meaning |
|---|---|
| ri:type | The name of the ADF macro |
ac:adf-attribute
An ADF macro parameter. The value is given in the content of the node.
| Attribute | Meaning |
|---|---|
| key | the name of the parameter |
ac:adf-content
The content of the macro, given in the content of the node.
ac:adf-mark
<ac:image ac:align="left" ac:layout="align-start" ac:original-height="1200" ac:original-width="1200" ac:custom-width="true" ac:alt="some alt text" ac:width="50">
<ri:attachment ri:filename="rock.jpg" ri:version-at-save="1" />
<ac:caption>
<p>sos<em>asdas</em>ame ca<strong>sasd</strong>ion</p>
</ac:caption>
<ac:adf-mark key="border" size="2" color="#091e4224" />
</ac:image>
Seems to define styling. Seen as a direct child of the ac:image macro. The possible parameters might depend the value of the key attribute
| Attribute | Meaning |
|---|---|
| key | The type of mark. We know about "border" |
| size (for key="border") | The size of the border |
| color (for key="border") | The color of the border |
Standard HTML tags with specific considerations
img
<img class="emoticon emoticon-warning" title="(warning)" src="http://confluence.atlatian.net/s/en_US/7901/4635873c8e185dc5df37b4e2487dfbef570b5e2c/_/images/icons/emoticons/warning.svg" alt="(warning)" border="0" />Formerly used to represent emoticons. See ac:emoticon. And possibly regular images.
a
Defines a link in some text, or in a macro parameter. Works like the usual XHTML element of the same name. See also ac:link.
Quirks
Remains of the WYSIWYG editor's cursor
Confluence XHTML documents are full of <p class="auto-cursor-target"><br /></p> elements. They need to be cleaned up because they are artifacts of the wysiwyg edition and they don't do anything in Confluence. However, they would cause new lines in XWiki if not handled carefully.
See:
- https://jira.xwiki.org/browse/CONFLUENCE-399
- https://jira.xwiki.org/projects/CONFLUENCE/issues/CONFLUENCE-208?
Some inline macros are outside the paragraph inside which they are supposed to be
And instead, we have a paragraph (p tag), then this inline macro outside any paragraph, and then a new p tag.
We believe this is caused by some third party extensions, that this also creates issues in Confluence (including in edit mode), but some hack probably make it so that these inline macros seem like this whole paragraph -inline macro - paragraph chain is a unique paragraph.
We don't currently handle this at all because it seems complicated to do given how the XHTML parsing is done.