Skip to content

Commit 5c9b665

Browse files
committed
[RELEASE] iText pdfHtml 6.2.1
2 parents 9e5bfc1 + 18f5c58 commit 5c9b665

File tree

1,116 files changed

+7855
-392
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,116 files changed

+7855
-392
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
<parent>
66
<groupId>com.itextpdf</groupId>
77
<artifactId>root</artifactId>
8-
<version>9.2.0</version>
8+
<version>9.3.0</version>
99
<relativePath />
1010
</parent>
1111

1212
<artifactId>html2pdf</artifactId>
13-
<version>6.2.0</version>
13+
<version>6.2.1</version>
1414

1515
<name>pdfHTML</name>
1616
<description>pdfHTML is an iText add-on that lets you to parse (X)HTML snippets and the associated CSS and converts

src/main/java/com/itextpdf/html2pdf/actions/data/PdfHtmlProductData.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ This file is part of the iText (R) project.
3030
*/
3131
public final class PdfHtmlProductData {
3232
private static final String PDF_HTML_PUBLIC_PRODUCT_NAME = "pdfHTML";
33-
private static final String PDF_HTML_VERSION = "6.2.0";
33+
private static final String PDF_HTML_VERSION = "6.2.1";
3434
private static final int PDF_HTML_COPYRIGHT_SINCE = 2000;
3535
private static final int PDF_HTML_COPYRIGHT_TO = 2025;
3636

src/main/java/com/itextpdf/html2pdf/attach/impl/OutlineHandler.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ This file is part of the iText (R) project.
3434
import com.itextpdf.kernel.pdf.action.PdfAction;
3535
import com.itextpdf.layout.element.IElement;
3636
import com.itextpdf.layout.properties.Property;
37+
import com.itextpdf.styledxmlparser.CommonAttributeConstants;
3738
import com.itextpdf.styledxmlparser.node.IElementNode;
3839
import com.itextpdf.styledxmlparser.node.impl.jsoup.node.JsoupElementNode;
3940

41+
import java.util.HashSet;
42+
import java.util.Set;
4043
import org.slf4j.Logger;
4144
import org.slf4j.LoggerFactory;
4245

@@ -299,7 +302,8 @@ protected OutlineHandler addOutlineAndDestToDocument(ITagWorker tagWorker, IElem
299302
levelsInProcess.pop();
300303
}
301304
PdfOutline outline = parent.addOutline(generateOutlineName(element));
302-
String destination = generateUniqueDestinationName(element);
305+
String destination = element.getAttribute(CommonAttributeConstants.ID) == null
306+
? generateUniqueDestinationName(element) : element.getAttribute(CommonAttributeConstants.ID);
303307
PdfAction action = PdfAction.createGoTo(destination);
304308
outline.addAction(action);
305309
destinationsInProcess.push(new Tuple2<String, PdfDictionary>(destination, action.getPdfObject()));
@@ -326,7 +330,13 @@ protected OutlineHandler setDestinationToElement(ITagWorker tagWorker, IElementN
326330
if (null != tagWorker && hasMarkPriorityMapping(markName) && destinationsInProcess.size() > 0) {
327331
Tuple2<String, PdfDictionary> content = destinationsInProcess.pop();
328332
if (tagWorker.getElementResult() instanceof IElement) {
329-
tagWorker.getElementResult().setProperty(Property.DESTINATION, content);
333+
Set<Object> existingDestinations =
334+
tagWorker.getElementResult().<Set<Object>>getProperty(Property.DESTINATION);
335+
if (existingDestinations == null) {
336+
existingDestinations = new HashSet<>();
337+
}
338+
existingDestinations.add(content);
339+
tagWorker.getElementResult().setProperty(Property.DESTINATION, existingDestinations);
330340
} else {
331341
Logger logger = LoggerFactory.getLogger(OutlineHandler.class);
332342
logger.warn(MessageFormatUtil.format(

src/main/java/com/itextpdf/html2pdf/attach/impl/tags/ABlockTagWorker.java

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,14 @@ This file is part of the iText (R) project.
2323
package com.itextpdf.html2pdf.attach.impl.tags;
2424

2525
import com.itextpdf.html2pdf.attach.ProcessorContext;
26+
import com.itextpdf.html2pdf.attach.impl.tags.util.ATagUtil;
2627
import com.itextpdf.html2pdf.attach.util.LinkHelper;
27-
import com.itextpdf.kernel.pdf.tagging.StandardRoles;
28-
import com.itextpdf.layout.element.Div;
29-
import com.itextpdf.layout.properties.Property;
3028
import com.itextpdf.html2pdf.html.AttributeConstants;
29+
import com.itextpdf.layout.properties.Property;
3130
import com.itextpdf.styledxmlparser.node.IElementNode;
32-
import com.itextpdf.styledxmlparser.resolver.resource.UriResolver;
3331

34-
import java.net.MalformedURLException;
32+
import java.util.HashSet;
33+
import java.util.Set;
3534

3635
/**
3736
* TagWorker class for a link block.
@@ -57,26 +56,20 @@ public void processEnd(IElementNode element, ProcessorContext context) {
5756

5857
String url = element.getAttribute(AttributeConstants.HREF);
5958
if (url != null) {
60-
String base = context.getBaseUri();
61-
if (base != null) {
62-
UriResolver uriResolver = new UriResolver(base);
63-
if (!(url.startsWith("#") && uriResolver.isLocalBaseUri()))
64-
try {
65-
String resolvedUri = uriResolver.resolveAgainstBaseUri(url).toExternalForm();
66-
if (!url.endsWith("/") && resolvedUri.endsWith("/"))
67-
resolvedUri = resolvedUri.substring(0, resolvedUri.length() - 1);
68-
if (!resolvedUri.startsWith("file:"))
69-
url = resolvedUri;
70-
} catch (MalformedURLException exception) {
71-
}
72-
}
73-
((Div) getElementResult()).getAccessibilityProperties().setRole(StandardRoles.LINK);
74-
LinkHelper.applyLinkAnnotation(getElementResult(), url, context, element);
59+
String anchorLink = element.getAttribute(AttributeConstants.HREF);
60+
String baseUri = context.getBaseUri();
61+
String modifiedUrl = ATagUtil.resolveAnchorLink(anchorLink, baseUri);
62+
LinkHelper.applyLinkAnnotation(getElementResult(), modifiedUrl, context, element);
7563
}
7664

7765
if (getElementResult() != null) {
7866
String name = element.getAttribute(AttributeConstants.NAME);
79-
getElementResult().setProperty(Property.DESTINATION, name);
67+
Set<Object> existingDestinations = getElementResult().<Set<Object>>getProperty(Property.DESTINATION);
68+
if (existingDestinations == null) {
69+
existingDestinations = new HashSet<>();
70+
}
71+
existingDestinations.add(name);
72+
getElementResult().setProperty(Property.DESTINATION, existingDestinations);
8073
}
8174
}
8275
}

src/main/java/com/itextpdf/html2pdf/attach/impl/tags/ATagWorker.java

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@ This file is part of the iText (R) project.
2424

2525
import com.itextpdf.html2pdf.attach.ProcessorContext;
2626
import com.itextpdf.html2pdf.attach.impl.layout.RunningElement;
27+
import com.itextpdf.html2pdf.attach.impl.tags.util.ATagUtil;
2728
import com.itextpdf.html2pdf.attach.util.LinkHelper;
28-
import com.itextpdf.kernel.pdf.tagging.StandardRoles;
29+
import com.itextpdf.html2pdf.html.AttributeConstants;
2930
import com.itextpdf.layout.IPropertyContainer;
3031
import com.itextpdf.layout.element.Div;
3132
import com.itextpdf.layout.element.IBlockElement;
3233
import com.itextpdf.layout.properties.FloatPropertyValue;
3334
import com.itextpdf.layout.properties.Property;
3435
import com.itextpdf.layout.properties.Transform;
35-
import com.itextpdf.html2pdf.html.AttributeConstants;
3636
import com.itextpdf.styledxmlparser.node.IElementNode;
37-
import com.itextpdf.styledxmlparser.resolver.resource.UriResolver;
3837

39-
import java.net.MalformedURLException;
38+
import java.util.HashSet;
39+
import java.util.Set;
4040

4141

4242
/**
@@ -63,26 +63,15 @@ public void processEnd(IElementNode element, ProcessorContext context) {
6363

6464
String url = element.getAttribute(AttributeConstants.HREF);
6565
if (url != null) {
66-
String base = context.getBaseUri();
67-
if (base != null) {
68-
UriResolver uriResolver = new UriResolver(base);
69-
if (!(url.startsWith("#") && uriResolver.isLocalBaseUri()))
70-
try {
71-
String resolvedUri = uriResolver.resolveAgainstBaseUri(url).toExternalForm();
72-
if (!url.endsWith("/") && resolvedUri.endsWith("/"))
73-
resolvedUri = resolvedUri.substring(0, resolvedUri.length() - 1);
74-
if (!resolvedUri.startsWith("file:"))
75-
url = resolvedUri;
76-
} catch (MalformedURLException exception) {
77-
}
78-
}
66+
String anchorLink = element.getAttribute(AttributeConstants.HREF);
67+
String baseUri = context.getBaseUri();
68+
String modifiedUrl = ATagUtil.resolveAnchorLink(anchorLink, baseUri);
7969
for (int i = 0; i < getAllElements().size(); i++) {
8070
if (getAllElements().get(i) instanceof RunningElement) {
8171
continue;
8272
}
8373
if (getAllElements().get(i) instanceof IBlockElement) {
8474
Div simulatedDiv = new Div();
85-
simulatedDiv.getAccessibilityProperties().setRole(StandardRoles.LINK);
8675
Transform cssTransform = getAllElements().get(i).<Transform>getProperty(Property.TRANSFORM);
8776
if (cssTransform != null) {
8877
getAllElements().get(i).deleteOwnProperty(Property.TRANSFORM);
@@ -100,14 +89,19 @@ public void processEnd(IElementNode element, ProcessorContext context) {
10089
}
10190
getAllElements().set(i, simulatedDiv);
10291
}
103-
LinkHelper.applyLinkAnnotation(getAllElements().get(i), url, context, element);
92+
LinkHelper.applyLinkAnnotation(getAllElements().get(i), modifiedUrl, context, element);
10493
}
10594
}
10695

10796
if (!getAllElements().isEmpty()) {
10897
String name = element.getAttribute(AttributeConstants.NAME);
10998
IPropertyContainer firstElement = getAllElements().get(0);
110-
firstElement.setProperty(Property.DESTINATION, name);
99+
Set<Object> existingDestinations = firstElement.<Set<Object>>getProperty(Property.DESTINATION);
100+
if (existingDestinations == null) {
101+
existingDestinations = new HashSet<>();
102+
}
103+
existingDestinations.add(name);
104+
firstElement.setProperty(Property.DESTINATION, existingDestinations);
111105
firstElement.setProperty(Property.ID, name);
112106
}
113107
}

src/main/java/com/itextpdf/html2pdf/attach/impl/tags/BrTagWorker.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ This file is part of the iText (R) project.
2626
import com.itextpdf.html2pdf.attach.ProcessorContext;
2727
import com.itextpdf.html2pdf.attach.util.AccessiblePropHelper;
2828
import com.itextpdf.html2pdf.css.CssConstants;
29+
import com.itextpdf.kernel.pdf.tagging.StandardRoles;
2930
import com.itextpdf.layout.IPropertyContainer;
3031
import com.itextpdf.layout.element.Text;
31-
import com.itextpdf.styledxmlparser.util.FontFamilySplitterUtil;
3232
import com.itextpdf.styledxmlparser.node.IElementNode;
33+
import com.itextpdf.styledxmlparser.util.FontFamilySplitterUtil;
34+
3335
import java.util.List;
3436

3537
/**
@@ -38,7 +40,7 @@ This file is part of the iText (R) project.
3840
public class BrTagWorker implements ITagWorker {
3941

4042
/** A new line Text element. */
41-
private Text newLine = new Text("\n");
43+
private final Text newLine;
4244

4345
/**
4446
* Creates a new {@link BrTagWorker} instance.
@@ -47,6 +49,8 @@ public class BrTagWorker implements ITagWorker {
4749
* @param context the context
4850
*/
4951
public BrTagWorker(IElementNode element, ProcessorContext context) {
52+
newLine = new Text("\n");
53+
newLine.getAccessibilityProperties().setRole(StandardRoles.ARTIFACT);
5054
//There is no mappings for BR element in DefaultTagCssApplierMapping,
5155
// because only font-family should be applied to <br /> element.
5256
String fontFamily = element.getStyles().get(CssConstants.FONT_FAMILY);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2025 Apryse Group NV
4+
Authors: Apryse Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
package com.itextpdf.html2pdf.attach.impl.tags.util;
24+
25+
import com.itextpdf.styledxmlparser.resolver.resource.UriResolver;
26+
27+
import java.net.MalformedURLException;
28+
29+
/**
30+
* Utility class to work with the data in A tag.
31+
*/
32+
public final class ATagUtil {
33+
34+
private ATagUtil() {
35+
//Empty constructor
36+
}
37+
38+
/**
39+
* Resolves a link in A tag.
40+
*
41+
* @param anchorLink the link in A tag
42+
* @param baseUrl the base URL
43+
*
44+
* @return the resolved link
45+
*/
46+
public static String resolveAnchorLink(String anchorLink, String baseUrl) {
47+
if (baseUrl != null) {
48+
UriResolver uriResolver = new UriResolver(baseUrl);
49+
if (!anchorLink.startsWith("#")) {
50+
try {
51+
String resolvedUri = uriResolver.resolveAgainstBaseUri(anchorLink).toExternalForm();
52+
if (!anchorLink.endsWith("/") && resolvedUri.endsWith("/")) {
53+
resolvedUri = resolvedUri.substring(0, resolvedUri.length() - 1);
54+
}
55+
if (!resolvedUri.startsWith("file:")) {
56+
return resolvedUri;
57+
}
58+
} catch (MalformedURLException exception) {
59+
}
60+
}
61+
}
62+
return anchorLink;
63+
}
64+
}

src/main/java/com/itextpdf/html2pdf/attach/util/LinkHelper.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,20 @@ This file is part of the iText (R) project.
3232
import com.itextpdf.kernel.geom.Rectangle;
3333
import com.itextpdf.kernel.pdf.PdfArray;
3434
import com.itextpdf.kernel.pdf.PdfDictionary;
35+
import com.itextpdf.kernel.pdf.PdfVersion;
3536
import com.itextpdf.kernel.pdf.action.PdfAction;
3637
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
3738
import com.itextpdf.kernel.pdf.annot.PdfLinkAnnotation;
39+
import com.itextpdf.kernel.pdf.tagging.PdfNamespace;
3840
import com.itextpdf.kernel.pdf.tagging.StandardRoles;
41+
import com.itextpdf.kernel.pdf.tagutils.AccessibilityProperties;
3942
import com.itextpdf.layout.IPropertyContainer;
40-
import com.itextpdf.layout.element.ILeafElement;
4143
import com.itextpdf.layout.properties.Property;
4244
import com.itextpdf.layout.tagging.IAccessibleElement;
4345
import com.itextpdf.styledxmlparser.node.IElementNode;
46+
47+
import java.util.HashSet;
48+
import java.util.Set;
4449
import org.slf4j.Logger;
4550
import org.slf4j.LoggerFactory;
4651

@@ -100,11 +105,17 @@ public static void applyLinkAnnotation(IPropertyContainer container, String url,
100105

101106
}
102107

103-
104108
linkAnnotation.setBorder(new PdfArray(new float[]{0, 0, 0}));
105109
container.setProperty(Property.LINK_ANNOTATION, linkAnnotation);
106-
if (container instanceof ILeafElement && container instanceof IAccessibleElement) {
107-
((IAccessibleElement) container).getAccessibilityProperties().setRole(StandardRoles.LINK);
110+
if (container instanceof IAccessibleElement) {
111+
AccessibilityProperties accessibilityProperties =
112+
((IAccessibleElement) container).getAccessibilityProperties();
113+
String role = linkAnnotation.getRoleBasedOnDestination(context.getPdfDocument());
114+
if (StandardRoles.REFERENCE.equals(role) && context.getPdfDocument() != null &&
115+
PdfVersion.PDF_2_0.compareTo(context.getPdfDocument().getPdfVersion()) <= 0) {
116+
accessibilityProperties.setNamespace(PdfNamespace.getDefault(context.getPdfDocument()));
117+
}
118+
accessibilityProperties.setRole(role);
108119
}
109120
}
110121
}
@@ -138,8 +149,12 @@ public static void createDestination(ITagWorker tagWorker, IElementNode element,
138149
context.getLinkContext().addLinkAnnotation(id, linkAnnotation);
139150
}
140151

141-
propertyContainer.setProperty(Property.DESTINATION, new Tuple2<String, PdfDictionary>(id,
142-
linkAnnotation.getAction()));
152+
Set<Object> existingDestinations = propertyContainer.<Set<Object>>getProperty(Property.DESTINATION);
153+
if (existingDestinations == null) {
154+
existingDestinations = new HashSet<>();
155+
}
156+
existingDestinations.add(new Tuple2<String, PdfDictionary>(id, linkAnnotation.getAction()));
157+
propertyContainer.setProperty(Property.DESTINATION, existingDestinations);
143158
}
144159
if (propertyContainer != null) {
145160
propertyContainer.setProperty(Property.ID, id);

src/main/java/com/itextpdf/html2pdf/css/apply/impl/PageMarginBoxCssApplier.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public void apply(ProcessorContext context, IStylesContainer stylesContainer, IT
111111
marginBox.setProperty(Property.OVERFLOW_Y, OverflowPropertyValue.VISIBLE);
112112
}
113113

114-
//TODO DEVSIX-7024 Support outlines for page margin boxes
114+
//TODO DEVSIX-5725 support 'ouline' property for page margin boxes
115115
OutlineApplierUtil.applyOutlines(boxStyles, context, marginBox);
116116

117117
marginBox.setProperty(Property.FONT_PROVIDER, context.getFontProvider());

src/main/java/com/itextpdf/html2pdf/css/apply/util/FlexApplierUtil.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,15 @@ private static void applyAlignContent(Map<String, String> cssProps, IPropertyCon
253253
if (alignContentString != null) {
254254
AlignContentPropertyValue alignContent;
255255
switch (alignContentString) {
256+
case CommonCssConstants.START:
257+
alignContent = AlignContentPropertyValue.START;
258+
break;
256259
case CommonCssConstants.FLEX_START:
257260
alignContent = AlignContentPropertyValue.FLEX_START;
258261
break;
262+
case CommonCssConstants.END:
263+
alignContent = AlignContentPropertyValue.END;
264+
break;
259265
case CommonCssConstants.FLEX_END:
260266
alignContent = AlignContentPropertyValue.FLEX_END;
261267
break;
@@ -326,7 +332,9 @@ private static Map<String, Set<String>> createSupportedFlexContainerPropertiesAn
326332
supportedAlignContentValues.add(CommonCssConstants.STRETCH);
327333
supportedAlignContentValues.add(CommonCssConstants.NORMAL);
328334
supportedAlignContentValues.add(CommonCssConstants.FLEX_START);
335+
supportedAlignContentValues.add(CommonCssConstants.START);
329336
supportedAlignContentValues.add(CommonCssConstants.FLEX_END);
337+
supportedAlignContentValues.add(CommonCssConstants.END);
330338
supportedAlignContentValues.add(CommonCssConstants.CENTER);
331339
supportedAlignContentValues.add(CommonCssConstants.SPACE_AROUND);
332340
supportedAlignContentValues.add(CommonCssConstants.SPACE_BETWEEN);

0 commit comments

Comments
 (0)