aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Lehman <jonathan.lehman91@gmail.com>2017-02-03 17:00:21 -0500
committerJonathan Lehman <jonathan.lehman91@gmail.com>2017-02-03 17:00:21 -0500
commitee0baa36779e3ae2f2da9abe7e1c1c83fdcdf8fb (patch)
tree8594358f5a542453c35c1083b875f9d8fce5ef6e
parent15f4381cf54901895836551a30f66c0cee974a0c (diff)
Enable hyperlinks that are not defined with w:hyperlink
-rw-r--r--lib/docx/body-reader.js32
-rw-r--r--test/docx/body-reader.tests.js29
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) {