171 lines
5.9 KiB
Java
171 lines
5.9 KiB
Java
package net.ME1312.SubServers.Console;
|
|
|
|
import org.fusesource.jansi.AnsiOutputStream;
|
|
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
|
|
public class AnsiHTMLColorStream extends AnsiOutputStream {
|
|
private static final String[] ANSI_COLOR_MAP = new String[]{"000000", "cd0000", "25bc24", "e1e100", "0000ee", "cd00cd", "00e1e1", "ffffff"};
|
|
private static final byte[] BYTES_NBSP = " ".getBytes();
|
|
private static final byte[] BYTES_QUOT = """.getBytes();
|
|
private static final byte[] BYTES_AMP = "&".getBytes();
|
|
private static final byte[] BYTES_LT = "<".getBytes();
|
|
private static final byte[] BYTES_GT = ">".getBytes();
|
|
private LinkedList<String> closingAttributes = new LinkedList<String>();
|
|
private boolean underline = false;
|
|
private boolean strikethrough = false;
|
|
|
|
public void close() throws IOException {
|
|
this.closeAttributes();
|
|
super.close();
|
|
}
|
|
|
|
public AnsiHTMLColorStream(OutputStream os) {
|
|
super(os);
|
|
}
|
|
|
|
private void write(String s) throws IOException {
|
|
super.out.write(s.getBytes());
|
|
}
|
|
|
|
private void writeAttribute(String s) throws IOException {
|
|
this.write("<" + s + ">");
|
|
this.closingAttributes.add(0, s);
|
|
}
|
|
|
|
private void closeAttribute(String s) throws IOException {
|
|
LinkedList<String> closedAttributes = new LinkedList<String>();
|
|
LinkedList<String> closingAttributes = new LinkedList<String>();
|
|
LinkedList<String> unclosedAttributes = new LinkedList<String>();
|
|
|
|
closingAttributes.addAll(this.closingAttributes);
|
|
for (String attr : closingAttributes) {
|
|
if (attr.toLowerCase().startsWith(s.toLowerCase())) {
|
|
for (String a : unclosedAttributes) {
|
|
closedAttributes.add(0, a);
|
|
this.write("</" + a.split(" ", 2)[0] + ">");
|
|
}
|
|
this.closingAttributes.removeFirstOccurrence(attr);
|
|
unclosedAttributes.clear();
|
|
this.write("</" + attr.split(" ", 2)[0] + ">");
|
|
} else {
|
|
unclosedAttributes.add(attr);
|
|
}
|
|
}
|
|
for (String attr : closedAttributes) {
|
|
this.write("<" + attr + ">");
|
|
}
|
|
}
|
|
|
|
private void closeAttributes() throws IOException {
|
|
for (String attr : closingAttributes) {
|
|
this.write("</" + attr.split(" ", 2)[0] + ">");
|
|
}
|
|
|
|
this.underline = false;
|
|
this.strikethrough = false;
|
|
this.closingAttributes.clear();
|
|
}
|
|
|
|
private boolean nbsp = true;
|
|
@Override public void write(int data) throws IOException {
|
|
if (data == 32) {
|
|
if (nbsp) this.out.write(BYTES_NBSP);
|
|
else super.write(data);
|
|
nbsp = !nbsp;
|
|
} else {
|
|
nbsp = false;
|
|
switch(data) {
|
|
case 34:
|
|
this.out.write(BYTES_QUOT);
|
|
break;
|
|
case 38:
|
|
this.out.write(BYTES_AMP);
|
|
break;
|
|
case 60:
|
|
this.out.write(BYTES_LT);
|
|
break;
|
|
case 62:
|
|
this.out.write(BYTES_GT);
|
|
break;
|
|
default:
|
|
super.write(data);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void writeLine(byte[] buf, int offset, int len) throws IOException {
|
|
this.write(buf, offset, len);
|
|
this.closeAttributes();
|
|
}
|
|
|
|
private String parseTextDecoration() {
|
|
String dec = "";
|
|
if (underline) dec += " underline";
|
|
if (strikethrough) dec += " line-through";
|
|
if (dec.length() <= 0) dec += " none";
|
|
|
|
return dec.substring(1);
|
|
}
|
|
|
|
@Override
|
|
protected void processSetAttribute(int attribute) throws IOException {
|
|
switch(attribute) {
|
|
case 1:
|
|
this.writeAttribute("b");
|
|
break;
|
|
case 3:
|
|
this.writeAttribute("i");
|
|
break;
|
|
case 4:
|
|
this.closeAttribute("span class=\"ansi-decoration");
|
|
this.underline = true;
|
|
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
|
break;
|
|
case 9:
|
|
this.closeAttribute("span class=\"ansi-decoration");
|
|
this.strikethrough = true;
|
|
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
|
break;
|
|
case 22:
|
|
this.closeAttribute("b");
|
|
break;
|
|
case 23:
|
|
this.closeAttribute("i");
|
|
break;
|
|
case 24:
|
|
this.closeAttribute("span class=\"ansi-decoration");
|
|
this.underline = false;
|
|
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
|
break;
|
|
case 29:
|
|
this.closeAttribute("span class=\"ansi-decoration");
|
|
this.strikethrough = false;
|
|
this.writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void processAttributeRest() throws IOException {
|
|
this.closeAttributes();
|
|
}
|
|
|
|
@Override
|
|
protected void processSetForegroundColor(int color) throws IOException {
|
|
this.writeAttribute("span class=\"ansi-foreground\" style=\"color: #" + ANSI_COLOR_MAP[color] + ";\"");
|
|
}
|
|
|
|
@Override
|
|
protected void processSetBackgroundColor(int color) throws IOException {
|
|
this.writeAttribute("span class=\"ansi-background\" style=\"background-color: #" + ANSI_COLOR_MAP[color] + ";\"");
|
|
}
|
|
}
|