org.cobraparser.html.style.StyleElements Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Cobra Show documentation
Show all versions of Cobra Show documentation
Cobra is the rendering engine designed for LoboBrowser
package org.cobraparser.html.style;
import java.util.Vector;
import org.cobraparser.html.domimpl.HTMLElementImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import cz.vutbr.web.css.StyleSheet;
/**
* Borrowed from CSSBox HTMLNorm.java This class provides a mechanism of
* converting some HTML presentation atributes to the CSS styles and other
* methods related to HTML specifics.
*/
public class StyleElements {
public static StyleSheet convertAttributesToStyles(final Node n) {
if (n.getNodeType() == Node.ELEMENT_NODE) {
final HTMLElementImpl el = (HTMLElementImpl) n;
//Analyze HTML attributes
String attrs = "";
final String tagName = el.getTagName();
if ("TABLE".equalsIgnoreCase(tagName)) {
//setting table and cell borders
attrs = getTableElementStyle(el, attrs);
} else if ("FONT".equalsIgnoreCase(tagName)) {
//Text properties
attrs = getFontElementStyle(el, attrs);
} else if ("CANVAS".equalsIgnoreCase(tagName)) {
attrs = getCanvasElementStyle(el, attrs);
} else if ("IMG".equalsIgnoreCase(tagName)) {
attrs = getElementDimensionStyle(el, attrs);
}
if (attrs.length() > 0) {
return CSSUtilities.jParseInlineStyle(attrs, null, el, false);
}
}
return null;
}
private static String getCanvasElementStyle(HTMLElementImpl el, String attrs) {
final Node widthNode = el.getAttributes().getNamedItem("width");
if (widthNode != null) {
attrs += "width: " + pixelise(widthNode.getNodeValue()) + ";";
} else {
attrs += "width: 300px;";
}
final Node heightNode = el.getAttributes().getNamedItem("height");
if (heightNode != null) {
attrs += "height: " + pixelise(heightNode.getNodeValue()) + ";";
} else {
attrs += "height: 150px;";
}
return attrs;
}
private static String getElementDimensionStyle(HTMLElementImpl el, String attrs) {
final Node widthNode = el.getAttributes().getNamedItem("width");
if (widthNode != null) {
attrs += "width: " + pixelise(widthNode.getNodeValue()) + ";";
}
final Node heightNode = el.getAttributes().getNamedItem("height");
if (heightNode != null) {
attrs += "height: " + pixelise(heightNode.getNodeValue()) + ";";
}
return attrs;
}
private static String pixelise(final String value) {
try {
@SuppressWarnings("unused")
final int ignored = Integer.parseInt(value);
return value + "px";
} catch (NumberFormatException e) {
return value;
}
}
private static String getTableElementStyle(final Element el, String attrs) {
String border = "0";
String frame = "void";
//borders
if (el.getAttributes().getNamedItem("border") != null) {
border = el.getAttribute("border");
if (!border.equals("0")) {
frame = "border";
}
}
if (el.getAttributes().getNamedItem("frame") != null) {
frame = el.getAttribute("frame").toLowerCase();
}
if (!border.equals("0")) {
final String fstyle = "border-@-style:solid;border-@-width:" + border + "px;";
if (frame.equals("above")) {
attrs = attrs + applyBorders(fstyle, "top");
}
if (frame.equals("below")) {
attrs = attrs + applyBorders(fstyle, "bottom");
}
if (frame.equals("hsides")) {
attrs = attrs + applyBorders(fstyle, "left");
attrs = attrs + applyBorders(fstyle, "right");
}
if (frame.equals("lhs")) {
attrs = attrs + applyBorders(fstyle, "left");
}
if (frame.equals("rhs")) {
attrs = attrs + applyBorders(fstyle, "right");
}
if (frame.equals("vsides")) {
attrs = attrs + applyBorders(fstyle, "top");
attrs = attrs + applyBorders(fstyle, "bottom");
}
if (frame.equals("box")) {
attrs = appAllBorders(attrs, fstyle);
}
if (frame.equals("border")) {
attrs = appAllBorders(attrs, fstyle);
}
}
return attrs;
}
private static String appAllBorders(String attrs, final String fstyle) {
attrs = attrs + applyBorders(fstyle, "left");
attrs = attrs + applyBorders(fstyle, "right");
attrs = attrs + applyBorders(fstyle, "top");
attrs = attrs + applyBorders(fstyle, "bottom");
return attrs;
}
private static String getFontElementStyle(final Element el, String attrs) {
if (el.getAttributes().getNamedItem("color") != null) {
attrs = attrs + "color: " + el.getAttribute("color") + ";";
}
if (el.getAttributes().getNamedItem("face") != null) {
attrs = attrs + "font-family: " + el.getAttribute("face") + ";";
}
if (el.getAttributes().getNamedItem("size") != null) {
final String sz = el.getAttribute("size");
String ret = "normal";
if (sz.equals("1")) {
ret = "xx-small";
} else if (sz.equals("2")) {
ret = "x-small";
} else if (sz.equals("3")) {
ret = "small";
} else if (sz.equals("4")) {
ret = "normal";
} else if (sz.equals("5")) {
ret = "large";
} else if (sz.equals("6")) {
ret = "x-large";
} else if (sz.equals("7")) {
ret = "xx-large";
} else if (sz.startsWith("+")) {
final int sn = Integer.parseInt(sz.substring(1));
if ((sn > 0) && (sn <= 7)) {
ret = (100 + (sn * 20)) + "%";
}
} else if (sz.startsWith("-")) {
final int sn = Integer.parseInt(sz.substring(1));
if ((sn > 0) && (sn <= 7)) {
ret = (100 - (sn * 10)) + "%";
}
}
attrs = attrs + "font-size: " + ret;
}
return attrs;
}
private static String applyBorders(final String template, final String dir) {
return template.replaceAll("@", dir);
}
//======== Normalize the dom =============================
/**
* Provides a cleanup of a HTML DOM tree according to the HTML syntax
* restrictions. Currently, following actions are implemented:
*
* - Table cleanup
*
* - elements that are not acceptable within a table are moved before the table
*
*
*
*
* @param doc
* the processed DOM Document.
*/
public static void normalizeHTMLTree(final Document doc) {
//normalize tables
final NodeList tables = doc.getElementsByTagName("table");
for (int i = 0; i < tables.getLength(); i++) {
final Vector nodes = new Vector<>();
recursiveFindBadNodesInTable(tables.item(i), null, nodes);
for (final Node n : nodes) {
moveSubtreeBefore(n, tables.item(i));
}
}
}
/**
* Finds all the nodes in a table that cannot be contained in the table
* according to the HTML syntax.
*
* @param n
* table root
* @param cellroot
* last cell root
* @param nodes
* resulting list of nodes
*/
private static void recursiveFindBadNodesInTable(final Node n, final Node cellroot, final Vector nodes) {
Node cell = cellroot;
if (n.getNodeType() == Node.ELEMENT_NODE) {
final String tag = n.getNodeName().toLowerCase();
if (tag.equals("table")) {
if (cell != null) { //do not enter nested tables
return;
}
} else if (tag.equals("tbody") || tag.equals("thead") || tag.equals("tfoot")
|| tag.equals("tr") || tag.equals("col") || tag.equals("colgroup")) {
} else if (tag.equals("td") || tag.equals("th") || tag.equals("caption")) {
cell = n;
} else { //other elements
if (cell == null) {
nodes.add(n);
return;
}
}
} else if (n.getNodeType() == Node.TEXT_NODE) { //other nodes
if ((cell == null) && (n.getNodeValue().trim().length() > 0)) {
nodes.add(n);
return;
}
}
final NodeList child = n.getChildNodes();
for (int i = 0; i < child.getLength(); i++) {
recursiveFindBadNodesInTable(child.item(i), cell, nodes);
}
}
private static void moveSubtreeBefore(final Node root, final Node ref) {
root.getParentNode().removeChild(root);
ref.getParentNode().insertBefore(root, ref);
}
}