From 91ca28680eb950bff0ae7e7c9b8d5dfe90c73773 Mon Sep 17 00:00:00 2001 From: William Date: Thu, 20 Apr 2023 23:06:40 +0100 Subject: [PATCH] Remove MineDown dependency, update to 2.0 --- .github/workflows/gradle-ci.yml | 7 +- HEADER | 16 ++ build.gradle | 29 ++- .../desertwell/about/AboutMenu.java | 238 +++++++++--------- .../desertwell/util/ThrowingConsumer.java | 47 +++- .../desertwell/util/UpdateChecker.java | 20 ++ .../william278/desertwell/util/Version.java | 19 ++ .../desertwell/UpdateCheckerTests.java | 19 ++ .../william278/desertwell/VersionTests.java | 19 ++ 9 files changed, 278 insertions(+), 136 deletions(-) create mode 100644 HEADER diff --git a/.github/workflows/gradle-ci.yml b/.github/workflows/gradle-ci.yml index b8ab462..d9eb572 100644 --- a/.github/workflows/gradle-ci.yml +++ b/.github/workflows/gradle-ci.yml @@ -29,4 +29,9 @@ jobs: - name: Build with Gradle uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 with: - arguments: test \ No newline at end of file + arguments: test + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: artifact + path: target/*.jar \ No newline at end of file diff --git a/HEADER b/HEADER new file mode 100644 index 0000000..7d0d2db --- /dev/null +++ b/HEADER @@ -0,0 +1,16 @@ +This file is part of DesertWell, licensed under the Apache License 2.0. + + Copyright (c) William278 + Copyright (c) contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/build.gradle b/build.gradle index 992ff4b..f72186f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,24 +1,23 @@ plugins { - id 'java' - id 'maven-publish' id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'org.cadixdev.licenser' version '0.6.1' + id 'maven-publish' + id 'java' } group 'net.william278' version '2.0' +defaultTasks 'licenseFormat', 'build' repositories { mavenCentral() - maven { url 'https://repo.minebench.de/' } } dependencies { - implementation 'de.themoep:minedown-adventure:1.7.1-SNAPSHOT' implementation 'org.json:json:20230227' compileOnly 'net.kyori:adventure-api:4.13.1' compileOnly 'org.jetbrains:annotations:23.0.0' - testImplementation 'de.themoep:minedown-adventure:1.7.1-SNAPSHOT' testImplementation 'net.kyori:adventure-platform-bukkit:4.1.2' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' @@ -30,22 +29,36 @@ tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } -java { - withSourcesJar() - withJavadocJar() +license { + header = rootProject.file('HEADER') + include '**/*.java' + newLine = true } +logger.lifecycle("Building DesertWell ${version} by William278") +version rootProject.version +archivesBaseName = "${rootProject.name}" + +jar.dependsOn shadowJar +clean.delete "$rootDir/target" + javadoc { options.encoding = 'UTF-8' options.addStringOption('Xdoclint:none', '-quiet') } +java { + withSourcesJar() + withJavadocJar() +} + publishing { publications { shadow(MavenPublication) { publication -> from components.java } } + repositories { mavenLocal() } diff --git a/src/main/java/net/william278/desertwell/about/AboutMenu.java b/src/main/java/net/william278/desertwell/about/AboutMenu.java index 0523425..f1666f3 100644 --- a/src/main/java/net/william278/desertwell/about/AboutMenu.java +++ b/src/main/java/net/william278/desertwell/about/AboutMenu.java @@ -1,8 +1,31 @@ +/* + * This file is part of DesertWell, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.william278.desertwell.about; -import de.themoep.minedown.adventure.MineDown; -import de.themoep.minedown.adventure.Util; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentBuilder; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; import net.william278.desertwell.util.Version; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,17 +37,22 @@ import java.util.*; */ @SuppressWarnings("unused") public class AboutMenu { - private final String title; + private final Component title; + private final Component description; private final Version version; - private final String description; + private final TextColor themeColor; + private final TextColor secondaryColor; private final Map> attributions; private final List buttons; - private AboutMenu(@NotNull String title, @Nullable Version version, @Nullable String description, + private AboutMenu(@NotNull Component title, @Nullable Component description, @Nullable Version version, + @NotNull TextColor themeColor, @NotNull TextColor secondaryColor, @NotNull Map> attributions, @NotNull List buttons) { this.title = title; - this.version = version; this.description = description; + this.version = version; + this.themeColor = themeColor; + this.secondaryColor = secondaryColor; this.attributions = attributions; this.buttons = buttons; } @@ -34,123 +62,50 @@ public class AboutMenu { return new Builder(); } - /** - * Return the formatted {@link MineDown} menu - * - * @return The {@link MineDown} menu - */ @NotNull - public MineDown asMineDown() { - final StringJoiner menu = new StringJoiner("\n") - .add("[" + escapeMineDown(title) + "](#00fb9a bold)" - + (version != null ? " [| v" + escapeMineDown(version.toString()) + "](#00fb9a)" : "")); - if (description != null) { - menu.add("[" + escapeMineDown(description) + "](gray)"); - } - - if (!attributions.isEmpty()) { - menu.add(""); - } - for (Map.Entry> entry : attributions.entrySet()) { - final StringJoiner creditJoiner = new StringJoiner(", "); - for (final Credit credit : entry.getValue()) { - creditJoiner.add("[" + credit.name + "](" + credit.color + - (credit.description != null ? " show_text=&7" + escapeMineDown(credit.description) : "") + - (credit.url != null ? " open_url=" + escapeMineDown(credit.url) : "") - + ")"); - } - - if (!creditJoiner.toString().isBlank()) { - menu.add("[• " + entry.getKey() + ":](white) " + creditJoiner); - } - } - - if (!buttons.isEmpty()) { - final StringJoiner buttonsJoiner = new StringJoiner(" "); - for (final Link link : buttons) { - buttonsJoiner.add("[[" + (link.icon != null ? link.icon + " " : "") - + escapeMineDown(link.text) + "…]](" + link.color + " " - + "show_text=&7Click to open link open_url=" + escapeMineDown(link.url) + ")"); - } - menu.add("").add("[Links:](gray) " + buttonsJoiner); + private TextComponent asComponent() { + final TextComponent.Builder builder = Component.text() + .append(Component.newline()) + .append(title.colorIfAbsent(themeColor).decorate(TextDecoration.BOLD)); + if (version != null) { + builder.append(Component.text(" | v" + version).color(themeColor)); } - return new MineDown(menu.toString()).replace(); - } - - @NotNull - public Component asComponent() { - return asMineDown().toComponent(); - } - - /** - * Return the plaintext string formatted menu. - * - * @return The plaintext menu as a string - */ - @NotNull - public String asString() { - final StringJoiner menu = new StringJoiner("\n") - .add(title + (version != null ? " | Version " + version : "")); + // Add description if (description != null) { - menu.add(description); + builder.append(Component.newline()).append(description.colorIfAbsent(secondaryColor)); } - if (!attributions.entrySet().isEmpty()) { - menu.add("━━━━━━━━━━━━━━━━━━━━━━━━"); + // Add attributions + if (!attributions.isEmpty()) { + builder.append(Component.newline()); } - for (final Map.Entry> entry : attributions.entrySet()) { - final StringJoiner creditJoiner = new StringJoiner(", "); - for (final Credit credit : entry.getValue()) { - creditJoiner.add(credit.name + (credit.description != null ? " (" + credit.description + ")" : "")); - } - - if (!creditJoiner.toString().isBlank()) { - menu.add("- " + entry.getKey() + ": " + creditJoiner); - } + for (Map.Entry> entry : attributions.entrySet()) { + builder.append(Component.newline()) + .append(Component.text("• " + entry.getKey() + ": ").color(NamedTextColor.WHITE)); + entry.getValue().stream().map(Credit::toComponent).forEach(name -> builder + .append(name) + .append(Component.text(", "))); } + // Add buttons if (!buttons.isEmpty()) { - menu.add("━━━━━━━━━━━━━━━━━━━━━━━━"); - for (final Link link : buttons) { - menu.add("- " + link.text + ": " + link.url); - } + builder.append(Component.newline()) + .append(Component.text("Links: ").color(secondaryColor)); + buttons.stream().map(Link::toComponent).forEach(link -> builder + .append(link) + .append(Component.text(" "))); } - return menu.toString(); - } - - /** - * Escape a string from {@link MineDown} formatting for use in a MineDown-formatted locale - *

