Skip to content

Commit 7f611c0

Browse files
Egor MartsynkovskyiText-CI
authored andcommitted
Add support of attr() with type for url and string
Add support of attr() with fallback for url and string Add support of attr() in target-counter Add tests DEVSIX-2994 Autoported commit. Original commit hash: [a54cb196]
1 parent 1a98816 commit 7f611c0

File tree

8 files changed

+145
-13
lines changed

8 files changed

+145
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2021 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License version 3
8+
as published by the Free Software Foundation with the addition of the
9+
following permission added to Section 15 as permitted in Section 7(a):
10+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
11+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
12+
OF THIRD PARTY RIGHTS
13+
14+
This program is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE.
17+
See the GNU Affero General Public License for more details.
18+
You should have received a copy of the GNU Affero General Public License
19+
along with this program; if not, see http://www.gnu.org/licenses or write to
20+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
22+
http://itextpdf.com/terms-of-use/
23+
24+
The interactive user interfaces in modified source and object code versions
25+
of this program must display Appropriate Legal Notices, as required under
26+
Section 5 of the GNU Affero General Public License.
27+
28+
In accordance with Section 7(b) of the GNU Affero General Public License,
29+
a covered work must retain the producer line in every PDF that is created
30+
or manipulated using iText.
31+
32+
You can be released from the requirements of the license by purchasing
33+
a commercial license. Buying such a license is mandatory as soon as you
34+
develop commercial activities involving the iText software without
35+
disclosing the source code of your own applications.
36+
These activities include: offering paid services to customers as an ASP,
37+
serving PDFs on the fly in a web application, shipping iText with a closed
38+
source product.
39+
40+
For more information, please contact iText Software Corp. at this
41+
42+
*/
43+
using System;
44+
using iText.Html2pdf;
45+
46+
namespace iText.Html2pdf.Css.Resolve {
47+
public class CssContentPropertyResolverIntegrationTest : ExtendedHtmlConversionITextTest {
48+
public static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
49+
.CurrentContext.TestDirectory) + "/resources/itext/html2pdf/css" + "/CssContentPropertyResolverIntegrationTest/";
50+
51+
public static readonly String DESTINATION_FOLDER = NUnit.Framework.TestContext.CurrentContext.TestDirectory
52+
+ "/test/itext/html2pdf/css" + "/CssContentPropertyResolverIntegrationTest/";
53+
54+
[NUnit.Framework.OneTimeSetUp]
55+
public static void BeforeClass() {
56+
CreateOrClearDestinationFolder(DESTINATION_FOLDER);
57+
}
58+
59+
[NUnit.Framework.Test]
60+
public virtual void CheckSimpleAttrFunctionTest() {
61+
ConvertToPdfAndCompare("checkSimpleAttrFunctionTest", SOURCE_FOLDER, DESTINATION_FOLDER);
62+
}
63+
64+
[NUnit.Framework.Test]
65+
public virtual void CheckAttrFunctionWithTypeTest() {
66+
ConvertToPdfAndCompare("checkAttrFunctionWithTypeTest", SOURCE_FOLDER, DESTINATION_FOLDER);
67+
}
68+
}
69+
}

itext.tests/itext.html2pdf.tests/itext/html2pdf/css/resolve/CssContentPropertyResolverTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ You should have received a copy of the GNU Affero General Public License
2424
using System.Collections.Generic;
2525
using iText.Html2pdf.Css;
2626
using iText.Html2pdf.Css.Resolve.Func.Counter;
27+
using iText.StyledXmlParser.Css.Pseudo;
2728
using iText.StyledXmlParser.Node;
2829
using iText.Test;
2930
using iText.Test.Attributes;
@@ -100,5 +101,27 @@ public virtual void ResolveContentCounterNotPageTest() {
100101
NUnit.Framework.Assert.AreEqual(1, result.Count);
101102
NUnit.Framework.Assert.IsTrue(result[0] is ITextNode);
102103
}
104+
105+
[NUnit.Framework.Test]
106+
[LogMessage(iText.Html2pdf.LogMessageConstant.CONTENT_PROPERTY_INVALID, Count = 1)]
107+
public virtual void ResolveContentWrongTargetCounterTest() {
108+
IDictionary<String, String> styles = new Dictionary<String, String>();
109+
styles.Put(CssConstants.CONTENT, "target-counter(attr(), pages)");
110+
CssContext context = new CssContext();
111+
IElementNode iNode = new CssPseudoElementNode(null, "test");
112+
IList<INode> result = CssContentPropertyResolver.ResolveContent(styles, iNode, context);
113+
NUnit.Framework.Assert.IsNull(result);
114+
}
115+
116+
[NUnit.Framework.Test]
117+
[LogMessage(iText.Html2pdf.LogMessageConstant.CONTENT_PROPERTY_INVALID, Count = 1)]
118+
public virtual void ResolveContentWrongTargetCountersTest() {
119+
IDictionary<String, String> styles = new Dictionary<String, String>();
120+
styles.Put(CssConstants.CONTENT, "target-counters(attr(), pages)");
121+
CssContext context = new CssContext();
122+
IElementNode iNode = new CssPseudoElementNode(null, "test");
123+
IList<INode> result = CssContentPropertyResolver.ResolveContent(styles, iNode, context);
124+
NUnit.Framework.Assert.IsNull(result);
125+
}
103126
}
104127
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<html>
2+
3+
<head>
4+
<style>
5+
.toc-row a::after {
6+
content: " " target-counter(attr(href url), page);
7+
}
8+
</style>
9+
</head>
10+
<body>
11+
12+
<div class="toc-container">
13+
<div class="toc-row"><a href="#one">Link To Page One</a></div>
14+
<div class="toc-row"><a href="#two">Link To Page Two</a></div>
15+
</div>
16+
17+
<div class="content-container">
18+
<div class="page" id="one">Page One Content Here</div>
19+
<div class="page" id="two" style="page-break-before: always">Page Two Content Here</div>
20+
</div>
21+
22+
</body>
23+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<style>
4+
[data-foo]::before {
5+
content: attr(data-foo) " ";
6+
}
7+
</style>
8+
<body>
9+
<p data-foo="hello">world</p>
10+
</body>
11+
</html>

