Getting first image out of the page body

suedti1 November 23, 2015

Marketing departement has special requirements for a special formatted blog list, where the images are rendered in a column and the text in another column.

I was thinking about a user-macro that extracts the first image of every blog-posts for the output of the first column. 

I know that I can get the body of an page/blog with $page.getBodyAsString(). 

But I have no idea how to extract a piece of markup from the body.

 

Any ideas?

 

Thanks a lot!

 

philipp

4 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

2 votes
Answer accepted
Stephen Deutsch
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 24, 2015

Looks like this should work:

## @param Width:title=Image width|type=int|desc=If set, displays image with desired size.  Otherwise, the value on the original page is used.
#set ( $blogs = $pageManager.getBlogPosts($space, true) )
#set ( $count = 0 )
#set ( $width = "" )
#set ( $width = $paramWidth )
 
<ul class="user-macro-list-blog-posts"
  #foreach($blog in $blogs)
    #if ($count < 10)
      <li><a href="${req.contextPath}${blog.urlPath}">${blog.title}</a></li>
	  #set ( $contentBody = $blog.getBodyAsString() )
 
      #if ( $contentBody.contains("<ac:image") )
        #set ( $firstIndex = $contentBody.indexOf("<ac:image") )
        #set ( $middleIndex = $contentBody.indexOf("><ri:attachment") )
        #set ( $endIndex = $contentBody.indexOf("</ac:image>") + 11 )
        #set ( $imagePart = $contentBody.substring($firstIndex, $endIndex) )
        #set ( $middleIndex = $imagePart.indexOf("<ri:attachment") )
        #set ( $pageRefIndex = $imagePart.indexOf(" />") )
        #if ( !$imagePart.contains("content-title") )
          #set ( $continueIndex = $pageRefIndex + 3 )
          #set ( $imagePart = $imagePart.substring(0, $pageRefIndex) + '><ri:blog-post ri:content-title="' + $blog.title + '" ri:posting-day="' + $blog.datePath + '" /></ri:attachment>' + $imagePart.substring($continueIndex) )
        #end
        #if ( $width == "" )
          #set ( $imageString = $imagePart )
        #else
          #set ( $imageString = '<ac:image ac:thumbnail="true" ac:width="' + $width + '">' + $imagePart.substring($middleIndex) )
        #end
      #end
      $imageString
      ##<p class='$imagePart.substring($middleIndex)'></p>
      ##$blog.getBodyAsString()
      #set ( $count = $count + 1 )
    #end
  #end
<ul>

If it works, please mark it as an answer smile

suedti1 December 1, 2015

What would be the nicest way to reverse the order of the posts? I forgot that normally the newest posts are on top of a news-list.... Thanks!

Stephen Deutsch
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 1, 2015

I tried reversing the order, but that doesn't necessarily mean that the newest is on top; it seems like it doesn't sort by date, so I'll have to come up with another way to return the newest post, especially because the Velocity used by Confluence doesn't include the SortTool...

suedti1 December 10, 2015

I found a solution: getRecentlyAddedBlogPosts() returns a list with the correct order. {code} #set ( $blogs = $pageManager.getRecentlyAddedBlogPosts(20, "news") ) {code} whereas `news`is the space-key.

suedti1 February 3, 2016

Hi Stephen!

I just discovered that the loop does of course noch take into consideration any permissions set on the single blog-posts.

Do you have an idea how the check for permissions before outputting the single lines of blog-posts?

Thanks

suedti1 February 3, 2016

Also found a solution for the permissions: 

#if ($permissionHelper.canView($action.remoteUser,$blog))

within the loop will do the trick.

 

0 votes
suedti1 November 24, 2015

Thanks Stephen!

I extended your concept in order to extract also the excerpt.

In that way the layout of the Blogpost can be absolutely free and the macro is listing always the first image and the excerpt. 

Very nice result!

 

Philipp

 

This is the final user-macro.

## Custom List of Blog Items listing the first image and the excerpt
## @param Width:title=Image width|type=int|desc=If set, displays image with desired size.  Otherwise, the value on the original page is used.
#set ( $blogs = $pageManager.getBlogPosts($space, true) )
#set ( $count = 0 )
#set ( $width = "" )
#set ( $width = $paramWidth )
  
