diff options
| author | Michael Williamson <mike@zwobble.org> | 2018-01-16 22:21:21 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2018-01-16 22:21:21 +0000 |
| commit | cc1b5b19480befc5611a469424a5ae16f9ebce21 (patch) | |
| tree | 4774f2cbbae87b2b723902d7154b171c2060db78 | |
| parent | 062eb4ff3fea9c49cfce841327d01ddd0099264e (diff) | |
Read types of relationships
| -rw-r--r-- | lib/docx/body-reader.js | 8 | ||||
| -rw-r--r-- | lib/docx/docx-reader.js | 2 | ||||
| -rw-r--r-- | lib/docx/relationships-reader.js | 37 | ||||
| -rw-r--r-- | test/docx/body-reader.tests.js | 53 | ||||
| -rw-r--r-- | test/docx/relationships-reader.tests.js | 65 |
5 files changed, 138 insertions, 27 deletions
diff --git a/lib/docx/body-reader.js b/lib/docx/body-reader.js index 5958efe..5264d55 100644 --- a/lib/docx/body-reader.js +++ b/lib/docx/body-reader.js @@ -236,7 +236,7 @@ function BodyReader(options) { } if (relationshipId) { - var href = relationships[relationshipId].target; + var href = relationships.findTargetByRelationshipId(relationshipId); if (anchor) { href = uris.replaceFragment(href, anchor); } @@ -427,11 +427,11 @@ function BodyReader(options) { function findBlipImageFile(blip) { var embedRelationshipId = blip.attributes["r:embed"]; - var linkRelationshipid = blip.attributes["r:link"]; + var linkRelationshipId = blip.attributes["r:link"]; if (embedRelationshipId) { return findEmbeddedImageFile(embedRelationshipId); } else { - var imagePath = relationships[linkRelationshipid].target; + var imagePath = relationships.findTargetByRelationshipId(linkRelationshipId); return { path: imagePath, read: files.read.bind(files, imagePath) @@ -452,7 +452,7 @@ function BodyReader(options) { } function findEmbeddedImageFile(relationshipId) { - var path = uris.uriToZipEntryName("word", relationships[relationshipId].target); + var path = uris.uriToZipEntryName("word", relationships.findTargetByRelationshipId(relationshipId)); return { path: path, read: docxFile.read.bind(docxFile, path) diff --git a/lib/docx/docx-reader.js b/lib/docx/docx-reader.js index db15b95..54f2a3b 100644 --- a/lib/docx/docx-reader.js +++ b/lib/docx/docx-reader.js @@ -91,7 +91,7 @@ function readXmlFileWithBody(filename, options, func) { var readRelationshipsFromZipFile = xmlFileReader({ filename: relationshipsFilename(filename), readElement: relationshipsReader.readRelationships, - defaultValue: {} + defaultValue: relationshipsReader.defaultValue }); return readRelationshipsFromZipFile(options.docxFile).then(function(relationships) { diff --git a/lib/docx/relationships-reader.js b/lib/docx/relationships-reader.js index 93fc618..4db172e 100644 --- a/lib/docx/relationships-reader.js +++ b/lib/docx/relationships-reader.js @@ -1,14 +1,43 @@ exports.readRelationships = readRelationships; +exports.defaultValue = new Relationships([]); +exports.Relationships = Relationships; function readRelationships(element) { - var relationships = {}; + var relationships = []; element.children.forEach(function(child) { if (child.name === "{http://schemas.openxmlformats.org/package/2006/relationships}Relationship") { - relationships[child.attributes.Id] = { - target: child.attributes.Target + var relationship = { + relationshipId: child.attributes.Id, + target: child.attributes.Target, + type: child.attributes.Type }; + relationships.push(relationship); } }); - return relationships; + return new Relationships(relationships); +} + +function Relationships(relationships) { + var targetsByRelationshipId = {}; + relationships.forEach(function(relationship) { + targetsByRelationshipId[relationship.relationshipId] = relationship.target; + }); + + var targetsByType = {}; + relationships.forEach(function(relationship) { + if (!targetsByType[relationship.type]) { + targetsByType[relationship.type] = []; + } + targetsByType[relationship.type].push(relationship.target); + }); + + return { + findTargetByRelationshipId: function(relationshipId) { + return targetsByRelationshipId[relationshipId]; + }, + findTargetsByType: function(type) { + return targetsByType[type] || []; + } + }; } diff --git a/test/docx/body-reader.tests.js b/test/docx/body-reader.tests.js index 039a9db..ceeb9c1 100644 --- a/test/docx/body-reader.tests.js +++ b/test/docx/body-reader.tests.js @@ -25,6 +25,7 @@ var documents = require("../../lib/documents"); var xml = require("../../lib/xml"); var XmlElement = xml.Element; var Numbering = require("../../lib/docx/numbering-xml").Numbering; +var Relationships = require("../../lib/docx/relationships-reader").Relationships; var Styles = require("../../lib/docx/styles-reader").Styles; var warning = require("../../lib/results").warning; @@ -810,9 +811,9 @@ function isImage(options) { function readEmbeddedImage(element) { return readXmlElement(element, { - relationships: { - "rId5": {target: "media/hat.png"} - }, + relationships: new Relationships([ + imageRelationship("rId5", "media/hat.png") + ]), contentTypes: fakeContentTypes, docxFile: createFakeDocxFile({ "word/media/hat.png": IMAGE_BUFFER @@ -932,9 +933,9 @@ test("can read linked pictures", function() { }); var element = single(readXmlElementValue(drawing, { - relationships: { - "rId5": {target: "file:///media/hat.png"} - }, + relationships: new Relationships([ + imageRelationship("rId5", "file:///media/hat.png") + ]), contentTypes: fakeContentTypes, files: testing.createFakeFiles({ "file:///media/hat.png": IMAGE_BUFFER @@ -954,9 +955,9 @@ test("warning if unsupported image type", function() { }); var result = readXmlElement(drawing, { - relationships: { - "rId5": {target: "media/hat.emf"} - }, + relationships: new Relationships([ + imageRelationship("rId5", "media/hat.emf") + ]), contentTypes: fakeContentTypes, docxFile: createFakeDocxFile({ "word/media/hat.emf": IMAGE_BUFFER @@ -1009,9 +1010,9 @@ test("w:hyperlink", { "is read as external hyperlink if it has a relationship ID": function() { var runXml = new XmlElement("w:r", {}, []); var hyperlinkXml = new XmlElement("w:hyperlink", {"r:id": "r42"}, [runXml]); - var relationships = { - "r42": {target: "http://example.com"} - }; + var relationships = new Relationships([ + hyperlinkRelationship("r42", "http://example.com") + ]); var result = readXmlElement(hyperlinkXml, {relationships: relationships}); assert.deepEqual(result.value.href, "http://example.com"); assert.deepEqual(result.value.children[0].type, "run"); @@ -1020,9 +1021,9 @@ test("w:hyperlink", { "is read as external hyperlink if it has a relationship ID and an anchor": function() { var runXml = new XmlElement("w:r", {}, []); var hyperlinkXml = new XmlElement("w:hyperlink", {"r:id": "r42", "w:anchor": "fragment"}, [runXml]); - var relationships = { - "r42": {target: "http://example.com/"} - }; + var relationships = new Relationships([ + hyperlinkRelationship("r42", "http://example.com/") + ]); var result = readXmlElement(hyperlinkXml, {relationships: relationships}); assert.deepEqual(result.value.href, "http://example.com/#fragment"); assert.deepEqual(result.value.children[0].type, "run"); @@ -1031,9 +1032,9 @@ test("w:hyperlink", { "existing fragment is replaced when anchor is set on external link": function() { var runXml = new XmlElement("w:r", {}, []); var hyperlinkXml = new XmlElement("w:hyperlink", {"r:id": "r42", "w:anchor": "fragment"}, [runXml]); - var relationships = { - "r42": {target: "http://example.com/#previous"} - }; + var relationships = new Relationships([ + hyperlinkRelationship("r42", "http://example.com/#previous") + ]); var result = readXmlElement(hyperlinkXml, {relationships: relationships}); assert.deepEqual(result.value.href, "http://example.com/#fragment"); assert.deepEqual(result.value.children[0].type, "run"); @@ -1251,3 +1252,19 @@ function assertImageBuffer(element, expectedImageBuffer) { assert.equal(readValue, expectedImageBuffer); }); } + +function hyperlinkRelationship(relationshipId, target) { + return { + relationshipId: relationshipId, + target: target, + type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" + }; +} + +function imageRelationship(relationshipId, target) { + return { + relationshipId: relationshipId, + target: target, + type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" + }; +} diff --git a/test/docx/relationships-reader.tests.js b/test/docx/relationships-reader.tests.js new file mode 100644 index 0000000..60db3b4 --- /dev/null +++ b/test/docx/relationships-reader.tests.js @@ -0,0 +1,65 @@ +var assert = require("assert"); + +var readRelationships = require("../../lib/docx/relationships-reader").readRelationships; +var xml = require("../../lib/xml"); +var test = require("../test")(module); + + +test("relationships can be found by ID", function() { + var relationships = readRelationships(relationshipsElement([ + relationshipElement({ + "Id": "rId1", + "Target": "http://example.com/", + "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" + }), + relationshipElement({ + "Id": "rId2", + "Target": "http://example.net/", + "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" + }) + ])); + assert.equal(relationships.findTargetByRelationshipId("rId1"), "http://example.com/"); +}); + + +test("relationships can be found by type", function() { + var relationships = readRelationships(relationshipsElement([ + relationshipElement({ + "Id": "rId2", + "Target": "docProps/core.xml", + "Type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" + }), + relationshipElement({ + "Id": "rId1", + "Target": "word/document.xml", + "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" + }), + relationshipElement({ + "Id": "rId3", + "Target": "word/document2.xml", + "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" + }) + ])); + assert.deepEqual( + relationships.findTargetsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"), + ["word/document.xml", "word/document2.xml"] + ); +}); + + +test("when there are no relationships of requested type then empty array is returned", function() { + var relationships = readRelationships(relationshipsElement([])); + assert.deepEqual( + relationships.findTargetsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"), + [] + ); +}); + + +function relationshipsElement(children) { + return xml.element("{http://schemas.openxmlformats.org/package/2006/relationships}Relationships", {}, children) +} + +function relationshipElement(attributes) { + return xml.element("{http://schemas.openxmlformats.org/package/2006/relationships}Relationship", attributes, []) +} |
