Skip to content

Commit

Permalink
Merge branch 'main' into javascript-refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
grigoriev authored Sep 12, 2024
2 parents d26cacf + 3b36210 commit 79a4b0a
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package ch.sbb.polarion.extension.pdf_exporter.util.html;

import ch.sbb.polarion.extension.generic.regex.RegexMatcher;
import ch.sbb.polarion.extension.pdf_exporter.util.FileResourceProvider;
import com.polarion.core.util.StringUtils;

import java.util.Map;
import java.util.Optional;

public class ExternalCssInternalizer implements LinkInternalizer {

private static final String URL_REGEX = "url\\(\\s*([\"'])?(?<url>.*?)\\1?\\s*\\)";
private static final String DATA_PRECEDENCE = "data-precedence";
private static final String HREF = "href";
private final FileResourceProvider fileResourceProvider;

public ExternalCssInternalizer(FileResourceProvider fileResourceProvider) {
Expand All @@ -15,8 +20,9 @@ public ExternalCssInternalizer(FileResourceProvider fileResourceProvider) {

@Override
public Optional<String> inline(Map<String, String> attributes) {
String url = attributes.get(HREF);
if (!"stylesheet".equals(attributes.get("rel"))
|| !attributes.containsKey("href")) {
|| StringUtils.isEmptyTrimmed(url)) {
return Optional.empty();
}
StringBuilder inlinedContent = new StringBuilder("<style");
Expand All @@ -28,10 +34,25 @@ public Optional<String> inline(Map<String, String> attributes) {
.append("\"");
}
inlinedContent.append(">");
String url = attributes.get("href");
inlinedContent.append(new String(fileResourceProvider.getResourceAsBytes(url)));

String cssContent = new String(fileResourceProvider.getResourceAsBytes(url));
cssContent = processRelativeUrls(url, cssContent);
inlinedContent.append(cssContent);
inlinedContent.append("</style>");

return Optional.of(inlinedContent.toString());
}

private String processRelativeUrls(String resourceUrl, String cssContent) {
int lastSlashPosition = resourceUrl.lastIndexOf('/');
if (lastSlashPosition == -1) {
return cssContent;
}
String resourcePath = resourceUrl.substring(0, lastSlashPosition + 1);
return RegexMatcher.get(URL_REGEX).useJavaUtil().replace(cssContent, engine -> {
String url = engine.group("url");
return url.startsWith("/") || url.toLowerCase().startsWith("http:") || url.toLowerCase().startsWith("https:") ? null :
"url(%s%s)".formatted(resourcePath, url);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static Map<String, String> parseLinkTagAttributes(String linkTag) {
RegexMatcher.get(ATTRIBUTE_REGEX).useJavaUtil().processEntry(linkTag, regexEngine -> {
String attributeName = regexEngine.group(1);
String attributeValue = regexEngine.group(3);
attributes.put(attributeName, attributeValue);
attributes.put(attributeName.toLowerCase(), attributeValue);
});

return attributes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,30 @@ void shouldConvertStylesheetLinkAndTransferDataPrecedence() {
assertThat(result.get()).isEqualTo("""
<style data-precedence="test-data-precedence">test-stylesheet</style>""");
}

@Test
void shouldConvertStylesheetLinkAndProcessRelativeLinks() {
when(fileResourceProvider.getResourceAsBytes("/some/location/file.css")).thenReturn("""
@font-face {
src: url('../fonts/some-font.woff');
}
@font-face {
src: url('relative2/some-font2.woff');
}
@font-face {
src: url('/non-relative/fonts/some-font3.woff');
}
""".getBytes());
Optional<String> result = cssLinkInliner.inline(Map.of(
"rel", "stylesheet",
"href", "/some/location/file.css",
"data-precedence", "test-data-precedence"));

assertThat(result).isNotEmpty();
assertThat(result.get()).contains(
"src: url(/some/location/../fonts/some-font.woff)",
"src: url(/some/location/relative2/some-font2.woff)",
"src: url('/non-relative/fonts/some-font3.woff')"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ void shouldCallInlinersForLinkTags() {
void shouldParseAttributesAndReplaceLinkTags() {
when(linkInternalizer1.inline(anyMap())).thenReturn(Optional.of("<style>replacement</style>"));
String resultHtml = htmlLinksHelper.internalizeLinks("""
<html lang='en'><head><link attr1="value1" attr2="value2">some content</head>""");
<html lang='en'><head><link attr1="value1" ATTR2="value2">some content</head>""");

assertThat(resultHtml).isEqualTo("""
<html lang='en'><head><style>replacement</style>some content</head>""");
@SuppressWarnings("unchecked")
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
verify(linkInternalizer1).inline(captor.capture());
assertThat(captor.getValue()).containsExactly(Map.entry("attr1", "value1"), Map.entry("attr2", "value2"));
assertThat(captor.getValue()).containsExactly(Map.entry("attr1", "value1"), Map.entry("attr2", "value2")); // also it must lowercase attributes
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,25 @@ void testConverter() {
when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc2);
compareContentUsingReferenceImages(testName + "_complex_with_title", converter.convertToPdf(params, null));

params.setCoverPage(null);
DocumentData<IModule> liveDoc3 = DocumentData.builder(DocumentType.LIVE_DOC, module)
.projectName("Test")
.id("testId")
.title("specialSymbolsTitle")
.content(readHtmlResource("specialSymbols"))
.build();
when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc3);
compareContentUsingReferenceImages(testName + "_special_symbols", converter.convertToPdf(params, null));

DocumentData<IModule> liveDoc4 = DocumentData.builder(DocumentType.LIVE_DOC, module)
.projectName("Test")
.id("testId")
.title("svgImageTitle")
.content(readHtmlResource("svgImage"))
.build();
when(documentDataHelper.getLiveDoc(any(), any())).thenReturn(liveDoc4);
compareContentUsingReferenceImages(testName + "_svg_image", converter.convertToPdf(params, null));

//test wiki page export + {{ REVISION }} placeholder usage
DocumentData<IWikiPage> wikiPage = DocumentData.builder(DocumentType.LIVE_DOC, mock(IWikiPage.class))
.projectName("Test")
Expand All @@ -141,15 +160,15 @@ void testConverter() {
.build();
when(documentDataHelper.getWikiPage(any(), any())).thenReturn(wikiPage);
when(headerFooterSettings.load(any(), any())).thenReturn(new HeaderFooterModel("HL", "HC {{ REVISION }}", "HR", "FL", "FC", "FR {{ PAGE_NUMBER }}"));
params.setCoverPage(null);
params.setDocumentType(DocumentType.WIKI_PAGE);
params.setLocationPath("wikiFolder/wikiPage");
compareContentUsingReferenceImages(testName + "_wiki", converter.convertToPdf(params, null));
}

@SneakyThrows
private void compareContentUsingReferenceImages(String testName, byte[] pdf) {
//NOTE: if something will be changed in the future and images stop being equal then just copy&replace reference resource images
writeReportPdf(testName, "generated", pdf);
//NOTE: if something changes in the future and the images are no longer identical, simply copy&replace the reference resource images
//with the new ones from the reports folder after test execution
List<BufferedImage> resultImages = getAllPagesAsImagesAndLogAsReports(testName, pdf);
for (int i = 0; i < resultImages.size(); i++) {
Expand Down
130 changes: 130 additions & 0 deletions src/test/resources/weasyprint/html/specialSymbols.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="en">
<body>
<table>
<tbody>

<!-- table data taken from https://www.w3schools.com/charsets/ref_utf_arrows.asp -->

<tr>
<th>Char</th>
<th>Dec</th>
<th>Hex</th>
</tr>

<tr><td></td><td>8592</td><td>2190</td></tr>
<tr><td></td><td>8593</td><td>2191</td></tr>
<tr><td></td><td>8594</td><td>2192</td></tr>
<tr><td></td><td>8595</td><td>2193</td></tr>
<tr><td></td><td>8596</td><td>2194</td></tr>
<tr><td></td><td>8597</td><td>2195</td></tr>
<tr><td></td><td>8598</td><td>2196</td></tr>
<tr><td></td><td>8599</td><td>2197</td></tr>
<tr><td></td><td>8600</td><td>2198</td></tr>
<tr><td></td><td>8601</td><td>2199</td></tr>
<tr><td></td><td>8602</td><td>219A</td></tr>
<tr><td></td><td>8603</td><td>219B</td></tr>
<tr><td></td><td>8604</td><td>219C</td></tr>
<tr><td></td><td>8605</td><td>219D</td></tr>
<tr><td></td><td>8606</td><td>219E</td></tr>
<tr><td></td><td>8607</td><td>219F</td></tr>
<tr><td></td><td>8608</td><td>21A0</td></tr>
<tr><td></td><td>8609</td><td>21A1</td></tr>
<tr><td></td><td>8610</td><td>21A2</td></tr>
<tr><td></td><td>8611</td><td>21A3</td></tr>
<tr><td></td><td>8612</td><td>21A4</td></tr>
<tr><td></td><td>8613</td><td>21A5</td></tr>
<tr><td></td><td>8614</td><td>21A6</td></tr>
<tr><td></td><td>8615</td><td>21A7</td></tr>
<tr><td></td><td>8616</td><td>21A8</td></tr>
<tr><td></td><td>8617</td><td>21A9</td></tr>
<tr><td></td><td>8618</td><td>21AA</td></tr>
<tr><td></td><td>8619</td><td>21AB</td></tr>
<tr><td></td><td>8620</td><td>21AC</td></tr>
<tr><td></td><td>8621</td><td>21AD</td></tr>
<tr><td></td><td>8622</td><td>21AE</td></tr>
<tr><td></td><td>8623</td><td>21AF</td></tr>
<tr><td></td><td>8624</td><td>21B0</td></tr>
<tr><td></td><td>8625</td><td>21B1</td></tr>
<tr><td></td><td>8626</td><td>21B2</td></tr>
<tr><td></td><td>8627</td><td>21B3</td></tr>
<tr><td></td><td>8628</td><td>21B4</td></tr>
<tr><td></td><td>8629</td><td>21B5</td></tr>
<tr><td></td><td>8630</td><td>21B6</td></tr>
<tr><td></td><td>8631</td><td>21B7</td></tr>
<tr><td></td><td>8632</td><td>21B8</td></tr>
<tr><td></td><td>8633</td><td>21B9</td></tr>
<tr><td></td><td>8634</td><td>21BA</td></tr>
<tr><td></td><td>8635</td><td>21BB</td></tr>
<tr><td></td><td>8636</td><td>21BC</td></tr>
<tr><td></td><td>8637</td><td>21BD</td></tr>
<tr><td></td><td>8638</td><td>21BE</td></tr>
<tr><td></td><td>8639</td><td>21BF</td></tr>
<tr><td></td><td>8640</td><td>21C0</td></tr>
<tr><td></td><td>8641</td><td>21C1</td></tr>
<tr><td></td><td>8642</td><td>21C2</td></tr>
<tr><td></td><td>8643</td><td>21C3</td></tr>
<tr><td></td><td>8644</td><td>21C4</td></tr>
<tr><td></td><td>8645</td><td>21C5</td></tr>
<tr><td></td><td>8646</td><td>21C6</td></tr>
<tr><td></td><td>8647</td><td>21C7</td></tr>
<tr><td></td><td>8648</td><td>21C8</td></tr>
<tr><td></td><td>8649</td><td>21C9</td></tr>
<tr><td></td><td>8650</td><td>21CA</td></tr>
<tr><td></td><td>8651</td><td>21CB</td></tr>
<tr><td></td><td>8652</td><td>21CC</td></tr>
<tr><td></td><td>8653</td><td>21CD</td></tr>
<tr><td></td><td>8654</td><td>21CE</td></tr>
<tr><td></td><td>8655</td><td>21CF</td></tr>
<tr><td></td><td>8656</td><td>21D0</td></tr>
<tr><td></td><td>8657</td><td>21D1</td></tr>
<tr><td></td><td>8658</td><td>21D2</td></tr>
<tr><td></td><td>8659</td><td>21D3</td></tr>
<tr><td></td><td>8660</td><td>21D4</td></tr>
<tr><td></td><td>8661</td><td>21D5</td></tr>
<tr><td></td><td>8662</td><td>21D6</td></tr>
<tr><td></td><td>8663</td><td>21D7</td></tr>
<tr><td></td><td>8664</td><td>21D8</td></tr>
<tr><td></td><td>8665</td><td>21D9</td></tr>
<tr><td></td><td>8666</td><td>21DA</td></tr>
<tr><td></td><td>8667</td><td>21DB</td></tr>
<tr><td></td><td>8668</td><td>21DC</td></tr>
<tr><td></td><td>8669</td><td>21DD</td></tr>
<tr><td></td><td>8670</td><td>21DE</td></tr>
<tr><td></td><td>8671</td><td>21DF</td></tr>
<tr><td></td><td>8672</td><td>21E0</td></tr>
<tr><td></td><td>8673</td><td>21E1</td></tr>
<tr><td></td><td>8674</td><td>21E2</td></tr>
<tr><td></td><td>8675</td><td>21E3</td></tr>
<tr><td></td><td>8676</td><td>21E4</td></tr>
<tr><td></td><td>8677</td><td>21E5</td></tr>
<tr><td></td><td>8678</td><td>21E6</td></tr>
<tr><td></td><td>8679</td><td>21E7</td></tr>
<tr><td></td><td>8680</td><td>21E8</td></tr>
<tr><td></td><td>8681</td><td>21E9</td></tr>
<tr><td></td><td>8682</td><td>21EA</td></tr>
<tr><td></td><td>8683</td><td>21EB</td></tr>
<tr><td></td><td>8684</td><td>21EC</td></tr>
<tr><td></td><td>8685</td><td>21ED</td></tr>
<tr><td></td><td>8686</td><td>21EE</td></tr>
<tr><td></td><td>8687</td><td>21EF</td></tr>
<tr><td></td><td>8688</td><td>21F0</td></tr>
<tr><td></td><td>8689</td><td>21F1</td></tr>
<tr><td></td><td>8690</td><td>21F2</td></tr>
<tr><td></td><td>8691</td><td>21F3</td></tr>
<tr><td></td><td>8692</td><td>21F4</td></tr>
<tr><td></td><td>8693</td><td>21F5</td></tr>
<tr><td></td><td>8694</td><td>21F6</td></tr>
<tr><td></td><td>8695</td><td>21F7</td></tr>
<tr><td></td><td>8696</td><td>21F8</td></tr>
<tr><td></td><td>8697</td><td>21F9</td></tr>
<tr><td></td><td>8698</td><td>21FA</td></tr>
<tr><td></td><td>8699</td><td>21FB</td></tr>
<tr><td></td><td>8700</td><td>21FC</td></tr>
<tr><td></td><td>8701</td><td>21FD</td></tr>
<tr><td></td><td>8702</td><td>21FE</td></tr>
<tr><td></td><td>8703</td><td>21FF</td></tr>
</tbody>
</table>
</body>
</html>
22 changes: 22 additions & 0 deletions src/test/resources/weasyprint/html/svgImage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<body>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="450" height="400" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g stroke="#000" stroke-width="3.5">
<ellipse cx="225" cy="200" rx="205" ry="175" fill="#e6f0fa"/>
<g stroke-linejoin="round">
<rect transform="rotate(24.644)" x="272.9" y="-30.394" width="46.488" height="46.488" fill="#9ade00"/>
<path d="m281.09 233.89-54.361-23.887 47.867-35.134z" fill="#3cb371"/>
<path d="m235.2 327.38-25.016-29.542 20.365-32.92 37.602 9.1958 2.8741 38.603z" fill="#fd7118"/>
<path d="m116.6 256.91 26.929-12.304 24.311 19.257 3.3863 36.318-20.088 26.03-28.436-3.8587-15.371-30.842z" fill="#ff2a2a"/>
<path d="m105.76 230.16 36.583-10.533 22.896-36.272-88.191 16.11z" fill="#dda0dd"/>
<path d="m72.92 146.19 11.424-45.042 5.855 32.108 46.593 13.339z" fill="#fd7"/>
<rect transform="rotate(48.16)" x="155.93" y="-70.574" width="69.101" height="23.166" fill="#364e59"/>
<path d="m339.24 138.66 42.548-5.6497-13.92 58.209z" fill="#b50000"/>
<path d="m397 262-35.122 36.771-36.403 0.38891-1.2812-36.382 35.122-36.771 36.403-0.38891z" fill="#4682b4"/>
</g>
</g>
</svg>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 79a4b0a

Please sign in to comment.