package fitnesse.wikitext.parser;
import fitnesse.html.HtmlElement;
import java.util.Stack;
public class HtmlWriter {
private StringBuilder html = new StringBuilder();
private int lastEndLine = -1;
private Tags tags = new Tags();
public void startTag(String tag) {
closeCurrentTag(false);
indentTag();
tags.push(tag, false);
writeTag(tag);
}
public void startTagInline(String tag) {
closeCurrentTag(true);
tags.push(tag, true);
writeTag(tag);
}
public void putText(String text) {
closeCurrentTag(true);
html.append(text);
}
private void writeTag(String tag) {
html.append('<');
html.append(tag);
}
private void indentTag() {
for (int i = 0; i < tags.size(); i++) html.append('\t');
}
private void closeCurrentTag(boolean newTagInline) {
if (tags.size() > 0) {
if (tags.isOpen()) {
html.append('>');
tags.close();
}
if (!newTagInline) writeEndLine();
}
}
public void endTag() {
Tag tag = tags.pop();
if (tag.open) {
html.append(" />");
}
else {
if (html.length() == lastEndLine) {
indentTag();
}
html.append("</");
html.append(tag.name);
html.append('>');
}
if (!tag.inline) writeEndLine();
}
private void writeEndLine() {
if (html.length() == lastEndLine) return;
html.append(HtmlElement.endl);
lastEndLine = html.length();
}
public void putTag(String tag) {
startTag(tag);
endTag();
}
public void putTagInline(String tag) {
startTagInline(tag);
endTag();
}
public void putAttribute(String name, String value) {
html.append(' ');
html.append(name);
html.append("=\"");
html.append(value);
html.append('"');
}
public String toHtml() { return html.toString(); }
private class Tags {
private Stack<Tag> tags = new Stack<>();
private Tag top = new Tag(null, false);
private boolean isEmpty = true;
public void push(String name, boolean inline) {
if (!isEmpty) {
tags.push(top);
top = new Tag(name, inline);
}
else {
top.name = name;
top.inline = inline;
isEmpty = false;
}
}
public Tag pop() {
Tag result = top;
if (tags.empty()) {
isEmpty = true;
}
else {
top = tags.pop();
}
return result;
}
public int size() { return tags.size() + (isEmpty ? 0 : 1); }
public boolean isOpen() { return top.open; }
public void close() { top.open = false; }
}
private class Tag {
public String name;
public boolean open;
public boolean inline;
public Tag(String name, boolean inline) {
this.name = name;
this.inline = inline;
open = true;
}
}
}