Skip to content

Commit

Permalink
Added: Process variables recursively in Thymeleaf
Browse files Browse the repository at this point in the history
  • Loading branch information
djuarezgf committed Dec 5, 2024
1 parent 42a9597 commit 0528e63
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Enable minus in variables of email context
- Last document variables in email context
- Support for Thymeleaf standard processor by converting hyphenated variables to camel case
- Process variables recursively in Thymeleaf
73 changes: 73 additions & 0 deletions src/main/java/de/samply/email/thymeleaf/EmailContextProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.thymeleaf.templatemode.TemplateMode;

import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EmailContextProcessor extends AbstractElementTagProcessor {

Expand Down Expand Up @@ -50,9 +52,80 @@ protected void doProcess(ITemplateContext context, IProcessableElementTag tag, I
? defaultValue
: "";

// Replace ${XXX} variables with their values from the context
finalValue = resolveVariables(finalValue, context);

// Replace the tag with the final value
structureHandler.replaceWith(finalValue, false);

}
}

// TODO: Ideally, we should let Thymeleaf continue processing the replaced content
// so that all applicable processors (e.g., variable resolution, additional dialects)
// are automatically applied.
// Currently, setting `processable` to true in `structureHandler.replaceWith`
// only triggers the `StandardInliningTextProcessor`, which simply writes the content
// to the output without further processing.

/**
* Resolves ${XXX} variables in the input string using the Thymeleaf context.
*
* @param content The content with placeholders.
* @param context The Thymeleaf context.
* @return The content with variables replaced by their resolved values.
*/
/*
private String resolveVariables(String content, ITemplateContext context) {
// Regular expression to find ${XXX} placeholders
Pattern pattern = Pattern.compile("\\$\\{([^}]+)}");
Matcher matcher = pattern.matcher(content);
StringBuffer resolvedContent = new StringBuffer();
while (matcher.find()) {
String variableName = matcher.group(1); // Extract variable name inside ${}
Object variableValue = context.getVariable(variableName); // Resolve variable
String replacement = (variableValue != null) ? variableValue.toString() : ""; // Use empty string if not found
matcher.appendReplacement(resolvedContent, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(resolvedContent);
return resolvedContent.toString();
}
*/
private String resolveVariables(String content, ITemplateContext context) {
// Combined regular expression to match both ${variable} and <key /> patterns
Pattern combinedPattern = Pattern.compile(
"(\\$\\{([^}]+)})|(<\\s*([a-zA-Z0-9_-]+)\\s*/>)"
);
Matcher combinedMatcher = combinedPattern.matcher(content);

StringBuffer resolvedContent = new StringBuffer();

// Process the combined matches
while (combinedMatcher.find()) {
if (combinedMatcher.group(1) != null) {
// Match found for ${variable}
String variableName = combinedMatcher.group(2); // Extract variable name inside ${}
Object variableValue = context.getVariable(variableName); // Resolve variable
String replacement = (variableValue != null) ? variableValue.toString() : ""; // Use empty string if not found
combinedMatcher.appendReplacement(resolvedContent, Matcher.quoteReplacement(replacement));
} else if (combinedMatcher.group(3) != null) {
// Match found for <key />
String tagName = combinedMatcher.group(4); // Extract the tag name
Object tagValue = context.getVariable(tagName); // Resolve the value from context
String replacement = (tagValue != null) ? tagValue.toString() : ""; // Use empty string if not found
combinedMatcher.appendReplacement(resolvedContent, Matcher.quoteReplacement(replacement));
}
}

// Append any remaining content after the last match
combinedMatcher.appendTail(resolvedContent);

return resolvedContent.toString();
}


}

0 comments on commit 0528e63

Please sign in to comment.