Skip to content

Commit

Permalink
Fix issues with nested parsing (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
Phoenix616 committed Sep 10, 2022
1 parent 0e8dec4 commit 748586a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 30 deletions.
42 changes: 12 additions & 30 deletions src/main/java/de/themoep/minedown/adventure/MineDownParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,30 +137,14 @@ public ComponentBuilder parse(String message) throws IllegalArgumentException {
boolean isEscape = c == '\\' && i + 1 < message.length();
boolean isColorCode = isEnabled(Option.LEGACY_COLORS)
&& i + 1 < message.length() && (c == '§' || c == colorChar());
boolean isEvent = false;
if (isEnabled(Option.ADVANCED_FORMATTING) && c == '[') {
int nextEventClose = Util.indexOfNotEscaped(message, "](", i + 1);
if (nextEventClose != -1 && nextEventClose + 2 < message.length()) {
int nextDefClose = Util.indexOfNotEscaped(message, ")", i + 2);
if (nextDefClose != -1) {
int depth = 1;
isEvent = true;
boolean innerEscaped = false;
for (int j = i + 1; j < nextEventClose; j++) {
if (innerEscaped) {
innerEscaped = false;
} else if (message.charAt(j) == '\\') {
innerEscaped = true;
} else if (message.charAt(j) == '[') {
depth++;
} else if (message.charAt(j) == ']') {
depth--;
}
if (depth == 0) {
isEvent = false;
break;
}
}
int eventEndIndex = -1;
String eventDefinition = "";
if (!escaped && isEnabled(Option.ADVANCED_FORMATTING) && c == '[') {
eventEndIndex = Util.getUnescapedEndIndex(message, '[', ']', i);
if (eventEndIndex != -1 && message.length() > eventEndIndex + 1 && message.charAt(eventEndIndex + 1) == '(') {
int definitionClose = Util.getUnescapedEndIndex(message, '(', ')', eventEndIndex + 1);
if (definitionClose != -1) {
eventDefinition = message.substring(eventEndIndex + 2, definitionClose);
}
}
}
Expand Down Expand Up @@ -280,16 +264,14 @@ public ComponentBuilder parse(String message) throws IllegalArgumentException {
continue;

// Events
} else if (isEvent) {
int index = Util.indexOfNotEscaped(message, "](", i + 1);
int endIndex = Util.indexOfNotEscaped(message, ")", index + 2);
} else if (eventEndIndex != -1 && !eventDefinition.isEmpty()) {
appendValue();
if (!isFiltered(Option.ADVANCED_FORMATTING)) {
append(parseEvent(message.substring(i + 1, index), message.substring(index + 2, endIndex)));
append(parseEvent(message.substring(i + 1, eventEndIndex), eventDefinition));
} else {
append(copy(true).parse(message.substring(i + 1, index)));
append(copy(true).parse(message.substring(i + 1, eventEndIndex)));
}
i = endIndex;
i = eventEndIndex + 2 + eventDefinition.length();
continue;

// Simple formatting
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/de/themoep/minedown/adventure/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,34 @@ public static boolean isEscaped(String string, int index) {
return e % 2 != 0;
}

/**
* Gets the proper end index of a certain definition on the same depth while ignoring escaped chars.
* @param string The string to search
* @param startChar The start cahracter of the definition
* @param endChar The end character of the definition
* @param fromIndex The index to start searching from (should be at the start char)
* @return The first end index of that group or {@code -1} if not found
*/
public static int getUnescapedEndIndex(String string, char startChar, char endChar, int fromIndex) {
int depth = 0;
boolean innerEscaped = false;
for (int i = fromIndex; i < string.length(); i++) {
if (innerEscaped) {
innerEscaped = false;
} else if (string.charAt(i) == '\\') {
innerEscaped = true;
} else if (string.charAt(i) == startChar) {
depth++;
} else if (string.charAt(i) == endChar) {
depth--;
if (depth == 0) {
return i;
}
}
}
return -1;
}

/**
* Wrap a string if it is longer than the line length and contains no new line.
* Will try to wrap at spaces between words.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,13 @@ public void testNegated() {
() -> parse("&lBold [not bold](!bold) bold")
);
}

@Test
public void testParseNested() {
Assertions.assertAll(
() -> parse("[outer start [inner](green) outer end](aqua)"),
() -> parse("[outer start \\[[inner](green)\\] outer end](aqua)"),
() -> parse("[outer start [inner](green) outer end](aqua hover={[red hover](red)})")
);
}
}

0 comments on commit 748586a

Please sign in to comment.