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 splitMiniMessageString(String string) { Set tags = findTags(string); List splitString = new ArrayList<>(); Stack openTags = new Stack<>(); Stack 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 openTags, Set 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 findTags(String string) { List tags = new ArrayList<>(); HashSet 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; } }