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