diff --git a/build.gradle b/build.gradle
index 4a66efc..6342a58 100644
--- a/build.gradle
+++ b/build.gradle
@@ -32,11 +32,14 @@ repositories {
dependencies {
implementation('net.dv8tion:JDA:5.0.0-beta.21')
+ compileOnly('dev.latvian.apps:ansi:1.0.0-build.2')
implementation('dev.latvian.apps:tiny-java-server:1.0.0-build.7')
implementation('org.mongodb:mongodb-driver-sync:5.0.0')
// implementation('org.slf4j:slf4j-simple:2.0.5')
// implementation('com.google.guava:guava:31.1-jre') { exclude group: "com.google.code.findbugs" }
compileOnly('org.jetbrains:annotations:24.0.1')
+
+ testImplementation('dev.latvian.apps:ansi:1.0.0-build.2')
testImplementation('org.junit.jupiter:junit-jupiter-api:5.10.0')
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.10.0')
testImplementation('junit:junit:4.13.2')
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/Ansi.java b/src/main/java/dev/latvian/apps/webutils/ansi/Ansi.java
deleted file mode 100644
index 3013627..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/Ansi.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-import dev.latvian.apps.webutils.json.JSON;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Map;
-import java.util.regex.Pattern;
-
-/**
- * See ANSI Escape Sequences
- */
-public interface Ansi {
- Pattern PATTERN = Pattern.compile("\u001B\\[(?:\\d;)?\\d+[mD]");
- char CHAR = '\u001B';
-
- String[] COLOR_NAMES = {
- "black",
- "darkRed",
- "green",
- "orange",
- "navy",
- "purple",
- "teal",
- "lightGray",
- "darkGray",
- "red",
- "lime",
- "yellow",
- "blue",
- "magenta",
- "cyan",
- "white",
- };
-
- static AnsiComponent of() {
- return new AnsiComponent("");
- }
-
- static AnsiComponent of(Object text) {
- return text instanceof AnsiComponent ac ? ac : new AnsiComponent(text);
- }
-
- static AnsiComponent ofObject(Object object) {
- return ofObject0(object, 0);
- }
-
- private static AnsiComponent ofObject0(@Nullable Object object, int depth) {
- if (object == null || object == JSON.NULL) {
- return Ansi.darkRed("null");
- } else if (object instanceof Map, ?> map) {
- var builder = Ansi.of().treeColor(depth);
- builder.append('{');
- boolean first = true;
-
- for (var entry : map.entrySet()) {
- if (first) {
- first = false;
- } else {
- builder.append(',');
- }
-
- builder.append(Ansi.cyan("\"" + entry.getKey() + "\""));
- builder.append(':');
- builder.append(ofObject0(entry.getValue(), depth + 1));
- }
-
- builder.append('}');
- return builder;
- } else if (object instanceof Iterable> itr) {
- var builder = Ansi.of();
- builder.append('[');
- boolean first = true;
-
- for (var e : itr) {
- if (first) {
- first = false;
- } else {
- builder.append(',');
- }
-
- builder.append(ofObject0(e, depth + 1));
- }
-
- builder.append(']');
- return builder;
- } else if (object instanceof CharSequence) {
- return Ansi.orange("\"" + object + "\"");
- } else if (object instanceof Boolean b) {
- return b ? Ansi.green("true") : Ansi.red("false");
- } else if (object instanceof Number) {
- return Ansi.purple(object);
- } else if (object.getClass().isRecord()) {
- var builder = Ansi.of().treeColor(depth);
- builder.append('{');
- boolean first = true;
-
- for (var component : object.getClass().getRecordComponents()) {
- if (first) {
- first = false;
- } else {
- builder.append(',');
- }
-
- builder.append(Ansi.cyan("\"" + component.getName() + "\""));
- builder.append(':');
-
- try {
- builder.append(ofObject0(component.getAccessor().invoke(object), depth + 1));
- } catch (Exception ex) {
- builder.append(darkRed("").whiteBg());
- ex.printStackTrace();
- }
- }
-
- builder.append('}');
- return builder;
- } else if (object.getClass().isEnum()) {
- return Ansi.orange(object);
- } else {
- return Ansi.lightGray(object.toString());
- }
- }
-
- static AnsiComponent bold(Object text) {
- return of(text).bold();
- }
-
- static AnsiComponent italic(Object text) {
- return of(text).italic();
- }
-
- static AnsiComponent underline(Object text) {
- return of(text).underline();
- }
-
- static AnsiComponent blink(Object text) {
- return of(text).blink();
- }
-
- static AnsiComponent reverse(Object text) {
- return of(text).reverse();
- }
-
- static AnsiComponent hidden(Object text) {
- return of(text).hidden();
- }
-
- static AnsiComponent strikethrough(Object text) {
- return of(text).strikethrough();
- }
-
- static AnsiComponent black(Object text) {
- return of(text).black();
- }
-
- static AnsiComponent darkRed(Object text) {
- return of(text).darkRed();
- }
-
- static AnsiComponent green(Object text) {
- return of(text).green();
- }
-
- static AnsiComponent orange(Object text) {
- return of(text).orange();
- }
-
- static AnsiComponent navy(Object text) {
- return of(text).navy();
- }
-
- static AnsiComponent purple(Object text) {
- return of(text).purple();
- }
-
- static AnsiComponent teal(Object text) {
- return of(text).teal();
- }
-
- static AnsiComponent lightGray(Object text) {
- return of(text).lightGray();
- }
-
- static AnsiComponent darkGray(Object text) {
- return of(text).darkGray();
- }
-
- static AnsiComponent red(Object text) {
- return of(text).red();
- }
-
- static AnsiComponent lime(Object text) {
- return of(text).lime();
- }
-
- static AnsiComponent yellow(Object text) {
- return of(text).yellow();
- }
-
- static AnsiComponent blue(Object text) {
- return of(text).blue();
- }
-
- static AnsiComponent magenta(Object text) {
- return of(text).magenta();
- }
-
- static AnsiComponent cyan(Object text) {
- return of(text).cyan();
- }
-
- static AnsiComponent white(Object text) {
- return of(text).white();
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiAppendable.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiAppendable.java
deleted file mode 100644
index 92a4d72..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiAppendable.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-public interface AnsiAppendable {
- void appendAnsi(StringBuilder builder, AnsiContext ctx);
-
- default String toAnsiString() {
- var builder = new StringBuilder();
- appendAnsi(builder, AnsiContext.NONE);
- return builder.toString();
- }
-
- default String toDebugString() {
- var builder = new StringBuilder();
- appendAnsi(builder, new AnsiContext(1));
- return builder.toString();
- }
-
- default String toUnformattedString() {
- var builder = new StringBuilder();
- appendAnsi(builder, AnsiContext.UNFORMATTED);
- return builder.toString();
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiCode.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiCode.java
deleted file mode 100644
index b0bb6f9..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiCode.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-public enum AnsiCode implements AnsiAppendable {
- RESET("[0m"),
- LEFT("[1000D"),
- BOLD("[1m"),
- UNDERLINE("[4m"),
- REVERSE("[7m");
-
- public final String code;
-
- AnsiCode(String c) {
- code = c;
- }
-
- @Override
- public void appendAnsi(StringBuilder builder, AnsiContext ctx) {
- if (!ctx.unformatted()) {
- builder.append(ctx.debug() ? '§' : Ansi.CHAR);
- builder.append(code);
- }
- }
-
- @Override
- public String toString() {
- return Ansi.CHAR + code;
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiComponent.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiComponent.java
deleted file mode 100644
index 29e5653..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiComponent.java
+++ /dev/null
@@ -1,426 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class AnsiComponent implements AnsiAppendable {
- public AnsiComponent parent = null;
- public String text;
- private int color = -1;
- private int bgColor = -1;
- private int bold = -1;
- private int italic = -1;
- private int underline = -1;
- private int blink = -1;
- private int reverse = -1;
- private int hidden = -1;
- private int strikethrough = -1;
- private List children;
-
- public AnsiComponent(Object text) {
- this.text = String.valueOf(text);
- }
-
- private static boolean appendMode(StringBuilder builder, boolean semi, int prevMode, int mode, char code, char resetCode, AnsiContext ctx, String debug) {
- if (prevMode != mode) {
- if (semi) {
- builder.append(';');
- }
-
- if (ctx.debug()) {
- if (mode == 1) {
- builder.append(debug);
- } else {
- builder.append('!');
- builder.append(debug);
- }
- } else if (mode == 1) {
- builder.append(code);
- } else {
- builder.append('2');
- builder.append(resetCode);
- }
-
- return true;
- }
-
- return semi;
- }
-
- private static boolean appendColor(StringBuilder builder, boolean semi, int prevColor, int color, char code, String brightCode, AnsiContext ctx) {
- if (prevColor != color) {
- if (semi) {
- builder.append(';');
- }
-
- if (ctx.debug()) {
- if (color == -1) {
- builder.append("!color");
- } else if (color >= 0 && color < 16) {
- builder.append(Ansi.COLOR_NAMES[color]);
- } else {
- builder.append("#%06X".formatted(color & 0xFFFFFF));
- }
-
- return true;
- }
-
- int a = (color >> 24) & 0xFF;
- int r = (color >> 16) & 0xFF;
- int g = (color >> 8) & 0xFF;
- int b = color & 0xFF;
-
- if (color == -1) {
- builder.append(code);
- builder.append('9');
- } else if (a == 255) {
- builder.append(code);
- builder.append("8;2;");
- builder.append(r);
- builder.append(';');
- builder.append(g);
- builder.append(';');
- builder.append(b);
- } else if (color < 8) {
- builder.append(code);
- builder.append((char) (color + '0'));
- } else if (color < 16) {
- builder.append(brightCode);
- builder.append((char) (color - 8 + '0'));
- } else {
- builder.append(code);
- builder.append("8;5;");
- builder.append(color);
- }
-
- return true;
- }
-
- return semi;
- }
-
- @Override
- public void appendAnsi(StringBuilder builder, AnsiContext ctx) {
- if (ctx.unformatted()) {
- if (!text.isEmpty()) {
- builder.append(text);
- }
-
- if (children != null) {
- for (var c : children) {
- c.appendAnsi(builder, ctx);
- }
- }
-
- return;
- }
-
- int pColor = parent == null ? -1 : parent.color;
- int pBgColor = parent == null ? -1 : parent.bgColor;
- int pBold = parent == null ? -1 : parent.bold;
- int pItalic = parent == null ? -1 : parent.italic;
- int pUnderline = parent == null ? -1 : parent.underline;
- int pBlink = parent == null ? -1 : parent.blink;
- int pReverse = parent == null ? -1 : parent.reverse;
- int pHidden = parent == null ? -1 : parent.hidden;
- int pStrikethrough = parent == null ? -1 : parent.strikethrough;
- boolean changed = color != pColor || bgColor != pBgColor || bold != pBold || italic != pItalic || underline != pUnderline || blink != pBlink || reverse != pReverse || hidden != pHidden || strikethrough != pStrikethrough;
-
- if (changed) {
- builder.append(Ansi.CHAR);
-
- if (ctx.debug()) {
- builder.append("[9").append((ctx.index++ & 3) + 1).append("m§");
- }
-
- builder.append('[');
- boolean semi = false;
- semi = appendColor(builder, semi, pColor, color, '3', "9", ctx);
- semi = appendColor(builder, semi, pBgColor, bgColor, '4', "10", ctx);
- semi = appendMode(builder, semi, pBold, bold, '1', '2', ctx, "bold");
- semi = appendMode(builder, semi, pItalic, italic, '3', '3', ctx, "italic");
- semi = appendMode(builder, semi, pUnderline, underline, '4', '4', ctx, "underline");
- semi = appendMode(builder, semi, pBlink, blink, '5', '5', ctx, "blink");
- semi = appendMode(builder, semi, pReverse, reverse, '7', '7', ctx, "reverse");
- semi = appendMode(builder, semi, pHidden, hidden, '8', '8', ctx, "hidden");
- semi = appendMode(builder, semi, pStrikethrough, strikethrough, '9', '9', ctx, "strikethrough");
-
- if (ctx.debug()) {
- builder.append(']');
- builder.append(Ansi.CHAR);
- builder.append(AnsiCode.RESET.code);
- } else {
- builder.append('m');
- }
- }
-
- if (!text.isEmpty()) {
- builder.append(text);
- }
-
- if (children != null) {
- for (var c : children) {
- c.appendAnsi(builder, ctx);
- }
- }
-
- if (changed) {
- builder.append(Ansi.CHAR);
-
- if (ctx.debug()) {
- builder.append("[9").append((ctx.index++ & 3) + 1).append("m§");
- }
-
- builder.append('[');
- boolean semi = false;
- semi = appendColor(builder, semi, color, pColor, '3', "9", ctx);
- semi = appendColor(builder, semi, bgColor, pBgColor, '4', "10", ctx);
- semi = appendMode(builder, semi, bold, pBold, '1', '2', ctx, "bold");
- semi = appendMode(builder, semi, italic, pItalic, '3', '3', ctx, "italic");
- semi = appendMode(builder, semi, underline, pUnderline, '4', '4', ctx, "underline");
- semi = appendMode(builder, semi, blink, pBlink, '5', '5', ctx, "blink");
- semi = appendMode(builder, semi, reverse, pReverse, '7', '7', ctx, "reverse");
- semi = appendMode(builder, semi, hidden, pHidden, '8', '8', ctx, "hidden");
- semi = appendMode(builder, semi, strikethrough, pStrikethrough, '9', '9', ctx, "strikethrough");
-
- if (ctx.debug()) {
- builder.append(']');
- builder.append(Ansi.CHAR);
- builder.append(AnsiCode.RESET.code);
- } else {
- builder.append('m');
- }
- }
- }
-
- @Override
- public String toString() {
- return toAnsiString();
- }
-
- public AnsiComponent end() {
- return parent;
- }
-
- public AnsiComponent append(Object text) {
- var c = text instanceof AnsiComponent ac ? ac : new AnsiComponent(text);
- c.parent = this;
-
- if (children == null) {
- children = new ArrayList<>(1);
- }
-
- if (c.color == -1) {
- c.color = color;
- }
-
- if (c.bgColor == -1) {
- c.bgColor = bgColor;
- }
-
- c.bold |= bold;
- c.italic |= italic;
- c.underline |= underline;
- c.blink |= blink;
- c.reverse |= reverse;
- c.hidden |= hidden;
- c.strikethrough |= strikethrough;
- children.add(c);
- return this;
- }
-
- public AnsiComponent bold() {
- bold = 1;
- return this;
- }
-
- public AnsiComponent italic() {
- italic = 1;
- return this;
- }
-
- public AnsiComponent underline() {
- underline = 1;
- return this;
- }
-
- public AnsiComponent blink() {
- blink = 1;
- return this;
- }
-
- public AnsiComponent reverse() {
- reverse = 1;
- return this;
- }
-
- public AnsiComponent hidden() {
- hidden = 1;
- return this;
- }
-
- public AnsiComponent strikethrough() {
- strikethrough = 1;
- return this;
- }
-
- public AnsiComponent color(int color) {
- this.color = color;
- return this;
- }
-
- public AnsiComponent rgb(int color) {
- return color(0xFF000000 | color);
- }
-
- public AnsiComponent black() {
- return color(0);
- }
-
- public AnsiComponent darkRed() {
- return color(1);
- }
-
- public AnsiComponent green() {
- return color(2);
- }
-
- public AnsiComponent orange() {
- return color(3);
- }
-
- public AnsiComponent navy() {
- return color(4);
- }
-
- public AnsiComponent purple() {
- return color(5);
- }
-
- public AnsiComponent teal() {
- return color(6);
- }
-
- public AnsiComponent lightGray() {
- return color(7);
- }
-
- public AnsiComponent darkGray() {
- return color(8);
- }
-
- public AnsiComponent red() {
- return color(9);
- }
-
- public AnsiComponent lime() {
- return color(10);
- }
-
- public AnsiComponent yellow() {
- return color(11);
- }
-
- public AnsiComponent blue() {
- return color(12);
- }
-
- public AnsiComponent magenta() {
- return color(13);
- }
-
- public AnsiComponent cyan() {
- return color(14);
- }
-
- public AnsiComponent white() {
- return color(15);
- }
-
- public AnsiComponent error() {
- return white().darkRedBg();
- }
-
- public AnsiComponent treeColor(int index) {
- return switch (index & 3) {
- case 0 -> red();
- case 1 -> green();
- case 2 -> blue();
- case 3 -> yellow();
- default -> this;
- };
- }
-
- public AnsiComponent bgColor(int color) {
- bgColor = color;
- return this;
- }
-
- public AnsiComponent rgbBg(int color) {
- return bgColor(0xFF000000 | color);
- }
-
- public AnsiComponent blackBg() {
- return bgColor(0);
- }
-
- public AnsiComponent darkRedBg() {
- return bgColor(1);
- }
-
- public AnsiComponent greenBg() {
- return bgColor(2);
- }
-
- public AnsiComponent orangeBg() {
- return bgColor(3);
- }
-
- public AnsiComponent navyBg() {
- return bgColor(4);
- }
-
- public AnsiComponent purpleBg() {
- return bgColor(5);
- }
-
- public AnsiComponent tealBg() {
- return bgColor(6);
- }
-
- public AnsiComponent lightGrayBg() {
- return bgColor(7);
- }
-
- public AnsiComponent darkGrayBg() {
- return bgColor(8);
- }
-
- public AnsiComponent redBg() {
- return bgColor(9);
- }
-
- public AnsiComponent limeBg() {
- return bgColor(10);
- }
-
- public AnsiComponent yellowBg() {
- return bgColor(11);
- }
-
- public AnsiComponent blueBg() {
- return bgColor(12);
- }
-
- public AnsiComponent magentaBg() {
- return bgColor(13);
- }
-
- public AnsiComponent cyanBg() {
- return bgColor(14);
- }
-
- public AnsiComponent whiteBg() {
- return bgColor(15);
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiContext.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiContext.java
deleted file mode 100644
index 31dabfd..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiContext.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-public class AnsiContext {
- public static final AnsiContext UNFORMATTED = new AnsiContext(-1);
- public static final AnsiContext NONE = new AnsiContext(0);
-
- public int index;
-
- public AnsiContext(int index) {
- this.index = index;
- }
-
- public boolean unformatted() {
- return index == -1;
- }
-
- public boolean debug() {
- return index != 0;
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiPrintStream.java b/src/main/java/dev/latvian/apps/webutils/ansi/AnsiPrintStream.java
deleted file mode 100644
index b1a5f7f..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/AnsiPrintStream.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-import org.jetbrains.annotations.NotNull;
-
-import java.io.PrintStream;
-
-// WIP for printing exceptions to console with ANSI colors
-public class AnsiPrintStream extends PrintStream {
- public final PrintStream parent;
-
- public AnsiPrintStream(@NotNull PrintStream parent) {
- super(parent);
- this.parent = parent;
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/Log.java b/src/main/java/dev/latvian/apps/webutils/ansi/Log.java
deleted file mode 100644
index b8c2d38..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/Log.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-import dev.latvian.apps.webutils.TimeUtils;
-
-import java.util.Date;
-
-public class Log {
- public enum Type {
- INFO,
- WARN,
- ERROR,
- DEBUG,
- SUCCESS,
- FAIL,
- IMPORTANT,
- CODE
- }
-
- public static Log INSTANCE = new Log();
-
- public static void info(Object message) {
- INSTANCE.log(Type.INFO, message);
- }
-
- public static void warn(Object message) {
- INSTANCE.log(Type.WARN, message);
- }
-
- public static void error(Object message) {
- INSTANCE.log(Type.ERROR, message);
- }
-
- public static void debug(Object message) {
- INSTANCE.log(Type.DEBUG, message);
- }
-
- public static void success(Object message) {
- INSTANCE.log(Type.SUCCESS, message);
- }
-
- public static void fail(Object message) {
- INSTANCE.log(Type.FAIL, message);
- }
-
- public static void success(Object message, boolean success) {
- if (success) {
- success(message);
- } else {
- fail(message);
- }
- }
-
- public static void important(Object message) {
- INSTANCE.log(Type.IMPORTANT, message);
- }
-
- public static void code(Object message) {
- INSTANCE.log(Type.CODE, message);
- }
-
- public void log(Type type, Object message) {
- var now = new Date();
- var c = Ansi.of();
- c.append(Ansi.cyan(TimeUtils.formatDate(new StringBuilder(), now).toString()));
- c.append(' ');
- c.append(format(message, type));
- System.out.println(c);
- }
-
- public AnsiComponent format(Object message, Type type) {
- return switch (type) {
- case WARN -> Ansi.of(message).yellow();
- case ERROR -> Ansi.of(message).error();
- case DEBUG -> Ansi.of(message).lightGray();
- case SUCCESS -> Ansi.of(message).green();
- case FAIL -> Ansi.of(message).red();
- case IMPORTANT -> Ansi.of(message).orange();
- case CODE -> Ansi.of(message).teal();
- default -> Ansi.of(message);
- };
- }
-}
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/Table.java b/src/main/java/dev/latvian/apps/webutils/ansi/Table.java
deleted file mode 100644
index da2a6cd..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/Table.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package dev.latvian.apps.webutils.ansi;
-
-import dev.latvian.apps.webutils.html.PairedTag;
-import dev.latvian.apps.webutils.html.Tag;
-import org.jetbrains.annotations.Nullable;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class Table {
- public static class Cell {
- private AnsiComponent value = Ansi.of("");
- private Tag tag = null;
- private char padding = ' ';
- private boolean alignRight = false;
-
- private Cell() {
- }
-
- public Cell value(Object v) {
- value = Ansi.of(v);
- return this;
- }
-
- public Tag tag() {
- tag = new PairedTag("");
- return tag;
- }
-
- public Cell padding(char p) {
- padding = p;
- return this;
- }
-
- public Cell alignRight() {
- alignRight = true;
- return this;
- }
-
- public void fill(Tag cellTag) {
- if (tag != null) {
- cellTag.add(tag);
- } else {
- cellTag.string(value.toUnformattedString());
- }
- }
-
- public String unformattedValue() {
- return tag == null ? value.toUnformattedString() : tag.toRawString();
- }
-
- public int unformattedLength() {
- return unformattedValue().length();
- }
- }
-
- public static String escapeCSVSpecialCharacters(@Nullable String data) {
- if (data == null) {
- return "null";
- }
-
- String escapedData = data.replaceAll("\\R", " ");
- if (data.contains(",") || data.contains("\"") || data.contains("'")) {
- data = data.replace("\"", "\"\"");
- escapedData = "\"" + data + "\"";
- }
- return escapedData;
-
- //return "\"" + data.replace("\"", "\"\"") + "\"";
- }
-
- public final Cell[] head;
- public final List rows;
-
- public Table(String... h) {
- head = new Cell[h.length];
- rows = new ArrayList<>();
-
- for (int i = 0; i < head.length; i++) {
- head[i] = new Cell().value(Ansi.bold(h[i]));
- }
- }
-
- public Cell[] addRow() {
- Cell[] cells = new Cell[head.length];
-
- for (int i = 0; i < head.length; i++) {
- cells[i] = new Cell();
- }
-
- rows.add(cells);
- return cells;
- }
-
- public void addRow(Object... h) {
- Cell[] c = addRow();
-
- for (int i = 0; i < h.length; i++) {
- c[i].value(h[i]);
- }
- }
-
- private void printLine(List lines, boolean colors, StringBuilder sb, int[] max, int type) {
- sb.setLength(0);
- sb.append(type == 0 ? '┌' : type == 1 ? '├' : '└');
-
- for (int i : max) {
- for (int k = 0; k < i + 2; k++) {
- sb.append('─');
- }
-
- sb.append(type == 0 ? '┬' : type == 1 ? '┼' : '┴');
- }
-
- sb.setCharAt(sb.length() - 1, type == 0 ? '┐' : type == 1 ? '┤' : '┘');
-
- if (colors) {
- lines.add(sb.toString());
- } else {
- lines.add(Ansi.PATTERN.matcher(sb.toString()).replaceAll(""));
- }
- }
-
- private void printRow(List lines, boolean colors, StringBuilder sb, int[] max, Cell[] cells) {
- sb.setLength(0);
- sb.append('│');
-
- for (int i = 0; i < max.length; i++) {
- sb.append(' ');
-
- int l = max[i] - cells[i].unformattedLength();
-
- if (cells[i].alignRight) {
- for (int j = 0; j < l; j++) {
- sb.append(cells[i].padding);
- }
- }
-
- sb.append(cells[i].value);
- sb.append(AnsiCode.RESET);
-
- if (!cells[i].alignRight) {
- for (int j = 0; j < l; j++) {
- sb.append(cells[i].padding);
- }
- }
-
- sb.append(" │");
- }
-
- if (colors) {
- lines.add(sb.toString());
- } else {
- lines.add(Ansi.PATTERN.matcher(sb.toString()).replaceAll(""));
- }
- }
-
- public List getCSVLines(boolean includeHead) {
- List lines = new ArrayList<>();
-
- if (includeHead) {
- addCSVLine(lines, head);
- }
-
- for (Cell[] c : rows) {
- addCSVLine(lines, c);
- }
-
- return lines;
- }
-
- public byte[] getCSVBytes(boolean includeHead) {
- return String.join("\n", getCSVLines(includeHead)).getBytes(StandardCharsets.UTF_8);
- }
-
- private void addCSVLine(List lines, Cell[] cells) {
- lines.add(Arrays.stream(cells).map(c -> escapeCSVSpecialCharacters(c.unformattedValue())).collect(Collectors.joining(",")));
- }
-
- public List getLines(boolean colors) {
- List lines = new ArrayList<>();
- if (head.length == 0) {
- lines.add("┌───────┐");
- lines.add("│ Empty │");
- lines.add("└───────┘");
- return lines;
- }
-
- int[] max = new int[head.length];
-
- for (int i = 0; i < head.length; i++) {
- max[i] = head[i].unformattedLength();
- }
-
- for (Cell[] cells : rows) {
- for (int i = 0; i < head.length; i++) {
- max[i] = Math.max(max[i], cells[i].unformattedLength());
- }
- }
-
- StringBuilder sb = new StringBuilder();
- printLine(lines, colors, sb, max, 0);
- printRow(lines, colors, sb, max, head);
- printLine(lines, colors, sb, max, 1);
-
- for (Cell[] cells : rows) {
- printRow(lines, colors, sb, max, cells);
- }
-
- printLine(lines, colors, sb, max, 2);
- return lines;
- }
-
- public void print() {
- Log.info("\n" + String.join("\n", getLines(true)));
- }
-
- public Tag toTag() {
- Tag table = new PairedTag("table");
-
- var theadTag = table.thead();
- var headTag = theadTag.tr();
-
- for (var cell : head) {
- cell.fill(headTag.th());
- }
-
- var tbodyTag = table.tbody();
-
- for (var cells : rows) {
- var rowTag = tbodyTag.tr();
-
- for (var cell : cells) {
- cell.fill(rowTag.td());
- }
- }
-
- return table;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/dev/latvian/apps/webutils/ansi/package-info.java b/src/main/java/dev/latvian/apps/webutils/ansi/package-info.java
deleted file mode 100644
index eef858f..0000000
--- a/src/main/java/dev/latvian/apps/webutils/ansi/package-info.java
+++ /dev/null
@@ -1,2 +0,0 @@
-@dev.latvian.apps.webutils.NonnullByDefault
-package dev.latvian.apps.webutils.ansi;
\ No newline at end of file
diff --git a/src/main/java/dev/latvian/apps/webutils/data/Lazy.java b/src/main/java/dev/latvian/apps/webutils/data/Lazy.java
index 6f311ea..1552166 100644
--- a/src/main/java/dev/latvian/apps/webutils/data/Lazy.java
+++ b/src/main/java/dev/latvian/apps/webutils/data/Lazy.java
@@ -1,27 +1,22 @@
package dev.latvian.apps.webutils.data;
-import dev.latvian.apps.webutils.ansi.Log;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
+import java.util.concurrent.Callable;
import java.util.function.Supplier;
public class Lazy implements Supplier {
- @FunctionalInterface
- public interface LazySupplier {
- T get() throws Exception;
- }
-
- private record Present(T value) implements LazySupplier {
+ private record Present(T value) implements Callable {
@Override
- public T get() {
+ public T call() {
return value;
}
}
- public static final Lazy> EMPTY = of(() -> null);
+ public static final Lazy> EMPTY = present(null);
- public static Lazy of(LazySupplier getter) {
+ public static Lazy of(Callable getter) {
return new Lazy<>(getter);
}
@@ -34,11 +29,11 @@ public static Lazy empty() {
return (Lazy) EMPTY;
}
- private final LazySupplier getter;
+ private final Callable getter;
private T object;
private boolean inited;
- private Lazy(LazySupplier g) {
+ private Lazy(Callable g) {
getter = g;
}
@@ -54,9 +49,9 @@ public T get() {
inited = true;
try {
- object = getter.get();
+ object = getter.call();
} catch (Exception ex) {
- Log.error(ex);
+ throw new RuntimeException(ex);
}
}
diff --git a/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java b/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java
index 65b0b84..9ca963b 100644
--- a/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java
+++ b/src/main/java/dev/latvian/apps/webutils/html/PairedTag.java
@@ -1,8 +1,5 @@
package dev.latvian.apps.webutils.html;
-import dev.latvian.apps.webutils.ansi.Ansi;
-import dev.latvian.apps.webutils.ansi.AnsiComponent;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -153,51 +150,4 @@ public void appendRaw(StringBuilder builder) {
}
}
}
-
- @Override
- public void ansi(AnsiComponent component, int depth, int indent) {
- int col = TagUtils.ANSI_COLORS[depth % TagUtils.ANSI_COLORS.length];
-
- if (!this.name.isEmpty()) {
- component.append(Ansi.of("<" + this.name).color(col));
- TagUtils.ansiAttributes(component, this.attributes, depth);
- component.append(Ansi.of(">").color(col));
- }
-
- boolean shouldIndent = indent >= 0 && !this.name.isEmpty();
-
- if (shouldIndent) {
- shouldIndent = false;
-
- if (this.content != null && !this.content.isEmpty()) {
- for (var tag : this.content) {
- if (tag instanceof UnpairedTag) {
- shouldIndent = true;
- break;
- }
- }
- }
- }
-
- if (this.content != null && !this.content.isEmpty()) {
- for (var tag : this.content) {
- if (shouldIndent) {
- component.append('\n');
- component.append(" ".repeat(indent + 1));
- tag.ansi(component, depth + 1, indent + 1);
- } else {
- tag.ansi(component, depth + 1, indent);
- }
- }
- }
-
- if (shouldIndent) {
- component.append('\n');
- component.append(" ".repeat(indent));
- }
-
- if (!this.name.isEmpty()) {
- component.append(Ansi.of("" + this.name + ">").color(col));
- }
- }
}
diff --git a/src/main/java/dev/latvian/apps/webutils/html/Tag.java b/src/main/java/dev/latvian/apps/webutils/html/Tag.java
index 30af2cf..56b9c5f 100644
--- a/src/main/java/dev/latvian/apps/webutils/html/Tag.java
+++ b/src/main/java/dev/latvian/apps/webutils/html/Tag.java
@@ -3,9 +3,6 @@
import dev.latvian.apps.tinyserver.content.MimeType;
import dev.latvian.apps.tinyserver.http.response.HTTPResponse;
import dev.latvian.apps.tinyserver.http.response.HTTPStatus;
-import dev.latvian.apps.webutils.ansi.Ansi;
-import dev.latvian.apps.webutils.ansi.AnsiComponent;
-import dev.latvian.apps.webutils.ansi.Log;
import org.jetbrains.annotations.Nullable;
import java.nio.charset.StandardCharsets;
@@ -33,18 +30,13 @@ default Tag end() {
void appendRaw(StringBuilder builder);
- default void ansi(AnsiComponent component, int depth, int indent) {
- component.append(toRawString());
- }
-
default String toRawString() {
var builder = new StringBuilder();
try {
appendRaw(builder);
} catch (OutOfMemoryError error) {
- Log.error("Out of memory while generating HTML:");
- error.printStackTrace();
+ throw new RuntimeException("Out of memory while generating HTML:", error);
} catch (Throwable error) {
error.printStackTrace();
}
@@ -58,8 +50,7 @@ default String toTagString(boolean header) {
try {
append(builder, header);
} catch (OutOfMemoryError error) {
- Log.error("Out of memory while generating HTML:");
- error.printStackTrace();
+ throw new RuntimeException("Out of memory while generating HTML:", error);
} catch (Throwable error) {
error.printStackTrace();
}
@@ -67,12 +58,6 @@ default String toTagString(boolean header) {
return builder.toString();
}
- default AnsiComponent toAnsi(boolean indent) {
- var component = Ansi.of();
- ansi(component, 0, indent ? 0 : -1);
- return component;
- }
-
default Tag add(Tag tag) {
addAnd(tag);
return this;
diff --git a/src/main/java/dev/latvian/apps/webutils/html/TagANSI.java b/src/main/java/dev/latvian/apps/webutils/html/TagANSI.java
new file mode 100644
index 0000000..db70d3f
--- /dev/null
+++ b/src/main/java/dev/latvian/apps/webutils/html/TagANSI.java
@@ -0,0 +1,104 @@
+package dev.latvian.apps.webutils.html;
+
+import dev.latvian.apps.ansi.ANSI;
+import dev.latvian.apps.ansi.color.Color16;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+public interface TagANSI {
+ static ANSI of(Tag tag) {
+ return of(tag, false);
+ }
+
+ static ANSI of(Tag tag, boolean indent) {
+ var component = ANSI.empty();
+ ansi(tag, component, 0, indent ? 0 : -1);
+ return component;
+ }
+
+ private static void ansi(Tag tag, ANSI component, int depth, int indent) {
+ if (tag instanceof PairedTag paired) {
+ paired(paired, component, depth, indent);
+ } else if (tag instanceof UnpairedTag unpaired) {
+ unpaired(unpaired, component, depth, indent);
+ } else {
+ component.append(tag.toRawString());
+ }
+ }
+
+ private static void unpaired(UnpairedTag tag, ANSI component, int depth, int indent) {
+ var col = Color16.tree(depth);
+
+ component.append(ANSI.of("<" + tag.name).foreground(col));
+ TagANSI.attributes(component, tag.attributes, depth);
+ component.append(ANSI.of(" />").foreground(col));
+ }
+
+ private static void paired(PairedTag tag, ANSI component, int depth, int indent) {
+ var col = Color16.tree(depth);
+
+ if (!tag.name.isEmpty()) {
+ component.append(ANSI.of("<" + tag.name).foreground(col));
+ TagANSI.attributes(component, tag.attributes, depth);
+ component.append(ANSI.of(">").foreground(col));
+ }
+
+ boolean shouldIndent = indent >= 0 && !tag.name.isEmpty();
+
+ if (shouldIndent) {
+ shouldIndent = false;
+
+ if (tag.content != null && !tag.content.isEmpty()) {
+ for (var c : tag.content) {
+ if (c instanceof UnpairedTag) {
+ shouldIndent = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (tag.content != null && !tag.content.isEmpty()) {
+ for (var c : tag.content) {
+ if (shouldIndent) {
+ component.append('\n');
+ component.append(" ".repeat(indent + 1));
+ ansi(c, component, depth + 1, indent + 1);
+ } else {
+ ansi(c, component, depth + 1, indent);
+ }
+ }
+ }
+
+ if (shouldIndent) {
+ component.append('\n');
+ component.append(" ".repeat(indent));
+ }
+
+ if (!tag.name.isEmpty()) {
+ component.append(ANSI.of("" + tag.name + ">").foreground(col));
+ }
+ }
+
+ static void attributes(ANSI component, @Nullable Map attributes, int depth) {
+ var col = Color16.tree(depth);
+
+ if (attributes != null) {
+ var sb = new StringBuilder();
+
+ for (var entry : attributes.entrySet()) {
+ component.append(' ');
+ component.append(ANSI.lime(entry.getKey()));
+
+ if (!entry.getValue().equals("")) {
+ component.append(ANSI.of("=\"").foreground(col));
+ TagUtils.encode(sb, entry.getValue());
+ component.append(ANSI.yellow(sb.toString()));
+ sb.setLength(0);
+ component.append(ANSI.of("\"").foreground(col));
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java b/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java
index e471706..1b265a5 100644
--- a/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java
+++ b/src/main/java/dev/latvian/apps/webutils/html/TagUtils.java
@@ -1,19 +1,10 @@
package dev.latvian.apps.webutils.html;
-import dev.latvian.apps.webutils.ansi.Ansi;
-import dev.latvian.apps.webutils.ansi.AnsiComponent;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
public class TagUtils {
- public static final int[] ANSI_COLORS = {
- 13, // MAGENTA
- 5, // PURPLE
- 12, // BLUE
- 14, // CYAN
- };
-
public static String encode(char c) {
return switch (c) {
case '&' -> "&";
@@ -314,25 +305,4 @@ public static void writeAttributes(StringBuilder writer, @Nullable Map attributes, int depth) {
- int col = ANSI_COLORS[depth % ANSI_COLORS.length];
-
- if (attributes != null) {
- var sb = new StringBuilder();
-
- for (var entry : attributes.entrySet()) {
- component.append(' ');
- component.append(Ansi.lime(entry.getKey()));
-
- if (!entry.getValue().equals("")) {
- component.append(Ansi.of("=\"").color(col));
- encode(sb, entry.getValue());
- component.append(Ansi.yellow(sb.toString()));
- sb.setLength(0);
- component.append(Ansi.of("\"").color(col));
- }
- }
- }
- }
}
diff --git a/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java b/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java
index 00e8db1..03557db 100644
--- a/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java
+++ b/src/main/java/dev/latvian/apps/webutils/html/UnpairedTag.java
@@ -1,7 +1,5 @@
package dev.latvian.apps.webutils.html;
-import dev.latvian.apps.webutils.ansi.Ansi;
-import dev.latvian.apps.webutils.ansi.AnsiComponent;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
@@ -68,13 +66,4 @@ public void append(StringBuilder builder, boolean header) {
@Override
public void appendRaw(StringBuilder builder) {
}
-
- @Override
- public void ansi(AnsiComponent component, int depth, int indent) {
- int col = TagUtils.ANSI_COLORS[depth % TagUtils.ANSI_COLORS.length];
-
- component.append(Ansi.of("<" + this.name).color(col));
- TagUtils.ansiAttributes(component, this.attributes, depth);
- component.append(Ansi.of(" />").color(col));
- }
}
diff --git a/src/main/java/dev/latvian/apps/webutils/json/ArrayJSONAdapter.java b/src/main/java/dev/latvian/apps/webutils/json/ArrayJSONAdapter.java
deleted file mode 100644
index 5ce106d..0000000
--- a/src/main/java/dev/latvian/apps/webutils/json/ArrayJSONAdapter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package dev.latvian.apps.webutils.json;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.lang.reflect.Array;
-import java.util.Collection;
-
-public class ArrayJSONAdapter implements JSONAdapter |