Skip to content

Commit 0fe4d98

Browse files
author
Dmitry Radchuk
committed
Add css variables support
DEVSIX-8943
1 parent 655cb6c commit 0fe4d98

38 files changed

+856
-10
lines changed

src/main/java/com/itextpdf/html2pdf/css/resolve/DefaultCssResolver.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,19 @@ This file is part of the iText (R) project.
5656
import com.itextpdf.styledxmlparser.node.INode;
5757
import com.itextpdf.styledxmlparser.node.IStylesContainer;
5858
import com.itextpdf.styledxmlparser.resolver.resource.ResourceResolver;
59+
import com.itextpdf.styledxmlparser.util.CssVariableUtil;
5960
import com.itextpdf.styledxmlparser.util.StyleUtil;
6061

6162
import java.io.InputStream;
6263
import java.util.ArrayList;
64+
import java.util.Collections;
6365
import java.util.HashSet;
6466
import java.util.LinkedList;
6567
import java.util.List;
6668
import java.util.Map;
6769
import java.util.Map.Entry;
6870
import java.util.Set;
71+
6972
import org.slf4j.Logger;
7073
import org.slf4j.LoggerFactory;
7174

@@ -74,6 +77,13 @@ This file is part of the iText (R) project.
7477
*/
7578
public class DefaultCssResolver implements ICssResolver {
7679

80+
/**
81+
* Css inheritance checker
82+
*/
83+
private static final Set<IStyleInheritance> INHERITANCE_RULES = Collections.unmodifiableSet(new HashSet<>(
84+
Collections.singletonList((IStyleInheritance) new CssInheritance())));
85+
86+
7787
/**
7888
* The CSS style sheet.
7989
*/
@@ -84,11 +94,6 @@ public class DefaultCssResolver implements ICssResolver {
8494
*/
8595
private MediaDeviceDescription deviceDescription;
8696

87-
/**
88-
* Css inheritance checker
89-
*/
90-
private IStyleInheritance cssInheritance = new CssInheritance();
91-
9297
/**
9398
* The list of fonts.
9499
*/
@@ -183,12 +188,10 @@ private Map<String, String> resolveStyles(INode element, CssContext context) {
183188
}
184189

185190
if (parentStyles != null) {
186-
Set<IStyleInheritance> inheritanceRules = new HashSet<>();
187-
inheritanceRules.add(cssInheritance);
188191
for (Map.Entry<String, String> entry : parentStyles.entrySet()) {
189192
elementStyles = StyleUtil
190193
.mergeParentStyleDeclaration(elementStyles, entry.getKey(), entry.getValue(), parentStyles.get(
191-
CommonCssConstants.FONT_SIZE), inheritanceRules);
194+
CommonCssConstants.FONT_SIZE), INHERITANCE_RULES);
192195

193196
// If the parent has display: flex, the flex item is blockified
194197
// no matter what display value is set for it (except 'none' and 'grid' values).
@@ -205,6 +208,8 @@ private Map<String, String> resolveStyles(INode element, CssContext context) {
205208
}
206209
}
207210

211+
CssVariableUtil.resolveCssVariables(elementStyles);
212+
208213
String elementFontSize = elementStyles.get(CssConstants.FONT_SIZE);
209214
if (CssTypesValidationUtils.isRelativeValue(elementFontSize) || CssConstants.LARGER.equals(elementFontSize)
210215
|| CssConstants.SMALLER.equals(elementFontSize)) {

src/test/java/com/itextpdf/html2pdf/css/grid/GridTemplatesTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This file is part of the iText (R) project.
2525
import com.itextpdf.html2pdf.ConverterProperties;
2626
import com.itextpdf.html2pdf.ExtendedHtmlConversionITextTest;
2727
import com.itextpdf.html2pdf.logs.Html2PdfLogMessageConstant;
28+
import com.itextpdf.io.logs.IoLogMessageConstant;
2829
import com.itextpdf.layout.exceptions.LayoutExceptionMessageConstant;
2930
import com.itextpdf.layout.logs.LayoutLogMessageConstant;
3031
import com.itextpdf.styledxmlparser.logs.StyledXmlParserLogMessageConstant;
@@ -643,8 +644,10 @@ public void maxHeightFlexRowsTest2() throws IOException, InterruptedException {
643644
}
644645

645646
@LogMessages(messages = {
646-
@LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION, logLevel =
647-
LogLevelConstants.WARN)})
647+
@LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION,
648+
logLevel = LogLevelConstants.WARN),
649+
@LogMessage(messageTemplate = IoLogMessageConstant.UNKNOWN_COLOR_FORMAT_MUST_BE_RGB_OR_RRGGBB,
650+
logLevel = LogLevelConstants.ERROR, count = 11)})
648651
@Test
649652
public void divNestingTest() throws IOException, InterruptedException {
650653
runTest("divNestingTest");
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.itextpdf.html2pdf.css.resolve;
2+
3+
import com.itextpdf.html2pdf.ExtendedHtmlConversionITextTest;
4+
import com.itextpdf.styledxmlparser.logs.StyledXmlParserLogMessageConstant;
5+
import com.itextpdf.test.annotations.LogMessage;
6+
import com.itextpdf.test.annotations.LogMessages;
7+
import org.junit.jupiter.api.BeforeAll;
8+
import org.junit.jupiter.api.Tag;
9+
import org.junit.jupiter.api.Test;
10+
11+
import java.io.IOException;
12+
13+
@Tag("IntegrationTest")
14+
public class CssVariableResolverTest extends ExtendedHtmlConversionITextTest {
15+
private static final String SOURCE_FOLDER = "./src/test/resources/com/itextpdf/html2pdf/css"
16+
+ "/CssVariableResolverTest/";
17+
private static final String DESTINATION_FOLDER = "./target/test/com/itextpdf/html2pdf/css"
18+
+ "/CssVariableResolverTest/";
19+
20+
@BeforeAll
21+
public static void beforeClass() {
22+
createOrClearDestinationFolder(DESTINATION_FOLDER);
23+
}
24+
25+
@Test
26+
public void variableScopeTest() throws IOException, InterruptedException {
27+
convertToPdfAndCompare("variableScope", SOURCE_FOLDER, DESTINATION_FOLDER);
28+
}
29+
30+
@Test
31+
public void reversedDeclarationVariableScopeTest() throws IOException, InterruptedException {
32+
convertToPdfAndCompare("reversedDeclarationVariableScope", SOURCE_FOLDER, DESTINATION_FOLDER);
33+
}
34+
35+
@Test
36+
public void defaultValueTest() throws IOException, InterruptedException {
37+
convertToPdfAndCompare("defaultValue", SOURCE_FOLDER, DESTINATION_FOLDER);
38+
}
39+
40+
@Test
41+
public void incorrectDefaultValueTest() throws IOException, InterruptedException {
42+
convertToPdfAndCompare("incorrectDefaultValue", SOURCE_FOLDER, DESTINATION_FOLDER);
43+
}
44+
45+
@Test
46+
public void simpleRootSelectorTest() throws IOException, InterruptedException {
47+
convertToPdfAndCompare("simpleRootSelector", SOURCE_FOLDER, DESTINATION_FOLDER);
48+
}
49+
50+
@Test
51+
public void varInSameContextTest() throws IOException, InterruptedException {
52+
convertToPdfAndCompare("varInSameContext", SOURCE_FOLDER, DESTINATION_FOLDER);
53+
}
54+
55+
@LogMessages(messages = @LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION))
56+
@Test
57+
public void varOverridingTest() throws IOException, InterruptedException {
58+
convertToPdfAndCompare("varOverriding", SOURCE_FOLDER, DESTINATION_FOLDER);
59+
}
60+
61+
@LogMessages(messages = @LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION))
62+
@Test
63+
public void varInheritanceTest() throws IOException, InterruptedException {
64+
convertToPdfAndCompare("varInheritance", SOURCE_FOLDER, DESTINATION_FOLDER);
65+
}
66+
67+
@LogMessages(messages = @LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION))
68+
@Test
69+
public void rootSelectorTest() throws IOException, InterruptedException {
70+
convertToPdfAndCompare("rootSelector", SOURCE_FOLDER, DESTINATION_FOLDER);
71+
}
72+
73+
@Test
74+
public void backgroundTest() throws IOException, InterruptedException {
75+
convertToPdfAndCompare("background", SOURCE_FOLDER, DESTINATION_FOLDER);
76+
}
77+
78+
@Test
79+
public void varAsShorthandTest() throws IOException, InterruptedException {
80+
convertToPdfAndCompare("varAsShorthand", SOURCE_FOLDER, DESTINATION_FOLDER);
81+
}
82+
83+
@Test
84+
public void varInShorthandTest() throws IOException, InterruptedException {
85+
convertToPdfAndCompare("varInShorthand", SOURCE_FOLDER, DESTINATION_FOLDER);
86+
}
87+
88+
@Test
89+
public void varsInShorthandTest() throws IOException, InterruptedException {
90+
convertToPdfAndCompare("varsInShorthand", SOURCE_FOLDER, DESTINATION_FOLDER);
91+
}
92+
93+
@LogMessages(messages = @LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION))
94+
@Test
95+
public void defaultValuesWithValidationTest() throws IOException, InterruptedException {
96+
convertToPdfAndCompare("defaultValuesWithValidation", SOURCE_FOLDER, DESTINATION_FOLDER);
97+
}
98+
99+
@LogMessages(messages = @LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION))
100+
@Test
101+
public void extraSpacesInVarTest() throws IOException, InterruptedException {
102+
convertToPdfAndCompare("extraSpacesInVar", SOURCE_FOLDER, DESTINATION_FOLDER);
103+
}
104+
105+
@Test
106+
public void varInStyleAttributeTest() throws IOException, InterruptedException {
107+
convertToPdfAndCompare("varInStyleAttribute", SOURCE_FOLDER, DESTINATION_FOLDER);
108+
}
109+
110+
@Test
111+
public void complexTest() throws IOException, InterruptedException {
112+
convertToPdfAndCompare("complex", SOURCE_FOLDER, DESTINATION_FOLDER);
113+
}
114+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>CSS Variables - Button Variations</title>
6+
<style>
7+
:root {
8+
--primary: #0076c6;
9+
--secondary: #333333;
10+
--error: #ce0606;
11+
--success: #009070;
12+
--white: #ffffff;
13+
}
14+
15+
/* base style for all buttons */
16+
.btn {
17+
padding: 1rem 1.5rem;
18+
background: transparent;
19+
font-weight: 700;
20+
cursor: pointer;
21+
}
22+
23+
/* variations */
24+
.btn-primary {
25+
background: var(--primary);
26+
color: var(--white);
27+
}
28+
29+
.btn-secondary {
30+
background: var(--secondary);
31+
color: var(--white);
32+
}
33+
34+
.btn-success {
35+
background: var(--success);
36+
color: var(--white);
37+
}
38+
39+
.btn-error {
40+
background: var(--error);
41+
color: var(--white);
42+
}
43+
44+
.btn-link {
45+
color: var(--primary);
46+
}
47+
</style>
48+
</head>
49+
<body>
50+
<section>
51+
<div class="container">
52+
<h1 class="title">CSS Color Variations</h1>
53+
<div class="btn-group">
54+
<button class="btn btn-primary">Primary</button>
55+
<button class="btn btn-secondary">Secondary</button>
56+
<button class="btn btn-link">Link</button>
57+
<button class="btn btn-success">Success</button>
58+
<button class="btn btn-error">Error</button>
59+
</div>
60+
</div>
61+
</section>
62+
</body>
63+
</html>

0 commit comments

Comments
 (0)