Don't have to worry about linked style or hover style.
I want to automatically convert files like this
<html> <body> <style> body{background:#FFC} p{background:red} body, p{font-weight:bold} </style> <p>...</p> </body> </html>
to files like this
<html> <body style="background:red;font-weight:bold"> <p style="background:#FFC;font-weight:bold">...</p> </body> </html>
I would be even more interested if there was an HTML parser that would do this.
The reason I want to do this is so I can display emails that use global style sheets without their style sheets messing up the rest of my web page. I also would like to send the resulting style to web based rich text editor for reply and original message.
Inlining is the process of prepping an HTML email for delivery to email clients. Some email clients strip out your email's styles unless they are written inline with style tags. Here's what the inliner does: Inlining CSS: All of your CSS is embedded directly into the HTML as style attributes on each tag.
The main difference between inline CSS and external CSS is that inline CSS is processed faster as it only requires the browser to download 1 file while using external CSS will require downloading HTML and CSS files separately.
An inline CSS will load faster if the CSS content size downloads faster than your server would respond to an external CSS file request (considering DNS time, server latency, etc).
Inline styles added to an element (e.g., style="font-weight: bold;" ) always overwrite any normal styles in author stylesheets, and therefore, can be thought of as having the highest specificity.
Here is a solution on java, I made it with the JSoup Library: http://jsoup.org/download
import java.io.IOException; import java.util.StringTokenizer; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class AutomaticCssInliner { /** * Hecho por Grekz, http://grekz.wordpress.com */ public static void main(String[] args) throws IOException { final String style = "style"; final String html = "<html>" + "<body> <style>" + "body{background:#FFC} \n p{background:red}" + "body, p{font-weight:bold} </style>" + "<p>...</p> </body> </html>"; // Document doc = Jsoup.connect("http://mypage.com/inlineme.php").get(); Document doc = Jsoup.parse(html); Elements els = doc.select(style);// to get all the style elements for (Element e : els) { String styleRules = e.getAllElements().get(0).data().replaceAll( "\n", "").trim(), delims = "{}"; StringTokenizer st = new StringTokenizer(styleRules, delims); while (st.countTokens() > 1) { String selector = st.nextToken(), properties = st.nextToken(); Elements selectedElements = doc.select(selector); for (Element selElem : selectedElements) { String oldProperties = selElem.attr(style); selElem.attr(style, oldProperties.length() > 0 ? concatenateProperties( oldProperties, properties) : properties); } } e.remove(); } System.out.println(doc);// now we have the result html without the // styles tags, and the inline css in each // element } private static String concatenateProperties(String oldProp, String newProp) { oldProp = oldProp.trim(); if (!newProp.endsWith(";")) newProp += ";"; return newProp + oldProp; // The existing (old) properties should take precedence. } }
Using jsoup + cssparser:
private static final String STYLE_ATTR = "style"; private static final String CLASS_ATTR = "class"; public String inlineStyles(String html, File cssFile, boolean removeClasses) throws IOException { Document document = Jsoup.parse(html); CSSOMParser parser = new CSSOMParser(new SACParserCSS3()); InputSource source = new InputSource(new FileReader(cssFile)); CSSStyleSheet stylesheet = parser.parseStyleSheet(source, null, null); CSSRuleList ruleList = stylesheet.getCssRules(); Map<Element, Map<String, String>> allElementsStyles = new HashMap<>(); for (int ruleIndex = 0; ruleIndex < ruleList.getLength(); ruleIndex++) { CSSRule item = ruleList.item(ruleIndex); if (item instanceof CSSStyleRule) { CSSStyleRule styleRule = (CSSStyleRule) item; String cssSelector = styleRule.getSelectorText(); Elements elements = document.select(cssSelector); for (Element element : elements) { Map<String, String> elementStyles = allElementsStyles.computeIfAbsent(element, k -> new LinkedHashMap<>()); CSSStyleDeclaration style = styleRule.getStyle(); for (int propertyIndex = 0; propertyIndex < style.getLength(); propertyIndex++) { String propertyName = style.item(propertyIndex); String propertyValue = style.getPropertyValue(propertyName); elementStyles.put(propertyName, propertyValue); } } } } for (Map.Entry<Element, Map<String, String>> elementEntry : allElementsStyles.entrySet()) { Element element = elementEntry.getKey(); StringBuilder builder = new StringBuilder(); for (Map.Entry<String, String> styleEntry : elementEntry.getValue().entrySet()) { builder.append(styleEntry.getKey()).append(":").append(styleEntry.getValue()).append(";"); } builder.append(element.attr(STYLE_ATTR)); element.attr(STYLE_ATTR, builder.toString()); if (removeClasses) { element.removeAttr(CLASS_ATTR); } } return document.html(); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With