18 package org.turro.mail.impl;
20 import com.steadystate.css.parser.CSSOMParser;
22 import java.io.FilenameFilter;
23 import java.io.IOException;
24 import java.io.StringReader;
25 import java.util.HashMap;
26 import java.util.LinkedHashMap;
28 import java.util.StringTokenizer;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31 import org.turro.string.Strings;
32 import org.jsoup.Jsoup;
33 import org.jsoup.nodes.Document;
34 import org.jsoup.nodes.Element;
35 import org.jsoup.select.Elements;
36 import org.turro.elephant.context.ElephantContext;
37 import org.turro.elephant.impl.util.FileUtil;
38 import org.turro.html.HTMLEntities;
39 import org.w3c.css.sac.InputSource;
40 import org.w3c.dom.css.CSSRule;
41 import org.w3c.dom.css.CSSRuleList;
42 import org.w3c.dom.css.CSSStyleDeclaration;
43 import org.w3c.dom.css.CSSStyleRule;
44 import org.w3c.dom.css.CSSStyleSheet;
54 public static final String
MAIL_CSS =
"/WEB-INF/elephant/templates-mail/css";
56 public String
inline(String html) {
57 if(Strings.isBlank(html)) {
66 if (rootCSS.exists()) {
67 for (File css : rootCSS.listFiles(
new FilenameFilter() {
69 public boolean accept(File dir, String name) {
70 return name.endsWith(
".css");
74 html = inlineCSS(css, html);
75 }
catch (IOException ex) {
83 private String inlineCSS(File css, String html)
throws IOException {
84 CSSOMParser parser =
new CSSOMParser();
85 CSSStyleSheet stylesheet = parser.parseStyleSheet(
new InputSource(
new StringReader(
FileUtil.
getContent(css))),
null,
null);
87 final Document doc = Jsoup.parse(html);
88 final CSSRuleList rules = stylesheet.getCssRules();
89 final Map<Element, Map<String, String>> elementStyles =
new HashMap<>();
91 for (
int i = 0; i < rules.getLength(); i++) {
92 final CSSRule rule = rules.item(i);
93 if (rule instanceof CSSStyleRule) {
94 final CSSStyleRule styleRule = (CSSStyleRule) rule;
95 final String selector = styleRule.getSelectorText();
97 if (!selector.contains(
":")) {
98 final Elements selectedElements = doc.select(selector);
99 for (
final Element selected : selectedElements) {
100 if (!elementStyles.containsKey(selected)) {
101 elementStyles.put(selected,
new LinkedHashMap<String, String>());
104 final CSSStyleDeclaration styleDeclaration = styleRule.getStyle();
106 for (
int j = 0; j < styleDeclaration.getLength(); j++) {
107 final String propertyName = styleDeclaration.item(j);
108 final String propertyValue = styleDeclaration.getPropertyValue(propertyName);
109 final Map<String, String> elementStyle = elementStyles.get(selected);
110 elementStyle.put(propertyName, convert(propertyValue));
118 for (
final Map.Entry<Element, Map<String, String>> elementEntry : elementStyles.entrySet()) {
119 final Element element = elementEntry.getKey();
120 final StringBuilder builder =
new StringBuilder();
121 for (
final Map.Entry<String, String> styleEntry : elementEntry.getValue().entrySet()) {
122 builder.append(styleEntry.getKey()).append(
":").append(styleEntry.getValue()).append(
";");
124 builder.append(element.attr(
"style"));
125 element.attr(
"style", builder.toString());
133 final Document doc = Jsoup.parse(html);
134 String style =
"style";
135 Elements els = doc.select(style);
136 for (Element e : els) {
137 String styleRules = e.getAllElements().get(0).data().replaceAll(
"\n",
"").trim(), delims
139 StringTokenizer st =
new StringTokenizer(styleRules, delims);
140 while (st.countTokens() > 1) {
141 String selector = st.nextToken(), properties = st.nextToken();
142 if (selector.indexOf(
":") > 0) {
143 selector = selector.substring(0, selector.indexOf(
":"));
145 if (Strings.isBlank(selector)) {
148 Elements selectedElements = doc.select(selector);
149 for (Element selElem : selectedElements) {
150 String oldProperties = selElem.attr(style);
153 oldProperties.length() > 0 ? concatenateProperties(oldProperties,
154 properties) : properties);
163 private static String concatenateProperties(String oldProp, String newProp) {
164 oldProp = oldProp.trim();
165 if (!newProp.endsWith(
";")) {
168 return newProp + oldProp;
171 private String convert(String propertyValue) {
172 if(propertyValue.startsWith(
"rgb")) {
173 String colors[] = propertyValue.substring(4, propertyValue.length() - 1).split(
"\\s*,\\s*");
174 propertyValue = String.format(
"#%02x%02x%02x",
175 Integer.parseInt(colors[0]), Integer.parseInt(colors[1]), Integer.parseInt(colors[2]));
177 return propertyValue;
static String getRealPath(String path)
static String logMsg(String msg)
static String getContent(File file)
static String escape(String html)