- * Although MineDown provides {@link MineDown#escape(String)}, that method fails to escape events - * properly when using the escaped string in a replacement, so this is used instead - * - * @param string The string to escape - * @return The escaped string - */ - @NotNull - private static String escapeMineDown(@NotNull String string) { - final StringBuilder value = new StringBuilder(); - for (int i = 0; i < string.length(); ++i) { - char c = string.charAt(i); - boolean isEscape = c == '\\'; - boolean isColorCode = i + 1 < string.length() && (c == 167 || c == '&'); - boolean isEvent = c == '[' || c == ']' || c == '(' || c == ')'; - boolean isFormatting = (c == '_' || c == '*' || c == '~' || c == '?' || c == '#') && Util.isDouble(string, i); - if (isEscape || isColorCode || isEvent || isFormatting) { - value.append('\\'); - } - - value.append(c); - } - return value.toString(); + return builder.build(); } public static class Builder { - private String title; + private Component title; + private Component description; private Version version; - private String description; + private TextColor themeColor = TextColor.color(0x00FB9A); + private TextColor secondaryColor = TextColor.color(0xAAAAAA); private final Map> attributions = new LinkedHashMap<>(); private final List buttons = new ArrayList<>(); @@ -164,7 +119,7 @@ public class AboutMenu { * @return The {@link Builder} */ @NotNull - public Builder title(@NotNull String title) { + public Builder title(@NotNull Component title) { this.title = title; return this; } @@ -176,11 +131,35 @@ public class AboutMenu { * @return The {@link Builder} */ @NotNull - public Builder description(@Nullable String description) { + public Builder description(@Nullable Component description) { this.description = description; return this; } + /** + * Set the theme color of the resource to display on the menu + * + * @param themeColor The resource theme color + * @return The {@link Builder} + */ + @NotNull + public Builder themeColor(@NotNull TextColor themeColor) { + this.themeColor = themeColor; + return this; + } + + /** + * Set the secondary color of the resource to display on the menu + * + * @param secondaryColor The resource secondary color + * @return The {@link Builder} + */ + @NotNull + public Builder secondaryColor(@NotNull TextColor secondaryColor) { + this.secondaryColor = secondaryColor; + return this; + } + /** * Set the {@link Version} of the resource to display on the menu * @@ -230,7 +209,7 @@ public class AboutMenu { if (title == null) { throw new IllegalStateException("Title must be set"); } - return new AboutMenu(title, version, description, attributions, buttons); + return new AboutMenu(title, description, version, themeColor, secondaryColor, attributions, buttons); } } @@ -239,14 +218,10 @@ public class AboutMenu { * Represents a link related to the resource */ public static class Link { - @NotNull private String text = "Link"; - @NotNull - private String color = "#00fb9a"; - @Nullable - private String icon; - @NotNull + private TextColor color = TextColor.color(0x00fb9a); private final String url; + private String icon; private Link(@NotNull String url) { this.url = url; @@ -268,7 +243,7 @@ public class AboutMenu { * @param text The text * @return The {@link Link} */ - public Link withText(@NotNull String text) { + public Link text(@NotNull String text) { this.text = text; return this; } @@ -279,7 +254,7 @@ public class AboutMenu { * @param icon The icon character * @return The {@link Link} */ - public Link withIcon(@NotNull String icon) { + public Link icon(@NotNull String icon) { this.icon = icon; return this; } @@ -290,25 +265,29 @@ public class AboutMenu { * @param color The color * @return The {@link Link} */ - public Link withColor(@NotNull String color) { + public Link color(@NotNull TextColor color) { this.color = color; return this; } + @NotNull + public Component toComponent() { + return Component.text((icon == null ? "" : icon) + " " + text, color) + .clickEvent(ClickEvent.openUrl(url)); + } + } /** * Represents information about someone who worked on the resource */ public static class Credit { - @NotNull private final String name; @Nullable private String description; @Nullable private String url; - @NotNull - private String color = "gray"; + private TextColor color = TextColor.color(0xAAAAAA); private Credit(@NotNull String name) { this.name = name; @@ -320,6 +299,7 @@ public class AboutMenu { * @param name The name of the person to credit * @return The {@link Credit} */ + @NotNull public static Credit of(@NotNull String name) { return new Credit(name); } @@ -355,11 +335,23 @@ public class AboutMenu { * @return The {@link Credit} */ @NotNull - public Credit color(@NotNull String color) { + public Credit color(@NotNull TextColor color) { this.color = color; return this; } + @NotNull + public Component toComponent() { + final ComponentBuilder builder = Component.text().content(name); + if (description != null) { + builder.append(Component.text(" (" + description + ")")); + } + if (url != null) { + builder.clickEvent(ClickEvent.openUrl(url)); + } + return builder.color(color).build(); + } + } } diff --git a/src/main/java/net/william278/desertwell/util/ThrowingConsumer.java b/src/main/java/net/william278/desertwell/util/ThrowingConsumer.java index 0af8ceb..5954f67 100644 --- a/src/main/java/net/william278/desertwell/util/ThrowingConsumer.java +++ b/src/main/java/net/william278/desertwell/util/ThrowingConsumer.java @@ -1,19 +1,58 @@ +/* + * This file is part of DesertWell, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.william278.desertwell.util; import java.util.function.Consumer; +/** + * A Consumer that can throw an exception + * + * @param The type of the element to consume + * @since 2.0 + */ @FunctionalInterface public interface ThrowingConsumer extends Consumer { + /** + * Accepts the element, wrapping any exceptions in a {@link RuntimeException} + * + * @param element the input argument to accept + * @throws RuntimeException If an exception occurs + * @since 2.0 + */ @Override - default void accept(final T elem) { + default void accept(final T element) throws RuntimeException { try { - acceptThrows(elem); - } catch (final Exception e) { + acceptThrows(element); + } catch (final Throwable e) { throw new RuntimeException(e); } } - void acceptThrows(T elem) throws Exception; + /** + * Accepts the element, potentially throwing an exception + * + * @param elem The element to accept + * @throws Throwable If an exception occurs + * @since 2.0 + */ + void acceptThrows(T elem) throws Throwable; } \ No newline at end of file diff --git a/src/main/java/net/william278/desertwell/util/UpdateChecker.java b/src/main/java/net/william278/desertwell/util/UpdateChecker.java index afb787d..5dc38ab 100644 --- a/src/main/java/net/william278/desertwell/util/UpdateChecker.java +++ b/src/main/java/net/william278/desertwell/util/UpdateChecker.java @@ -1,3 +1,22 @@ +/* + * This file is part of DesertWell, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.william278.desertwell.util; import org.jetbrains.annotations.NotNull; @@ -94,6 +113,7 @@ public class UpdateChecker { /** * Represents endpoints from which the latest version can be queried + * @since 2.0 */ public enum Endpoint { SPIGOT((resource -> { diff --git a/src/main/java/net/william278/desertwell/util/Version.java b/src/main/java/net/william278/desertwell/util/Version.java index e8d4d9b..76c76e5 100644 --- a/src/main/java/net/william278/desertwell/util/Version.java +++ b/src/main/java/net/william278/desertwell/util/Version.java @@ -1,3 +1,22 @@ +/* + * This file is part of DesertWell, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.william278.desertwell.util; import org.jetbrains.annotations.NotNull; diff --git a/src/test/java/net/william278/desertwell/UpdateCheckerTests.java b/src/test/java/net/william278/desertwell/UpdateCheckerTests.java index a0547c3..4bf5435 100644 --- a/src/test/java/net/william278/desertwell/UpdateCheckerTests.java +++ b/src/test/java/net/william278/desertwell/UpdateCheckerTests.java @@ -1,3 +1,22 @@ +/* + * This file is part of DesertWell, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.william278.desertwell; import net.william278.desertwell.util.UpdateChecker; diff --git a/src/test/java/net/william278/desertwell/VersionTests.java b/src/test/java/net/william278/desertwell/VersionTests.java index 45b8e19..69a1f50 100644 --- a/src/test/java/net/william278/desertwell/VersionTests.java +++ b/src/test/java/net/william278/desertwell/VersionTests.java @@ -1,3 +1,22 @@ +/* + * This file is part of DesertWell, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.william278.desertwell; import net.william278.desertwell.util.Version;