-
Notifications
You must be signed in to change notification settings - Fork 294
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Communication: Fix announcement emails not rendering correctly (#9850)
- Loading branch information
Showing
10 changed files
with
409 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
...it/aet/artemis/communication/service/notifications/MarkdownCustomLinkRendererService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package de.tum.cit.aet.artemis.communication.service.notifications; | ||
|
||
import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE; | ||
|
||
import java.net.URL; | ||
import java.util.Set; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.util.UriComponentsBuilder; | ||
|
||
/** | ||
* This service implements the rendering of markdown tags that represent a link. | ||
* It takes the tag, transforms it into an <a></a> tag, and sets the corresponding href. | ||
*/ | ||
@Profile(PROFILE_CORE) | ||
@Service | ||
public class MarkdownCustomLinkRendererService implements MarkdownCustomRendererService { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(MarkdownCustomLinkRendererService.class); | ||
|
||
private final Set<String> supportedTags; | ||
|
||
@Value("${server.url}") | ||
private URL artemisServerUrl; | ||
|
||
public MarkdownCustomLinkRendererService() { | ||
this.supportedTags = Set.of("programming", "modeling", "quiz", "text", "file-upload", "lecture", "attachment", "lecture-unit", "slide", "faq"); | ||
} | ||
|
||
/** | ||
* Takes a string and replaces all occurrences of custom markdown tags (e.g. [programming], [faq], etc.) with a link | ||
* | ||
* @param content string to render | ||
* | ||
* @return the newly rendered string. | ||
*/ | ||
public String render(String content) { | ||
String tagPattern = String.join("|", supportedTags); | ||
// The pattern checks for the occurrence of any tag and then extracts the link from it | ||
Pattern pattern = Pattern.compile("\\[(" + tagPattern + ")\\](.*?)\\((.*?)\\)(.*?)\\[/\\1\\]"); | ||
Matcher matcher = pattern.matcher(content); | ||
String parsedContent = content; | ||
|
||
while (matcher.find()) { | ||
try { | ||
String textStart = matcher.group(2); | ||
String link = matcher.group(3); | ||
String textEnd = matcher.group(4); | ||
String text = (textStart + " " + textEnd).trim(); | ||
|
||
String absoluteUrl = UriComponentsBuilder.fromUri(artemisServerUrl.toURI()).path(link).build().toUriString(); | ||
|
||
parsedContent = parsedContent.substring(0, matcher.start()) + "<a href=\"" + absoluteUrl + "\">" + text + "</a>" + parsedContent.substring(matcher.end()); | ||
} | ||
catch (Exception e) { | ||
log.error("Not able to render tag. Replacing with empty.", e); | ||
parsedContent = parsedContent.substring(0, matcher.start()) + parsedContent.substring(matcher.end()); | ||
} | ||
|
||
matcher = pattern.matcher(parsedContent); | ||
} | ||
|
||
return parsedContent; | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
...t/artemis/communication/service/notifications/MarkdownCustomReferenceRendererService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package de.tum.cit.aet.artemis.communication.service.notifications; | ||
|
||
import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE; | ||
|
||
import java.util.HashMap; | ||
import java.util.Set; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.stereotype.Service; | ||
|
||
/** | ||
* This service implements the rendering of markdown tags that represent a reference (to e.g. a user). | ||
* These references cannot directly represent a link, so they are rendered as their text only. | ||
*/ | ||
@Profile(PROFILE_CORE) | ||
@Service | ||
public class MarkdownCustomReferenceRendererService implements MarkdownCustomRendererService { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(MarkdownCustomReferenceRendererService.class); | ||
|
||
private final Set<String> supportedTags; | ||
|
||
private final HashMap<String, String> startingCharacters; | ||
|
||
public MarkdownCustomReferenceRendererService() { | ||
supportedTags = Set.of("user", "channel"); | ||
startingCharacters = new HashMap<>(); | ||
startingCharacters.put("user", "@"); | ||
startingCharacters.put("channel", "#"); | ||
} | ||
|
||
/** | ||
* Takes a string and replaces all occurrences of custom markdown tags (e.g. [user], [channel], etc.) with text. | ||
* To make it better readable, it prepends an appropriate character. (e.g. for users an @, for channels a #) | ||
* | ||
* @param content string to render | ||
* | ||
* @return the newly rendered string. | ||
*/ | ||
@Override | ||
public String render(String content) { | ||
String tagPattern = String.join("|", supportedTags); | ||
Pattern pattern = Pattern.compile("\\[(" + tagPattern + ")\\](.*?)\\((.*?)\\)(.*?)\\[/\\1\\]"); | ||
Matcher matcher = pattern.matcher(content); | ||
String parsedContent = content; | ||
|
||
while (matcher.find()) { | ||
try { | ||
String tag = matcher.group(1); | ||
String startingCharacter = startingCharacters.get(tag); | ||
startingCharacter = startingCharacter == null ? "" : startingCharacter; | ||
String textStart = matcher.group(2); | ||
String textEnd = matcher.group(4); | ||
String text = startingCharacter + (textStart + " " + textEnd).trim(); | ||
|
||
parsedContent = parsedContent.substring(0, matcher.start()) + text + parsedContent.substring(matcher.end()); | ||
} | ||
catch (Exception e) { | ||
log.error("Not able to render tag. Replacing with empty.", e); | ||
parsedContent = parsedContent.substring(0, matcher.start()) + parsedContent.substring(matcher.end()); | ||
} | ||
|
||
matcher = pattern.matcher(parsedContent); | ||
} | ||
|
||
return parsedContent; | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
...um/cit/aet/artemis/communication/service/notifications/MarkdownCustomRendererService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package de.tum.cit.aet.artemis.communication.service.notifications; | ||
|
||
public interface MarkdownCustomRendererService { | ||
|
||
String render(String content); | ||
} |
44 changes: 44 additions & 0 deletions
44
...e/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package de.tum.cit.aet.artemis.communication.service.notifications; | ||
|
||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import org.commonmark.node.Image; | ||
import org.commonmark.node.Node; | ||
import org.commonmark.node.Text; | ||
import org.commonmark.renderer.NodeRenderer; | ||
import org.commonmark.renderer.html.HtmlNodeRendererContext; | ||
import org.commonmark.renderer.html.HtmlWriter; | ||
|
||
public class MarkdownImageBlockRenderer implements NodeRenderer { | ||
|
||
private final String baseUrl; | ||
|
||
private final HtmlWriter html; | ||
|
||
MarkdownImageBlockRenderer(HtmlNodeRendererContext context, String baseUrl) { | ||
html = context.getWriter(); | ||
this.baseUrl = baseUrl; | ||
} | ||
|
||
@Override | ||
public Set<Class<? extends Node>> getNodeTypes() { | ||
return Set.of(Image.class); | ||
} | ||
|
||
@Override | ||
public void render(Node node) { | ||
Image image = (Image) node; | ||
|
||
html.tag("a", Map.of("href", baseUrl + image.getDestination())); | ||
|
||
try { | ||
html.text(((Text) image.getFirstChild()).getLiteral()); | ||
} | ||
catch (Exception e) { | ||
html.text(image.getDestination()); | ||
} | ||
|
||
html.tag("/a"); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...it/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package de.tum.cit.aet.artemis.communication.service.notifications; | ||
|
||
import org.commonmark.renderer.NodeRenderer; | ||
import org.commonmark.renderer.html.HtmlNodeRendererContext; | ||
import org.commonmark.renderer.html.HtmlNodeRendererFactory; | ||
|
||
public class MarkdownImageBlockRendererFactory implements HtmlNodeRendererFactory { | ||
|
||
private final String baseUrl; | ||
|
||
public MarkdownImageBlockRendererFactory(String baseUrl) { | ||
this.baseUrl = baseUrl; | ||
} | ||
|
||
@Override | ||
public NodeRenderer create(HtmlNodeRendererContext context) { | ||
return new MarkdownImageBlockRenderer(context, baseUrl); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
.../communication/service/notifications/MarkdownRelativeToAbsolutePathAttributeProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package de.tum.cit.aet.artemis.communication.service.notifications; | ||
|
||
import java.util.Map; | ||
|
||
import org.commonmark.node.Node; | ||
import org.commonmark.renderer.html.AttributeProvider; | ||
|
||
public class MarkdownRelativeToAbsolutePathAttributeProvider implements AttributeProvider { | ||
|
||
private final String baseUrl; | ||
|
||
public MarkdownRelativeToAbsolutePathAttributeProvider(String baseUrl) { | ||
this.baseUrl = baseUrl; | ||
} | ||
|
||
/** | ||
* We store images and attachments with relative urls, so when rendering we need to replace them with absolute ones | ||
* | ||
* @param node rendered Node, if Image or Link we try to replace the source | ||
* @param attributes of the Node | ||
* @param tagName of the html element | ||
*/ | ||
@Override | ||
public void setAttributes(Node node, String tagName, Map<String, String> attributes) { | ||
if ("a".equals(tagName)) { | ||
String href = attributes.get("href"); | ||
if (href != null && href.startsWith("/")) { | ||
attributes.put("href", baseUrl + href); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.