Show Jira Issue Comments — Confluence Cloud Macro
This Confluence user macro calls the Jira REST API to fetch comments, then recursively parses comment body nodes using a Velocity #macro to extract plain text. The result is rendered in an AUI table with sorting enabled and supplemented by AUI elements such as avatars and lozenges for authors and timestamps.
Template
## Parameters:
## issueIdOrKey (required) - Jira issue ID or key to fetch comments for
## order (optional) - ASC / DESC (defaults to created ascending)
## maxResults (optional) - number of comments to request (Jira default is 100)
#set($issueIdOrKey = $parameters["issueIdOrKey"])
#if(!$issueIdOrKey)
## Display a message if issueIdOrKey is not provided
<div role="note" aria-labelledby="no-issue-key-title" class="aui-message aui-message-info" style="width:100%; height: 100%;">
<p id="no-issue-key-title" class="title">
Note: Issue key/id not provided
</p>
<p>
Please set the <code>issueIdOrKey</code> parameter for this macro.
</p>
</div>
#else
#set($rawOrder = $parameters["order"])
#set($orderBy = "created")
#if($rawOrder)
#set($order = $rawOrder.toUpperCase())
#if($order == "ASC")
#set($orderBy = "+created")
#elseif($order == "DESC")
#set($orderBy = "-created")
#end
#end
#set($maxResultsParam = "")
#set($maxResultsInput = $parameters["maxResults"])
#if($maxResultsInput)
#set($maxResultsParam = "&maxResults=" + $maxResultsInput)
#end
## Fetch comments
#set($requestUrl = "/rest/api/3/issue/" + $issueIdOrKey + "/comment?orderBy=" + $orderBy + $maxResultsParam)
#set($response = $JiraManager.get($requestUrl).comments)
#set($parsePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
## Build a table if there are comments
#if($response && $response.size() > 0)
<table class="aui aui-table-sortable" style="width:100%;">
<thead>
<tr>
<th>Author</th>
<th>Comment</th>
<th class="aui-table-column-unsortable">Created 🟢 / Updated 🟣</th>
</tr>
</thead>
<tbody>
#foreach($c in $response)
#set($auth = $c.updateAuthor)
#if(!$auth)
#set($auth = $c.author)
#end
#set($displayName = $auth.displayName)
#set($avatar = $auth.avatarUrls.get("48x48"))
#if(!$avatar)
#set($avatar = "https://icon-library.com/images/avatar-icon-images/avatar-icon-images-4.jpg")
#end
## Format dates
#set($createdFormatted = "")
#if($c.created)
#set($createdFormatted = $DateUtils.parseDate($c.created, $parsePattern))
#end
#set($updatedFormatted = "")
#if($c.updated)
#set($updatedFormatted = $DateUtils.parseDate($c.updated, $parsePattern))
#end
## Render ADF to HTML
#set($html = "")
#set($stack = $c.body.content)
#foreach($lvl in [1..20])
#set($next = [])
#foreach($node in $stack)
## Paragraph
#if($node.type == "paragraph")
#set($p = "")
#if($node.content)
#foreach($n in $node.content)
#if($n.text)
#set($p = $p + $n.text)
#end
#end
#end
#set($html = $html + "<p>" + $p + "</p>")
#end
## Bullet List
#if($node.type == "bulletList")
#set($html = $html + "<ul>")
#foreach($item in $node.content)
#set($li = "")
#foreach($pnode in $item.content)
#foreach($t in $pnode.content)
#if($t.text)
#set($li = $li + $t.text)
#end
#end
#end
#set($html = $html + "<li>" + $li + "</li>")
#end
#set($html = $html + "</ul>")
#end
## Ordered List
#if($node.type == "orderedList")
#set($html = $html + "<ol>")
#foreach($item in $node.content)
#set($li = "")
#foreach($pnode in $item.content)
#foreach($t in $pnode.content)
#if($t.text)
#set($li = $li + $t.text)
#end
#end
#end
#set($html = $html + "<li>" + $li + "</li>")
#end
#set($html = $html + "</ol>")
#end
## Fallback recursion
#if($node.content)
#foreach($c2 in $node.content)
#set($discard = $next.add($c2))
#end
#end
#end
#if(!$next || $next.size() == 0)
#break
#end
#set($stack = $next)
#end
#if($html == "")
#set($html = "(no text)")
#end
<tr>
<td style="vertical-align:middle;">
<div style="display:flex; align-items:center;">
<div>
<aui-avatar size="medium" type="user" src="$avatar" title="$displayName" alt="avatar-$displayName"></aui-avatar>
</div>
<div style="margin-left:10px; line-height:1.1;">
$!displayName
</div>
</div>
</td>
<td style="word-break:break-word; vertical-align: middle;">
$html
</td>
<td style="white-space:nowrap;">
#if($createdFormatted)
<span class="aui-lozenge aui-lozenge-subtle aui-lozenge-success">$createdFormatted</span><br>
#end
#if($updatedFormatted)
<span class="aui-lozenge aui-lozenge-subtle aui-lozenge-new">$updatedFormatted</span>
#end
</td>
</tr>
#end
</tbody>
</table>
#else
## Display a message if no comments found
<div role="note" aria-labelledby="no-comments-title" class="aui-message aui-message-info" style="width:100%; height:100%;">
<p id="no-comments-title" class="title">
No comments found
</p>
<p>
Please check the <code>issueIdOrKey</code> or try another issue.
</p>
</div>
#end
#endUser Parameters
Issue ID or Key
Enter a Jira issue ID or key
Order
Choose the order in which comments are displayed (ASC or DESC by creation date)
maxResults
Set the maximum number of items to return
You May Also Like
Shows worklogs from the Jira issue
Display the top comments from a selected Confluence page or the current page by default.
List issues (work items) from Jira to get essential information in a readable and well-organized format
Shows H1 headings directly to children's topics for easy navigation.
Filter Confluence groups based on a specified filter value and display the results in different formats.
Shows page creation date
Retrieve and display labels from a specified space.
Find image within page attachments. Handy for reuse files and update them all at once
Show filtered issues and their relations
Create dropdown menus in Confluence Cloud with custom sets of options, multiselect features, and permission gates