aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2021-08-01 17:32:46 +0100
committerMichael Williamson <mike@zwobble.org>2021-08-01 17:32:46 +0100
commit554a0fe289bb74e5048b209546d22c423d33c528 (patch)
tree62908056e7cd1f8c128554f39d39d825a58122d2 /src
parent59f4df1d2d39e1dee5278626bd2efb16d4a56847 (diff)
Handle internal hyperlinks created with complex fields
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java43
-rw-r--r--src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java29
2 files changed, 53 insertions, 19 deletions
diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
index 366cf16..b6bd51e 100644
--- a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
+++ b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
@@ -40,16 +40,16 @@ class StatefulBodyXmlReader {
private interface ComplexField {
ComplexField UNKNOWN = new ComplexField() {};
- static ComplexField hyperlink(String href) {
- return new HyperlinkComplexField(href);
+ static ComplexField hyperlink(Function<List<DocumentElement>, Hyperlink> childrenToHyperlink) {
+ return new HyperlinkComplexField(childrenToHyperlink);
}
}
private static class HyperlinkComplexField implements ComplexField {
- private final String href;
+ private final Function<List<DocumentElement>, Hyperlink> childrenToHyperlink;
- private HyperlinkComplexField(String href) {
- this.href = href;
+ private HyperlinkComplexField(Function<List<DocumentElement>, Hyperlink> childrenToHyperlink) {
+ this.childrenToHyperlink = childrenToHyperlink;
}
}
@@ -173,9 +173,9 @@ class StatefulBodyXmlReader {
readRunStyle(properties),
readElements(element.getChildren()),
(style, children) -> {
- Optional<String> hyperlinkHref = currentHyperlinkHref();
- if (hyperlinkHref.isPresent()) {
- children = list(Hyperlink.href(hyperlinkHref.get(), Optional.empty(), children));
+ Optional<HyperlinkComplexField> hyperlinkComplexField = currentHyperlinkComplexField();
+ if (hyperlinkComplexField.isPresent()) {
+ children = list(hyperlinkComplexField.get().childrenToHyperlink.apply(children));
}
return new Run(
@@ -193,9 +193,8 @@ class StatefulBodyXmlReader {
);
}
- private Optional<String> currentHyperlinkHref() {
- return tryGetLast(lazyFilter(this.complexFieldStack, HyperlinkComplexField.class))
- .map(field -> field.href);
+ private Optional<HyperlinkComplexField> currentHyperlinkComplexField() {
+ return tryGetLast(lazyFilter(this.complexFieldStack, HyperlinkComplexField.class));
}
private boolean isBold(XmlElementLike properties) {
@@ -287,14 +286,22 @@ class StatefulBodyXmlReader {
return ReadResult.EMPTY_SUCCESS;
}
- private Optional<String> parseHyperlinkFieldCode(String instrText) {
- Pattern pattern = Pattern.compile("\\s*HYPERLINK \"(.*)\"");
- Matcher matcher = pattern.matcher(instrText);
- if (matcher.lookingAt()) {
- return Optional.of(matcher.group(1));
- } else {
- return Optional.empty();
+ private Optional<Function<List<DocumentElement>, Hyperlink>> parseHyperlinkFieldCode(String instrText) {
+ Pattern externalLinkPattern = Pattern.compile("\\s*HYPERLINK \"(.*)\"");
+ Matcher externalLinkMatcher = externalLinkPattern.matcher(instrText);
+ if (externalLinkMatcher.lookingAt()) {
+ String href = externalLinkMatcher.group(1);
+ return Optional.of(children -> Hyperlink.href(href, Optional.empty(), children));
+ }
+
+ Pattern internalLinkPattern = Pattern.compile("\\s*HYPERLINK\\s+\\\\l\\s+\"(.*)\"");
+ Matcher internalLinkMatcher = internalLinkPattern.matcher(instrText);
+ if (internalLinkMatcher.lookingAt()) {
+ String anchor = internalLinkMatcher.group(1);
+ return Optional.of(children -> Hyperlink.anchor(anchor, Optional.empty(), children));
}
+
+ return Optional.empty();
}
private InternalResult<Optional<Style>> readParagraphStyle(XmlElementLike properties) {
diff --git a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java
index 75af768..6c04f80 100644
--- a/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java
+++ b/src/test/java/org/zwobble/mammoth/tests/docx/BodyXmlTests.java
@@ -291,7 +291,7 @@ public class BodyXmlTests {
}
@Test
- public void runsInAComplexFieldForHyperlinksAreReadAsHyperlinks() {
+ public void runsInAComplexFieldForHyperlinksWithoutSwitchAreReadAsExternalHyperlinks() {
XmlElement hyperlinkRunXml = runXml("this is a hyperlink");
XmlElement element = paragraphXml(list(
BEGIN_COMPLEX_FIELD,
@@ -316,6 +316,33 @@ public class BodyXmlTests {
}
@Test
+ public void runsInAComplexFieldForHyperlinksWithLSwitchAreReadAsInternalHyperlinks() {
+ XmlElement hyperlinkRunXml = runXml("this is a hyperlink");
+ XmlElement element = paragraphXml(list(
+ BEGIN_COMPLEX_FIELD,
+ element("w:instrText", list(
+ XmlNodes.text(" HYPERLINK \\l \"InternalLink\"")
+ )),
+ SEPARATE_COMPLEX_FIELD,
+ hyperlinkRunXml,
+ END_COMPLEX_FIELD
+ ));
+ DocumentElement paragraph = readSuccess(bodyReader(), element);
+
+ assertThat(paragraph, isParagraph(hasChildren(
+ isEmptyRun(),
+ isEmptyHyperlinkedRun(),
+ isHyperlinkedRun(
+ hasAnchor("InternalLink"),
+ hasChildren(
+ isTextElement("this is a hyperlink")
+ )
+ ),
+ isEmptyRun()
+ )));
+ }
+
+ @Test
public void runsAfterAComplexFieldForHyperlinksAreNotReadAsHyperlinks() {
XmlElement afterEndXml = runXml("this will not be a hyperlink");
XmlElement element = paragraphXml(list(