aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2021-08-01 17:11:32 +0100
committerMichael Williamson <mike@zwobble.org>2021-08-01 17:11:32 +0100
commit67142b61cdbdaca99effb4f18e86b56bcb07c57e (patch)
tree31991b4740ba1722147160ffc814dfbe45c0b6f6
parent2a3c8d6d3b4d08bd70f30cd35bcf7ddd450ac25a (diff)
Handle internal hyperlinks created with complex fields
-rw-r--r--NEWS4
-rw-r--r--lib/docx/body-reader.js29
-rw-r--r--test/docx/body-reader.tests.js35
3 files changed, 54 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index e0f134b..2864efc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+# 1.4.19
+
+* Handle internal hyperlinks created with complex fields.
+
# 1.4.18
* When extracting raw text, convert tab elements to tab characters.
diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js
index 90c2b39..0d04ccd 100644
--- a/lib/docx/body-reader.js
+++ b/lib/docx/body-reader.js
@@ -139,28 +139,33 @@ function BodyReader(options) {
} else if (type === "end") {
complexFieldStack.pop();
} else if (type === "separate") {
- var href = parseHyperlinkFieldCode(currentInstrText.join(''));
- var complexField = href === null ? unknownComplexField : {type: "hyperlink", href: href};
+ var hyperlinkOptions = parseHyperlinkFieldCode(currentInstrText.join(''));
+ var complexField = hyperlinkOptions === null ? unknownComplexField : {type: "hyperlink", options: hyperlinkOptions};
complexFieldStack.pop();
complexFieldStack.push(complexField);
}
return emptyResult();
}
- function currentHyperlinkHref() {
+ function currentHyperlinkOptions() {
var topHyperlink = _.last(complexFieldStack.filter(function(complexField) {
return complexField.type === "hyperlink";
}));
- return topHyperlink ? topHyperlink.href : null;
+ return topHyperlink ? topHyperlink.options : null;
}
function parseHyperlinkFieldCode(code) {
- var result = /\s*HYPERLINK "(.*)"/.exec(code);
- if (result) {
- return result[1];
- } else {
- return null;
+ var externalLinkResult = /\s*HYPERLINK "(.*)"/.exec(code);
+ if (externalLinkResult) {
+ return {href: externalLinkResult[1]};
+ }
+
+ var internalLinkResult = /\s*HYPERLINK\s+\\l\s+"(.*)"/.exec(code);
+ if (internalLinkResult) {
+ return {anchor: internalLinkResult[1]};
}
+
+ return null;
}
function readInstrText(element) {
@@ -236,9 +241,9 @@ function BodyReader(options) {
var properties = _.find(children, isRunProperties);
children = children.filter(negate(isRunProperties));
- var hyperlinkHref = currentHyperlinkHref();
- if (hyperlinkHref !== null) {
- children = [new documents.Hyperlink(children, {href: hyperlinkHref})];
+ var hyperlinkOptions = currentHyperlinkOptions();
+ if (hyperlinkOptions !== null) {
+ children = [new documents.Hyperlink(children, hyperlinkOptions)];
}
return new documents.Run(children, properties);
diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js
index 49ea73c..c539aad 100644
--- a/test/docx/body-reader.tests.js
+++ b/test/docx/body-reader.tests.js
@@ -246,7 +246,7 @@ test("complex fields", (function() {
function isHyperlinkedRun(hyperlinkProperties) {
return isRun({
children: contains(
- isHyperlink(_.extend({href: uri}, hyperlinkProperties))
+ isHyperlink(hyperlinkProperties)
)
});
}
@@ -257,7 +257,7 @@ test("complex fields", (function() {
assert.deepEqual(instrText, []);
},
- "runs in a complex field for hyperlinks are read as hyperlinks": function() {
+ "runs in a complex field for hyperlink without switch are read as external hyperlinks": function() {
var hyperlinkRunXml = runOfText("this is a hyperlink");
var paragraphXml = new XmlElement("w:p", {}, [
beginXml,
@@ -272,6 +272,33 @@ test("complex fields", (function() {
isEmptyRun,
isEmptyHyperlinkedRun,
isHyperlinkedRun({
+ href: uri,
+ children: contains(
+ isText("this is a hyperlink")
+ )
+ }),
+ isEmptyRun
+ ));
+ },
+
+ "runs in a complex field for hyperlink with l switch are read as internal hyperlinks": function() {
+ var hyperlinkRunXml = runOfText("this is a hyperlink");
+ var paragraphXml = new XmlElement("w:p", {}, [
+ beginXml,
+ new XmlElement("w:instrText", {}, [
+ xml.text(' HYPERLINK \\l "InternalLink"')
+ ]),
+ separateXml,
+ hyperlinkRunXml,
+ endXml
+ ]);
+ var paragraph = readXmlElementValue(paragraphXml);
+
+ assertThat(paragraph.children, contains(
+ isEmptyRun,
+ isEmptyHyperlinkedRun,
+ isHyperlinkedRun({
+ anchor: "InternalLink",
children: contains(
isText("this is a hyperlink")
)
@@ -324,6 +351,7 @@ test("complex fields", (function() {
isEmptyRun,
isEmptyHyperlinkedRun,
isHyperlinkedRun({
+ href: uri,
children: contains(
isText("this is a hyperlink")
)
@@ -356,6 +384,7 @@ test("complex fields", (function() {
isEmptyHyperlinkedRun,
isEmptyHyperlinkedRun,
isHyperlinkedRun({
+ href: uri,
children: contains(
isText("this is a hyperlink")
)
@@ -387,6 +416,7 @@ test("complex fields", (function() {
isEmptyHyperlinkedRun,
isEmptyHyperlinkedRun,
isHyperlinkedRun({
+ href: uri,
children: contains(
isText("John Doe")
)
@@ -415,6 +445,7 @@ test("complex fields", (function() {
isEmptyHyperlinkedRun,
isEmptyHyperlinkedRun,
isHyperlinkedRun({
+ href: uri,
children: contains(
isText("this is a hyperlink")
)