diff options
| author | Jonathan Lehman <jonathan.lehman91@gmail.com> | 2017-02-03 17:00:21 -0500 |
|---|---|---|
| committer | Jonathan Lehman <jonathan.lehman91@gmail.com> | 2017-02-03 17:00:21 -0500 |
| commit | ee0baa36779e3ae2f2da9abe7e1c1c83fdcdf8fb (patch) | |
| tree | 8594358f5a542453c35c1083b875f9d8fce5ef6e | |
| parent | 15f4381cf54901895836551a30f66c0cee974a0c (diff) | |
Enable hyperlinks that are not defined with w:hyperlink
| -rw-r--r-- | lib/docx/body-reader.js | 32 | ||||
| -rw-r--r-- | test/docx/body-reader.tests.js | 29 |
2 files changed, 56 insertions, 5 deletions
diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js index 529d6f2..8e71aa6 100644 --- a/lib/docx/body-reader.js +++ b/lib/docx/body-reader.js @@ -6,6 +6,7 @@ var documents = require("../documents"); var Result = require("../results").Result; var warning = require("../results").warning; var uriToZipEntryName = require("./uris").uriToZipEntryName; +var lastInstrText = null; function BodyReader(options) { @@ -133,14 +134,27 @@ function BodyReader(options) { return readXmlElements(element.children) .map(function(children) { var properties = _.find(children, isRunProperties); - - return new documents.Run( - children.filter(negate(isRunProperties)), - properties - ); + var filteredChildren = children.filter(negate(isRunProperties)); + + if (properties && properties.styleName === 'Hyperlink' && lastInstrText) { + return new documents.Hyperlink(filteredChildren, {href: parseHyperlink(lastInstrText)}); + } + + return new documents.Run(filteredChildren, properties); }); }, "w:rPr": readRunProperties, + "w:fldChar": function(element) { + var type = element.attributes["w:fldCharType"]; + if (type === 'end') { + clearState(); + } + return emptyResult(); + }, + "w:instrText": function(element) { + lastInstrText = (element.children[0] || {}).value || ''; + return emptyResult(); + }, "w:t": function(element) { return elementResult(new documents.Text(element.text())); }, @@ -491,3 +505,11 @@ function joinElements(first, second) { function identity(value) { return value; } + +function clearState() { + lastInstrText = null; +} + +function parseHyperlink(instrText) { + return (instrText.match(/HYPERLINK "(.*)"/) || [])[1]; +} diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js index f605c2d..d1f0311 100644 --- a/test/docx/body-reader.tests.js +++ b/test/docx/body-reader.tests.js @@ -141,6 +141,18 @@ test("numbering properties are ignored if w:numId is missing", function() { assert.equal(numberingLevel, null); }); +test("stores instrText returns empty result", function() { + var instrTextXml = new XmlElement("w:instrText", {}, [xml.text(' HYPERLINK "http://example.com"')]); + var instrText = readXmlElementValue(instrTextXml); + assert.deepEqual(instrText, []); +}); + +test("run is wrapped in a hyperlink if the runStyle is Hyperlink", function() { + var hyperlink = createHyperlink("http://example.com"); + assert.equal(hyperlink.type, 'hyperlink'); + assert.equal(hyperlink.href, 'http://example.com'); +}); + test("run has no style if it has no properties", function() { var runXml = runWithProperties([]); var run = readXmlElementValue(runXml); @@ -861,6 +873,23 @@ function createLinkedBlip(relationshipId) { return new XmlElement("a:blip", {"r:link": relationshipId}); } +function createHyperlink(link) { + var beginXml = new XmlElement("w:r", {}, [ + new XmlElement("w:fldChar", {"w:fldCharType": "begin"}) + ]); + var endXml = new XmlElement("w:r", {}, [ + new XmlElement("w:fldChar", {"w:fldCharType": "end"}) + ]); + var instrTextXml = new XmlElement("w:instrText", {}, [xml.text(' HYPERLINK "' + link + '"')]); + var instrRunXml = new XmlElement("w:r", {}, [instrTextXml]); + var styleXml = new XmlElement("w:rStyle", {"w:val": "Hyperlink"}); + var runStyleXml = runWithProperties([styleXml]); + var parXml = new XmlElement("w:p", {}, [beginXml, instrRunXml, runStyleXml, endXml]); + var styles = new Styles({}, {"Hyperlink": {name: "Hyperlink"}}); + var par = readXmlElementValue(parXml, {styles: styles}); + return par.children[2]; +} + function assertImageBuffer(element, expectedImageBuffer) { return element.read() .then(function(readValue) { |
