outgoing
import com.atlassian.jira.component.ComponentAccessor /** * Class to transform from wiki notation to html * This version will replace inline images with a note that there is one */ class WikiToHtml { static String transform(String wikiFormat) { if (!wikiFormat) { return null } // access the correct services def jcl = ComponentAccessor.classLoader def app = ComponentAccessor.getApplicationProperties() def epubClass = jcl.loadClass("com.atlassian.event.api.EventPublisher") def epub = ComponentAccessor.getOSGiComponentInstanceOfType(epubClass) def fmanClass = jcl.loadClass("com.atlassian.jira.config.FeatureManager") def fman = ComponentAccessor.getOSGiComponentInstanceOfType(fmanClass) def vreqClass = jcl.loadClass("com.atlassian.jira.util.velocity.VelocityRequestContextFactory") def vreq = ComponentAccessor.getOSGiComponentInstanceOfType(vreqClass) def wrenderClass = jcl.loadClass("com.atlassian.jira.issue.fields.renderer.wiki.AtlassianWikiRenderer") def wrender = wrenderClass.newInstance(epub, app, vreq, fman) def fixImage = wikiFormat?.replaceAll(/\!(\S+)\|\S+\!/, '<!-- inline image filename=#$1# -->') fixImage = fixImage.replaceAll(/\!\^(\S+)\|\S+\!/, '<!-- inline image filename=#$1# -->') fixImage = fixImage.replaceAll(/\!\^(\S+)\!/, '<!-- inline image filename=#$1# -->') fixImage = fixImage.replaceAll(/\!(\S+)\!/, '<!-- inline image filename=#$1# -->') // wiki text can also contain files fixImage = fixImage.replaceAll(/\[(\S+)\|\^(\S+)\]/, '<!-- inline file filename=#$2# -->') fixImage = fixImage.replaceAll(/\[\^(\S+)\]/, '<!-- inline file filename=#$1# -->') return wrender.render(fixImage, null) } } replica.key = issue.key replica.type = issue.type replica.reporter = issue.reporter replica.summary = issue.summary replica.description = WikiToHtml.transform(issue.description) replica.labels = issue.labels replica.comments = issue.comments.collect { comment -> comment.body = WikiToHtml.transform (comment.body) comment } replica.resolution = issue.resolution replica.parentId = issue.parentId replica.priority = issue.priority replica.attachments = issue.attachments replica.project = issue.project replica.status = issue.status replica.project.versions = [] replica.project.components = []
incoming
if(firstSync){ // Set type name from source entity, if not found set a default workItem.projectKey = "Mathieu" workItem.typeName = nodeHelper.getIssueType(replica.type?.name)?.name ?: "Task"; } workItem.summary = replica.summary workItem.attachments = attachmentHelper.mergeAttachments(workItem, replica) def processInlineImages = { str -> def processUnescapedLtGtTags = { def counter = 0 while (counter < 1000) { def matcher = (str =~ /<!-- inline image filename=#(([^#]+)|(([^#]+)#([^#]+)))# -->/) if (matcher.size() < 1) { break; } def match = matcher[0] if (match.size() < 2) { break; } //log.error("replica.attachments=${replica.attachments}") def attId = replica.attachments.find { it.filename?.equals(match[1]) }?.remoteId if (!attId) { log.error("""Could not find attachment with name ${match[1]}, known names: ${replica.attachments.filename}, match: ${replica.attachments.find { it.filename?.equals(match[1]) }} """) str = str.replace(match[0], """<!-- inline processed image filename=#${match[1]}# -->""".toString()) } else { def tmpStr = str.replace(match[0], """<img src="/secure/attachment/${attId}/${attId}_${match[1]}" />""".toString()) if (tmpStr == str) { break; } str = tmpStr } counter++ } str } def processLtGtTags = { def counter = 0 while (counter < 1000) { def matcher = (str =~ /<!-- inline image filename=#(([^#]+)|(([^#]+)#([^#]+)))# -->/) if (matcher.size() < 1) { break; } def match = matcher[0] if (match.size() < 2) { break; } def attId = replica.attachments.find { it.filename?.equals(match[1]) }?.remoteId if (!attId) { log.error("""Could not find attachment with name ${match[1]}, known names: ${replica.attachments.filename}, match: ${replica.attachments.find { it.filename?.equals(match[1]) }} """) str = str.replace(match[0], """<!-- inline processed image filename=#${match[1]}# -->""".toString()) } else { def tmpStr = str.replace(match[0], """<img src="/secure/attachment/${attId}/${attId}_${match[1]}" />""".toString()) if (tmpStr == str) { break; } str = tmpStr } counter++ } str } def processNoImage = { //"<p><img // src=\"https://jira.smartodds.co.uk/images/icons/attach/noimage.png\" // imagetext=\"Screenshot from 2022-11-18 11-09-25.png|thumbnail\" // align=\"absmiddle\" // border=\"0\" /></p>" def counter = 0 while (counter < 1000) { def matcher = (str =~ /<img src="[^"]+" imagetext="(([^"]+)\|thumbnail)" align="absmiddle" border="0" \/>/) if (matcher.size() < 1) { break; } def match = matcher[0] if (match.size() < 2) { break; } def filename = match[2] def attId = replica.attachments.find { it.filename?.equals(filename) }?.remoteId if (!attId) { log.error("""Could not find attachment with name ${filename}, known names: ${replica.attachments.filename}, match: ${replica.attachments.find { it.filename?.equals(filename) }} """) str = str.replace(match[0], """<img src="/images/icons/attach/noimage.png" processed imagetext="$filename|thumbnail" align="absmiddle" border="0" />""".toString()) } else { def tmpStr = str.replace(match[0], """<img src="/secure/attachment/${attId}/${attId}_${filename}" />""".toString()) if (tmpStr == str) { break; } str = tmpStr } counter++ } str } def processImgTagsWithIds = { //"<p>TEST DECS23456 </p> \n //<p><span class=\"image-wrap\" style=\"\"><img src=\"/rest/api/3/attachment/content/36820\"></span></p> \n //<p>TESt </p> \n //<p><span class=\"image-wrap\" style=\"\"><img src=\"/rest/api/3/attachment/content/36821\"></span></p> \n //<p>and more</p>" def counter = 0 while (counter < 1000) { def matcher = (str =~ /<img src="\/rest\/api\/3\/attachment\/content\/(\d+)">/) if (matcher.size() < 1) { return str } def match = matcher[0] //println("match[1]=$match[1]") if (match.size() < 2) { // match[0]=<img src="/rest/api/3/attachment/content/36820"> match[1]=36820 return str } def attId = match[1] def attachment = replica.attachments.find { (it.remoteId as String) == ( attId as String ) } if (!attachment) { log.error("""Could not find attachment with id ${attId}, known ids: ${replica.attachments.remoteId}, match: ${replica.attachments.find { (it.remoteId as String) == ( attId as String ) }} """) str = str.replace(match[0], """<img src="/rest/api/3/attachment/content/${attId}" processed />""".toString()) } else { def tmpStr = str.replace(match[0], """<img src="/secure/attachment/${attId}/${attId}_${attachment.filename}" />""".toString()) if (tmpStr == str) { break; } str = tmpStr } counter++ } str } //log.error("#processimages 0 $str") str = processUnescapedLtGtTags() //log.error("#processimages 1 $str") str = processLtGtTags() //log.error("#processimages 2 $str") str = processNoImage() //log.error("#processimages 3 $str") str = processImgTagsWithIds() log.error("#processimages $str") str } workItem.comments = commentHelper.mergeComments(workItem, replica, { comment -> def attrAuthor = comment.author?.displayName ?: "Default-" comment.body = "<b> ${attrAuthor} said:</b> " + comment.body comment.body = processInlineImages (comment.body) comment }) //workItem."Microsoft.VSTS.TCM.ReproSteps" = processInlineImages(replica.description)