package de.neuland.jade4j.parser.node; import de.neuland.jade4j.Jade4J; import de.neuland.jade4j.compiler.IndentWriter; import de.neuland.jade4j.exceptions.ExpressionException; import de.neuland.jade4j.exceptions.JadeCompilerException; import de.neuland.jade4j.lexer.token.Doctypes; import de.neuland.jade4j.model.JadeModel; import de.neuland.jade4j.template.JadeTemplate; import org.apache.commons.lang3.ArrayUtils; import java.util.LinkedList; public class TagNode extends AttrsNode { private Node textNode; private static final String[] inlineTags = { "a", "abbr", "acronym", "b", "br", "code", "em", "font", "i", "img", "ins", "kbd", "map", "samp", "small", "span", "strong", "sub", "sup"}; private boolean buffer = false; public TagNode() { this.block = new BlockNode(); } public void setTextNode(Node textNode) { this.textNode = textNode; } public Node getTextNode() { return textNode; } public boolean hasTextNode() { return textNode != null; } public boolean isInline(){ return ArrayUtils.indexOf(inlineTags,this.name) > -1; } private boolean isInline(Node node){ // Recurse if the node is a block if (node instanceof BlockNode) return everyIsInline(node.getNodes()); return node instanceof TextNode || (ArrayUtils.indexOf(inlineTags,node.getName()) > -1); } private boolean everyIsInline(LinkedList<Node> nodes){ boolean multilineInlineOnlyTag = true; for (Node node : nodes) { if(!isInline(node)) multilineInlineOnlyTag = false; } return multilineInlineOnlyTag; } public boolean canInline (){ Node block = this.getBlock(); if(block==null) return true; LinkedList<Node> nodes = block.getNodes(); // Empty tag if (nodes.size()==0) return true; // Text-only or inline-only tag if (1 == nodes.size()) return isInline(nodes.get(0)); // Multi-line inline-only tag if (everyIsInline(nodes)) { for (int i = 1, len = nodes.size(); i < len; ++i) { if (nodes.get(i-1) instanceof TextNode && nodes.get(i) instanceof TextNode) return false; } return true; } // Mixed tag return false; }; @Override public void execute(IndentWriter writer, JadeModel model, JadeTemplate template) throws JadeCompilerException { writer.increment(); if (!writer.isCompiledTag()) { if (!writer.isCompiledDoctype() && "html".equals(name)) { // template.setDoctype(null); } writer.setCompiledTag(true); } if ("pre".equals(this.name)) writer.setEscape(true); if(writer.isPp() && !isInline()){ writer.prettyIndent(0,true); } if (isSelfClosing() || isSelfClosing(template)) { writer.append("<"); writer.append(bufferName(template, model)); writer.append(visitAttributes(model, template)); if (isTerse(template)) { writer.append(">"); }else { writer.append("/>"); } if (hasBlock()) { //Fehlerbehandlung } }else { writer.append("<"); writer.append(bufferName(template, model)); writer.append(visitAttributes(model, template)); writer.append(">"); if (hasCodeNode()) { codeNode.execute(writer, model, template); } if (hasBlock()) { block.execute(writer, model, template); } // pretty print if (writer.isPp() && !isInline() && !"pre".equals(name) && !canInline()){ writer.prettyIndent(0, true); } writer.append("</"); writer.append(bufferName(template,model)); writer.append(">"); } if ("pre".equals(this.name)) writer.setEscape(false); writer.decrement(); } private boolean isEmpty() { return !hasBlock() && !hasTextNode() && !hasCodeNode(); } private String bufferName(JadeTemplate template, JadeModel model) { if (isBuffer()) { try { return template.getExpressionHandler().evaluateStringExpression(name, model); } catch (ExpressionException e) { e.printStackTrace(); return null; } }else { return name; } } public boolean isBuffer() { return buffer; } public void setBuffer(boolean buffer) { this.buffer = buffer; } }