summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2018-01-26 23:30:13 +0000
committerMichael Williamson <mike@zwobble.org>2018-01-26 23:30:13 +0000
commit8b9ca6ca68fec89926cfb02a96506bbee54a5b2c (patch)
tree34f701ec9078d533d86ad63fc6aa11dbd91ad278
parent9196e8bc6f2ff2c59a9b4fde4813e7bc26b8c23d (diff)
Find comments part using document relationships
-rw-r--r--lib/docx/docx-reader.js63
-rw-r--r--lib/zipfile.js16
-rw-r--r--test/docx/docx-reader.tests.js38
-rw-r--r--test/zipfile.tests.js9
4 files changed, 110 insertions, 16 deletions
diff --git a/lib/docx/docx-reader.js b/lib/docx/docx-reader.js
index cbeaccd..e6dd798 100644
--- a/lib/docx/docx-reader.js
+++ b/lib/docx/docx-reader.js
@@ -83,29 +83,64 @@ function read(docxFile, input) {
function findPartPaths(docxFile) {
return readPackageRelationships(docxFile).then(function(packageRelationships) {
- var documentFilename = findDocumentFilename(docxFile, packageRelationships);
- return {
- mainDocument: documentFilename,
- comments: "word/comments.xml",
- endnotes: "word/endnotes.xml",
- footnotes: "word/footnotes.xml",
- numbering: "word/numbering.xml",
- styles: "word/styles.xml"
- };
+ var mainDocumentPath = findPartPath({
+ docxFile: docxFile,
+ relationships: packageRelationships,
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
+ basePath: "",
+ fallbackPath: "word/document.xml"
+ });
+
+ if (!docxFile.exists(mainDocumentPath)) {
+ throw new Error("Could not find main document part. Are you sure this is a valid .docx file?");
+ }
+
+ return xmlFileReader({
+ filename: relationshipsFilename(mainDocumentPath),
+ readElement: relationshipsReader.readRelationships,
+ defaultValue: relationshipsReader.defaultValue
+ })(docxFile).then(function(documentRelationships) {
+ function findPartRelatedToMainDocument(options) {
+ return findPartPath({
+ docxFile: docxFile,
+ relationships: documentRelationships,
+ relationshipType: options.relationshipType,
+ basePath: zipfile.splitPath(mainDocumentPath).dirname,
+ fallbackPath: options.fallbackPath
+ });
+ }
+
+ return {
+ mainDocument: mainDocumentPath,
+ comments: findPartRelatedToMainDocument({
+ relationshipType: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
+ fallbackPath: "word/comments.xml"
+ }),
+ endnotes: "word/endnotes.xml",
+ footnotes: "word/footnotes.xml",
+ numbering: "word/numbering.xml",
+ styles: "word/styles.xml"
+ };
+ });
});
}
-function findDocumentFilename(docxFile, relationships) {
- var officeDocumentType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
- var targets = relationships.findTargetsByType(officeDocumentType).concat(["word/document.xml"]);
+function findPartPath(options) {
+ var docxFile = options.docxFile;
+ var relationships = options.relationships;
+ var relationshipType = options.relationshipType;
+ var basePath = options.basePath;
+ var fallbackPath = options.fallbackPath;
+
+ var targets = relationships.findTargetsByType(relationshipType);
var normalisedTargets = targets.map(function(target) {
- return stripPrefix(target, "/");
+ return stripPrefix(zipfile.joinPath(basePath, target), "/");
});
var validTargets = normalisedTargets.filter(function(target) {
return docxFile.exists(target);
});
if (validTargets.length === 0) {
- throw new Error("Could not find main document part. Are you sure this is a valid .docx file?");
+ return fallbackPath;
} else {
return validTargets[0];
}
diff --git a/lib/zipfile.js b/lib/zipfile.js
index ae51310..8d46d92 100644
--- a/lib/zipfile.js
+++ b/lib/zipfile.js
@@ -51,7 +51,19 @@ function splitPath(path) {
}
function joinPath() {
- return Array.prototype.filter.call(arguments, function(path) {
+ var nonEmptyPaths = Array.prototype.filter.call(arguments, function(path) {
return path;
- }).join("/");
+ });
+
+ var relevantPaths = [];
+
+ nonEmptyPaths.forEach(function(path) {
+ if (/^\//.test(path)) {
+ relevantPaths = [path];
+ } else {
+ relevantPaths.push(path);
+ }
+ });
+
+ return relevantPaths.join("/");
}
diff --git a/test/docx/docx-reader.tests.js b/test/docx/docx-reader.tests.js
index 0556405..0d51f45 100644
--- a/test/docx/docx-reader.tests.js
+++ b/test/docx/docx-reader.tests.js
@@ -113,5 +113,43 @@ test("part paths", {
return docxReader._findPartPaths(docxFile).then(function(partPaths) {
assert.equal(partPaths.mainDocument, "word/document.xml");
});
+ },
+
+ "comments part is found using main document relationships": function() {
+ var docxFile = createFakeDocxFile({
+ "_rels/.rels": createPackageRelationships("word/document.xml"),
+ "word/document.xml": " ",
+ "word/_rels/document.xml.rels": xml.writeString(xml.element("r:Relationships", {}, [
+ xml.element("r:Relationship", {
+ "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
+ "Target": "comments2.xml"
+ })
+ ]), relationshipNamespaces),
+ "word/comments2.xml": " "
+ });
+ return docxReader._findPartPaths(docxFile).then(function(partPaths) {
+ assert.equal(partPaths.comments, "word/comments2.xml");
+ });
+ },
+
+ "word/comments.xml is used as fallback location for comments part": function() {
+ var docxFile = createFakeDocxFile({
+ "_rels/.rels": createPackageRelationships("word/document.xml"),
+ "word/document.xml": " ",
+ "word/comments.xml": " "
+ });
+ return docxReader._findPartPaths(docxFile).then(function(partPaths) {
+ assert.equal(partPaths.comments, "word/comments.xml");
+ });
}
});
+
+
+function createPackageRelationships(mainDocumentPath) {
+ return xml.writeString(xml.element("r:Relationships", {}, [
+ xml.element("r:Relationship", {
+ "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
+ "Target": mainDocumentPath
+ })
+ ]), relationshipNamespaces);
+}
diff --git a/test/zipfile.tests.js b/test/zipfile.tests.js
index 3087dc8..5383c49 100644
--- a/test/zipfile.tests.js
+++ b/test/zipfile.tests.js
@@ -39,6 +39,7 @@ test("when path has no forward slashes then splitPath returns empty dirname", fu
test("joinPath joins arguments with forward slashes", function() {
assert.equal(zipfile.joinPath("a", "b"), "a/b");
assert.equal(zipfile.joinPath("a/b", "c"), "a/b/c");
+ assert.equal(zipfile.joinPath("a", "b/c"), "a/b/c");
assert.equal(zipfile.joinPath("/a/b", "c"), "/a/b/c");
});
@@ -48,3 +49,11 @@ test("empty parts are ignored when joining paths", function() {
assert.equal(zipfile.joinPath("", "b"), "b");
assert.equal(zipfile.joinPath("a", "", "b"), "a/b");
});
+
+
+test("when joining paths then absolute paths ignore earlier paths", function() {
+ assert.equal(zipfile.joinPath("a", "/b"), "/b");
+ assert.equal(zipfile.joinPath("a", "/b", "c"), "/b/c");
+ assert.equal(zipfile.joinPath("/a", "/b"), "/b");
+ assert.equal(zipfile.joinPath("/a"), "/a");
+});