♻️ Replace Guava’s HTML escaping with kotlinx.html
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 6 Oct 2025 16:20:46 +0000 (18:20 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 6 Oct 2025 16:20:46 +0000 (18:20 +0200)
src/main/java/net/pterodactylus/rhynodge/states/AbstractState.java
src/test/kotlin/net/pterodactylus/rhynodge/states/AbstractStateTest.kt

index f925f8c..81e6a05 100644 (file)
@@ -20,6 +20,7 @@ package net.pterodactylus.rhynodge.states;
 import java.time.Clock;
 import java.util.Objects;
 
+import kotlinx.html.DIV;
 import net.pterodactylus.rhynodge.Reaction;
 import net.pterodactylus.rhynodge.State;
 import net.pterodactylus.rhynodge.output.DefaultOutput;
@@ -27,11 +28,12 @@ import net.pterodactylus.rhynodge.output.Output;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.google.common.escape.Escaper;
-import com.google.common.html.HtmlEscapers;
 import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
+import static java.util.Collections.emptyMap;
+import static kotlinx.html.stream.StreamKt.createHTML;
+
 /**
  * Abstract implementation of a {@link State} that knows about the basic
  * attributes of a {@link State}.
@@ -220,13 +222,12 @@ public abstract class AbstractState implements State {
 
        @Nullable
        protected String htmlText() {
-               //noinspection UnstableApiUsage
-               return "<div>" + htmlEscaper.escape(plainText()) + "</div>";
+               var tagConsumer = createHTML(false, false);
+               var div = new DIV(emptyMap(), tagConsumer);
+               div.text(plainText());
+               return tagConsumer.finalize();
        }
 
-       @SuppressWarnings("UnstableApiUsage")
-       private static final Escaper htmlEscaper = HtmlEscapers.htmlEscaper();
-
        @Override
        public int hashCode() {
                return Objects.hash(success, empty, time, failCount, exception);
index d6362c3..8913170 100644 (file)
@@ -78,6 +78,14 @@ class AbstractStateTest {
                assertThat(first.equals(second), equalTo(false))
        }
 
+       @Test
+       fun `state encodes html text correctly`() {
+               val state = object : AbstractState() {
+                       override fun plainText() = "a & b"
+               }
+               assertThat(state.htmlText(), equalTo("a &amp; b"))
+       }
+
 }
 
 private val testClock = Clock.fixed(now(), UTC)