| 1 | package fr.sii.ogham.html.inliner.impl.regexp; | |
| 2 | ||
| 3 | import static fr.sii.ogham.core.util.HtmlUtils.CSS_IMAGE_PROPERTIES_PATTERN; | |
| 4 | import static fr.sii.ogham.core.util.HtmlUtils.getCssUrlFunctions; | |
| 5 | import static fr.sii.ogham.html.inliner.impl.regexp.CssImageInlinerConstants.INLINED_URL_FUNC; | |
| 6 | import static fr.sii.ogham.html.inliner.impl.regexp.CssImageInlinerConstants.INLINE_MODE_PROPERTY; | |
| 7 | ||
| 8 | import java.util.List; | |
| 9 | import java.util.function.Function; | |
| 10 | import java.util.regex.Matcher; | |
| 11 | import java.util.regex.Pattern; | |
| 12 | ||
| 13 | import org.slf4j.Logger; | |
| 14 | import org.slf4j.LoggerFactory; | |
| 15 | ||
| 16 | import fr.sii.ogham.core.util.CssUrlFunction; | |
| 17 | import fr.sii.ogham.html.inliner.ImageResource; | |
| 18 | import fr.sii.ogham.html.inliner.impl.regexp.CssImageInlinerConstants.InlineMode; | |
| 19 | ||
| 20 | /** | |
| 21 |  * Helper class that factorizes code for classes that are using inliners. | |
| 22 |  *  | |
| 23 |  * @author Aurélien Baudet | |
| 24 |  * | |
| 25 |  */ | |
| 26 | public final class CssImageInlineUtils { | |
| 27 | 	private static final Logger LOG = LoggerFactory.getLogger(CssImageInlineUtils.class); | |
| 28 | ||
| 29 | 	private static final String QUOTE_ENTITY = """; | |
| 30 | 	private static final String QUOTE_TEMP_ESCAPE = ""__semicolon__"; | |
| 31 | 	private static final Pattern ESCAPE_QUOTE_ENTITIES = Pattern.compile(Pattern.quote(QUOTE_ENTITY), Pattern.CASE_INSENSITIVE); | |
| 32 | 	private static final Pattern UNESCAPE_QUOTE_ENTITIES = Pattern.compile(Pattern.quote(QUOTE_TEMP_ESCAPE), Pattern.CASE_INSENSITIVE); | |
| 33 | 	private static final Pattern RULE_START = Pattern.compile("(?<rulestart>[{])|(?<style>(?<quote>['\"])\\s*=\\s*elyts)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); | |
| 34 | 	private static final Pattern INLINE_PROPERTY_PATTERN = Pattern.compile("(?<property>(?<propertyname>" + Pattern.quote(INLINE_MODE_PROPERTY) + ")\\s*:)(?<value>[^;}>]+)\\s*;?", | |
| 35 | 			Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); | |
| 36 | 	private static final Pattern INLINE_PROPERTY_MODE_PATTERN = Pattern.compile("\\s*((?<imageurl>[^=]+)=(?<specificmode>[^=\"';\\s]+))|(?<globalmode>[^=;\"'\\s]+)"); | |
| 37 | 	private static final Pattern INLINED_URL_PATTERN = Pattern.compile(Pattern.quote(INLINED_URL_FUNC)); | |
| 38 | ||
| 39 | 	/** | |
| 40 | 	 * Search for all images included by CSS properties using {@code url()} | |
| 41 | 	 * (either defined in CSS rules or style attributes). | |
| 42 | 	 *  | |
| 43 | 	 * <p> | |
| 44 | 	 * For each matched URL, it delegates the replacement value to | |
| 45 | 	 * {@code inlineHandler} parameter. The HTML content is updated with the new | |
| 46 | 	 * URL if the image points to a local image and the handler corresponds to | |
| 47 | 	 * the inline mode. | |
| 48 | 	 *  | |
| 49 | 	 * <p> | |
| 50 | 	 * The inline mode can be specified globally (default mode if none is | |
| 51 | 	 * specified), per CSS rule or per image using | |
| 52 | 	 * {@link CssImageInlinerConstants#INLINE_MODE_PROPERTY}. | |
| 53 | 	 *  | |
| 54 | 	 *  | |
| 55 | 	 * @param htmlContent | |
| 56 | 	 *            the HTML content that may include CSS properties that points | |
| 57 | 	 *            to images that need to be inlined | |
| 58 | 	 * @param images | |
| 59 | 	 *            the images to inline | |
| 60 | 	 * @param mode | |
| 61 | 	 *            the inline mode | |
| 62 | 	 * @param inlineHandler | |
| 63 | 	 *            the handler that provides the URL replacement | |
| 64 | 	 * @return the updated HTML | |
| 65 | 	 */ | |
| 66 | 	public static String inline(String htmlContent, List<ImageResource> images, InlineMode mode, Function<CssImageDeclaration, String> inlineHandler) { | |
| 67 | 		StringBuffer sb = new StringBuffer(); | |
| 68 | 		String escapedHtml = escapeQuoteEntities(htmlContent); | |
| 69 | 		Matcher propertyDeclarationMatcher = CSS_IMAGE_PROPERTIES_PATTERN.matcher(escapedHtml); | |
| 70 | 
3
1. inline : negated conditional → NO_COVERAGE 2. inline : negated conditional → KILLED 3. inline : negated conditional → KILLED  | 
		while (propertyDeclarationMatcher.find()) { | 
| 71 | 			String value = propertyDeclarationMatcher.group("value"); | |
| 72 | 			String newValue = value; | |
| 73 | 			List<CssUrlFunction> matches = getCssUrlFunctions(value, QUOTE_ENTITY, QUOTE_TEMP_ESCAPE); | |
| 74 | 			for (CssUrlFunction match : matches) { | |
| 75 | 				boolean inlined = true; | |
| 76 | 				String newUrl = getInlinedUrl(escapedHtml, propertyDeclarationMatcher, match, images, mode, inlineHandler); | |
| 77 | 				// if no new url => use old one | |
| 78 | 
3
1. inline : negated conditional → NO_COVERAGE 2. inline : negated conditional → KILLED 3. inline : negated conditional → KILLED  | 
				if (newUrl == null) { | 
| 79 | 					newUrl = match.getUrl(); | |
| 80 | 					inlined = false; | |
| 81 | 				} | |
| 82 | 				newValue = newValue.replace(match.getSource(), markAsInlined(inlined, match.rewriteUrl(newUrl))); | |
| 83 | 			} | |
| 84 | 			propertyDeclarationMatcher.appendReplacement(sb, Matcher.quoteReplacement(propertyDeclarationMatcher.group("property") + newValue)); | |
| 85 | 		} | |
| 86 | 		propertyDeclarationMatcher.appendTail(sb); | |
| 87 | 
3
1. inline : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::inline → NO_COVERAGE 2. inline : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::inline → KILLED 3. inline : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::inline → KILLED  | 
		return unescapeQuoteEntities(sb.toString()); | 
| 88 | 	} | |
| 89 | ||
| 90 | 	/** | |
| 91 | 	 * Checks if inlining mode is allowed on the provided element. | |
| 92 | 	 *  | |
| 93 | 	 * @param img | |
| 94 | 	 *            the image element to check if the actual inlining mode is | |
| 95 | 	 *            allowed | |
| 96 | 	 * @param mode | |
| 97 | 	 *            the actual mode | |
| 98 | 	 * @return true if this mode is allowed, false otherwise | |
| 99 | 	 */ | |
| 100 | 	@SuppressWarnings("squid:S1126") | |
| 101 | 	private static boolean isInlineModeAllowed(CssImageDeclaration img, InlineMode mode) { | |
| 102 | 		// if already inlined, the regexp won't match so don't need to | |
| 103 | 		// check if skipped here | |
| 104 | ||
| 105 | 		// if inline mode defined but not the wanted mode => reject | |
| 106 | 
6
1. isInlineModeAllowed : negated conditional → NO_COVERAGE 2. isInlineModeAllowed : negated conditional → NO_COVERAGE 3. isInlineModeAllowed : negated conditional → KILLED 4. isInlineModeAllowed : negated conditional → KILLED 5. isInlineModeAllowed : negated conditional → KILLED 6. isInlineModeAllowed : negated conditional → KILLED  | 
		if (img.getMode() != null && !mode.is(img.getMode())) { | 
| 107 | 
3
1. isInlineModeAllowed : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeAllowed → NO_COVERAGE 2. isInlineModeAllowed : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeAllowed → KILLED 3. isInlineModeAllowed : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeAllowed → KILLED  | 
			return false; | 
| 108 | 		} | |
| 109 | 		// if inline mode defined and matches the wanted mode => allow | |
| 110 | 		// if no inline mode defined => allow (any mode allowed) | |
| 111 | 
3
1. isInlineModeAllowed : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeAllowed → NO_COVERAGE 2. isInlineModeAllowed : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeAllowed → KILLED 3. isInlineModeAllowed : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeAllowed → KILLED  | 
		return true; | 
| 112 | 	} | |
| 113 | ||
| 114 | 	/** | |
| 115 | 	 * Remove properties that are used only by Ogham: | |
| 116 | 	 * <ul> | |
| 117 | 	 * <li>{@link CssImageInlinerConstants#INLINE_MODE_PROPERTY}</li> | |
| 118 | 	 * <li>{@link CssImageInlinerConstants#INLINED_URL_FUNC}</li> | |
| 119 | 	 * </ul> | |
| 120 | 	 *  | |
| 121 | 	 * @param html | |
| 122 | 	 *            the html to clean | |
| 123 | 	 * @return the cleaned html | |
| 124 | 	 */ | |
| 125 | 	public static String removeOghamProperties(String html) { | |
| 126 | 		String cleaned = html; | |
| 127 | 		cleaned = INLINED_URL_PATTERN.matcher(cleaned).replaceAll("url"); | |
| 128 | 		cleaned = INLINE_PROPERTY_PATTERN.matcher(cleaned).replaceAll(""); | |
| 129 | 
3
1. removeOghamProperties : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::removeOghamProperties → NO_COVERAGE 2. removeOghamProperties : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::removeOghamProperties → KILLED 3. removeOghamProperties : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::removeOghamProperties → KILLED  | 
		return cleaned; | 
| 130 | 	} | |
| 131 | ||
| 132 | 	private static String getInlinedUrl(String htmlContent, Matcher propertyDeclarationMatcher, CssUrlFunction matchedUrl, List<ImageResource> images, InlineMode mode, | |
| 133 | 			Function<CssImageDeclaration, String> inlineHandler) { | |
| 134 | 		String url = matchedUrl.getUrl(); | |
| 135 | 		ImageResource image = getImage(url, images); | |
| 136 | 		// url may match external url => simply skip it | |
| 137 | 
3
1. getInlinedUrl : negated conditional → NO_COVERAGE 2. getInlinedUrl : negated conditional → KILLED 3. getInlinedUrl : negated conditional → KILLED  | 
		if (image == null) { | 
| 138 | 			LOG.debug("Skipping {}", url); | |
| 139 | 
3
1. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → NO_COVERAGE 2. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → KILLED 3. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → KILLED  | 
			return null; | 
| 140 | 		} | |
| 141 | 		String enclosingCssRule = getEnclosingCssRule(htmlContent, propertyDeclarationMatcher); | |
| 142 | 		CssImageDeclaration imageDeclaration = new CssImageDeclaration(new MatchedUrl(matchedUrl.getUrl(), matchedUrl.getEnclosingQuoteChar()), getInlineProperty(enclosingCssRule, matchedUrl), image); | |
| 143 | 
3
1. getInlinedUrl : negated conditional → NO_COVERAGE 2. getInlinedUrl : negated conditional → KILLED 3. getInlinedUrl : negated conditional → KILLED  | 
		if (!isInlineModeAllowed(imageDeclaration, mode)) { | 
| 144 | 
3
1. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → NO_COVERAGE 2. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → KILLED 3. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → KILLED  | 
			return null; | 
| 145 | 		} | |
| 146 | 
3
1. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → NO_COVERAGE 2. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → KILLED 3. getInlinedUrl : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlinedUrl → KILLED  | 
		return inlineHandler.apply(imageDeclaration); | 
| 147 | 	} | |
| 148 | ||
| 149 | 	private static ImageResource getImage(String url, List<ImageResource> images) { | |
| 150 | 		// @formatter:off | |
| 151 | 
3
1. getImage : replaced return value with null for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getImage → NO_COVERAGE 2. getImage : replaced return value with null for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getImage → KILLED 3. getImage : replaced return value with null for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getImage → KILLED  | 
		return images.stream() | 
| 152 | 
6
1. lambda$getImage$0 : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::lambda$getImage$0 → NO_COVERAGE 2. lambda$getImage$0 : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::lambda$getImage$0 → NO_COVERAGE 3. lambda$getImage$0 : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::lambda$getImage$0 → KILLED 4. lambda$getImage$0 : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::lambda$getImage$0 → KILLED 5. lambda$getImage$0 : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::lambda$getImage$0 → KILLED 6. lambda$getImage$0 : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::lambda$getImage$0 → KILLED  | 
				.filter(i -> url.equals(i.getSrcUrl())) | 
| 153 | 				.findFirst() | |
| 154 | 				.orElse(null); | |
| 155 | 		// @formatter:on | |
| 156 | 	} | |
| 157 | ||
| 158 | 	private static String unescapeQuoteEntities(String str) { | |
| 159 | 
3
1. unescapeQuoteEntities : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::unescapeQuoteEntities → NO_COVERAGE 2. unescapeQuoteEntities : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::unescapeQuoteEntities → KILLED 3. unescapeQuoteEntities : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::unescapeQuoteEntities → KILLED  | 
		return UNESCAPE_QUOTE_ENTITIES.matcher(str).replaceAll(QUOTE_ENTITY); | 
| 160 | 	} | |
| 161 | ||
| 162 | 	private static String escapeQuoteEntities(String htmlContent) { | |
| 163 | 
3
1. escapeQuoteEntities : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::escapeQuoteEntities → NO_COVERAGE 2. escapeQuoteEntities : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::escapeQuoteEntities → KILLED 3. escapeQuoteEntities : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::escapeQuoteEntities → KILLED  | 
		return ESCAPE_QUOTE_ENTITIES.matcher(htmlContent).replaceAll(QUOTE_TEMP_ESCAPE); | 
| 164 | 	} | |
| 165 | ||
| 166 | 	private static String getEnclosingCssRule(String htmlContent, Matcher propertyDeclarationMatcher) { | |
| 167 | 		String untilPropertyDeclaration = htmlContent.substring(0, propertyDeclarationMatcher.start()); | |
| 168 | 		Matcher m = RULE_START.matcher(new StringBuilder(untilPropertyDeclaration).reverse()); | |
| 169 | 		int ruleStart = -1; | |
| 170 | 		char endChar = '}'; | |
| 171 | 
3
1. getEnclosingCssRule : negated conditional → NO_COVERAGE 2. getEnclosingCssRule : negated conditional → KILLED 3. getEnclosingCssRule : negated conditional → KILLED  | 
		if (m.find()) { | 
| 172 | 
2
1. getEnclosingCssRule : Replaced integer subtraction with addition → SURVIVED 2. getEnclosingCssRule : Replaced integer subtraction with addition → NO_COVERAGE  | 
			ruleStart = untilPropertyDeclaration.length() - m.start(); | 
| 173 | 
3
1. getEnclosingCssRule : negated conditional → NO_COVERAGE 2. getEnclosingCssRule : negated conditional → KILLED 3. getEnclosingCssRule : negated conditional → KILLED  | 
			if (m.group("style") != null) { | 
| 174 | 				endChar = m.group("quote").charAt(0); | |
| 175 | 			} | |
| 176 | 		} | |
| 177 | 
3
1. getEnclosingCssRule : negated conditional → NO_COVERAGE 2. getEnclosingCssRule : negated conditional → KILLED 3. getEnclosingCssRule : negated conditional → KILLED  | 
		if (ruleStart == -1) { | 
| 178 | 			// @formatter:off | |
| 179 | 			throw new IllegalStateException("Inlining of CSS images (through either background, list-style, cursor, ...) " | |
| 180 | 			 		+ "can't be performed safely because we can't determine the beginning of the enclosing CSS rule declaration.\n" | |
| 181 | 			 		+ "\n" | |
| 182 | 			 		+ "[            CSS property]="+propertyDeclarationMatcher.group()+"\n" | |
| 183 | 			 		+ "[text before CSS property]="+untilPropertyDeclaration+"\n\n" | |
| 184 | 			 		+ "can't find either { character that declares the beginning of a CSS rule " | |
| 185 | 			 		+ "or style= that declares the beginning of CSS styles on an HTML tag"); | |
| 186 | 			// @formatter:on | |
| 187 | 		} | |
| 188 | 		int ruleEnd = htmlContent.indexOf(endChar, propertyDeclarationMatcher.start()); | |
| 189 | 
3
1. getEnclosingCssRule : negated conditional → NO_COVERAGE 2. getEnclosingCssRule : negated conditional → KILLED 3. getEnclosingCssRule : negated conditional → KILLED  | 
		if (ruleEnd == -1) { | 
| 190 | 			// @formatter:off | |
| 191 | 			throw new IllegalStateException("Inlining of CSS images (through either background, list-style, cursor, ...) " | |
| 192 | 			 		+ "can't be performed safely because we can't determine the end of the enclosing CSS rule declaration.\n" | |
| 193 | 			 		+ "\n" | |
| 194 | 			 		+ "[           CSS property]="+propertyDeclarationMatcher.group()+"\n" | |
| 195 | 			 		+ "[text after CSS property]="+htmlContent.substring(propertyDeclarationMatcher.end())+"\n\n" | |
| 196 | 			 		+ "can't find either } character that declares the end of a CSS rule " | |
| 197 | 			 		+ "or "+endChar+" that declares the end of CSS styles on an HTML tag"); | |
| 198 | 			// @formatter:on | |
| 199 | 		} | |
| 200 | 
3
1. getEnclosingCssRule : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getEnclosingCssRule → NO_COVERAGE 2. getEnclosingCssRule : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getEnclosingCssRule → KILLED 3. getEnclosingCssRule : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getEnclosingCssRule → KILLED  | 
		return htmlContent.substring(ruleStart, ruleEnd); | 
| 201 | 	} | |
| 202 | ||
| 203 | 	private static String getInlineProperty(String enclosingCssRule, CssUrlFunction matchedUrl) { | |
| 204 | 		Matcher m = INLINE_PROPERTY_PATTERN.matcher(enclosingCssRule); | |
| 205 | 
3
1. getInlineProperty : negated conditional → NO_COVERAGE 2. getInlineProperty : negated conditional → KILLED 3. getInlineProperty : negated conditional → KILLED  | 
		if (m.find()) { | 
| 206 | 			String modes = m.group("value"); | |
| 207 | 			Matcher imageModeMatcher = INLINE_PROPERTY_MODE_PATTERN.matcher(modes); | |
| 208 | 			String globalMode = null; | |
| 209 | 
3
1. getInlineProperty : negated conditional → NO_COVERAGE 2. getInlineProperty : negated conditional → KILLED 3. getInlineProperty : negated conditional → KILLED  | 
			while (imageModeMatcher.find()) { | 
| 210 | 				String specificInlineModeUrl = imageModeMatcher.group("imageurl"); | |
| 211 | 				// specific inline mode | |
| 212 | 
3
1. getInlineProperty : negated conditional → NO_COVERAGE 2. getInlineProperty : negated conditional → KILLED 3. getInlineProperty : negated conditional → KILLED  | 
				if (isInlineModeForImage(specificInlineModeUrl, matchedUrl)) { | 
| 213 | 
2
1. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → NO_COVERAGE 2. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → KILLED  | 
					return imageModeMatcher.group("specificmode"); | 
| 214 | 				} | |
| 215 | 				// if global mode defined | |
| 216 | 				String global = imageModeMatcher.group("globalmode"); | |
| 217 | 
6
1. getInlineProperty : negated conditional → NO_COVERAGE 2. getInlineProperty : negated conditional → NO_COVERAGE 3. getInlineProperty : negated conditional → KILLED 4. getInlineProperty : negated conditional → KILLED 5. getInlineProperty : negated conditional → KILLED 6. getInlineProperty : negated conditional → KILLED  | 
				if (global != null && globalMode == null) { | 
| 218 | 					globalMode = global; | |
| 219 | 				} | |
| 220 | 			} | |
| 221 | 			// @formatter:off | |
| 222 | 			// return either: | |
| 223 | 			//  - globalMode => global mode for all images included in the CSS rule | |
| 224 | 			//  - null => use default mode | |
| 225 | 			// @formatter:on | |
| 226 | 
3
1. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → NO_COVERAGE 2. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → KILLED 3. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → KILLED  | 
			return globalMode; | 
| 227 | 		} | |
| 228 | 
3
1. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → NO_COVERAGE 2. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → KILLED 3. getInlineProperty : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::getInlineProperty → KILLED  | 
		return null; | 
| 229 | 	} | |
| 230 | ||
| 231 | 	private static boolean isInlineModeForImage(String inlineUrl, CssUrlFunction matchedUrl) { | |
| 232 | 
3
1. isInlineModeForImage : negated conditional → NO_COVERAGE 2. isInlineModeForImage : negated conditional → KILLED 3. isInlineModeForImage : negated conditional → KILLED  | 
		if (inlineUrl == null) { | 
| 233 | 
3
1. isInlineModeForImage : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → NO_COVERAGE 2. isInlineModeForImage : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → KILLED 3. isInlineModeForImage : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → KILLED  | 
			return false; | 
| 234 | 		} | |
| 235 | 
4
1. isInlineModeForImage : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → NO_COVERAGE 2. isInlineModeForImage : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → NO_COVERAGE 3. isInlineModeForImage : replaced boolean return with false for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → KILLED 4. isInlineModeForImage : replaced boolean return with true for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::isInlineModeForImage → KILLED  | 
		return matchedUrl.getUrl().contains(inlineUrl); | 
| 236 | 	} | |
| 237 | ||
| 238 | 	private static String markAsInlined(boolean inlined, String value) { | |
| 239 | 
3
1. markAsInlined : negated conditional → NO_COVERAGE 2. markAsInlined : negated conditional → SURVIVED 3. markAsInlined : negated conditional → KILLED  | 
		if (inlined) { | 
| 240 | 
3
1. markAsInlined : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::markAsInlined → NO_COVERAGE 2. markAsInlined : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::markAsInlined → KILLED 3. markAsInlined : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::markAsInlined → KILLED  | 
			return value.replace("url", INLINED_URL_FUNC); | 
| 241 | 		} | |
| 242 | 
3
1. markAsInlined : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::markAsInlined → NO_COVERAGE 2. markAsInlined : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::markAsInlined → KILLED 3. markAsInlined : replaced return value with "" for fr/sii/ogham/html/inliner/impl/regexp/CssImageInlineUtils::markAsInlined → KILLED  | 
		return value; | 
| 243 | 	} | |
| 244 | ||
| 245 | 	private CssImageInlineUtils() { | |
| 246 | 		super(); | |
| 247 | 	} | |
| 248 | } | |
Mutations | ||
| 70 | 
 
 1.1 2.2 3.3  | 
|
| 78 | 
 
 1.1 2.2 3.3  | 
|
| 87 | 
 
 1.1 2.2 3.3  | 
|
| 106 | 
 
 1.1 2.2 3.3 4.4 5.5 6.6  | 
|
| 107 | 
 
 1.1 2.2 3.3  | 
|
| 111 | 
 
 1.1 2.2 3.3  | 
|
| 129 | 
 
 1.1 2.2 3.3  | 
|
| 137 | 
 
 1.1 2.2 3.3  | 
|
| 139 | 
 
 1.1 2.2 3.3  | 
|
| 143 | 
 
 1.1 2.2 3.3  | 
|
| 144 | 
 
 1.1 2.2 3.3  | 
|
| 146 | 
 
 1.1 2.2 3.3  | 
|
| 151 | 
 
 1.1 2.2 3.3  | 
|
| 152 | 
 
 1.1 2.2 3.3 4.4 5.5 6.6  | 
|
| 159 | 
 
 1.1 2.2 3.3  | 
|
| 163 | 
 
 1.1 2.2 3.3  | 
|
| 171 | 
 
 1.1 2.2 3.3  | 
|
| 172 | 
 
 1.1 2.2  | 
|
| 173 | 
 
 1.1 2.2 3.3  | 
|
| 177 | 
 
 1.1 2.2 3.3  | 
|
| 189 | 
 
 1.1 2.2 3.3  | 
|
| 200 | 
 
 1.1 2.2 3.3  | 
|
| 205 | 
 
 1.1 2.2 3.3  | 
|
| 209 | 
 
 1.1 2.2 3.3  | 
|
| 212 | 
 
 1.1 2.2 3.3  | 
|
| 213 | 
 
 1.1 2.2  | 
|
| 217 | 
 
 1.1 2.2 3.3 4.4 5.5 6.6  | 
|
| 226 | 
 
 1.1 2.2 3.3  | 
|
| 228 | 
 
 1.1 2.2 3.3  | 
|
| 232 | 
 
 1.1 2.2 3.3  | 
|
| 233 | 
 
 1.1 2.2 3.3  | 
|
| 235 | 
 
 1.1 2.2 3.3 4.4  | 
|
| 239 | 
 
 1.1 2.2 3.3  | 
|
| 240 | 
 
 1.1 2.2 3.3  | 
|
| 242 | 
 
 1.1 2.2 3.3  |