From 75e327ddfff69d7bdbaff994e4662f7c37cc2b85 Mon Sep 17 00:00:00 2001 From: Jonathan Lehman Date: Fri, 17 Feb 2017 11:59:38 -0500 Subject: Handle split instrText elements --- lib/docx/body-reader.js | 12 +++++--- test/docx/body-reader.tests.js | 64 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js index e92f8b4..9345e02 100644 --- a/lib/docx/body-reader.js +++ b/lib/docx/body-reader.js @@ -21,6 +21,7 @@ function createBodyReader(options) { function BodyReader(options) { var fieldHyperlink = null; + var currentInstrText = []; var relationships = options.relationships; var contentTypes = options.contentTypes; var docxFile = options.docxFile; @@ -159,14 +160,17 @@ function BodyReader(options) { var type = element.attributes["w:fldCharType"]; if (type === "end") { fieldHyperlink = null; + } else if (type === "separate") { + var hyperlink = parseHyperlinkFieldCode(currentInstrText.join('')); + if (hyperlink !== null) { + fieldHyperlink = hyperlink; + } + currentInstrText = []; } return emptyResult(); }, "w:instrText": function(element) { - var hyperlink = parseHyperlinkFieldCode(element.text()); - if (hyperlink !== null) { - fieldHyperlink = hyperlink; - } + currentInstrText.push(element.text()); return emptyResult(); }, "w:t": function(element) { diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js index ab4995c..4cb7bb3 100644 --- a/test/docx/body-reader.tests.js +++ b/test/docx/body-reader.tests.js @@ -148,6 +148,9 @@ test("complex fields", (function() { var endXml = new XmlElement("w:r", {}, [ new XmlElement("w:fldChar", {"w:fldCharType": "end"}) ]); + var separateXml = new XmlElement("w:r", {}, [ + new XmlElement("w:fldChar", {"w:fldCharType": "separate"}) + ]); var hyperlinkInstrText = new XmlElement("w:instrText", {}, [ xml.text(' HYPERLINK "' + uri + '"') ]); @@ -160,10 +163,10 @@ test("complex fields", (function() { "runs in a complex field for hyperlinks are read as hyperlinks": function() { var hyperlinkRunXml = runOfText("this is a hyperlink"); - var afterEndXml = runOfText("this will not be a hyperlink"); var paragraphXml = new XmlElement("w:p", {}, [ beginXml, hyperlinkInstrText, + separateXml, hyperlinkRunXml, endXml ]); @@ -171,6 +174,14 @@ test("complex fields", (function() { assertThat(paragraph.children, contains( isEmptyRun, + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: [] + }) + ) + }), isRun({ children: contains( isHyperlink({ @@ -190,6 +201,7 @@ test("complex fields", (function() { var paragraphXml = new XmlElement("w:p", {}, [ beginXml, hyperlinkInstrText, + separateXml, endXml, afterEndXml ]); @@ -197,6 +209,14 @@ test("complex fields", (function() { assertThat(paragraph.children, contains( isEmptyRun, + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: [] + }) + ) + }), isEmptyRun, isRun({ children: contains( @@ -204,6 +224,48 @@ test("complex fields", (function() { ) }) )); + }, + + "can handle split instrText elements": function() { + var hyperlinkRunXml = runOfText("this is a hyperlink"); + var hyperlinkInstrTextPart1 = new XmlElement("w:instrText", {}, [ + xml.text(" HYPE") + ]); + var hyperlinkInstrTextPart2 = new XmlElement("w:instrText", {}, [ + xml.text('RLINK "' + uri + '"') + ]); + var paragraphXml = new XmlElement("w:p", {}, [ + beginXml, + hyperlinkInstrTextPart1, + hyperlinkInstrTextPart2, + separateXml, + hyperlinkRunXml, + endXml + ]); + var paragraph = readXmlElementValue(paragraphXml); + + assertThat(paragraph.children, contains( + isEmptyRun, + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: [] + }) + ) + }), + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: contains( + isText("this is a hyperlink") + ) + }) + ) + }), + isEmptyRun + )); } }; })()); -- cgit v1.2.3 From c044f44f404bb4e38d38082d2989c5686604bb3e Mon Sep 17 00:00:00 2001 From: Jonathan Lehman Date: Fri, 17 Feb 2017 12:35:26 -0500 Subject: Handle nested complex fields --- lib/docx/body-reader.js | 13 ++++++------- test/docx/body-reader.tests.js | 44 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js index 9345e02..e671f53 100644 --- a/lib/docx/body-reader.js +++ b/lib/docx/body-reader.js @@ -20,7 +20,7 @@ function createBodyReader(options) { } function BodyReader(options) { - var fieldHyperlink = null; + var fieldHyperlinks = []; var currentInstrText = []; var relationships = options.relationships; var contentTypes = options.contentTypes; @@ -148,8 +148,9 @@ function BodyReader(options) { var properties = _.find(children, isRunProperties); children = children.filter(negate(isRunProperties)); - if (fieldHyperlink !== null) { - children = [new documents.Hyperlink(children, {href: fieldHyperlink})]; + var validFieldHyperlinks = _.compact(fieldHyperlinks); + if (validFieldHyperlinks.length !== 0) { + children = [new documents.Hyperlink(children, {href: _.last(validFieldHyperlinks)})]; } return new documents.Run(children, properties); @@ -159,12 +160,10 @@ function BodyReader(options) { "w:fldChar": function(element) { var type = element.attributes["w:fldCharType"]; if (type === "end") { - fieldHyperlink = null; + fieldHyperlinks.pop(); } else if (type === "separate") { var hyperlink = parseHyperlinkFieldCode(currentInstrText.join('')); - if (hyperlink !== null) { - fieldHyperlink = hyperlink; - } + fieldHyperlinks.push(hyperlink); currentInstrText = []; } return emptyResult(); diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js index 4cb7bb3..1882f3a 100644 --- a/test/docx/body-reader.tests.js +++ b/test/docx/body-reader.tests.js @@ -154,6 +154,7 @@ test("complex fields", (function() { var hyperlinkInstrText = new XmlElement("w:instrText", {}, [ xml.text(' HYPERLINK "' + uri + '"') ]); + var hyperlinkRunXml = runOfText("this is a hyperlink"); return { "stores instrText returns empty result": function() { @@ -227,7 +228,6 @@ test("complex fields", (function() { }, "can handle split instrText elements": function() { - var hyperlinkRunXml = runOfText("this is a hyperlink"); var hyperlinkInstrTextPart1 = new XmlElement("w:instrText", {}, [ xml.text(" HYPE") ]); @@ -266,6 +266,48 @@ test("complex fields", (function() { }), isEmptyRun )); + }, + + "hyperlink with a nested complex field uses the outer hyperlink": function() { + var authorInstrText = new XmlElement("w:instrText", {}, [ + xml.text(' AUTHOR "John Doe"') + ]); + var paragraphXml = new XmlElement("w:p", {}, [ + beginXml, + beginXml, + authorInstrText, + endXml, + hyperlinkInstrText, + separateXml, + hyperlinkRunXml, + endXml + ]); + var paragraph = readXmlElementValue(paragraphXml); + + assertThat(paragraph.children, contains( + isEmptyRun, + isEmptyRun, + isEmptyRun, + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: [] + }) + ) + }), + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: contains( + isText("this is a hyperlink") + ) + }) + ) + }), + isEmptyRun + )); } }; })()); -- cgit v1.2.3 From 2555036e27441428666e08408a082346fbef3b62 Mon Sep 17 00:00:00 2001 From: Jonathan Lehman Date: Sat, 18 Feb 2017 11:40:43 -0500 Subject: Store all complex fields with types - Currently only stores hyperlink complex fields and all other fields are null --- lib/docx/body-reader.js | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js index e671f53..11aeec5 100644 --- a/lib/docx/body-reader.js +++ b/lib/docx/body-reader.js @@ -20,7 +20,7 @@ function createBodyReader(options) { } function BodyReader(options) { - var fieldHyperlinks = []; + var complexFields = []; var currentInstrText = []; var relationships = options.relationships; var contentTypes = options.contentTypes; @@ -148,9 +148,9 @@ function BodyReader(options) { var properties = _.find(children, isRunProperties); children = children.filter(negate(isRunProperties)); - var validFieldHyperlinks = _.compact(fieldHyperlinks); - if (validFieldHyperlinks.length !== 0) { - children = [new documents.Hyperlink(children, {href: _.last(validFieldHyperlinks)})]; + var scopedHyperlink = scopedComplexFieldOfType(complexFields, "hyperlink"); + if (scopedHyperlink !== undefined) { + children = [new documents.Hyperlink(children, {href: scopedHyperlink.href})]; } return new documents.Run(children, properties); @@ -160,10 +160,14 @@ function BodyReader(options) { "w:fldChar": function(element) { var type = element.attributes["w:fldCharType"]; if (type === "end") { - fieldHyperlinks.pop(); + complexFields.pop(); } else if (type === "separate") { - var hyperlink = parseHyperlinkFieldCode(currentInstrText.join('')); - fieldHyperlinks.push(hyperlink); + var href = parseHyperlinkFieldCode(currentInstrText.join('')); + if (href !== null) { + complexFields.push({type: "hyperlink", href: href}); + } else { + complexFields.push(null); + } currentInstrText = []; } return emptyResult(); @@ -533,3 +537,13 @@ function parseHyperlinkFieldCode(code) { return null; } } + +function complexFieldsOfType(complexFields, type) { + return complexFields.filter(function(complexField) { + return complexField.type === type; + }); +} + +function scopedComplexFieldOfType(complexFields, type) { + return _.last(complexFieldsOfType(complexFields, type)); +} -- cgit v1.2.3 From 35df4eed2249ee7e582cca4d371a78ce92c44d2a Mon Sep 17 00:00:00 2001 From: Jonathan Lehman Date: Sat, 18 Feb 2017 11:48:22 -0500 Subject: Add test case for complex fields nested within a hyperlink complex field --- test/docx/body-reader.tests.js | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js index 1882f3a..a670202 100644 --- a/test/docx/body-reader.tests.js +++ b/test/docx/body-reader.tests.js @@ -308,6 +308,55 @@ test("complex fields", (function() { }), isEmptyRun )); + }, + + "complex field nested within a hyperlink complex field is wrapped with the hyperlink": function() { + var authorInstrText = new XmlElement("w:instrText", {}, [ + xml.text(' AUTHOR "John Doe"') + ]); + var paragraphXml = new XmlElement("w:p", {}, [ + beginXml, + hyperlinkInstrText, + separateXml, + hyperlinkRunXml, + beginXml, + authorInstrText, + endXml, + endXml + ]); + var paragraph = readXmlElementValue(paragraphXml); + + assertThat(paragraph.children, contains( + isEmptyRun, + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: [] + }) + ) + }), + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: contains( + isText("this is a hyperlink") + ) + }) + ) + }), + isRun({ + children: contains( + isHyperlink({ + href: uri, + children: [] + }) + ) + }), + isEmptyRun, + isEmptyRun + )); } }; })()); -- cgit v1.2.3