Repository: kovetskiy/mark
Pull request #321 (2023-05-23 09:10:49)

Drop newlines
Newlines will cause trouble when rendering and the macro is used inside a table.
Without this change, we'll have this:

```
                              <tr>
                              <td><ac:structured-macro ac:name="profile"></td>
                              <td></td>
                              <td></td>
                              </tr>
                              <tr>
                              <td><ac:parameter ac:name="user"></td>
                              <td></td>
                              <td></td>
                              </tr>
                              <tr>
                              <td><ri:user ri:userkey="XXXX" /></ac:parameter></td>
                              <td></td>
                              <td></td>
                              </tr>
                              <tr>
                              <td></ac:structured-macro></td>
                              <td></td>
                              <td></td>
                              </tr>



Patch:
diff --git a/pkg/mark/stdlib/stdlib.go b/pkg/mark/stdlib/stdlib.go
index 2025492..4ef4a59 100644
--- a/pkg/mark/stdlib/stdlib.go
+++ b/pkg/mark/stdlib/stdlib.go
@@ -113,15 +113,15 @@ func templates(api *confluence.API) (*template.Template, error) {
 
 		// This template is used for rendering code in ```
 		`ac:code`: text(
-			`<ac:structured-macro ac:name="{{ if eq .Language "mermaid" }}cloudscript-confluence-mermaid{{ else }}code{{ end }}">{{printf "\n"}}`,
-			/**/ `{{ if eq .Language "mermaid" }}<ac:parameter ac:name="showSource">true</ac:parameter>{{printf "\n"}}{{ else }}`,
-			/**/ `<ac:parameter ac:name="language">{{ .Language }}</ac:parameter>{{printf "\n"}}{{ end }}`,
-			/**/ `<ac:parameter ac:name="collapse">{{ .Collapse }}</ac:parameter>{{printf "\n"}}`,
-			/**/ `{{ if .Theme }}<ac:parameter ac:name="theme">{{ .Theme }}</ac:parameter>{{printf "\n"}}{{ end }}`,
-			/**/ `{{ if .Linenumbers }}<ac:parameter ac:name="linenumbers">{{ .Linenumbers }}</ac:parameter>{{printf "\n"}}{{ end }}`,
-			/**/ `{{ if .Firstline }}<ac:parameter ac:name="firstline">{{ .Firstline }}</ac:parameter>{{printf "\n"}}{{ end }}`,
-			/**/ `{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{printf "\n"}}{{ end }}`,
-			/**/ `<ac:plain-text-body><![CDATA[{{ .Text | cdata }}]]></ac:plain-text-body>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="{{ if eq .Language "mermaid" }}cloudscript-confluence-mermaid{{ else }}code{{ end }}">`,
+			/**/ `{{ if eq .Language "mermaid" }}<ac:parameter ac:name="showSource">true</ac:parameter>{{ else }}`,
+			/**/ `<ac:parameter ac:name="language">{{ .Language }}</ac:parameter>{{ end }}`,
+			/**/ `<ac:parameter ac:name="collapse">{{ .Collapse }}</ac:parameter>`,
+			/**/ `{{ if .Theme }}<ac:parameter ac:name="theme">{{ .Theme }}</ac:parameter>{{ end }}`,
+			/**/ `{{ if .Linenumbers }}<ac:parameter ac:name="linenumbers">{{ .Linenumbers }}</ac:parameter>{{ end }}`,
+			/**/ `{{ if .Firstline }}<ac:parameter ac:name="firstline">{{ .Firstline }}</ac:parameter>{{ end }}`,
+			/**/ `{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{ end }}`,
+			/**/ `<ac:plain-text-body><![CDATA[{{ .Text | cdata }}]]></ac:plain-text-body>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
@@ -130,7 +130,7 @@ func templates(api *confluence.API) (*template.Template, error) {
 			`<ac:parameter ac:name="colour">{{ or .Color "Grey" }}</ac:parameter>`,
 			`<ac:parameter ac:name="title">{{ or .Title .Color }}</ac:parameter>`,
 			`<ac:parameter ac:name="subtle">{{ or .Subtle false }}</ac:parameter>`,
-			`</ac:structured-macro>`,
+			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		`ac:link:user`: text(
@@ -150,7 +150,7 @@ func templates(api *confluence.API) (*template.Template, error) {
 		`ac:jira:ticket`: text(
 			`<ac:structured-macro ac:name="jira">`,
 			`<ac:parameter ac:name="key">{{ .Ticket }}</ac:parameter>`,
-			`</ac:structured-macro>`,
+			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/doc/jira-issues-macro-139380.html */
@@ -166,53 +166,53 @@ func templates(api *confluence.API) (*template.Template, error) {
 			`<ac:parameter ac:name="title">{{ or .Title "Jira Issues" }}</ac:parameter>`,
 			`<ac:parameter ac:name="url">{{ .URL }}</ac:parameter>`,
 			`<ac:parameter ac:name="width">{{ or .Width "100%" }}</ac:parameter>`,
-			`</ac:structured-macro>`,
+			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/info-tip-note-and-warning-macros-792499127.html */
 
 		`ac:box`: text(
-			`<ac:structured-macro ac:name="{{ .Name }}">{{printf "\n"}}`,
-			`<ac:parameter ac:name="icon">{{ or .Icon "false" }}</ac:parameter>{{printf "\n"}}`,
-			`{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{printf "\n"}}{{ end }}`,
-			`<ac:rich-text-body>{{ .Body }}</ac:rich-text-body>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="{{ .Name }}">`,
+			`<ac:parameter ac:name="icon">{{ or .Icon "false" }}</ac:parameter>`,
+			`{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{ end }}`,
+			`<ac:rich-text-body>{{ .Body }}</ac:rich-text-body>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/table-of-contents-macro-792499210.html */
 
 		`ac:toc`: text(
-			`<ac:structured-macro ac:name="toc">{{printf "\n"}}`,
-			`<ac:parameter ac:name="printable">{{ or .Printable "true" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="style">{{ or .Style "disc" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="maxLevel">{{ or .MaxLevel "7" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="indent">{{ or .Indent "" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="minLevel">{{ or .MinLevel "1" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="exclude">{{ or .Exclude "" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="type">{{ or .Type "list" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="outline">{{ or .Outline "clear" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="include">{{ or .Include "" }}</ac:parameter>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="toc">`,
+			`<ac:parameter ac:name="printable">{{ or .Printable "true" }}</ac:parameter>`,
+			`<ac:parameter ac:name="style">{{ or .Style "disc" }}</ac:parameter>`,
+			`<ac:parameter ac:name="maxLevel">{{ or .MaxLevel "7" }}</ac:parameter>`,
+			`<ac:parameter ac:name="indent">{{ or .Indent "" }}</ac:parameter>`,
+			`<ac:parameter ac:name="minLevel">{{ or .MinLevel "1" }}</ac:parameter>`,
+			`<ac:parameter ac:name="exclude">{{ or .Exclude "" }}</ac:parameter>`,
+			`<ac:parameter ac:name="type">{{ or .Type "list" }}</ac:parameter>`,
+			`<ac:parameter ac:name="outline">{{ or .Outline "clear" }}</ac:parameter>`,
+			`<ac:parameter ac:name="include">{{ or .Include "" }}</ac:parameter>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/doc/children-display-macro-139501.html */
 
 		`ac:children`: text(
-			`<ac:structured-macro ac:name="children">{{printf "\n"}}`,
-			`{{ if .Reverse}}<ac:parameter ac:name="reverse">{{ or .Reverse }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Sort}}<ac:parameter ac:name="sort">{{ .Sort }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Style}}<ac:parameter ac:name="style">{{ .Style }}</ac:parameter>{{printf "\n"}}{{end}}`,
+			`<ac:structured-macro ac:name="children">`,
+			`{{ if .Reverse}}<ac:parameter ac:name="reverse">{{ or .Reverse }}</ac:parameter>{{end}}`,
+			`{{ if .Sort}}<ac:parameter ac:name="sort">{{ .Sort }}</ac:parameter>{{end}}`,
+			`{{ if .Style}}<ac:parameter ac:name="style">{{ .Style }}</ac:parameter>{{end}}`,
 			`{{ if .Page}}`,
 			/**/ `<ac:parameter ac:name="page">`,
 			/**/ `<ac:link>`,
 			/**/ `<ri:page ri:content-title="{{ .Page }}"/>`,
 			/**/ `</ac:link>`,
 			/**/ `</ac:parameter>`,
-			`{{printf "\n"}}{{end}}`,
-			`{{ if .Excerpt}}<ac:parameter ac:name="excerptType">{{ .Excerpt }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .First}}<ac:parameter ac:name="first">{{ .First }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Depth}}<ac:parameter ac:name="depth">{{ .Depth }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .All}}<ac:parameter ac:name="all">{{ .All }}</ac:parameter>{{printf "\n"}}{{end}}`,
+			`{{end}}`,
+			`{{ if .Excerpt}}<ac:parameter ac:name="excerptType">{{ .Excerpt }}</ac:parameter>{{end}}`,
+			`{{ if .First}}<ac:parameter ac:name="first">{{ .First }}</ac:parameter>{{end}}`,
+			`{{ if .Depth}}<ac:parameter ac:name="depth">{{ .Depth }}</ac:parameter>{{end}}`,
+			`{{ if .All}}<ac:parameter ac:name="all">{{ .All }}</ac:parameter>{{end}}`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
@@ -236,105 +236,105 @@ func templates(api *confluence.API) (*template.Template, error) {
 		/* https://confluence.atlassian.com/doc/widget-connector-macro-171180449.html#WidgetConnectorMacro-YouTube */
 
 		`ac:youtube`: text(
-			`<ac:structured-macro ac:name="widget">{{printf "\n"}}`,
-			`<ac:parameter ac:name="overlay">youtube</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="_template">com/atlassian/confluence/extra/widgetconnector/templates/youtube.vm</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="width">{{ or .Width "640px" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="height">{{ or .Height "360px" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="url"><ri:url ri:value="{{ .URL }}" /></ac:parameter>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="widget">`,
+			`<ac:parameter ac:name="overlay">youtube</ac:parameter>`,
+			`<ac:parameter ac:name="_template">com/atlassian/confluence/extra/widgetconnector/templates/youtube.vm</ac:parameter>`,
+			`<ac:parameter ac:name="width">{{ or .Width "640px" }}</ac:parameter>`,
+			`<ac:parameter ac:name="height">{{ or .Height "360px" }}</ac:parameter>`,
+			`<ac:parameter ac:name="url"><ri:url ri:value="{{ .URL }}" /></ac:parameter>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://support.atlassian.com/confluence-cloud/docs/insert-the-iframe-macro/ */
 
 		`ac:iframe`: text(
-			`<ac:structured-macro ac:name="iframe">{{printf "\n"}}`,
-			`<ac:parameter ac:name="src"><ri:url ri:value="{{ .URL }}" /></ac:parameter>{{printf "\n"}}`,
-			`{{ if .Frameborder }}<ac:parameter ac:name="frameborder">{{ .Frameborder }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Scrolling }}<ac:parameter ac:name="id">{{ .Scrolling }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Align }}<ac:parameter ac:name="align">{{ .Align }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`<ac:parameter ac:name="width">{{ or .Width "640px" }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="height">{{ or .Height "360px" }}</ac:parameter>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="iframe">`,
+			`<ac:parameter ac:name="src"><ri:url ri:value="{{ .URL }}" /></ac:parameter>`,
+			`{{ if .Frameborder }}<ac:parameter ac:name="frameborder">{{ .Frameborder }}</ac:parameter>{{end}}`,
+			`{{ if .Scrolling }}<ac:parameter ac:name="id">{{ .Scrolling }}</ac:parameter>{{end}}`,
+			`{{ if .Align }}<ac:parameter ac:name="align">{{ .Align }}</ac:parameter>{{end}}`,
+			`<ac:parameter ac:name="width">{{ or .Width "640px" }}</ac:parameter>`,
+			`<ac:parameter ac:name="height">{{ or .Height "360px" }}</ac:parameter>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/doc/blog-posts-macro-139470.html */
 
 		`ac:blog-posts`: text(
-			`<ac:structured-macro ac:name="blog-posts">{{printf "\n"}}`,
-			`{{ if .Content }}<ac:parameter ac:name="content">{{ .Content }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Spaces }}<ac:parameter ac:name="spaces">{{ .Spaces }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Author }}<ac:parameter ac:name="author">{{ .Author }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Time }}<ac:parameter ac:name="time">{{ .Time }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Reverse }}<ac:parameter ac:name="reverse">{{ .Reverse }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Sort }}<ac:parameter ac:name="sort">{{ .Sort }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Max }}<ac:parameter ac:name="max">{{ .Max }}</ac:parameter>{{printf "\n"}}{{end}}`,
-			`{{ if .Label }}<ac:parameter ac:name="label">{{ .Label }}</ac:parameter>{{printf "\n"}}{{end}}`,
+			`<ac:structured-macro ac:name="blog-posts">`,
+			`{{ if .Content }}<ac:parameter ac:name="content">{{ .Content }}</ac:parameter>{{end}}`,
+			`{{ if .Spaces }}<ac:parameter ac:name="spaces">{{ .Spaces }}</ac:parameter>{{end}}`,
+			`{{ if .Author }}<ac:parameter ac:name="author">{{ .Author }}</ac:parameter>{{end}}`,
+			`{{ if .Time }}<ac:parameter ac:name="time">{{ .Time }}</ac:parameter>{{end}}`,
+			`{{ if .Reverse }}<ac:parameter ac:name="reverse">{{ .Reverse }}</ac:parameter>{{end}}`,
+			`{{ if .Sort }}<ac:parameter ac:name="sort">{{ .Sort }}</ac:parameter>{{end}}`,
+			`{{ if .Max }}<ac:parameter ac:name="max">{{ .Max }}</ac:parameter>{{end}}`,
+			`{{ if .Label }}<ac:parameter ac:name="label">{{ .Label }}</ac:parameter>{{end}}`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/include-page-macro-792499125.html */
 
 		`ac:include`: text(
-			`<ac:structured-macro ac:name="include">{{printf "\n"}}`,
-			`<ac:parameter ac:name="">{{printf "\n"}}`,
-			`<ac:link>{{printf "\n"}}`,
-			`<ri:page ri:content-title="{{ .Page }}" {{if .Space }}ri:space-key="{{ .Space }}"{{end}}/>{{printf "\n"}}`,
-			`</ac:link>{{printf "\n"}}`,
-			`</ac:parameter>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="include">`,
+			`<ac:parameter ac:name="">`,
+			`<ac:link>`,
+			`<ri:page ri:content-title="{{ .Page }}" {{if .Space }}ri:space-key="{{ .Space }}"{{end}}/>`,
+			`</ac:link>`,
+			`</ac:parameter>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/excerpt-include-macro-792499101.html */
 
 		`ac:excerpt-include`: text(
-			`<ac:macro ac:name="excerpt-include">{{printf "\n"}}`,
-			`<ac:parameter ac:name="nopanel">{{ if .NoPanel }}{{ .NoPanel }}{{ else }}false{{ end }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:default-parameter>{{ .Page }}</ac:default-parameter>{{printf "\n"}}`,
+			`<ac:macro ac:name="excerpt-include">`,
+			`<ac:parameter ac:name="nopanel">{{ if .NoPanel }}{{ .NoPanel }}{{ else }}false{{ end }}</ac:parameter>`,
+			`<ac:default-parameter>{{ .Page }}</ac:default-parameter>`,
 			`</ac:macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/excerpt-macro-792499102.html */
 
 		`ac:excerpt`: text(
-			`<ac:structured-macro ac:name="excerpt">{{printf "\n"}}`,
-			`<ac:parameter ac:name="hidden">{{ if .Hidden }}{{ .Hidden }}{{ else }}false{{ end }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:parameter ac:name="atlassian-macro-output-type">{{ if .OutputType }}{{ .OutputType }}{{ else }}BLOCK{{ end }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:rich-text-body>{{printf "\n"}}`,
-			`{{ .Excerpt }}{{printf "\n"}}`,
-			`</ac:rich-text-body>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="excerpt">`,
+			`<ac:parameter ac:name="hidden">{{ if .Hidden }}{{ .Hidden }}{{ else }}false{{ end }}</ac:parameter>`,
+			`<ac:parameter ac:name="atlassian-macro-output-type">{{ if .OutputType }}{{ .OutputType }}{{ else }}BLOCK{{ end }}</ac:parameter>`,
+			`<ac:rich-text-body>`,
+			`{{ .Excerpt }}`,
+			`</ac:rich-text-body>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/anchor-macro-792499068.html */
 
 		`ac:anchor`: text(
-			`<ac:structured-macro ac:name="anchor">{{printf "\n"}}`,
-			`<ac:parameter ac:name="">{{ .Anchor }}</ac:parameter>{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="anchor">`,
+			`<ac:parameter ac:name="">{{ .Anchor }}</ac:parameter>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/expand-macro-792499106.html */
 
 		`ac:expand`: text(
-			`<ac:structured-macro ac:name="expand">{{printf "\n"}}`,
-			`<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{printf "\n"}}`,
-			`<ac:rich-text-body>{{ .Body }}</ac:rich-text-body>{{printf "\n"}}`,
-			`</ac:structured-macro>`,
+			`<ac:structured-macro ac:name="expand">`,
+			`<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>`,
+			`<ac:rich-text-body>{{ .Body }}</ac:rich-text-body>`,
+			`</ac:structured-macro>{{printf "\n"}}`,
 		),
 
 		/* https://confluence.atlassian.com/conf59/user-profile-macro-792499223.html */
 
 		`ac:profile`: text(
 			`{{ with .Name | user  }}`,
-			`<ac:structured-macro ac:name="profile">{{printf "\n"}}`,
-			`<ac:parameter ac:name="user">{{printf "\n"}}`,
+			`<ac:structured-macro ac:name="profile">`,
+			`<ac:parameter ac:name="user">`,
 			`{{ with .AccountID }}`,
-			/**/ `<ri:user ri:account-id="{{ .AccountID }}" />{{printf "\n"}}`,
+			/**/ `<ri:user ri:account-id="{{ .AccountID }}" />`,
 			`{{ else }}`,
 			/**/ `<ri:user ri:userkey="{{ .UserKey }}" />`,
 			`{{ end }}`,
-			`</ac:parameter>{{printf "\n"}}`,
+			`</ac:parameter>`,
 			`</ac:structured-macro>{{printf "\n"}}`,
 			`{{ end }}`,
 		),


Test patch:
diff --git a/pkg/mark/testdata/codes.html b/pkg/mark/testdata/codes.html
index 163f71c..0757528 100644
--- a/pkg/mark/testdata/codes.html
+++ b/pkg/mark/testdata/codes.html
@@ -1,88 +1,32 @@
 <p><code>inline</code></p>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language"></ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[some code]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">bash</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[code bash]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">bash</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[with a newline
-]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">unknown</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[unknown code]]></ac:plain-text-body>
-</ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language"></ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[some code]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">bash</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[code bash]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">bash</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[with a newline
+]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">unknown</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[unknown code]]></ac:plain-text-body></ac:structured-macro>
 <p>text
 text 2</p>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">unknown</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[unknown code 2]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">sh</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:parameter ac:name="title">A b c</ac:parameter>
-<ac:plain-text-body><![CDATA[no-collapse-title]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">bash</ac:parameter>
-<ac:parameter ac:name="collapse">true</ac:parameter>
-<ac:parameter ac:name="title">A b c</ac:parameter>
-<ac:plain-text-body><![CDATA[collapse-and-title]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">c</ac:parameter>
-<ac:parameter ac:name="collapse">true</ac:parameter>
-<ac:plain-text-body><![CDATA[collapse-no-title]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language">nested</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[code
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">unknown</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[unknown code 2]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">sh</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:parameter ac:name="title">A b c</ac:parameter><ac:plain-text-body><![CDATA[no-collapse-title]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">bash</ac:parameter><ac:parameter ac:name="collapse">true</ac:parameter><ac:parameter ac:name="title">A b c</ac:parameter><ac:plain-text-body><![CDATA[collapse-and-title]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">c</ac:parameter><ac:parameter ac:name="collapse">true</ac:parameter><ac:plain-text-body><![CDATA[collapse-no-title]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language">nested</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[code
 ``` more code ```
-even more code]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="code">
-<ac:parameter ac:name="language"></ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[indented code block
-with multiple lines]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="cloudscript-confluence-mermaid">
-<ac:parameter ac:name="showSource">true</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:plain-text-body><![CDATA[graph TD;
+even more code]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="code"><ac:parameter ac:name="language"></ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[indented code block
+with multiple lines]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="cloudscript-confluence-mermaid"><ac:parameter ac:name="showSource">true</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:plain-text-body><![CDATA[graph TD;
     A-->B;
     A-->C;
     B-->D;
-    C-->D;]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="cloudscript-confluence-mermaid">
-<ac:parameter ac:name="showSource">true</ac:parameter>
-<ac:parameter ac:name="collapse">true</ac:parameter>
-<ac:parameter ac:name="title">my mermaid graph</ac:parameter>
-<ac:plain-text-body><![CDATA[graph TD;
+    C-->D;]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="cloudscript-confluence-mermaid"><ac:parameter ac:name="showSource">true</ac:parameter><ac:parameter ac:name="collapse">true</ac:parameter><ac:parameter ac:name="title">my mermaid graph</ac:parameter><ac:plain-text-body><![CDATA[graph TD;
     A-->B;
     A-->C;
     B-->D;
-    C-->D;]]></ac:plain-text-body>
-</ac:structured-macro>
-<ac:structured-macro ac:name="cloudscript-confluence-mermaid">
-<ac:parameter ac:name="showSource">true</ac:parameter>
-<ac:parameter ac:name="collapse">false</ac:parameter>
-<ac:parameter ac:name="title">my mermaid graph</ac:parameter>
-<ac:plain-text-body><![CDATA[graph TD;
+    C-->D;]]></ac:plain-text-body></ac:structured-macro>
+<ac:structured-macro ac:name="cloudscript-confluence-mermaid"><ac:parameter ac:name="showSource">true</ac:parameter><ac:parameter ac:name="collapse">false</ac:parameter><ac:parameter ac:name="title">my mermaid graph</ac:parameter><ac:plain-text-body><![CDATA[graph TD;
     A-->B;
     A-->C;
     B-->D;
-    C-->D;]]></ac:plain-text-body>
-</ac:structured-macro>
+    C-->D;]]></ac:plain-text-body></ac:structured-macro>