Skip to content

Commit e18422f

Browse files
author
Dmitry Radchuk
committed
Add columns shorthand
DEVSIX-7555
1 parent f913efa commit e18422f

File tree

5 files changed

+261
-2
lines changed

5 files changed

+261
-2
lines changed

styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/CommonCssConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ public class CommonCssConstants {
304304
*/
305305
public static final String COLUMN_GAP = "column-gap";
306306

307+
/**
308+
* The Constant COLUMNS
309+
*/
310+
public static final String COLUMNS = "columns";
311+
307312
/**
308313
* The Constant DARKEN.
309314
*/

styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/resolve/shorthand/IShorthandResolver.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@ This file is part of the iText (R) project.
2828

2929
/**
3030
* Interface for shorthand resolvers.
31+
* <p>
32+
* CSS shorthand is a group of CSS properties that allow values of multiple properties to be set simultaneously. These
33+
* values are separated by spaces. For example, the border property is shorthand for the border-width, border-style, and
34+
* border-color properties. So in CSS, border: 5px solid red; would specify a border that’s five px wide, solid, and
35+
* red.
3136
*/
3237
public interface IShorthandResolver {
33-
38+
3439
/**
3540
* Resolves a shorthand expression.
3641
*
3742
* @param shorthandExpression the shorthand expression
43+
*
3844
* @return a list of CSS declaration
3945
*/
4046
List<CssDeclaration> resolveShorthand(String shorthandExpression);

styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/resolve/shorthand/ShorthandResolverFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ This file is part of the iText (R) project.
2323
package com.itextpdf.styledxmlparser.css.resolve.shorthand;
2424

2525

26-
2726
import com.itextpdf.styledxmlparser.css.CommonCssConstants;
2827
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.BackgroundPositionShorthandResolver;
2928
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.BackgroundShorthandResolver;
@@ -36,6 +35,7 @@ This file is part of the iText (R) project.
3635
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.BorderStyleShorthandResolver;
3736
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.BorderTopShorthandResolver;
3837
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.BorderWidthShorthandResolver;
38+
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.ColumnsShorthandResolver;
3939
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.FlexFlowShorthandResolver;
4040
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.FlexShorthandResolver;
4141
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.FontShorthandResolver;
@@ -80,6 +80,7 @@ public class ShorthandResolverFactory {
8080
shorthandResolvers.put(CommonCssConstants.FLEX_FLOW, new FlexFlowShorthandResolver());
8181
shorthandResolvers.put(CommonCssConstants.GAP, new GapShorthandResolver());
8282
shorthandResolvers.put(CommonCssConstants.PLACE_ITEMS, new PlaceItemsShorthandResolver());
83+
shorthandResolvers.put(CommonCssConstants.COLUMNS, new ColumnsShorthandResolver());
8384
}
8485

8586
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.itextpdf.styledxmlparser.css.resolve.shorthand.impl;
2+
3+
import com.itextpdf.commons.utils.MessageFormatUtil;
4+
import com.itextpdf.styledxmlparser.css.CommonCssConstants;
5+
import com.itextpdf.styledxmlparser.css.CssDeclaration;
6+
import com.itextpdf.styledxmlparser.css.resolve.shorthand.IShorthandResolver;
7+
import com.itextpdf.styledxmlparser.css.util.CssTypesValidationUtils;
8+
import com.itextpdf.styledxmlparser.logs.StyledXmlParserLogMessageConstant;
9+
10+
import java.util.ArrayList;
11+
import java.util.Arrays;
12+
import java.util.Collections;
13+
import java.util.List;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
17+
/**
18+
* Shorthand resolver for the column property.
19+
* This property is a shorthand for the column-count and column-width properties.
20+
*/
21+
public class ColumnsShorthandResolver implements IShorthandResolver {
22+
23+
private static final Logger LOGGER = LoggerFactory.getLogger(ColumnsShorthandResolver.class);
24+
25+
/**
26+
* Creates a new {@link ColumnsShorthandResolver} instance.
27+
*/
28+
public ColumnsShorthandResolver() {
29+
//empty constructor
30+
}
31+
32+
/**
33+
* {@inheritDoc}
34+
*/
35+
@Override
36+
public List<CssDeclaration> resolveShorthand(String shorthandExpression) {
37+
shorthandExpression = shorthandExpression.trim();
38+
if (CssTypesValidationUtils.isInitialOrInheritOrUnset(shorthandExpression)) {
39+
return Arrays.asList(
40+
new CssDeclaration(CommonCssConstants.COLUMN_COUNT, shorthandExpression),
41+
new CssDeclaration(CommonCssConstants.COLUMN_WIDTH, shorthandExpression)
42+
);
43+
}
44+
if (CssTypesValidationUtils.containsInitialOrInheritOrUnset(shorthandExpression)) {
45+
return handleExpressionError(StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION,
46+
CommonCssConstants.COLUMNS, shorthandExpression);
47+
}
48+
if (shorthandExpression.isEmpty()) {
49+
return handleExpressionError(StyledXmlParserLogMessageConstant.SHORTHAND_PROPERTY_CANNOT_BE_EMPTY,
50+
CommonCssConstants.COLUMNS, shorthandExpression);
51+
}
52+
53+
final String[] properties = shorthandExpression.split(" ");
54+
if (properties.length > 2) {
55+
return handleExpressionError(StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION,
56+
CommonCssConstants.COLUMNS, shorthandExpression);
57+
}
58+
List<CssDeclaration> result = new ArrayList<>(2);
59+
for (String property : properties) {
60+
CssDeclaration declaration = processProperty(property);
61+
if (declaration != null) {
62+
result.add(declaration);
63+
}
64+
if (declaration == null && !CommonCssConstants.AUTO.equals(property)) {
65+
return handleExpressionError(StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION,
66+
CommonCssConstants.COLUMNS, shorthandExpression);
67+
}
68+
}
69+
if (result.size() == 2 && result.get(0).getProperty().equals(result.get(1).getProperty())) {
70+
return handleExpressionError(StyledXmlParserLogMessageConstant.INVALID_CSS_PROPERTY_DECLARATION,
71+
CommonCssConstants.COLUMNS, shorthandExpression);
72+
}
73+
return result;
74+
}
75+
76+
private static CssDeclaration processProperty(String value) {
77+
if (CssTypesValidationUtils.isMetricValue(value) || CssTypesValidationUtils.isRelativeValue(value)) {
78+
return new CssDeclaration(CommonCssConstants.COLUMN_WIDTH, value);
79+
}
80+
if (CssTypesValidationUtils.isNumber(value)) {
81+
return new CssDeclaration(CommonCssConstants.COLUMN_COUNT, value);
82+
}
83+
return null;
84+
}
85+
86+
private static List<CssDeclaration> handleExpressionError(String logMessage, String attribute,
87+
String shorthandExpression) {
88+
LOGGER.warn(MessageFormatUtil.format(logMessage, attribute, shorthandExpression));
89+
return Collections.<CssDeclaration>emptyList();
90+
}
91+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
package com.itextpdf.styledxmlparser.css.resolve.shorthand;
2+
3+
import com.itextpdf.styledxmlparser.css.CommonCssConstants;
4+
import com.itextpdf.styledxmlparser.css.CssDeclaration;
5+
import com.itextpdf.styledxmlparser.css.resolve.shorthand.impl.ColumnsShorthandResolver;
6+
import com.itextpdf.styledxmlparser.logs.StyledXmlParserLogMessageConstant;
7+
import com.itextpdf.test.ExtendedITextTest;
8+
import com.itextpdf.test.annotations.LogMessage;
9+
import com.itextpdf.test.annotations.LogMessages;
10+
import com.itextpdf.test.annotations.type.UnitTest;
11+
12+
import java.util.Collections;
13+
import java.util.List;
14+
import org.junit.Assert;
15+
import org.junit.Test;
16+
import org.junit.experimental.categories.Category;
17+
18+
@Category(UnitTest.class)
19+
public class ColumnsShorthandResolverTest extends ExtendedITextTest {
20+
@Test
21+
public void initialOrInheritOrUnsetValuesTest() {
22+
IShorthandResolver resolver = new ColumnsShorthandResolver();
23+
24+
String initialShorthand = CommonCssConstants.INITIAL;
25+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(initialShorthand);
26+
Assert.assertEquals(2, resolvedShorthand.size());
27+
Assert.assertEquals(CommonCssConstants.COLUMN_COUNT, resolvedShorthand.get(0).getProperty());
28+
Assert.assertEquals(CommonCssConstants.INITIAL, resolvedShorthand.get(0).getExpression());
29+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(1).getProperty());
30+
Assert.assertEquals(CommonCssConstants.INITIAL, resolvedShorthand.get(1).getExpression());
31+
32+
String inheritShorthand = CommonCssConstants.INHERIT;
33+
resolvedShorthand = resolver.resolveShorthand(inheritShorthand);
34+
Assert.assertEquals(2, resolvedShorthand.size());
35+
Assert.assertEquals(CommonCssConstants.COLUMN_COUNT, resolvedShorthand.get(0).getProperty());
36+
Assert.assertEquals(CommonCssConstants.INHERIT, resolvedShorthand.get(0).getExpression());
37+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(1).getProperty());
38+
Assert.assertEquals(CommonCssConstants.INHERIT, resolvedShorthand.get(1).getExpression());
39+
40+
String unsetShorthand = CommonCssConstants.UNSET;
41+
resolvedShorthand = resolver.resolveShorthand(unsetShorthand);
42+
Assert.assertEquals(2, resolvedShorthand.size());
43+
Assert.assertEquals(CommonCssConstants.COLUMN_COUNT, resolvedShorthand.get(0).getProperty());
44+
Assert.assertEquals(CommonCssConstants.UNSET, resolvedShorthand.get(0).getExpression());
45+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(1).getProperty());
46+
Assert.assertEquals(CommonCssConstants.UNSET, resolvedShorthand.get(1).getExpression());
47+
}
48+
49+
@Test
50+
@LogMessages(messages = @LogMessage(messageTemplate = StyledXmlParserLogMessageConstant.SHORTHAND_PROPERTY_CANNOT_BE_EMPTY, count = 2))
51+
public void emptyShorthandTest() {
52+
IShorthandResolver resolver = new ColumnsShorthandResolver();
53+
String emptyShorthand = "";
54+
Assert.assertEquals(Collections.<CssDeclaration>emptyList(), resolver.resolveShorthand(emptyShorthand));
55+
56+
String shorthandWithSpaces = " ";
57+
Assert.assertEquals(Collections.<CssDeclaration>emptyList(), resolver.resolveShorthand(shorthandWithSpaces));
58+
}
59+
60+
@Test
61+
public void columnsWithOneAbsoluteValueTest() {
62+
IShorthandResolver resolver = new ColumnsShorthandResolver();
63+
64+
String shorthand = "10px";
65+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
66+
67+
Assert.assertEquals(1, resolvedShorthand.size());
68+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(0).getProperty());
69+
Assert.assertEquals("10px", resolvedShorthand.get(0).getExpression());
70+
}
71+
72+
@Test
73+
public void columnWithOneMetricValueTest() {
74+
IShorthandResolver resolver = new ColumnsShorthandResolver();
75+
76+
String shorthand = "10px";
77+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
78+
79+
Assert.assertEquals(1, resolvedShorthand.size());
80+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(0).getProperty());
81+
Assert.assertEquals("10px", resolvedShorthand.get(0).getExpression());
82+
}
83+
84+
@Test
85+
public void columnWithOneRelativeValueTest() {
86+
IShorthandResolver resolver = new ColumnsShorthandResolver();
87+
88+
String shorthand = "10em";
89+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
90+
91+
Assert.assertEquals(1, resolvedShorthand.size());
92+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(0).getProperty());
93+
Assert.assertEquals("10em", resolvedShorthand.get(0).getExpression());
94+
}
95+
96+
@Test
97+
public void columnWithColumnCountTest() {
98+
IShorthandResolver resolver = new ColumnsShorthandResolver();
99+
100+
String shorthand = "3";
101+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
102+
103+
Assert.assertEquals(1, resolvedShorthand.size());
104+
Assert.assertEquals(CommonCssConstants.COLUMN_COUNT, resolvedShorthand.get(0).getProperty());
105+
Assert.assertEquals("3", resolvedShorthand.get(0).getExpression());
106+
}
107+
108+
@Test
109+
public void columnWithAutoValuesTest() {
110+
IShorthandResolver resolver = new ColumnsShorthandResolver();
111+
112+
String shorthand = "auto auto";
113+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
114+
115+
Assert.assertTrue(resolvedShorthand.isEmpty());
116+
}
117+
118+
@Test
119+
public void columnWithAutoAndRelativeValueTest() {
120+
IShorthandResolver resolver = new ColumnsShorthandResolver();
121+
122+
String shorthand = "3em auto";
123+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
124+
125+
Assert.assertEquals(1, resolvedShorthand.size());
126+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(0).getProperty());
127+
Assert.assertEquals("3em", resolvedShorthand.get(0).getExpression());
128+
}
129+
130+
@Test
131+
public void columnWithRelativeAndAutoValueTest() {
132+
IShorthandResolver resolver = new ColumnsShorthandResolver();
133+
134+
String shorthand = "auto 3em";
135+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
136+
137+
Assert.assertEquals(1, resolvedShorthand.size());
138+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(0).getProperty());
139+
Assert.assertEquals("3em", resolvedShorthand.get(0).getExpression());
140+
}
141+
142+
@Test
143+
public void columnWithRelativeAndCountValueTest() {
144+
IShorthandResolver resolver = new ColumnsShorthandResolver();
145+
146+
String shorthand = "12 3em";
147+
List<CssDeclaration> resolvedShorthand = resolver.resolveShorthand(shorthand);
148+
149+
Assert.assertEquals(2, resolvedShorthand.size());
150+
Assert.assertEquals(CommonCssConstants.COLUMN_COUNT, resolvedShorthand.get(0).getProperty());
151+
Assert.assertEquals("12", resolvedShorthand.get(0).getExpression());
152+
Assert.assertEquals(CommonCssConstants.COLUMN_WIDTH, resolvedShorthand.get(1).getProperty());
153+
Assert.assertEquals("3em", resolvedShorthand.get(1).getExpression());
154+
}
155+
156+
}

0 commit comments

Comments
 (0)