diff options
| author | Michael Williamson <mike@zwobble.org> | 2021-08-01 17:11:32 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2021-08-01 17:11:32 +0100 |
| commit | 67142b61cdbdaca99effb4f18e86b56bcb07c57e (patch) | |
| tree | 31991b4740ba1722147160ffc814dfbe45c0b6f6 | |
| parent | 2a3c8d6d3b4d08bd70f30cd35bcf7ddd450ac25a (diff) | |
Handle internal hyperlinks created with complex fields
| -rw-r--r-- | NEWS | 4 | ||||
| -rw-r--r-- | lib/docx/body-reader.js | 29 | ||||
| -rw-r--r-- | test/docx/body-reader.tests.js | 35 |
3 files changed, 54 insertions, 14 deletions
@@ -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") ) |
