001/* 002 * Copyright 2021 Siroshun09 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.github.siroshun09.mcmessage.util; 018 019import org.jetbrains.annotations.NotNull; 020 021import java.util.regex.Pattern; 022 023public final class Colorizer { 024 025 private static final String EMPTY = ""; 026 private static final char COLOR_MARK = '&'; 027 private static final String COLOR_MARK_STRING = String.valueOf(COLOR_MARK); 028 private static final char COLOR_SECTION = '§'; 029 private static final String COLOR_SECTION_STRING = String.valueOf(COLOR_SECTION); 030 private static final char HEX_MARK = '#'; 031 private static final char X = 'x'; 032 private static final String COLOR_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRr"; 033 private static final Pattern COLOR_SECTION_PATTERN = Pattern.compile("(?i)" + COLOR_SECTION + "[0-9A-FK-ORX]"); 034 private static final Pattern COLOR_MARK_PATTERN = 035 Pattern.compile(COLOR_MARK + "((" + HEX_MARK + "[0-9a-fA-F]{6})|([0-9a-fk-orxA-FK-ORX]))"); 036 037 private Colorizer() { 038 throw new UnsupportedOperationException(); 039 } 040 041 @NotNull 042 public static String colorize(String str) { 043 if (str == null || str.isEmpty()) { 044 return EMPTY; 045 } 046 047 if (str.contains(COLOR_MARK_STRING)) { 048 StringBuilder builder = new StringBuilder(str); 049 return colorize(builder).toString(); 050 } else { 051 return str; 052 } 053 } 054 055 public static @NotNull StringBuilder colorize(StringBuilder builder) { 056 if (builder == null) { 057 return new StringBuilder(); 058 } 059 060 int i = builder.indexOf(COLOR_MARK_STRING); 061 062 if (i == -1) { 063 return builder; 064 } 065 066 int l = builder.length(); 067 068 while (i != -1 && i + 1 < l) { 069 if (builder.charAt(i + 1) == HEX_MARK) { 070 if (i + 7 < l) { 071 String hex = builder.substring(i + 2, i + 8); 072 073 try { 074 Integer.parseInt(hex, 16); 075 } catch (NumberFormatException e) { 076 i = builder.indexOf(COLOR_MARK_STRING, i + 1); 077 continue; 078 } 079 080 builder.setCharAt(i, COLOR_SECTION); 081 builder.setCharAt(i + 1, X); 082 083 for (int j = i + 7; j != i + 1; j--) { 084 builder.insert(j, COLOR_SECTION_STRING); 085 } 086 087 l = builder.length(); 088 } 089 090 i = builder.indexOf(COLOR_MARK_STRING, i + 1); 091 continue; 092 } 093 094 if (-1 < COLOR_CODES.indexOf(builder.charAt(i + 1))) { 095 builder.setCharAt(i, COLOR_SECTION); 096 } 097 098 i = builder.indexOf(COLOR_MARK_STRING, i + 1); 099 } 100 101 return builder; 102 } 103 104 /** 105 * Strips the given string of color. 106 * <p> 107 * Example: {@code §aHello, §bWorld!} {@literal ->} {@code Hello, World!} 108 * 109 * @param str the string to strip 110 * @return stripped string 111 */ 112 @NotNull 113 public static String stripColorCode(String str) { 114 return stripColorCode(str, COLOR_SECTION_PATTERN); 115 } 116 117 @NotNull 118 public static String stripMarkedColorCode(String str) { 119 return stripColorCode(str, COLOR_MARK_PATTERN); 120 } 121 122 @NotNull 123 public static String stripColorCode(String str, @NotNull Pattern pattern) { 124 if (str == null || str.isEmpty()) { 125 return EMPTY; 126 } 127 128 return pattern.matcher(str).replaceAll(""); 129 } 130}