",
+ engine.parse("{text} {text.raw}",
+ new Variant(Locale.ENGLISH, "application/xhtml+xml;charset=UTF-8", "UTF-8")).data("text", "
")
+ .render());
}
@TemplateData
diff --git a/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/EngineProducer.java b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/EngineProducer.java
index 26bc5754ad824..f01e316cdd49a 100644
--- a/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/EngineProducer.java
+++ b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/EngineProducer.java
@@ -113,8 +113,8 @@ public EngineProducer(QuteContext context, QuteConfig config, QuteRuntimeConfig
}
}
- // Escape some characters for HTML templates
- builder.addResultMapper(new HtmlEscaper());
+ // Escape some characters for HTML/XML templates
+ builder.addResultMapper(new HtmlEscaper(List.copyOf(config.escapeContentTypes)));
// Fallback reflection resolver
builder.addValueResolver(new ReflectionValueResolver());
diff --git a/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/QuteConfig.java b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/QuteConfig.java
index 416b5624646fc..28bf7ed2d4a81 100644
--- a/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/QuteConfig.java
+++ b/extensions/qute/runtime/src/main/java/io/quarkus/qute/runtime/QuteConfig.java
@@ -74,4 +74,11 @@ public class QuteConfig {
@ConfigItem(defaultValue = "
")
public String iterationMetadataPrefix;
+ /**
+ * The list of content types for which the {@code '}, {@code "}, {@code <}, {@code >} and {@code &} characters are escaped
+ * if a template variant is set.
+ */
+ @ConfigItem(defaultValue = "text/html,text/xml,application/xml,application/xhtml+xml")
+ public List escapeContentTypes;
+
}
diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java
index 14ceea7639254..14bd0496f5627 100644
--- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java
+++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/devmode/console/DevConsoleProcessor.java
@@ -516,7 +516,7 @@ private Engine buildEngine(List devTemplatePaths,
EngineBuilder builder = Engine.builder().addDefaults();
// Escape some characters for HTML templates
- builder.addResultMapper(new HtmlEscaper());
+ builder.addResultMapper(new HtmlEscaper(List.of(Variant.TEXT_HTML)));
builder.strictRendering(true)
.addValueResolver(new ReflectionValueResolver())
diff --git a/independent-projects/qute/core/src/main/java/io/quarkus/qute/HtmlEscaper.java b/independent-projects/qute/core/src/main/java/io/quarkus/qute/HtmlEscaper.java
index 5788c7e2656f6..f7405dc45d038 100644
--- a/independent-projects/qute/core/src/main/java/io/quarkus/qute/HtmlEscaper.java
+++ b/independent-projects/qute/core/src/main/java/io/quarkus/qute/HtmlEscaper.java
@@ -1,11 +1,18 @@
package io.quarkus.qute;
import io.quarkus.qute.TemplateNode.Origin;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class HtmlEscaper implements ResultMapper {
+ private final List escapedContentTypes;
+
+ public HtmlEscaper(List escapedContentTypes) {
+ this.escapedContentTypes = escapedContentTypes;
+ }
+
@Override
public boolean appliesTo(Origin origin, Object result) {
if (result instanceof RawString) {
@@ -37,10 +44,17 @@ String escape(CharSequence value) {
return value.toString();
}
- static boolean requiresDefaultEscaping(Variant variant) {
- return variant.getContentType() != null
- ? (Variant.TEXT_HTML.equals(variant.getContentType()) || Variant.TEXT_XML.equals(variant.getContentType()))
- : false;
+ private boolean requiresDefaultEscaping(Variant variant) {
+ String contentType = variant.getContentType();
+ if (contentType == null) {
+ return false;
+ }
+ for (String escaped : escapedContentTypes) {
+ if (contentType.startsWith(escaped)) {
+ return true;
+ }
+ }
+ return false;
}
private String doEscape(CharSequence value, int index, StringBuilder builder) {
diff --git a/independent-projects/qute/core/src/test/java/io/quarkus/qute/HtmlEscaperTest.java b/independent-projects/qute/core/src/test/java/io/quarkus/qute/HtmlEscaperTest.java
index 9f24a043e1fff..87ff040002539 100644
--- a/independent-projects/qute/core/src/test/java/io/quarkus/qute/HtmlEscaperTest.java
+++ b/independent-projects/qute/core/src/test/java/io/quarkus/qute/HtmlEscaperTest.java
@@ -6,6 +6,7 @@
import io.quarkus.qute.TemplateNode.Origin;
import java.io.IOException;
+import java.util.List;
import java.util.Locale;
import java.util.Optional;
import org.junit.jupiter.api.Test;
@@ -14,7 +15,7 @@ public class HtmlEscaperTest {
@Test
public void testAppliesTo() {
- HtmlEscaper html = new HtmlEscaper();
+ HtmlEscaper html = new HtmlEscaper(List.of(Variant.TEXT_HTML));
Origin htmlOrigin = new Origin() {
@Override
@@ -53,7 +54,7 @@ public int getLine() {
@Test
public void testEscaping() throws IOException {
- HtmlEscaper html = new HtmlEscaper();
+ HtmlEscaper html = new HtmlEscaper(List.of(Variant.TEXT_HTML));
assertEquals("Čolek", html.escape("Čolek"));
assertEquals("<strong>Čolek</strong>", html.escape("Čolek"));
assertEquals("<a>&link"'</a>", html.escape("&link\"'"));