110 lines
3.7 KiB
Java
110 lines
3.7 KiB
Java
|
|
package com.alttd.cometskyblock.util;
|
||
|
|
|
||
|
|
import java.util.*;
|
||
|
|
import java.util.stream.Collectors;
|
||
|
|
|
||
|
|
public class StringUtil {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Splits a mini message string into smaller chunks. It re-opens any unclosed tags it encounters for
|
||
|
|
* each part of the string added to the list
|
||
|
|
*
|
||
|
|
* @param string the mini message string to split
|
||
|
|
* @return a list of the split strings
|
||
|
|
*/
|
||
|
|
public static List<String> splitMiniMessageString(String string) {
|
||
|
|
Set<String> tags = findTags(string);
|
||
|
|
List<String> splitString = new ArrayList<>();
|
||
|
|
Stack<String> openTags = new Stack<>();
|
||
|
|
Stack<String> previousOpenTags = new Stack<>();
|
||
|
|
int startCurString = 0;
|
||
|
|
int len = 0;
|
||
|
|
int i = 0;
|
||
|
|
for (; i < string.length(); i++) {
|
||
|
|
while (string.charAt(i) == '<') {
|
||
|
|
i = skipTags(i, string, openTags, tags);
|
||
|
|
}
|
||
|
|
len++;
|
||
|
|
if (len != 30) {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
while (i < string.length() && !Character.isWhitespace(string.charAt(i))) {
|
||
|
|
while (string.charAt(i) == '<') {
|
||
|
|
i = skipTags(i, string, openTags, tags);
|
||
|
|
}
|
||
|
|
if (Character.isWhitespace(string.charAt(i))) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
String prependTags = previousOpenTags.stream().map(str -> "<" + str + ">").collect(Collectors.joining(""));
|
||
|
|
splitString.add(prependTags + string.substring(startCurString, i));
|
||
|
|
previousOpenTags.clear();
|
||
|
|
previousOpenTags.addAll(openTags);
|
||
|
|
startCurString = ++i;
|
||
|
|
len = 0;
|
||
|
|
}
|
||
|
|
if (startCurString < string.length()) {
|
||
|
|
String prependTags = previousOpenTags.stream().map(str -> "<" + str + ">").collect(Collectors.joining(""));
|
||
|
|
splitString.add(prependTags + string.substring(startCurString));
|
||
|
|
}
|
||
|
|
return splitString;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int skipTags(int i, String string, Stack<String> openTags, Set<String> tags) {
|
||
|
|
StringBuilder tagBuilder = new StringBuilder();
|
||
|
|
i++;
|
||
|
|
for (; i < string.length() && string.charAt(i) != '>'; i++) {
|
||
|
|
tagBuilder.append(string.charAt(i));
|
||
|
|
}
|
||
|
|
String tagString = tagBuilder.toString();
|
||
|
|
if (!tagString.isEmpty() && tagString.charAt(0) == '/') {
|
||
|
|
if (!openTags.isEmpty() && openTags.peek().contentEquals(tagString.substring(1))) {
|
||
|
|
openTags.pop();
|
||
|
|
}
|
||
|
|
} else if (tags.contains(tagString)) {
|
||
|
|
openTags.add(tagString);
|
||
|
|
}
|
||
|
|
tagBuilder.setLength(0);
|
||
|
|
return Math.min(++i, string.length() - 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static Set<String> findTags(String string) {
|
||
|
|
List<String> tags = new ArrayList<>();
|
||
|
|
HashSet<String> closedTags = new HashSet<>();
|
||
|
|
StringBuilder tag = new StringBuilder();
|
||
|
|
boolean tagFound = false;
|
||
|
|
|
||
|
|
for (int i = 0; i < string.length(); i++) {
|
||
|
|
if (string.charAt(i) == '<') {
|
||
|
|
tagFound = true;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (string.charAt(i) == '>') {
|
||
|
|
tagFound = false;
|
||
|
|
|
||
|
|
if (tag.charAt(0) != '/') {
|
||
|
|
tags.add(tag.toString());
|
||
|
|
} else {
|
||
|
|
String closingTag = tag.substring(1);
|
||
|
|
if (tags.contains(closingTag)) {
|
||
|
|
tags.remove(closingTag);
|
||
|
|
closedTags.add(closingTag);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
tag.setLength(0);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (tagFound) {
|
||
|
|
tag.append(string.charAt(i));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return closedTags;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|