1 | package fr.sii.ogham.html.inliner.impl.jsoup; | |
2 | ||
3 | import static fr.sii.ogham.core.util.HtmlUtils.CSS_URL_FUNC_PATTERN; | |
4 | import static fr.sii.ogham.core.util.HtmlUtils.relativize; | |
5 | import static fr.sii.ogham.html.inliner.impl.jsoup.CssInlineUtils.isInlineModeAllowed; | |
6 | ||
7 | import java.util.List; | |
8 | import java.util.StringTokenizer; | |
9 | import java.util.regex.Matcher; | |
10 | import java.util.regex.Pattern; | |
11 | ||
12 | import org.jsoup.Jsoup; | |
13 | import org.jsoup.nodes.DataNode; | |
14 | import org.jsoup.nodes.Document; | |
15 | import org.jsoup.nodes.Element; | |
16 | import org.jsoup.parser.Tag; | |
17 | import org.jsoup.select.Elements; | |
18 | import org.slf4j.Logger; | |
19 | import org.slf4j.LoggerFactory; | |
20 | ||
21 | import fr.sii.ogham.html.inliner.CssInliner; | |
22 | import fr.sii.ogham.html.inliner.CssInlinerConstants.InlineModes; | |
23 | import fr.sii.ogham.html.inliner.ExternalCss; | |
24 | ||
25 | public class JsoupCssInliner implements CssInliner { | |
26 | private static final Logger LOG = LoggerFactory.getLogger(JsoupCssInliner.class); | |
27 | | |
28 | private static final String HREF_ATTR = "href"; | |
29 | private static final String TEMP_STYLE_ATTR = "data-cssstyle"; | |
30 | private static final String STYLE_ATTR = "style"; | |
31 | private static final String STYLE_TAG = "style"; | |
32 | private static final String CSS_LINKS_SELECTOR = "link[rel*=\"stylesheet\"], link[type=\"text/css\"], link[href$=\".css\"]"; | |
33 | private static final Pattern NEW_LINES = Pattern.compile("\n"); | |
34 | private static final Pattern COMMENTS = Pattern.compile("/\\*.*?\\*/"); | |
35 | private static final Pattern SPACES = Pattern.compile(" +"); | |
36 | ||
37 | @Override | |
38 | public String inline(String htmlContent, List<ExternalCss> cssContents) { | |
39 | Document doc = Jsoup.parse(htmlContent); | |
40 | ||
41 |
3
1. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::internStyles → NO_COVERAGE 2. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::internStyles → KILLED 3. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::internStyles → KILLED |
internStyles(doc, cssContents); |
42 | String stylesheet = fetchStyles(doc); | |
43 |
3
1. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::extractStyles → NO_COVERAGE 2. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::extractStyles → KILLED 3. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::extractStyles → KILLED |
extractStyles(doc, stylesheet); |
44 |
3
1. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::applyStyles → NO_COVERAGE 2. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::applyStyles → KILLED 3. inline : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::applyStyles → KILLED |
applyStyles(doc); |
45 | ||
46 |
3
1. inline : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::inline → NO_COVERAGE 2. inline : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::inline → KILLED 3. inline : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::inline → KILLED |
return doc.outerHtml(); |
47 | } | |
48 | ||
49 | /** | |
50 | * Applies the styles to a <code>data-cssstyle</code> attribute. This is | |
51 | * because the styles need to be applied sequentially, but before the | |
52 | * <code>style</code> defined for the element inline. | |
53 | * | |
54 | * @param doc | |
55 | * the html document | |
56 | */ | |
57 | private static void extractStyles(Document doc, String stylesheet) { | |
58 | String cleanedStylesheet = ignoreAtRules(stylesheet); | |
59 | cleanedStylesheet = NEW_LINES.matcher(cleanedStylesheet).replaceAll(""); | |
60 | cleanedStylesheet = COMMENTS.matcher(cleanedStylesheet).replaceAll(""); | |
61 | cleanedStylesheet = SPACES.matcher(cleanedStylesheet).replaceAll(" "); | |
62 | String styleRules = cleanedStylesheet.trim(); | |
63 | String delims = "{}"; | |
64 | StringTokenizer st = new StringTokenizer(styleRules, delims); | |
65 |
6
1. extractStyles : changed conditional boundary → SURVIVED 2. extractStyles : changed conditional boundary → SURVIVED 3. extractStyles : changed conditional boundary → NO_COVERAGE 4. extractStyles : negated conditional → NO_COVERAGE 5. extractStyles : negated conditional → KILLED 6. extractStyles : negated conditional → KILLED |
while (st.countTokens() > 1) { |
66 | String selector = st.nextToken(); | |
67 | String properties = st.nextToken(); | |
68 | Elements selectedElements = doc.select(selector.trim()); | |
69 | for (Element selElem : selectedElements) { | |
70 | String oldProperties = selElem.attr(TEMP_STYLE_ATTR); | |
71 |
6
1. extractStyles : changed conditional boundary → NO_COVERAGE 2. extractStyles : negated conditional → NO_COVERAGE 3. extractStyles : changed conditional boundary → KILLED 4. extractStyles : changed conditional boundary → KILLED 5. extractStyles : negated conditional → KILLED 6. extractStyles : negated conditional → KILLED |
selElem.attr(TEMP_STYLE_ATTR, oldProperties.length() > 0 ? concatenateProperties(oldProperties, properties) : properties); |
72 | } | |
73 | } | |
74 | } | |
75 | | |
76 | /** | |
77 | * Replace link tags with style tags in order to keep the same inclusion | |
78 | * order | |
79 | * | |
80 | * @param doc | |
81 | * the html document | |
82 | * @param cssContents | |
83 | * the list of external css files with their content | |
84 | */ | |
85 | private static void internStyles(Document doc, List<ExternalCss> cssContents) { | |
86 | Elements els = doc.select(CSS_LINKS_SELECTOR); | |
87 | for (Element e : els) { | |
88 |
3
1. internStyles : negated conditional → NO_COVERAGE 2. internStyles : negated conditional → KILLED 3. internStyles : negated conditional → KILLED |
if (isInlineModeAllowed(e, InlineModes.STYLE_ATTR)) { |
89 | String path = e.attr(HREF_ATTR); | |
90 | ExternalCss css = getCss(cssContents, path); | |
91 |
3
1. internStyles : negated conditional → NO_COVERAGE 2. internStyles : negated conditional → KILLED 3. internStyles : negated conditional → KILLED |
if (css != null) { |
92 | Element style = new Element(Tag.valueOf(STYLE_TAG), ""); | |
93 | style.appendChild(new DataNode(getCssContent(css))); | |
94 |
3
1. internStyles : removed call to org/jsoup/nodes/Element::replaceWith → NO_COVERAGE 2. internStyles : removed call to org/jsoup/nodes/Element::replaceWith → KILLED 3. internStyles : removed call to org/jsoup/nodes/Element::replaceWith → KILLED |
e.replaceWith(style); |
95 | } | |
96 | } | |
97 | } | |
98 | } | |
99 | ||
100 | private static ExternalCss getCss(List<ExternalCss> cssContents, String path) { | |
101 | for (ExternalCss css : cssContents) { | |
102 |
3
1. getCss : negated conditional → NO_COVERAGE 2. getCss : negated conditional → KILLED 3. getCss : negated conditional → KILLED |
if (css.getPath().getOriginalPath().contains(path)) { |
103 |
3
1. getCss : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::getCss → NO_COVERAGE 2. getCss : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::getCss → KILLED 3. getCss : replaced return value with null for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::getCss → KILLED |
return css; |
104 | } | |
105 | } | |
106 | return null; | |
107 | } | |
108 | ||
109 | /** | |
110 | * Generates a stylesheet from an html document | |
111 | * | |
112 | * @param doc | |
113 | * the html document | |
114 | * @return a string representing the stylesheet. | |
115 | */ | |
116 | private static String fetchStyles(Document doc) { | |
117 | Elements els = doc.select(STYLE_TAG); | |
118 | StringBuilder styles = new StringBuilder(); | |
119 | for (Element e : els) { | |
120 |
3
1. fetchStyles : negated conditional → NO_COVERAGE 2. fetchStyles : negated conditional → KILLED 3. fetchStyles : negated conditional → KILLED |
if (isInlineModeAllowed(e, InlineModes.STYLE_ATTR)) { |
121 | styles.append(e.data()); | |
122 |
3
1. fetchStyles : removed call to org/jsoup/nodes/Element::remove → NO_COVERAGE 2. fetchStyles : removed call to org/jsoup/nodes/Element::remove → KILLED 3. fetchStyles : removed call to org/jsoup/nodes/Element::remove → KILLED |
e.remove(); |
123 | } | |
124 | } | |
125 |
3
1. fetchStyles : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::fetchStyles → NO_COVERAGE 2. fetchStyles : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::fetchStyles → KILLED 3. fetchStyles : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::fetchStyles → KILLED |
return styles.toString(); |
126 | } | |
127 | ||
128 | /** | |
129 | * Transfers styles from the <code>data-cssstyle</code> attribute to the | |
130 | * <code>style</code> attribute. | |
131 | * | |
132 | * @param doc | |
133 | * the html document | |
134 | */ | |
135 | private static void applyStyles(Document doc) { | |
136 | Elements allStyledElements = doc.getElementsByAttribute(TEMP_STYLE_ATTR); | |
137 | ||
138 | for (Element e : allStyledElements) { | |
139 |
3
1. applyStyles : negated conditional → NO_COVERAGE 2. applyStyles : negated conditional → KILLED 3. applyStyles : negated conditional → KILLED |
if (isInlineModeAllowed(e, InlineModes.STYLE_ATTR)) { |
140 | String newStyle = e.attr(TEMP_STYLE_ATTR); | |
141 | String oldStyle = e.attr(STYLE_ATTR); | |
142 | e.attr(STYLE_ATTR, (trimAll(newStyle) + ";" + trimAll(oldStyle)).replaceAll(";+", ";").trim()); | |
143 | } | |
144 | e.removeAttr(TEMP_STYLE_ATTR); | |
145 | } | |
146 | } | |
147 | ||
148 | private static String concatenateProperties(String oldProp, String newProp) { | |
149 | String prop = oldProp; | |
150 |
3
1. concatenateProperties : negated conditional → NO_COVERAGE 2. concatenateProperties : negated conditional → SURVIVED 3. concatenateProperties : negated conditional → SURVIVED |
if (!prop.endsWith(";")) { |
151 | prop += ";"; | |
152 | } | |
153 |
3
1. concatenateProperties : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::concatenateProperties → NO_COVERAGE 2. concatenateProperties : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::concatenateProperties → KILLED 3. concatenateProperties : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::concatenateProperties → KILLED |
return trimAll(prop) + " " + trimAll(newProp) + ";"; |
154 | } | |
155 | | |
156 | private static String trimAll(String str) { | |
157 |
3
1. trimAll : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::trimAll → NO_COVERAGE 2. trimAll : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::trimAll → KILLED 3. trimAll : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::trimAll → KILLED |
return str.replaceAll("\\s+", " ").trim(); |
158 | } | |
159 | | |
160 | ||
161 | private static String ignoreAtRules(String stylesheet) { | |
162 | StringBuilder sb = new StringBuilder(); | |
163 | AtRuleParserContext ctx = new AtRuleParserContext(); | |
164 |
9
1. ignoreAtRules : changed conditional boundary → NO_COVERAGE 2. ignoreAtRules : Changed increment from 1 to -1 → NO_COVERAGE 3. ignoreAtRules : negated conditional → NO_COVERAGE 4. ignoreAtRules : changed conditional boundary → KILLED 5. ignoreAtRules : changed conditional boundary → KILLED 6. ignoreAtRules : Changed increment from 1 to -1 → KILLED 7. ignoreAtRules : Changed increment from 1 to -1 → KILLED 8. ignoreAtRules : negated conditional → KILLED 9. ignoreAtRules : negated conditional → KILLED |
for (int i=0 ; i<stylesheet.length() ; i++) { |
165 | char c = stylesheet.charAt(i); | |
166 |
3
1. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateLineNumberIfNewLine → SURVIVED 2. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateLineNumberIfNewLine → SURVIVED 3. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateLineNumberIfNewLine → NO_COVERAGE |
updateLineNumberIfNewLine(ctx, c); |
167 |
3
1. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsStartOfAtRuleIfAtChar → SURVIVED 2. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsStartOfAtRuleIfAtChar → NO_COVERAGE 3. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsStartOfAtRuleIfAtChar → KILLED |
markAsStartOfAtRuleIfAtChar(ctx, c); |
168 |
3
1. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket → NO_COVERAGE 2. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket → SURVIVED 3. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket → KILLED |
markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket(ctx, c); |
169 |
3
1. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket → NO_COVERAGE 2. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket → SURVIVED 3. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket → KILLED |
markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket(ctx, c); |
170 |
3
1. ignoreAtRules : negated conditional → NO_COVERAGE 2. ignoreAtRules : negated conditional → KILLED 3. ignoreAtRules : negated conditional → KILLED |
if (ignoreAtRuleIfAtEndOfAtRule(ctx, c)) { |
171 | continue; | |
172 | } | |
173 |
3
1. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateStylesAndAtRuleContent → NO_COVERAGE 2. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateStylesAndAtRuleContent → KILLED 3. ignoreAtRules : removed call to fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateStylesAndAtRuleContent → KILLED |
updateStylesAndAtRuleContent(ctx, sb, c); |
174 | } | |
175 |
3
1. ignoreAtRules : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRules → NO_COVERAGE 2. ignoreAtRules : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRules → KILLED 3. ignoreAtRules : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRules → KILLED |
return sb.toString(); |
176 | } | |
177 | ||
178 | private static boolean ignoreAtRuleIfAtEndOfAtRule(AtRuleParserContext ctx, char c) { | |
179 |
7
1. ignoreAtRuleIfAtEndOfAtRule : negated conditional → NO_COVERAGE 2. ignoreAtRuleIfAtEndOfAtRule : negated conditional → NO_COVERAGE 3. ignoreAtRuleIfAtEndOfAtRule : negated conditional → NO_COVERAGE 4. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED 5. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED 6. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED 7. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED |
if (ctx.inAtRule && !ctx.inNestedAtRule && c == ';') { |
180 | ctx.inAtRule = false; | |
181 | LOG.warn("{} rule is not handled by JsoupCssInliner implementation. Line {}:'{}' is skipped", rulename(ctx.rule), ctx.startLineOfCurrentAtRule, ctx.rule); | |
182 |
2
1. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → NO_COVERAGE 2. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → KILLED |
return true; |
183 | } | |
184 |
7
1. ignoreAtRuleIfAtEndOfAtRule : negated conditional → NO_COVERAGE 2. ignoreAtRuleIfAtEndOfAtRule : negated conditional → SURVIVED 3. ignoreAtRuleIfAtEndOfAtRule : negated conditional → NO_COVERAGE 4. ignoreAtRuleIfAtEndOfAtRule : negated conditional → NO_COVERAGE 5. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED 6. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED 7. ignoreAtRuleIfAtEndOfAtRule : negated conditional → KILLED |
if (ctx.inAtRule && ctx.inNestedAtRule && ctx.numberOfOpenedAtRules == 0) { |
185 | ctx.inAtRule = false; | |
186 | ctx.inNestedAtRule = false; | |
187 | LOG.warn("{} rule is not handled by JsoupCssInliner implementation. Lines {}-{} are skipped", rulename(ctx.rule), ctx.startLineOfCurrentAtRule, ctx.line); | |
188 |
2
1. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → SURVIVED 2. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → NO_COVERAGE |
return true; |
189 | } | |
190 |
3
1. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → NO_COVERAGE 2. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → KILLED 3. ignoreAtRuleIfAtEndOfAtRule : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::ignoreAtRuleIfAtEndOfAtRule → KILLED |
return false; |
191 | } | |
192 | ||
193 | private static void updateStylesAndAtRuleContent(AtRuleParserContext ctx, StringBuilder sb, char c) { | |
194 |
3
1. updateStylesAndAtRuleContent : negated conditional → NO_COVERAGE 2. updateStylesAndAtRuleContent : negated conditional → KILLED 3. updateStylesAndAtRuleContent : negated conditional → KILLED |
if (!ctx.inAtRule) { |
195 | sb.append(c); | |
196 | ctx.rule = new StringBuilder(); | |
197 | } else { | |
198 | ctx.rule.append(c); | |
199 | } | |
200 | } | |
201 | ||
202 | private static void markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket(AtRuleParserContext ctx, char c) { | |
203 |
7
1. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → SURVIVED 2. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → NO_COVERAGE 3. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → NO_COVERAGE 4. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → NO_COVERAGE 5. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → KILLED 6. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → KILLED 7. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : negated conditional → KILLED |
if (ctx.inAtRule && ctx.inNestedAtRule && c == '}') { |
204 |
2
1. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : Replaced integer subtraction with addition → NO_COVERAGE 2. markAsEndOfNestedAtRuleIfAlreadyInAtRuleAndIsClosingBracket : Replaced integer subtraction with addition → KILLED |
ctx.numberOfOpenedAtRules--; |
205 | } | |
206 | } | |
207 | ||
208 | private static void markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket(AtRuleParserContext ctx, char c) { | |
209 |
5
1. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : negated conditional → NO_COVERAGE 2. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : negated conditional → SURVIVED 3. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : negated conditional → NO_COVERAGE 4. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : negated conditional → KILLED 5. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : negated conditional → KILLED |
if (ctx.inAtRule && c == '{') { |
210 | ctx.inNestedAtRule = true; | |
211 |
2
1. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : Replaced integer addition with subtraction → NO_COVERAGE 2. markAsStartOfNestedAtRuleIfAlreadyInAtRuleAndIsOpeningBracket : Replaced integer addition with subtraction → KILLED |
ctx.numberOfOpenedAtRules++; |
212 | } | |
213 | } | |
214 | ||
215 | private static void markAsStartOfAtRuleIfAtChar(AtRuleParserContext ctx, char c) { | |
216 |
5
1. markAsStartOfAtRuleIfAtChar : negated conditional → NO_COVERAGE 2. markAsStartOfAtRuleIfAtChar : negated conditional → NO_COVERAGE 3. markAsStartOfAtRuleIfAtChar : negated conditional → KILLED 4. markAsStartOfAtRuleIfAtChar : negated conditional → KILLED 5. markAsStartOfAtRuleIfAtChar : negated conditional → KILLED |
if (c == '@' && !ctx.inAtRule) { |
217 | ctx.inAtRule = true; | |
218 | ctx.startLineOfCurrentAtRule = ctx.line; | |
219 | } | |
220 | } | |
221 | ||
222 | private static void updateLineNumberIfNewLine(AtRuleParserContext ctx, char c) { | |
223 |
3
1. updateLineNumberIfNewLine : negated conditional → SURVIVED 2. updateLineNumberIfNewLine : negated conditional → NO_COVERAGE 3. updateLineNumberIfNewLine : negated conditional → SURVIVED |
if (c == '\n') { |
224 |
3
1. updateLineNumberIfNewLine : Replaced integer addition with subtraction → SURVIVED 2. updateLineNumberIfNewLine : Replaced integer addition with subtraction → NO_COVERAGE 3. updateLineNumberIfNewLine : Replaced integer addition with subtraction → SURVIVED |
ctx.line++; |
225 | } | |
226 | } | |
227 | | |
228 | private static String rulename(StringBuilder rule) { | |
229 | StringBuilder name = new StringBuilder(); | |
230 |
6
1. rulename : changed conditional boundary → SURVIVED 2. rulename : changed conditional boundary → NO_COVERAGE 3. rulename : Changed increment from 1 to -1 → NO_COVERAGE 4. rulename : negated conditional → NO_COVERAGE 5. rulename : negated conditional → SURVIVED 6. rulename : Changed increment from 1 to -1 → KILLED |
for (int i=0 ; i<rule.length() ; i++) { |
231 | char c = rule.charAt(i); | |
232 |
8
1. rulename : negated conditional → SURVIVED 2. rulename : negated conditional → NO_COVERAGE 3. rulename : negated conditional → SURVIVED 4. rulename : negated conditional → NO_COVERAGE 5. rulename : negated conditional → SURVIVED 6. rulename : negated conditional → NO_COVERAGE 7. rulename : negated conditional → SURVIVED 8. rulename : negated conditional → NO_COVERAGE |
if (c != '@' && c != '-' && !Character.isAlphabetic(c) && !Character.isDigit(c)) { |
233 | break; | |
234 | } | |
235 | name.append(c); | |
236 | } | |
237 |
2
1. rulename : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::rulename → SURVIVED 2. rulename : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::rulename → NO_COVERAGE |
return name.toString(); |
238 | } | |
239 | ||
240 | ||
241 | private static String getCssContent(ExternalCss css) { | |
242 | String content = css.getContent(); | |
243 |
3
1. getCssContent : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::getCssContent → NO_COVERAGE 2. getCssContent : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::getCssContent → KILLED 3. getCssContent : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::getCssContent → KILLED |
return updateRelativeUrls(content, css); |
244 | } | |
245 | ||
246 | private static String updateRelativeUrls(String content, ExternalCss css) { | |
247 | StringBuffer sb = new StringBuffer(); | |
248 | Matcher m = CSS_URL_FUNC_PATTERN.matcher(content); | |
249 |
3
1. updateRelativeUrls : negated conditional → NO_COVERAGE 2. updateRelativeUrls : negated conditional → KILLED 3. updateRelativeUrls : negated conditional → KILLED |
while (m.find()) { |
250 | String delim = ""; | |
251 | String url = m.group("unquotedurl"); | |
252 |
3
1. updateRelativeUrls : negated conditional → NO_COVERAGE 2. updateRelativeUrls : negated conditional → KILLED 3. updateRelativeUrls : negated conditional → KILLED |
if (url == null) { |
253 | url = m.group("doublequotedurl"); | |
254 | delim = "\""; | |
255 | } | |
256 |
3
1. updateRelativeUrls : negated conditional → NO_COVERAGE 2. updateRelativeUrls : negated conditional → KILLED 3. updateRelativeUrls : negated conditional → KILLED |
if (url == null) { |
257 | url = m.group("singlequotedurl"); | |
258 | delim = "'"; | |
259 | } | |
260 | m.appendReplacement(sb, Matcher.quoteReplacement(m.group("start")+delim+relativize(css.getPath().getOriginalPath(), url)+delim+m.group("end"))); | |
261 | } | |
262 | m.appendTail(sb); | |
263 |
3
1. updateRelativeUrls : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateRelativeUrls → NO_COVERAGE 2. updateRelativeUrls : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateRelativeUrls → KILLED 3. updateRelativeUrls : replaced return value with "" for fr/sii/ogham/html/inliner/impl/jsoup/JsoupCssInliner::updateRelativeUrls → KILLED |
return sb.toString(); |
264 | } | |
265 | ||
266 | private static class AtRuleParserContext { | |
267 | protected int line; | |
268 | protected int startLineOfCurrentAtRule; | |
269 | protected boolean inAtRule; | |
270 | protected boolean inNestedAtRule; | |
271 | protected int numberOfOpenedAtRules; | |
272 | protected StringBuilder rule; | |
273 | | |
274 | public AtRuleParserContext() { | |
275 | super(); | |
276 | this.line = 1; | |
277 | this.startLineOfCurrentAtRule = 0; | |
278 | this.inAtRule = false; | |
279 | this.inNestedAtRule = false; | |
280 | this.numberOfOpenedAtRules = 0; | |
281 | this.rule = new StringBuilder(); | |
282 | } | |
283 | | |
284 | | |
285 | } | |
286 | } | |
Mutations | ||
41 |
1.1 2.2 3.3 |
|
43 |
1.1 2.2 3.3 |
|
44 |
1.1 2.2 3.3 |
|
46 |
1.1 2.2 3.3 |
|
65 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
71 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
88 |
1.1 2.2 3.3 |
|
91 |
1.1 2.2 3.3 |
|
94 |
1.1 2.2 3.3 |
|
102 |
1.1 2.2 3.3 |
|
103 |
1.1 2.2 3.3 |
|
120 |
1.1 2.2 3.3 |
|
122 |
1.1 2.2 3.3 |
|
125 |
1.1 2.2 3.3 |
|
139 |
1.1 2.2 3.3 |
|
150 |
1.1 2.2 3.3 |
|
153 |
1.1 2.2 3.3 |
|
157 |
1.1 2.2 3.3 |
|
164 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 |
|
166 |
1.1 2.2 3.3 |
|
167 |
1.1 2.2 3.3 |
|
168 |
1.1 2.2 3.3 |
|
169 |
1.1 2.2 3.3 |
|
170 |
1.1 2.2 3.3 |
|
173 |
1.1 2.2 3.3 |
|
175 |
1.1 2.2 3.3 |
|
179 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
182 |
1.1 2.2 |
|
184 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
188 |
1.1 2.2 |
|
190 |
1.1 2.2 3.3 |
|
194 |
1.1 2.2 3.3 |
|
203 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
204 |
1.1 2.2 |
|
209 |
1.1 2.2 3.3 4.4 5.5 |
|
211 |
1.1 2.2 |
|
216 |
1.1 2.2 3.3 4.4 5.5 |
|
223 |
1.1 2.2 3.3 |
|
224 |
1.1 2.2 3.3 |
|
230 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
232 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
237 |
1.1 2.2 |
|
243 |
1.1 2.2 3.3 |
|
249 |
1.1 2.2 3.3 |
|
252 |
1.1 2.2 3.3 |
|
256 |
1.1 2.2 3.3 |
|
263 |
1.1 2.2 3.3 |