itext/itext.html2pdf/itext/html2pdf/css/resolve/CssContentPropertyResolver.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ source product.
4848
using iText.Html2pdf.Css.Resolve.Func.Counter;
4949
using iText.Html2pdf.Html;
5050
using iText.IO.Util;
51+
using iText.StyledXmlParser.Css;
5152
using iText.StyledXmlParser.Css.Page;
5253
using iText.StyledXmlParser.Css.Parse;
5354
using iText.StyledXmlParser.Css.Pseudo;
@@ -158,7 +159,11 @@ internal static IList<INode> ResolveContent(IDictionary<String, String> styles,
158159
if (@params.Count < TARGET_COUNTER_MIN_PARAMS_SIZE) {
159160
return ErrorFallback(contentStr);
160161
}
161-
String target = CssUtils.ExtractUrl(@params[0]);
162+
String target = @params[0].StartsWith(CommonCssConstants.ATTRIBUTE + "(") ? CssUtils.ExtractAttributeValue
163+
(@params[0], (IElementNode)contentContainer.ParentNode()) : CssUtils.ExtractUrl(@params[0]);
164+
if (target == null) {
165+
return ErrorFallback(contentStr);
166+
}
162167
String counterName = @params[1].Trim();
163168
CounterDigitsGlyphStyle listStyleType = HtmlUtils.ConvertStringCounterGlyphStyleToEnum(@params.Count > TARGET_COUNTER_MIN_PARAMS_SIZE
164169
? @params[TARGET_COUNTER_MIN_PARAMS_SIZE].Trim() : null);
@@ -186,7 +191,11 @@ internal static IList<INode> ResolveContent(IDictionary<String, String> styles,
186191
if (@params.Count < TARGET_COUNTERS_MIN_PARAMS_SIZE) {
187192
return ErrorFallback(contentStr);
188193
}
189-
String target = CssUtils.ExtractUrl(@params[0]);
194+
String target = @params[0].StartsWith(CommonCssConstants.ATTRIBUTE + "(") ? CssUtils.ExtractAttributeValue
195+
(@params[0], (IElementNode)contentContainer.ParentNode()) : CssUtils.ExtractUrl(@params[0]);
196+
if (target == null) {
197+
return ErrorFallback(contentStr);
198+
}
190199
String counterName = @params[1].Trim();
191200
String counterSeparator = @params[2].Trim();
192201
counterSeparator = counterSeparator.JSubstring(1, counterSeparator.Length - 1);
@@ -224,17 +233,14 @@ internal static IList<INode> ResolveContent(IDictionary<String, String> styles,
224233
result.Add(new CssContentElementNode(contentContainer, TagConstants.DIV, attributes));
225234
}
226235
else {
227-
if (token.GetValue().StartsWith("attr(") && contentContainer is CssPseudoElementNode) {
228-
int endBracket = token.GetValue().IndexOf(')');
229-
if (endBracket > 5) {
230-
String attrName = token.GetValue().JSubstring(5, endBracket);
231-
if (attrName.Contains("(") || attrName.Contains(" ") || attrName.Contains("'") || attrName.Contains("\"")) {
232-
return ErrorFallback(contentStr);
233-
}
234-
IElementNode element = (IElementNode)contentContainer.ParentNode();
235-
String value = element.GetAttribute(attrName);
236-
result.Add(new CssContentPropertyResolver.ContentTextNode(contentContainer, value == null ? "" : value));
236+
if (token.GetValue().StartsWith(CommonCssConstants.ATTRIBUTE + "(") && contentContainer is CssPseudoElementNode
237+
) {
238+
String value = CssUtils.ExtractAttributeValue(token.GetValue(), (IElementNode)contentContainer.ParentNode(
239+
));
240+
if (value == null) {
241+
return ErrorFallback(contentStr);
237242
}
243+
result.Add(new CssContentPropertyResolver.ContentTextNode(contentContainer, value));
238244
}
239245
else {
240246
if (token.GetValue().EndsWith("quote") && contentContainer is IStylesContainer) {

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
a9bca9c275e780d5ecf4b1eb219b7e374c8c9988
1+
a54cb196505d4bfe08cf2c6fb6ea7836385b28c7

0 commit comments

Comments
 (0)