diff --git a/common/src/main/java/software/bluelib/markdown/syntax/Hyperlink.java b/common/src/main/java/software/bluelib/markdown/syntax/Hyperlink.java index 052fcc9c..c70e202f 100644 --- a/common/src/main/java/software/bluelib/markdown/syntax/Hyperlink.java +++ b/common/src/main/java/software/bluelib/markdown/syntax/Hyperlink.java @@ -90,139 +90,79 @@ public MutableComponent applyHyperlink(MutableComponent pComponent) { return pComponent; } - MutableComponent result = Component.empty(); - BaseLogger.log(BaseLogLevel.INFO, "Starting to process component: " + pComponent.getString(), true); - - // Define regex pattern Pattern pattern = Pattern.compile(Pattern.quote(prefix) + "(.*?)" + Pattern.quote(suffix) + "\\((.*?)\\)"); BaseLogger.log(BaseLogLevel.INFO, "Using regex pattern: " + pattern.pattern(), true); - // Handle components with no siblings (single-component case) + MutableComponent result = Component.empty(); + if (pComponent.getSiblings().isEmpty()) { BaseLogger.log(BaseLogLevel.INFO, "No siblings found. Processing the component itself.", true); - String componentText = pComponent.getString(); - - Matcher matcher = pattern.matcher(componentText); - MutableComponent beforeHyperlink = Component.empty(); - MutableComponent hyperlink = Component.empty(); - MutableComponent afterHyperlink = Component.empty(); - - int lastIndex = 0; - - // Process matches in the main component - while (matcher.find()) { - String beforeMatch = componentText.substring(lastIndex, matcher.start()); + processComponentText(pComponent.getString(), result, pattern); + } else { + BaseLogger.log(BaseLogLevel.INFO, "Processing component with siblings.", true); + result = processSiblings(pComponent, pattern); + } - // Append unstyled text before match - if (!beforeMatch.isEmpty()) { - BaseLogger.log(BaseLogLevel.INFO, "Appending unstyled text: " + beforeMatch, true); - beforeHyperlink.append(Component.literal(beforeMatch)); - } + BaseLogger.log(BaseLogLevel.INFO, "Final result component: " + result.getString(), true); + return result; + } - String linkText = matcher.group(1).trim(); - String url = matcher.group(2).trim(); - BaseLogger.log(BaseLogLevel.INFO, "Matched text: " + linkText + ", URL: " + url, true); + private void processComponentText(String text, MutableComponent result, Pattern pattern) { + Matcher matcher = pattern.matcher(text); + int lastIndex = 0; - if (MiscUtils.isValidURL(url)) { - if (!url.startsWith("http://") && !url.startsWith("https://")) { - url = "https://" + url; - } + while (matcher.find()) { + appendUnstyledText(text.substring(lastIndex, matcher.start()), result); + appendHyperlink(matcher.group(1), matcher.group(2), result); + lastIndex = matcher.end(); + } - hyperlink = Component.literal(linkText) - .setStyle(Style.EMPTY.withColor(TextColor.fromRgb(0x1F5FE1)) - .withUnderlined(true) - .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))); - } else { - BaseLogger.log(BaseLogLevel.WARNING, "Invalid URL detected: " + url, true); - hyperlink = Component.literal(matcher.group(0)); - } + appendUnstyledText(text.substring(lastIndex), result); + } - lastIndex = matcher.end(); - } + private MutableComponent processSiblings(MutableComponent pComponent, Pattern pattern) { + MutableComponent result = Component.empty(); - // Append remaining text after match - String remainingText = componentText.substring(lastIndex); - if (!remainingText.isEmpty()) { - BaseLogger.log(BaseLogLevel.INFO, "Appending remaining text: " + remainingText, true); - afterHyperlink.append(Component.literal(remainingText)); + for (Component sibling : pComponent.getSiblings()) { + if (sibling instanceof MutableComponent mutableSibling) { + BaseLogger.log(BaseLogLevel.INFO, "Processing sibling: " + mutableSibling.getString(), true); + processComponentText(mutableSibling.getString(), result, pattern); + } else { + BaseLogger.log(BaseLogLevel.INFO, "Sibling is not mutable. Appending as-is: " + sibling.getString(), true); + result.append(sibling); } + } - // Ensure all three components (before, hyperlink, after) are added as siblings - result.append(beforeHyperlink); - result.append(hyperlink); - result.append(afterHyperlink); - - BaseLogger.log(BaseLogLevel.INFO, "Final styled component: " + result.getString(), true); - - } else { // Process siblings as in the original method - for (Component sibling : pComponent.getSiblings()) { - BaseLogger.log(BaseLogLevel.INFO, "Processing sibling: " + sibling.getString(), true); - - if (sibling instanceof MutableComponent mutableSibling) { - String siblingText = mutableSibling.getString(); - BaseLogger.log(BaseLogLevel.INFO, "Sibling text: " + siblingText, true); - - Matcher matcher = pattern.matcher(siblingText); - MutableComponent beforeHyperlink = Component.empty(); - MutableComponent hyperlink = Component.empty(); - MutableComponent afterHyperlink = Component.empty(); - - int lastIndex = 0; - - // Process matches - while (matcher.find()) { - String beforeMatch = siblingText.substring(lastIndex, matcher.start()); - - // Append unstyled text before match - if (!beforeMatch.isEmpty()) { - BaseLogger.log(BaseLogLevel.INFO, "Appending unstyled text: " + beforeMatch, true); - beforeHyperlink.append(Component.literal(beforeMatch)); - } - - String linkText = matcher.group(1).trim(); - String url = matcher.group(2).trim(); - BaseLogger.log(BaseLogLevel.INFO, "Matched text: " + linkText + ", URL: " + url, true); - - // Validate and apply hyperlink - if (MiscUtils.isValidURL(url)) { - if (!url.startsWith("http://") && !url.startsWith("https://")) { - url = "https://" + url; - } - - hyperlink = Component.literal(linkText) - .setStyle(Style.EMPTY.withColor(TextColor.fromRgb(0x1F5FE1)) - .withUnderlined(true) - .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))); - } else { - BaseLogger.log(BaseLogLevel.WARNING, "Invalid URL detected: " + url, true); - hyperlink = Component.literal(matcher.group(0)); - } + return result; + } - lastIndex = matcher.end(); - } + private void appendUnstyledText(String text, MutableComponent result) { + if (!text.isEmpty()) { + BaseLogger.log(BaseLogLevel.INFO, "Appending unstyled text: " + text, true); + result.append(Component.literal(text)); + } + } - // Append remaining text after match - String remainingText = siblingText.substring(lastIndex); - if (!remainingText.isEmpty()) { - BaseLogger.log(BaseLogLevel.INFO, "Appending remaining text: " + remainingText, true); - afterHyperlink.append(Component.literal(remainingText)); - } + private void appendHyperlink(String linkText, String url, MutableComponent result) { + BaseLogger.log(BaseLogLevel.INFO, "Matched text: " + linkText + ", URL: " + url, true); - // Ensure all three components (before, hyperlink, after) are added as siblings - result.append(beforeHyperlink); - result.append(hyperlink); - result.append(afterHyperlink); + if (!MiscUtils.isValidURL(url)) { + BaseLogger.log(BaseLogLevel.WARNING, "Invalid URL detected: " + url, true); + result.append(Component.literal(prefix + linkText + suffix + "(" + url + ")")); + return; + } - BaseLogger.log(BaseLogLevel.INFO, "Final styled sibling: " + result.getString(), true); - } else { - BaseLogger.log(BaseLogLevel.INFO, "Sibling is not mutable. Appending as-is: " + sibling.getString(), true); - result.append(sibling); - } - } + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "https://" + url; } - BaseLogger.log(BaseLogLevel.INFO, "Final result component: " + result.getString(), true); - return result; + MutableComponent hyperlink = Component.literal(linkText) + .setStyle(Style.EMPTY + .withColor(TextColor.fromRgb(0x1F5FE1)) + .withUnderlined(true) + .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))); + + result.append(hyperlink); } /** diff --git a/common/src/main/java/software/bluelib/test/markdown/syntax/Hyperlink.java b/common/src/main/java/software/bluelib/test/markdown/syntax/Hyperlink.java index c77aebc2..cb6397ff 100644 --- a/common/src/main/java/software/bluelib/test/markdown/syntax/Hyperlink.java +++ b/common/src/main/java/software/bluelib/test/markdown/syntax/Hyperlink.java @@ -26,7 +26,7 @@ public static void hyperlinkStrikethrough(GameTestHelper pHelper) { } public static void hyperlinkHyperlink(GameTestHelper pHelper) { - MessageUtils.sendMessageToPlayers(pHelper, "§6 This is a hyperlink/hyperlink test: §r [[Hyperlink](https://www.curseforge.com/minecraft/mc-mods/bluelib) [Hyperlink](https://modrinth.com/mod/bluelib)"); + MessageUtils.sendMessageToPlayers(pHelper, "§6 This is a hyperlink/hyperlink test: §r [Hyperlink](https://www.curseforge.com/minecraft/mc-mods/bluelib) [Hyperlink](https://modrinth.com/mod/bluelib)"); } public static void hyperlinkColor(GameTestHelper pHelper) { diff --git a/common/src/main/java/software/bluelib/utils/math/MiscUtils.java b/common/src/main/java/software/bluelib/utils/math/MiscUtils.java index 01cdb5af..2732f71f 100644 --- a/common/src/main/java/software/bluelib/utils/math/MiscUtils.java +++ b/common/src/main/java/software/bluelib/utils/math/MiscUtils.java @@ -2,6 +2,8 @@ package software.bluelib.utils.math; +import java.net.URI; +import java.util.regex.Pattern; import software.bluelib.utils.logging.BaseLogLevel; import software.bluelib.utils.logging.BaseLogger; @@ -18,7 +20,7 @@ * * * @author MeAlam - * @version 1.4.0 + * @version 1.6.0 * @since 1.0.0 */ public class MiscUtils { @@ -57,11 +59,16 @@ private MiscUtils() {} public static boolean isValidURL(String pUrl) { try { if (!pUrl.startsWith("http://") && !pUrl.startsWith("https://")) { - pUrl = "https://" + pUrl; + return false; } - java.net.URI uri = new java.net.URI(pUrl); - return uri.isAbsolute() && ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())); + URI uri = new URI(pUrl); + + String domainRegex = "^[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; + Pattern pattern = Pattern.compile(domainRegex); + String host = uri.getHost(); + + return uri.isAbsolute() && (pattern.matcher(host).matches()); } catch (Exception pException) { return false; }