From 999016075c194061723dd2cfcb16ffd517fe6186 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 28 May 2026 13:38:30 +0200 Subject: [PATCH 1/4] Expose ComponentParser#asMiniMessage and partially implement MiniMessageAdapter --- .../gemstone/component/ComponentParser.java | 9 ++ .../component/ComponentParserImpl.java | 5 + .../component/MiniMessageAdapter.java | 105 ++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 src/main/java/gg/gemstone/component/MiniMessageAdapter.java diff --git a/src/main/java/gg/gemstone/component/ComponentParser.java b/src/main/java/gg/gemstone/component/ComponentParser.java index ff80c68..7a86429 100644 --- a/src/main/java/gg/gemstone/component/ComponentParser.java +++ b/src/main/java/gg/gemstone/component/ComponentParser.java @@ -204,6 +204,15 @@ static ComponentParser componentParserAmpersand() { */ Builder toBuilder(); + /** + * Returns an adapter that lets you use the more complex parsing features of this parser + * through the {@link MiniMessage} interface. Useful for dropping in this parser in an + * environment that currently expects MiniMessage. + * + * @return an adapter that exposes this parser's functionality through the MiniMessage interface + */ + MiniMessage asMiniMessage(); + /** * Builds a {@link ComponentParser} with a custom translator chain and * MiniMessage instance. diff --git a/src/main/java/gg/gemstone/component/ComponentParserImpl.java b/src/main/java/gg/gemstone/component/ComponentParserImpl.java index 0f1ba21..186a8b8 100644 --- a/src/main/java/gg/gemstone/component/ComponentParserImpl.java +++ b/src/main/java/gg/gemstone/component/ComponentParserImpl.java @@ -120,6 +120,11 @@ public ComponentParser.Builder toBuilder() { return new Builder(translators, miniMessage); } + @Override + public MiniMessage asMiniMessage() { + return new MiniMessageAdapter(this, miniMessage); + } + @VisibleForTesting @NotNull String translate(@NotNull String input) { requireNonNull(input, "input"); diff --git a/src/main/java/gg/gemstone/component/MiniMessageAdapter.java b/src/main/java/gg/gemstone/component/MiniMessageAdapter.java new file mode 100644 index 0000000..9152f72 --- /dev/null +++ b/src/main/java/gg/gemstone/component/MiniMessageAdapter.java @@ -0,0 +1,105 @@ +package gg.gemstone.component; + +import net.kyori.adventure.pointer.Pointered; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.tree.Node; +import org.jetbrains.annotations.NotNull; + +/** + * Adapts a {@link ComponentParser} to the {@link MiniMessage} interface. + */ +final class MiniMessageAdapter implements MiniMessage { + + private final ComponentParser parser; + private final MiniMessage miniMessage; + + /** + * Instantiates a {@link MiniMessageAdapter}. + * + * @param parser the parser to adapt method calls to + * @param miniMessage the underlying {@link MiniMessage} object the parser is using (used for + * functionality that the {@link MiniMessage} interface expects, but is + * not provided by the {@link ComponentParser} interface) + */ + MiniMessageAdapter(ComponentParser parser, MiniMessage miniMessage) { + this.parser = parser; + this.miniMessage = miniMessage; + } + + @Override + public @NotNull String escapeTags(@NotNull String input) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull String escapeTags(@NotNull String input, @NotNull TagResolver tagResolver) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull String stripTags(@NotNull String input) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull String stripTags(@NotNull String input, @NotNull TagResolver tagResolver) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target) { + return parser.parse(input, target); + } + + @Override + public @NotNull Component deserialize(@NotNull String input, @NotNull TagResolver tagResolver) { + return parser.parse(input, tagResolver); + } + + @Override + public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target, @NotNull TagResolver tagResolver) { + return parser.parse(input, target, tagResolver); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input) { + return parser.parseToTree(input); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull Pointered target) { + return parser.parseToTree(input, target); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull TagResolver tagResolver) { + return parser.parseToTree(input, tagResolver); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull Pointered target, @NotNull TagResolver tagResolver) { + return parser.parseToTree(input, target, tagResolver); + } + + @Override + public boolean strict() { + return miniMessage.strict(); + } + + @Override + public @NotNull TagResolver tags() { + return miniMessage.tags(); + } + + @Override + public @NotNull Component deserialize(@NotNull String input) { + return parser.parse(input); + } + + @Override + public @NotNull String serialize(@NotNull Component component) { + return miniMessage.serialize(component); + } +} From 4fb914862bbaa3ef2377c3a7af208a2970c5c308 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 28 May 2026 13:42:49 +0200 Subject: [PATCH 2/4] Add clarifying comment --- .../gg/gemstone/component/MiniMessageAdapter.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/gg/gemstone/component/MiniMessageAdapter.java b/src/main/java/gg/gemstone/component/MiniMessageAdapter.java index 9152f72..963bb59 100644 --- a/src/main/java/gg/gemstone/component/MiniMessageAdapter.java +++ b/src/main/java/gg/gemstone/component/MiniMessageAdapter.java @@ -48,6 +48,11 @@ final class MiniMessageAdapter implements MiniMessage { throw new UnsupportedOperationException(); } + @Override + public @NotNull Component deserialize(@NotNull String input) { + return parser.parse(input); + } + @Override public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target) { return parser.parse(input, target); @@ -93,13 +98,12 @@ public boolean strict() { return miniMessage.tags(); } - @Override - public @NotNull Component deserialize(@NotNull String input) { - return parser.parse(input); - } - @Override public @NotNull String serialize(@NotNull Component component) { + // Serializing can be done straight with the `miniMessage` reference. It does not make + // sense to inject other ways of formatting here; the ComponentParser natively supports + // the MiniMessage format, so anything serialized here will be able to be deserialized by + // any ComponentParser. return miniMessage.serialize(component); } } From 2a9e459093243e4533126cae4c218a6af83a10a0 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 28 May 2026 16:29:02 +0200 Subject: [PATCH 3/4] Refactor MiniMessageAdapter after merge --- .../component/ComponentParserImpl.java | 98 +++++++++++++++- .../component/MiniMessageAdapter.java | 109 ------------------ 2 files changed, 96 insertions(+), 111 deletions(-) delete mode 100644 src/main/java/gg/gemstone/component/MiniMessageAdapter.java diff --git a/src/main/java/gg/gemstone/component/ComponentParserImpl.java b/src/main/java/gg/gemstone/component/ComponentParserImpl.java index 5651251..eb9af76 100644 --- a/src/main/java/gg/gemstone/component/ComponentParserImpl.java +++ b/src/main/java/gg/gemstone/component/ComponentParserImpl.java @@ -24,8 +24,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.function.BiFunction; +import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.tree.Node; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.VisibleForTesting; @@ -42,7 +46,7 @@ class ComponentParserImpl implements ComponentParser { @Override public @NotNull Component parse(@NotNull String input) { - return miniMessage.deserialize(translate(input)); + return parse(input, MiniMessage::deserialize); } @Override @@ -64,7 +68,7 @@ public ComponentParser.Builder toBuilder() { @Override public MiniMessage asMiniMessage() { - return new MiniMessageAdapter(this, miniMessage); + return new MiniMessageAdapter(); } @VisibleForTesting @@ -79,6 +83,11 @@ public MiniMessage asMiniMessage() { return result; } + private @NotNull R parse(@NotNull String input, BiFunction miniMessageFunction) { + String translated = translate(input); + return miniMessageFunction.apply(miniMessage, translated); + } + static class Instances { static final ComponentParser COMPONENT_PARSER = new ComponentParserImpl( @@ -133,4 +142,89 @@ public ComponentParser build() { return new ComponentParserImpl(new ArrayList<>(translators), miniMessage); } } + + /** + * Adapts this {@link ComponentParser} to the {@link MiniMessage} interface. + */ + class MiniMessageAdapter implements MiniMessage { + + @Override + public @NotNull String escapeTags(@NotNull String input) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull String escapeTags(@NotNull String input, @NotNull TagResolver tagResolver) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull String stripTags(@NotNull String input) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull String stripTags(@NotNull String input, @NotNull TagResolver tagResolver) { + throw new UnsupportedOperationException(); + } + + @Override + public @NotNull Component deserialize(@NotNull String input) { + return parse(input, MiniMessage::deserialize); + } + + @Override + public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target) { + return parse(input, (mm, s) -> mm.deserialize(s, target)); + } + + @Override + public @NotNull Component deserialize(@NotNull String input, @NotNull TagResolver tagResolver) { + return parse(input, (mm, s) -> mm.deserialize(s, tagResolver)); + } + + @Override + public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target, @NotNull TagResolver tagResolver) { + return parse(input, (mm, s) -> mm.deserialize(s, target, tagResolver)); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input) { + return parse(input, MiniMessage::deserializeToTree); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull Pointered target) { + return parse(input, (mm, s) -> mm.deserializeToTree(s, target)); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull TagResolver tagResolver) { + return parse(input, (mm, s) -> mm.deserializeToTree(s, tagResolver)); + } + + @Override + public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull Pointered target, @NotNull TagResolver tagResolver) { + return parse(input, (mm, s) -> mm.deserializeToTree(s, target, tagResolver)); + } + + @Override + public boolean strict() { + return miniMessage.strict(); + } + + @Override + public @NotNull TagResolver tags() { + return miniMessage.tags(); + } + + @Override + public @NotNull String serialize(@NotNull Component component) { + // Serializing can be done straight with the `miniMessage` reference. It does not make + // sense to inject other ways of formatting here; the ComponentParser natively supports + // the MiniMessage format, so anything serialized here will be able to be deserialized by + // any ComponentParser. + return miniMessage.serialize(component); + } + } } diff --git a/src/main/java/gg/gemstone/component/MiniMessageAdapter.java b/src/main/java/gg/gemstone/component/MiniMessageAdapter.java deleted file mode 100644 index 963bb59..0000000 --- a/src/main/java/gg/gemstone/component/MiniMessageAdapter.java +++ /dev/null @@ -1,109 +0,0 @@ -package gg.gemstone.component; - -import net.kyori.adventure.pointer.Pointered; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; -import net.kyori.adventure.text.minimessage.tree.Node; -import org.jetbrains.annotations.NotNull; - -/** - * Adapts a {@link ComponentParser} to the {@link MiniMessage} interface. - */ -final class MiniMessageAdapter implements MiniMessage { - - private final ComponentParser parser; - private final MiniMessage miniMessage; - - /** - * Instantiates a {@link MiniMessageAdapter}. - * - * @param parser the parser to adapt method calls to - * @param miniMessage the underlying {@link MiniMessage} object the parser is using (used for - * functionality that the {@link MiniMessage} interface expects, but is - * not provided by the {@link ComponentParser} interface) - */ - MiniMessageAdapter(ComponentParser parser, MiniMessage miniMessage) { - this.parser = parser; - this.miniMessage = miniMessage; - } - - @Override - public @NotNull String escapeTags(@NotNull String input) { - throw new UnsupportedOperationException(); - } - - @Override - public @NotNull String escapeTags(@NotNull String input, @NotNull TagResolver tagResolver) { - throw new UnsupportedOperationException(); - } - - @Override - public @NotNull String stripTags(@NotNull String input) { - throw new UnsupportedOperationException(); - } - - @Override - public @NotNull String stripTags(@NotNull String input, @NotNull TagResolver tagResolver) { - throw new UnsupportedOperationException(); - } - - @Override - public @NotNull Component deserialize(@NotNull String input) { - return parser.parse(input); - } - - @Override - public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target) { - return parser.parse(input, target); - } - - @Override - public @NotNull Component deserialize(@NotNull String input, @NotNull TagResolver tagResolver) { - return parser.parse(input, tagResolver); - } - - @Override - public @NotNull Component deserialize(@NotNull String input, @NotNull Pointered target, @NotNull TagResolver tagResolver) { - return parser.parse(input, target, tagResolver); - } - - @Override - public Node.@NotNull Root deserializeToTree(@NotNull String input) { - return parser.parseToTree(input); - } - - @Override - public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull Pointered target) { - return parser.parseToTree(input, target); - } - - @Override - public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull TagResolver tagResolver) { - return parser.parseToTree(input, tagResolver); - } - - @Override - public Node.@NotNull Root deserializeToTree(@NotNull String input, @NotNull Pointered target, @NotNull TagResolver tagResolver) { - return parser.parseToTree(input, target, tagResolver); - } - - @Override - public boolean strict() { - return miniMessage.strict(); - } - - @Override - public @NotNull TagResolver tags() { - return miniMessage.tags(); - } - - @Override - public @NotNull String serialize(@NotNull Component component) { - // Serializing can be done straight with the `miniMessage` reference. It does not make - // sense to inject other ways of formatting here; the ComponentParser natively supports - // the MiniMessage format, so anything serialized here will be able to be deserialized by - // any ComponentParser. - return miniMessage.serialize(component); - } -} From acdd04bc95ac97e4980d6fae4a9edebfe63a0e09 Mon Sep 17 00:00:00 2001 From: Wouter Gritter Date: Thu, 28 May 2026 17:02:10 +0200 Subject: [PATCH 4/4] Delegate escaping and stripping --- .../component/ComponentParserImpl.java | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/main/java/gg/gemstone/component/ComponentParserImpl.java b/src/main/java/gg/gemstone/component/ComponentParserImpl.java index 1075caf..9f85cbf 100644 --- a/src/main/java/gg/gemstone/component/ComponentParserImpl.java +++ b/src/main/java/gg/gemstone/component/ComponentParserImpl.java @@ -46,33 +46,17 @@ class ComponentParserImpl implements ComponentParser { @Override public @NotNull Component parse(@NotNull String input) { - requireNonNull(input, "input"); - return parse(input, MiniMessage::deserialize); } @Override public @NotNull String escape(@NotNull String input) { - requireNonNull(input, "input"); - - String result = input; - for (MiniMessageTranslator translator : translators) { - result = translator.escape(result); - } - - return miniMessage.escapeTags(result); + return escape(input, MiniMessage::escapeTags); } @Override public @NotNull String strip(@NotNull String input) { - requireNonNull(input, "input"); - - String result = input; - for (MiniMessageTranslator translator : translators) { - result = translator.strip(result); - } - - return miniMessage.stripTags(result); + return strip(input, MiniMessage::stripTags); } @Override @@ -108,10 +92,34 @@ public MiniMessage asMiniMessage() { } private @NotNull R parse(@NotNull String input, BiFunction miniMessageFunction) { + requireNonNull(input, "input"); + String translated = translate(input); return miniMessageFunction.apply(miniMessage, translated); } + private @NotNull R escape(@NotNull String input, BiFunction miniMessageFunction) { + requireNonNull(input, "input"); + + String result = input; + for (MiniMessageTranslator translator : translators) { + result = translator.escape(result); + } + + return miniMessageFunction.apply(miniMessage, result); + } + + private @NotNull R strip(@NotNull String input, BiFunction miniMessageFunction) { + requireNonNull(input, "input"); + + String result = input; + for (MiniMessageTranslator translator : translators) { + result = translator.strip(result); + } + + return miniMessageFunction.apply(miniMessage, result); + } + static class Instances { static final ComponentParser COMPONENT_PARSER = new ComponentParserImpl( @@ -174,22 +182,22 @@ class MiniMessageAdapter implements MiniMessage { @Override public @NotNull String escapeTags(@NotNull String input) { - throw new UnsupportedOperationException(); + return escape(input, MiniMessage::escapeTags); } @Override public @NotNull String escapeTags(@NotNull String input, @NotNull TagResolver tagResolver) { - throw new UnsupportedOperationException(); + return escape(input, (mm, s) -> mm.escapeTags(s, tagResolver)); } @Override public @NotNull String stripTags(@NotNull String input) { - throw new UnsupportedOperationException(); + return strip(input, MiniMessage::stripTags); } @Override public @NotNull String stripTags(@NotNull String input, @NotNull TagResolver tagResolver) { - throw new UnsupportedOperationException(); + return strip(input, (mm, s) -> mm.stripTags(s, tagResolver)); } @Override