Skip to content

Commit feeb814

Browse files
Fix several additional formatting bugs (#8627)
1 parent 4d5dbf9 commit feeb814

7 files changed

Lines changed: 52 additions & 25 deletions

File tree

src/main/java/ch/njol/skript/log/LogEntry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ public String toFormattedString() {
147147

148148
return
149149
String.format(lineInfoMsg, node.getLine(), c.getFileName()) +
150-
String.format(detailsMsg, TextComponentParser.instance().escape(message.replaceAll("§", "&"))) + from +
151-
String.format(lineDetailsMsg, TextComponentParser.instance().escape(node.save().trim().replaceAll("§", "&")));
150+
String.format(detailsMsg, TextComponentParser.instance().escape(message)) + from +
151+
String.format(lineDetailsMsg, TextComponentParser.instance().escape(node.save().trim()));
152152
}
153153

154154
private String replaceNewline(String s) {

src/main/java/org/skriptlang/skript/bukkit/text/TextComponentParser.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.skriptlang.skript.bukkit.text;
22

3+
import ch.njol.skript.Skript;
34
import ch.njol.skript.registrations.Classes;
45
import ch.njol.util.coll.CollectionUtils;
56
import net.kyori.adventure.text.Component;
@@ -121,13 +122,13 @@ public TextReplacementConfig textReplacementConfig() {
121122
* A pattern for matching double hashtag hex color tags ({@code <##123456>}).
122123
* It also matches all preceding backslashes to determine whether the supposed tag is escaped.
123124
*/
124-
private static final Pattern LEGACY_DOUBLE_HASHTAG_PATTERN = Pattern.compile("(\\\\*)<(##[a-f0-9]{6})>");
125+
private static final Pattern LEGACY_DOUBLE_HASHTAG_PATTERN = Pattern.compile("(\\\\*)<(##[a-fA-F0-9]{6})>");
125126

126127
/**
127128
* A pattern for matching legacy hex codes ({@code &x&1&2&3&4&5&6}).
128129
* It also matches all preceding backslashes to determine whether the supposed tag is escaped.
129130
*/
130-
static final Pattern LEGACY_CODE_PATTERN = Pattern.compile("(\\\\*)([&§][a-f0-9klomnr])");
131+
static final Pattern LEGACY_CODE_PATTERN = Pattern.compile("(\\\\*)([&§][a-fA-F0-9kKlLoOmMnNrR])");
131132

132133
static {
133134
INSTANCE = new TextComponentParser();
@@ -436,7 +437,14 @@ private Component parse(Object message, boolean safe) {
436437
realMessage = reformatText(realMessage);
437438

438439
// parse as component
439-
Component component = safe ? safeParser.deserialize(realMessage) : parser.deserialize(realMessage);
440+
Component component;
441+
try {
442+
component = safe ? safeParser.deserialize(realMessage) : parser.deserialize(realMessage);
443+
} catch (ParsingException e) {
444+
Skript.exception(e, "An error occurred while trying to parse formatting for '" + realMessage + "'." +
445+
" This is likely caused by the presence of legacy formatting characters (such as '§') that Skript could not handle.");
446+
return Component.text(message instanceof String ? (String) message : Classes.toString(message));
447+
}
440448

441449
// replace links based on configuration setting
442450
if (linkParseMode != LinkParseMode.DISABLED) {
@@ -492,10 +500,12 @@ public String escape(String string) {
492500
// legacy compatibility, escape color codes
493501
if (string.contains("&") || string.contains("§")) {
494502
string = LEGACY_CODE_PATTERN.matcher(string).replaceAll(result -> {
503+
// Even if escaped, MiniMessage will throw an exception for legacy section codes
504+
String group = result.group().replace('§', '&');
495505
if (result.group(1).length() % 2 == 1) { // tag is already escaped
496-
return Matcher.quoteReplacement(result.group());
506+
return Matcher.quoteReplacement(group);
497507
}
498-
return Matcher.quoteReplacement('\\' + result.group());
508+
return Matcher.quoteReplacement('\\' + group);
499509
});
500510
}
501511
string = LEGACY_DOUBLE_HASHTAG_PATTERN.matcher(string).replaceAll(result -> {

src/main/java/org/skriptlang/skript/bukkit/text/TextComponentUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ private static Component appendToLastChild(Component base, Component appendee) {
7777
* A pattern for matching standard legacy codes ({@code &1}).
7878
* It also matches all preceding backslashes to determine whether the supposed tag is escaped.
7979
*/
80-
private static final Pattern LEGACY_HEX_PATTERN = Pattern.compile("[&§]x(?:[&§][a-f0-9]){6}");
80+
private static final Pattern LEGACY_HEX_PATTERN = Pattern.compile("[&§]x(?:[&§][a-fA-F0-9]){6}");
8181

8282
/**
8383
* Replaces all legacy formatting codes in a string with {@link net.kyori.adventure.text.minimessage.MiniMessage} equivalents.
@@ -93,7 +93,7 @@ public static String replaceLegacyFormattingCodes(String text) {
9393
String hex = result.group();
9494
StringBuilder replacement = new StringBuilder();
9595
replacement.append("<#");
96-
for (int i = 3; i <= 13; i += 2) { // isolate the specific numbers
96+
for (int i = 3; i <= 13; i += 2) { // isolate the specific numbers/letters
9797
replacement.append(hex.charAt(i));
9898
}
9999
replacement.append('>');
@@ -108,7 +108,7 @@ public static String replaceLegacyFormattingCodes(String text) {
108108
backslashes = backslashes.substring(1);
109109
}
110110
StringBuilder replacement = new StringBuilder(backslashes);
111-
ChatColor color = ChatColor.getByChar(result.group(2).charAt(1));
111+
ChatColor color = ChatColor.getByChar(Character.toLowerCase(result.group(2).charAt(1)));
112112
assert color != null;
113113
replacement.append('<').append(color.asBungee().getName()).append('>');
114114
return Matcher.quoteReplacement(replacement.toString());

src/main/java/org/skriptlang/skript/bukkit/text/TextModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void initSelf(SkriptAddon addon) {
3636
Comparators.registerComparator(Component.class, String.class, (component, string) -> {
3737
TextComponentParser parser = TextComponentParser.instance();
3838
String string1 = parser.toString(component);
39-
String string2 = parser.toString(parser.parseSafe(string));
39+
String string2 = parser.toString(parser.parse(string));
4040
return Comparators.compare(string1, string2);
4141
});
4242
Comparators.registerComparator(Component.class, Component.class, (component1, component2) -> {

src/main/java/org/skriptlang/skript/bukkit/text/types/TextComponentClassInfo.java

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer;
1212
import org.jetbrains.annotations.ApiStatus;
1313
import org.skriptlang.skript.addon.SkriptAddon;
14-
import org.skriptlang.skript.bukkit.text.TextComponentParser;
1514
import org.skriptlang.skript.lang.properties.Property;
1615
import org.skriptlang.skript.lang.properties.handlers.ContainsHandler;
1716

@@ -33,19 +32,7 @@ public TextComponentClassInfo(SkriptAddon addon) {
3332
.property(Property.CONTAINS,
3433
"Components can contain other components.",
3534
addon,
36-
new ContainsHandler<Component, Component>() {
37-
@Override
38-
public boolean contains(Component container, Component element) {
39-
var parser = org.skriptlang.skript.bukkit.text.TextComponentParser.instance();
40-
return StringUtils.contains(parser.toString(container), parser.toString(element), SkriptConfig.caseSensitive.value());
41-
}
42-
43-
@Override
44-
public Class<? extends Component>[] elementTypes() {
45-
//noinspection unchecked
46-
return new Class[]{Component.class};
47-
}
48-
}
35+
new TextComponentContainsHandler()
4936
);
5037
}
5138

@@ -96,4 +83,27 @@ protected boolean canBeInstantiated() {
9683

9784
}
9885

86+
private static final class TextComponentContainsHandler implements ContainsHandler<Component, Object> {
87+
88+
@Override
89+
public boolean contains(Component container, Object element) {
90+
var parser = org.skriptlang.skript.bukkit.text.TextComponentParser.instance();
91+
String haystack = parser.toString(container);
92+
String needle;
93+
if (element instanceof Component component) {
94+
needle = parser.toString(component);
95+
} else { // String
96+
needle = parser.toString(parser.parse(element));
97+
}
98+
return StringUtils.contains(haystack, needle, SkriptConfig.caseSensitive.value());
99+
}
100+
101+
@Override
102+
public Class<? extends Component>[] elementTypes() {
103+
//noinspection unchecked
104+
return new Class[]{Component.class, String.class};
105+
}
106+
107+
}
108+
99109
}

src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public void testLegacy() {
6565
for (ChatColor color : ChatColor.values()) {
6666
String message = "&" + color.getChar() + "hello";
6767
assertEquals(LegacyComponentSerializer.legacyAmpersand().deserialize(message), parser.parse(message));
68+
message = "&" + Character.toUpperCase(color.getChar()) + "hello";
69+
assertEquals(LegacyComponentSerializer.legacyAmpersand().deserialize(message), parser.parse(message));
6870
}
6971
}
7072

@@ -80,6 +82,10 @@ public void testLegacyDoubleHashtag() {
8082
TextComponentParser parser = new TextComponentParser();
8183
assertEquals(parser.parse("<#123456>hello"), parser.parse("<##123456>hello"));
8284
assertEquals("\\<##123456>hello", parser.escape("<##123456>hello"));
85+
// test letters in tag
86+
assertEquals(parser.parse("<#ffff11>hello"), parser.parse("<#ffff11>hello"));
87+
assertEquals(parser.parse("<#FFFF11>hello"), parser.parse("<##FFFF11>hello"));
88+
assertEquals(parser.parse("<#ffff11>hello"), parser.parse("<##FFFF11>hello"));
8389
}
8490

8591
}

src/test/java/org/skriptlang/skript/bukkit/text/TextComponentUtilsTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public void testReplaceLegacyFormattingCodes() {
1717
assertEquals("\\\\&cHello!", replaceLegacyFormattingCodes("\\\\\\&cHello!"));
1818
assertEquals("<#123456>Hello!", replaceLegacyFormattingCodes("&x&1&2&3&4&5&6Hello!"));
1919
assertEquals("<#123456><red>Hello!", replaceLegacyFormattingCodes("&x&1&2&3&4&5&6&cHello!"));
20+
assertEquals("<#FFFF11>Hello!", replaceLegacyFormattingCodes("&x&F&F&F&F&1&1Hello!"));
2021
// validate internal metacharacter escaping
2122
assertEquals("<red>You have $10", replaceLegacyFormattingCodes("&cYou have $10"));
2223
}

0 commit comments

Comments
 (0)