<div class="custom-blog-list"
  #foreach($blog in $blogs)
    #if ($count < 10)
   #set ($crDate=$action.dateFormatter.format($blog.getCreationDate()))
	  <div class="custom-blog-list-item">
      <a class="blogHeading" href="${req.contextPath}${blog.urlPath}">${blog.title}  </a>
		  <p class="custom-blog-list-meta">$userAccessor.getUser("${blog.CreatorName}").getFullName(), $crDate </p>
  
      #set ( $contentBody = $blog.getBodyAsString() )
      #if ( $contentBody.contains("<ac:rich-text-body") )
        #set ( $firstEIndex = $contentBody.indexOf("<ac:rich-text-body>") )
        #set ( $endEIndex = $contentBody.indexOf("</ac:rich-text-body>") + 20 )
        #set ( $ExcerptPart = $contentBody.substring($firstEIndex, $endEIndex) )
	  #end  
	  
      #if ( $contentBody.contains("<ac:image") )
        #set ( $firstIndex = $contentBody.indexOf("<ac:image") )
        #set ( $middleIndex = $contentBody.indexOf("><ri:attachment") )
        #set ( $endIndex = $contentBody.indexOf("</ac:image>") + 11 )
        #set ( $imagePart = $contentBody.substring($firstIndex, $endIndex) )
        #set ( $middleIndex = $imagePart.indexOf("<ri:attachment") )
        #set ( $pageRefIndex = $imagePart.indexOf(" />") )
        #if ( !$imagePart.contains("content-title") )
          #set ( $continueIndex = $pageRefIndex + 3 )
          #set ( $imagePart = $imagePart.substring(0, $pageRefIndex) + '><ri:blog-post ri:content-title="' + $blog.title + '" ri:posting-day="' + $blog.datePath + '" /></ri:attachment>' + $imagePart.substring($continueIndex) )
        #end
        #if ( $width == "" )
          #set ( $imageString = $imagePart )
        #else
          #set ( $imageString = '<ac:image ac:thumbnail="true" ac:width="' + $width + '" >' + $imagePart.substring($middleIndex) )  
        #end
      #end
      <div class="custom-blog-list-image">
      $imageString
      </div>
  
     <div class="custom-blog-list-text">
	 $ExcerptPart
     </div>	 <p style="float:none;break:before;clear:both;display:block;">  </p>
      #set ( $count = $count + 1 )
    #end
    </div> ## /custom-blog-list-item
  #end
</div>

 

 

0 votes
suedti1 November 24, 2015

Hi Stephen,

Wow this looks great. Tank you 

So this is my macro for looping through blog items. But I get "unknown attachment" instead of the image.

## @param Width:title=Image width|type=int|desc=If set, displays image with desired size.  Otherwise, the value on the original page is used.
#set ( $blogs = $pageManager.getBlogPosts($space, true) )
#set ( $count = 0 )
#set ( $width = "" )
#set ( $width = $paramWidth )
 
<ul class="user-macro-list-blog-posts"
  #foreach($blog in $blogs)
    #if ($count < 10)
      <li><a href="${req.contextPath}${blog.urlPath}">${blog.title}</a></li>
	  #set ( $contentBody = $blog.getBodyAsString() )
## $contentBody 
 
 #if ( $contentBody.contains("<ac:image") )
  #set ( $firstIndex = $contentBody.indexOf("<ac:image") )
  #set ( $middleIndex = $contentBody.indexOf("><ri:attachment") )
  #set ( $endIndex = $contentBody.indexOf("</ac:image>") + 11 )
  #set ( $imagePart = $contentBody.substring($firstIndex, $endIndex) )
  #set ( $middleIndex = $imagePart.indexOf("><ri:attachment") )
  #if ( $width == "" )
    #set ( $imageString = $imagePart )
  #else
    #set ( $imageString = '<ac:image ac:thumbnail="true" ac:width="' + $width + '"' + $imagePart.substring($middleIndex) )
  #end
#end
$imageString
<p class='$imagePart.substring($middleIndex)'></p>
##$blog.getBodyAsString()
      #set ( $count = $count + 1 )
    #end
  #end
<ul>

 

After some fiddling I found out that images from blog-posts need some special syntax.

Looks that the simple way does not work with blog posts.

<ac:image><ri:attachment ri:filename="image2015-8-27 11:10:27.png" /></ac:image>

 

But this does work:

<ac:image ac:height="250">
    <ri:attachment ri:filename="image2015-8-27 11:10:27.png">
      <ri:blog-post ri:content-title="Visit of the Slovenian delegation" ri:posting-day="2015/08/20"/>
    </ri:attachment>
  </ac:image>

 

So I would need to inject the ri:blog-post part into the ri:attachment part.

Any help would be really appreciated!!!

 

Tanks 

 

philipp

 

 

 

 

0 votes
Stephen Deutsch
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 24, 2015

Hi Philipp,

This should work, or you should be able to adapt it for your needs:

## @param Width:title=Image width|type=int|desc=If set, displays image with desired size.  Otherwise, the value on the original page is used.
#set ( $width = "" )
#set ( $width = $paramWidth )
#set ( $contentBody = $content.getBodyAsString() )
#if ( $contentBody.contains("<ac:image") )
  #set ( $firstIndex = $contentBody.indexOf("<ac:image") )
  #set ( $endIndex = $contentBody.indexOf("</ac:image>") + 11 )
  #set ( $imagePart = $contentBody.substring($firstIndex, $endIndex) )
  #set ( $middleIndex = $imagePart.indexOf("><ri:attachment") )
  #if ( $width == "" )
    #set ( $imageString = $imagePart )
  #else
    #set ( $imageString = '<ac:image ac:thumbnail="true" ac:width="' + $width + '"' + $imagePart.substring($middleIndex) )
  #end
#end
$imageString

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events