@depup/mammoth 1.12.0-depup.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/.eslintrc.json +75 -0
  2. package/.github/ISSUE_TEMPLATE.md +12 -0
  3. package/.github/pull_request_template.md +3 -0
  4. package/.github/workflows/tests.yml +26 -0
  5. package/LICENSE +22 -0
  6. package/NEWS +530 -0
  7. package/README.md +37 -0
  8. package/bin/mammoth +38 -0
  9. package/browser/docx/files.js +14 -0
  10. package/browser/unzip.js +12 -0
  11. package/changes.json +34 -0
  12. package/lib/document-to-html.js +469 -0
  13. package/lib/documents.js +254 -0
  14. package/lib/docx/body-reader.js +798 -0
  15. package/lib/docx/comments-reader.js +31 -0
  16. package/lib/docx/content-types-reader.js +58 -0
  17. package/lib/docx/document-xml-reader.js +30 -0
  18. package/lib/docx/docx-reader.js +226 -0
  19. package/lib/docx/files.js +80 -0
  20. package/lib/docx/notes-reader.js +28 -0
  21. package/lib/docx/numbering-xml.js +111 -0
  22. package/lib/docx/office-xml-reader.js +73 -0
  23. package/lib/docx/relationships-reader.js +43 -0
  24. package/lib/docx/style-map.js +75 -0
  25. package/lib/docx/styles-reader.js +90 -0
  26. package/lib/docx/uris.js +21 -0
  27. package/lib/html/ast.js +51 -0
  28. package/lib/html/index.js +41 -0
  29. package/lib/html/simplify.js +88 -0
  30. package/lib/images.js +31 -0
  31. package/lib/index.d.ts +86 -0
  32. package/lib/index.js +111 -0
  33. package/lib/main.js +63 -0
  34. package/lib/options-reader.js +107 -0
  35. package/lib/promises.js +42 -0
  36. package/lib/raw-text.js +14 -0
  37. package/lib/results.js +72 -0
  38. package/lib/style-reader.js +365 -0
  39. package/lib/styles/document-matchers.js +100 -0
  40. package/lib/styles/html-paths.js +75 -0
  41. package/lib/styles/parser/tokeniser.js +30 -0
  42. package/lib/transforms.js +62 -0
  43. package/lib/underline.js +11 -0
  44. package/lib/unzip.js +20 -0
  45. package/lib/writers/html-writer.js +159 -0
  46. package/lib/writers/index.js +14 -0
  47. package/lib/writers/markdown-writer.js +163 -0
  48. package/lib/xml/index.js +8 -0
  49. package/lib/xml/nodes.js +70 -0
  50. package/lib/xml/reader.js +69 -0
  51. package/lib/xml/writer.js +61 -0
  52. package/lib/xml/xmldom.js +23 -0
  53. package/lib/zipfile.js +72 -0
  54. package/mammoth.browser.js +22096 -0
  55. package/mammoth.browser.min.js +20 -0
  56. package/package.json +106 -0
  57. package/test/.eslintrc.json +7 -0
  58. package/test/document-to-html.tests.js +892 -0
  59. package/test/docx/body-reader.tests.js +2037 -0
  60. package/test/docx/comments-reader.tests.js +53 -0
  61. package/test/docx/content-types-reader.tests.js +45 -0
  62. package/test/docx/document-matchers.js +42 -0
  63. package/test/docx/document-xml-reader.tests.js +41 -0
  64. package/test/docx/docx-reader.tests.js +179 -0
  65. package/test/docx/files.tests.js +107 -0
  66. package/test/docx/notes-reader.tests.js +36 -0
  67. package/test/docx/numbering-xml.tests.js +183 -0
  68. package/test/docx/office-xml-reader.tests.js +41 -0
  69. package/test/docx/relationships-reader.tests.js +65 -0
  70. package/test/docx/style-map.tests.js +113 -0
  71. package/test/docx/styles-reader.tests.js +143 -0
  72. package/test/docx/testing.js +12 -0
  73. package/test/docx/uris.tests.js +22 -0
  74. package/test/html/simplify.tests.js +141 -0
  75. package/test/html/write.tests.js +42 -0
  76. package/test/images.tests.js +112 -0
  77. package/test/main.tests.js +89 -0
  78. package/test/mammoth.tests.js +523 -0
  79. package/test/mocha.opts +1 -0
  80. package/test/options-reader.tests.js +63 -0
  81. package/test/raw-text.tests.js +61 -0
  82. package/test/results.tests.js +15 -0
  83. package/test/style-reader.tests.js +291 -0
  84. package/test/styles/document-matchers.tests.js +91 -0
  85. package/test/styles/html-paths.tests.js +20 -0
  86. package/test/styles/parser/tokeniser.tests.js +104 -0
  87. package/test/test-data/comments.docx +0 -0
  88. package/test/test-data/embedded-style-map.docx +0 -0
  89. package/test/test-data/empty.docx +0 -0
  90. package/test/test-data/empty.zip +0 -0
  91. package/test/test-data/endnotes.docx +0 -0
  92. package/test/test-data/external-picture.docx +0 -0
  93. package/test/test-data/footnote-hyperlink.docx +0 -0
  94. package/test/test-data/footnotes.docx +0 -0
  95. package/test/test-data/hello.zip +0 -0
  96. package/test/test-data/hyperlinks/word/_rels/document.xml.rels +10 -0
  97. package/test/test-data/hyperlinks/word/document.xml +18 -0
  98. package/test/test-data/simple/word/document.xml +18 -0
  99. package/test/test-data/simple-list.docx +0 -0
  100. package/test/test-data/single-paragraph.docx +0 -0
  101. package/test/test-data/strict-format.docx +0 -0
  102. package/test/test-data/strikethrough.docx +0 -0
  103. package/test/test-data/tables.docx +0 -0
  104. package/test/test-data/text-box.docx +0 -0
  105. package/test/test-data/tiny-picture-target-base-relative.docx +0 -0
  106. package/test/test-data/tiny-picture.docx +0 -0
  107. package/test/test-data/tiny-picture.png +0 -0
  108. package/test/test-data/underline.docx +0 -0
  109. package/test/test-data/utf8-bom.docx +0 -0
  110. package/test/test.js +11 -0
  111. package/test/testing.js +55 -0
  112. package/test/transforms.tests.js +125 -0
  113. package/test/unzip.tests.js +38 -0
  114. package/test/writers/html-writer.tests.js +133 -0
  115. package/test/writers/markdown-writer.tests.js +304 -0
  116. package/test/xml/reader.tests.js +85 -0
  117. package/test/xml/writer.tests.js +81 -0
  118. package/test/zipfile.tests.js +61 -0
@@ -0,0 +1,183 @@
1
+ var assert = require("assert");
2
+ var duck = require("duck");
3
+
4
+ var readNumberingXml = require("../../lib/docx/numbering-xml").readNumberingXml;
5
+ var stylesReader = require("../../lib/docx/styles-reader");
6
+ var XmlElement = require("../../lib/xml").Element;
7
+ var test = require("../test")(module);
8
+
9
+
10
+ test('w:num element inherits levels from w:abstractNum', function() {
11
+ var numbering = readNumberingXml(
12
+ new XmlElement("w:numbering", {}, [
13
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "42"}, [
14
+ new XmlElement("w:lvl", {"w:ilvl": "0"}, [
15
+ new XmlElement("w:numFmt", {"w:val": "bullet"})
16
+ ]),
17
+ new XmlElement("w:lvl", {"w:ilvl": "1"}, [
18
+ new XmlElement("w:numFmt", {"w:val": "decimal"})
19
+ ])
20
+ ]),
21
+ new XmlElement("w:num", {"w:numId": "47"}, [
22
+ new XmlElement("w:abstractNumId", {"w:val": "42"})
23
+ ])
24
+ ]),
25
+ {styles: stylesReader.defaultStyles}
26
+ );
27
+ duck.assertThat(numbering.findLevel("47", "0"), duck.hasProperties({
28
+ isOrdered: false
29
+ }));
30
+ duck.assertThat(numbering.findLevel("47", "1"), duck.hasProperties({
31
+ isOrdered: true
32
+ }));
33
+ });
34
+
35
+
36
+ test('w:num element referencing non-existent w:abstractNumId is ignored', function() {
37
+ var numbering = readNumberingXml(
38
+ new XmlElement("w:numbering", {}, [
39
+ new XmlElement("w:num", {"w:numId": "47"}, [
40
+ new XmlElement("w:abstractNumId", {"w:val": "42"})
41
+ ])
42
+ ]),
43
+ {styles: stylesReader.defaultStyles}
44
+ );
45
+ duck.assertThat(numbering.findLevel("47", "0"), duck.equalTo(null));
46
+ });
47
+
48
+ test('given no other levels with index of 0 when level is missing w:ilvl then level index is 0', function() {
49
+ var numbering = readNumberingXml(
50
+ new XmlElement("w:numbering", {}, [
51
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "42"}, [
52
+ new XmlElement("w:lvl", {}, [
53
+ new XmlElement("w:numFmt", {"w:val": "decimal"})
54
+ ])
55
+ ]),
56
+ new XmlElement("w:num", {"w:numId": "47"}, [
57
+ new XmlElement("w:abstractNumId", {"w:val": "42"})
58
+ ])
59
+ ]),
60
+ {styles: stylesReader.defaultStyles}
61
+ );
62
+ duck.assertThat(numbering.findLevel("47", "0"), duck.hasProperties({
63
+ isOrdered: true
64
+ }));
65
+ });
66
+
67
+ test('given previous other level with index of 0 when level is missing w:ilvl then level is ignored', function() {
68
+ var numbering = readNumberingXml(
69
+ new XmlElement("w:numbering", {}, [
70
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "42"}, [
71
+ new XmlElement("w:lvl", {"w:ilvl": "0"}, [
72
+ new XmlElement("w:numFmt", {"w:val": "bullet"})
73
+ ]),
74
+ new XmlElement("w:lvl", {}, [
75
+ new XmlElement("w:numFmt", {"w:val": "decimal"})
76
+ ])
77
+ ]),
78
+ new XmlElement("w:num", {"w:numId": "47"}, [
79
+ new XmlElement("w:abstractNumId", {"w:val": "42"})
80
+ ])
81
+ ]),
82
+ {styles: stylesReader.defaultStyles}
83
+ );
84
+ duck.assertThat(numbering.findLevel("47", "0"), duck.hasProperties({
85
+ isOrdered: false
86
+ }));
87
+ });
88
+
89
+ test('given subsequent other level with index of 0 when level is missing w:ilvl then level is ignored', function() {
90
+ var numbering = readNumberingXml(
91
+ new XmlElement("w:numbering", {}, [
92
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "42"}, [
93
+ new XmlElement("w:lvl", {}, [
94
+ new XmlElement("w:numFmt", {"w:val": "decimal"})
95
+ ]),
96
+ new XmlElement("w:lvl", {"w:ilvl": "0"}, [
97
+ new XmlElement("w:numFmt", {"w:val": "bullet"})
98
+ ])
99
+ ]),
100
+ new XmlElement("w:num", {"w:numId": "47"}, [
101
+ new XmlElement("w:abstractNumId", {"w:val": "42"})
102
+ ])
103
+ ]),
104
+ {styles: stylesReader.defaultStyles}
105
+ );
106
+ duck.assertThat(numbering.findLevel("47", "0"), duck.hasProperties({
107
+ isOrdered: false
108
+ }));
109
+ });
110
+
111
+ test('when level is missing w:numFmt then level is ordered', function() {
112
+ var numbering = readNumberingXml(
113
+ new XmlElement("w:numbering", {}, [
114
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "42"}, [
115
+ new XmlElement("w:lvl", {"w:ilvl": "0"})
116
+ ]),
117
+ new XmlElement("w:num", {"w:numId": "47"}, [
118
+ new XmlElement("w:abstractNumId", {"w:val": "42"})
119
+ ])
120
+ ]),
121
+ {styles: stylesReader.defaultStyles}
122
+ );
123
+ duck.assertThat(numbering.findLevel("47", "0"), duck.hasProperties({
124
+ isOrdered: true
125
+ }));
126
+ });
127
+
128
+
129
+ test('when w:abstractNum has w:numStyleLink then style is used to find w:num', function() {
130
+ var numbering = readNumberingXml(
131
+ new XmlElement("w:numbering", {}, [
132
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "100"}, [
133
+ new XmlElement("w:lvl", {"w:ilvl": "0"}, [
134
+ new XmlElement("w:numFmt", {"w:val": "decimal"})
135
+ ])
136
+ ]),
137
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "101"}, [
138
+ new XmlElement("w:numStyleLink", {"w:val": "List1"})
139
+ ]),
140
+ new XmlElement("w:num", {"w:numId": "200"}, [
141
+ new XmlElement("w:abstractNumId", {"w:val": "100"})
142
+ ]),
143
+ new XmlElement("w:num", {"w:numId": "201"}, [
144
+ new XmlElement("w:abstractNumId", {"w:val": "101"})
145
+ ])
146
+ ]),
147
+ {styles: new stylesReader.Styles({}, {}, {}, {"List1": {numId: "200"}})}
148
+ );
149
+ duck.assertThat(numbering.findLevel("201", "0"), duck.hasProperties({
150
+ isOrdered: true
151
+ }));
152
+ });
153
+
154
+
155
+ // See: 17.9.23 pStyle (Paragraph Style's Associated Numbering Level) in ECMA-376, 4th Edition
156
+ test('numbering level can be found by paragraph style ID', function() {
157
+ var numbering = readNumberingXml(
158
+ new XmlElement("w:numbering", {}, [
159
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "42"}, [
160
+ new XmlElement("w:lvl", {"w:ilvl": "0"}, [
161
+ new XmlElement("w:numFmt", {"w:val": "bullet"})
162
+ ])
163
+ ]),
164
+ new XmlElement("w:abstractNum", {"w:abstractNumId": "43"}, [
165
+ new XmlElement("w:lvl", {"w:ilvl": "0"}, [
166
+ new XmlElement("w:pStyle", {"w:val": "List"}),
167
+ new XmlElement("w:numFmt", {"w:val": "decimal"})
168
+ ])
169
+ ])
170
+ ]),
171
+ {styles: stylesReader.defaultStyles}
172
+ );
173
+ duck.assertThat(numbering.findLevelByParagraphStyleId("List"), duck.hasProperties({
174
+ isOrdered: true
175
+ }));
176
+ duck.assertThat(numbering.findLevelByParagraphStyleId("Paragraph"), duck.equalTo(null));
177
+ });
178
+
179
+ test('when styles is missing then error is thrown', function() {
180
+ assert.throws(function() {
181
+ readNumberingXml(new XmlElement("w:numbering", {}, []));
182
+ }, /styles is missing/);
183
+ });
@@ -0,0 +1,41 @@
1
+ var assert = require("assert");
2
+
3
+ var xml = require("../../lib/xml");
4
+ var officeXmlReader = require("../../lib/docx/office-xml-reader");
5
+ var test = require("../test")(module);
6
+
7
+
8
+ test("mc:AlternateContent", {
9
+ "when mc:Fallback is present then mc:Fallback is read": function() {
10
+ var xmlString =
11
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
12
+ '<numbering xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">' +
13
+ '<mc:AlternateContent>' +
14
+ '<mc:Choice Requires="w14">' +
15
+ '<choice/>' +
16
+ '</mc:Choice>' +
17
+ '<mc:Fallback>' +
18
+ '<fallback/>' +
19
+ '</mc:Fallback>' +
20
+ '</mc:AlternateContent>' +
21
+ '</numbering>';
22
+ return officeXmlReader.read(xmlString).then(function(element) {
23
+ assert.deepEqual(element.children, [xml.element("fallback")]);
24
+ });
25
+ },
26
+
27
+ "when mc:Fallback is not present then element is ignored": function() {
28
+ var xmlString =
29
+ '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
30
+ '<numbering xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">' +
31
+ '<mc:AlternateContent>' +
32
+ '<mc:Choice Requires="w14">' +
33
+ '<choice/>' +
34
+ '</mc:Choice>' +
35
+ '</mc:AlternateContent>' +
36
+ '</numbering>';
37
+ return officeXmlReader.read(xmlString).then(function(element) {
38
+ assert.deepEqual(element.children, []);
39
+ });
40
+ }
41
+ });
@@ -0,0 +1,65 @@
1
+ var assert = require("assert");
2
+
3
+ var readRelationships = require("../../lib/docx/relationships-reader").readRelationships;
4
+ var xml = require("../../lib/xml");
5
+ var test = require("../test")(module);
6
+
7
+
8
+ test("relationships can be found by ID", function() {
9
+ var relationships = readRelationships(relationshipsElement([
10
+ relationshipElement({
11
+ "Id": "rId1",
12
+ "Target": "http://example.com/",
13
+ "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
14
+ }),
15
+ relationshipElement({
16
+ "Id": "rId2",
17
+ "Target": "http://example.net/",
18
+ "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
19
+ })
20
+ ]));
21
+ assert.equal(relationships.findTargetByRelationshipId("rId1"), "http://example.com/");
22
+ });
23
+
24
+
25
+ test("relationships can be found by type", function() {
26
+ var relationships = readRelationships(relationshipsElement([
27
+ relationshipElement({
28
+ "Id": "rId2",
29
+ "Target": "docProps/core.xml",
30
+ "Type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
31
+ }),
32
+ relationshipElement({
33
+ "Id": "rId1",
34
+ "Target": "word/document.xml",
35
+ "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
36
+ }),
37
+ relationshipElement({
38
+ "Id": "rId3",
39
+ "Target": "word/document2.xml",
40
+ "Type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
41
+ })
42
+ ]));
43
+ assert.deepEqual(
44
+ relationships.findTargetsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"),
45
+ ["word/document.xml", "word/document2.xml"]
46
+ );
47
+ });
48
+
49
+
50
+ test("when there are no relationships of requested type then empty array is returned", function() {
51
+ var relationships = readRelationships(relationshipsElement([]));
52
+ assert.deepEqual(
53
+ relationships.findTargetsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"),
54
+ []
55
+ );
56
+ });
57
+
58
+
59
+ function relationshipsElement(children) {
60
+ return xml.element("relationships:Relationships", {}, children);
61
+ }
62
+
63
+ function relationshipElement(attributes) {
64
+ return xml.element("relationships:Relationship", attributes, []);
65
+ }
@@ -0,0 +1,113 @@
1
+ var assert = require("assert");
2
+
3
+ var JSZip = require("jszip");
4
+
5
+ var zipfile = require("../../lib/zipfile");
6
+ var styleMap = require("../../lib/docx/style-map");
7
+ var test = require("../test")(module);
8
+
9
+ test('reading embedded style map on document without embedded style map returns null', function() {
10
+ return normalDocx().then(function(zip) {
11
+ return styleMap.readStyleMap(zip).then(function(contents) {
12
+ assert.equal(contents, null);
13
+ });
14
+ });
15
+ });
16
+
17
+ test('embedded style map can be read after being written', function() {
18
+ return normalDocx().then(function(zip) {
19
+ return styleMap.writeStyleMap(zip, "p => h1").then(function() {
20
+ return styleMap.readStyleMap(zip).then(function(contents) {
21
+ assert.equal(contents, "p => h1");
22
+ });
23
+ });
24
+ });
25
+ });
26
+
27
+ test('embedded style map is written to separate file', function() {
28
+ return normalDocx().then(function(zip) {
29
+ return styleMap.writeStyleMap(zip, "p => h1").then(function() {
30
+ return zip.read("mammoth/style-map", "utf8").then(function(contents) {
31
+ assert.equal(contents, "p => h1");
32
+ });
33
+ });
34
+ });
35
+ });
36
+
37
+ test('embedded style map is referenced in relationships', function() {
38
+ return normalDocx().then(function(zip) {
39
+ return styleMap.writeStyleMap(zip, "p => h1").then(function() {
40
+ return zip.read("word/_rels/document.xml.rels", "utf8").then(function(contents) {
41
+ assert.equal(contents, expectedRelationshipsXml);
42
+ });
43
+ });
44
+ });
45
+ });
46
+
47
+ test('re-embedding style map replaces original', function() {
48
+ return normalDocx().then(function(zip) {
49
+ return styleMap.writeStyleMap(zip, "p => h1").then(function() {
50
+ return styleMap.writeStyleMap(zip, "p => h2");
51
+ }).then(function() {
52
+ return zip.read("word/_rels/document.xml.rels", "utf8").then(function(contents) {
53
+ assert.equal(contents, expectedRelationshipsXml);
54
+ });
55
+ }).then(function() {
56
+ return styleMap.readStyleMap(zip).then(function(contents) {
57
+ assert.equal(contents, "p => h2");
58
+ });
59
+ });
60
+ });
61
+ });
62
+
63
+ test('embedded style map has override content type in [Content_Types].xml', function() {
64
+ return normalDocx().then(function(zip) {
65
+ return styleMap.writeStyleMap(zip, "p => h1").then(function() {
66
+ return zip.read("[Content_Types].xml", "utf8").then(function(contents) {
67
+ assert.equal(contents, expectedContentTypesXml);
68
+ });
69
+ });
70
+ });
71
+ });
72
+
73
+ test('replacing style map keeps content type', function() {
74
+ return normalDocx().then(function(zip) {
75
+ return styleMap.writeStyleMap(zip, "p => h1").then(function() {
76
+ return styleMap.writeStyleMap(zip, "p => h2");
77
+ }).then(function() {
78
+ return zip.read("[Content_Types].xml", "utf8").then(function(contents) {
79
+ assert.equal(contents, expectedContentTypesXml);
80
+ });
81
+ });
82
+ });
83
+ });
84
+
85
+ var expectedRelationshipsXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
86
+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
87
+ '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>' +
88
+ '<Relationship Id="rMammothStyleMap" Type="http://schemas.zwobble.org/mammoth/style-map" Target="/mammoth/style-map"/>' +
89
+ '</Relationships>';
90
+
91
+ var expectedContentTypesXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
92
+ '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">' +
93
+ '<Default Extension="png" ContentType="image/png"/>' +
94
+ '<Override PartName="/mammoth/style-map" ContentType="text/prs.mammoth.style-map"/>' +
95
+ '</Types>';
96
+
97
+ function normalDocx() {
98
+ var zip = new JSZip();
99
+ var originalRelationshipsXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
100
+ '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
101
+ '<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>' +
102
+ '</Relationships>';
103
+ var originalContentTypesXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
104
+ '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">' +
105
+ '<Default Extension="png" ContentType="image/png"/>' +
106
+ '</Types>';
107
+ zip.file("word/_rels/document.xml.rels", originalRelationshipsXml);
108
+ zip.file("[Content_Types].xml", originalContentTypesXml);
109
+ return zip.generateAsync({type: "arraybuffer"}).then(function(buffer) {
110
+ return zipfile.openArrayBuffer(buffer);
111
+ });
112
+ }
113
+
@@ -0,0 +1,143 @@
1
+ var assert = require("assert");
2
+
3
+ var readStylesXml = require("../../lib/docx/styles-reader").readStylesXml;
4
+ var XmlElement = require("../../lib/xml").Element;
5
+ var test = require("../test")(module);
6
+
7
+
8
+ test('paragraph style is null if no style with that ID exists', function() {
9
+ var styles = readStylesXml(
10
+ new XmlElement("w:styles", {}, [])
11
+ );
12
+ assert.equal(styles.findParagraphStyleById("Heading1"), null);
13
+ });
14
+
15
+ test('paragraph style can be found by ID', function() {
16
+ var styles = readStylesXml(
17
+ new XmlElement("w:styles", {}, [
18
+ paragraphStyleElement("Heading1", "Heading 1")
19
+ ])
20
+ );
21
+ assert.equal(styles.findParagraphStyleById("Heading1").styleId, "Heading1");
22
+ });
23
+
24
+ test('table style can be found by ID', function() {
25
+ var styles = readStylesXml(
26
+ new XmlElement("w:styles", {}, [
27
+ tableStyleElement("TableNormal", "Normal Table")
28
+ ])
29
+ );
30
+ assert.equal(styles.findTableStyleById("TableNormal").styleId, "TableNormal");
31
+ });
32
+
33
+ test('character style can be found by ID', function() {
34
+ var styles = readStylesXml(
35
+ new XmlElement("w:styles", {}, [
36
+ characterStyleElement("Heading1Char", "Heading 1 Char")
37
+ ])
38
+ );
39
+ assert.equal(styles.findCharacterStyleById("Heading1Char").styleId, "Heading1Char");
40
+ });
41
+
42
+ test('paragraph and character styles are distinct', function() {
43
+ var styles = readStylesXml(
44
+ new XmlElement("w:styles", {}, [
45
+ paragraphStyleElement("Heading1", "Heading 1"),
46
+ characterStyleElement("Heading1Char", "Heading 1 Char")
47
+ ])
48
+ );
49
+ assert.equal(styles.findCharacterStyleById("Heading1"), null);
50
+ assert.equal(styles.findParagraphStyleById("Heading1Char"), null);
51
+ });
52
+
53
+ test('character and table styles are distinct', function() {
54
+ var styles = readStylesXml(
55
+ new XmlElement("w:styles", {}, [
56
+ tableStyleElement("Heading1", "Heading 1")
57
+ ])
58
+ );
59
+ assert.equal(styles.findCharacterStyleById("Heading1"), null);
60
+ });
61
+
62
+ test('styles include names', function() {
63
+ var styles = readStylesXml(
64
+ new XmlElement("w:styles", {}, [
65
+ paragraphStyleElement("Heading1", "Heading 1")
66
+ ])
67
+ );
68
+ assert.equal(styles.findParagraphStyleById("Heading1").name, "Heading 1");
69
+ });
70
+
71
+ test('style name is null if w:name element does not exist', function() {
72
+ var styles = readStylesXml(
73
+ new XmlElement("w:styles", {}, [
74
+ styleWithoutWNameElement("paragraph", "Heading1"),
75
+ styleWithoutWNameElement("character", "Heading1Char")
76
+ ])
77
+ );
78
+ assert.equal(styles.findParagraphStyleById("Heading1").name, null);
79
+ assert.equal(styles.findCharacterStyleById("Heading1Char").name, null);
80
+ });
81
+
82
+ test('numbering style is null if no style with that ID exists', function() {
83
+ var styles = readStylesXml(
84
+ new XmlElement("w:styles", {}, [])
85
+ );
86
+ assert.equal(styles.findNumberingStyleById("List1"), null);
87
+ });
88
+
89
+ test('numbering style has null numId if style has no paragraph properties', function() {
90
+ var styles = readStylesXml(
91
+ new XmlElement("w:styles", {}, [
92
+ new XmlElement("w:style", {"w:type": "numbering", "w:styleId": "List1"})
93
+ ])
94
+ );
95
+ assert.equal(styles.findNumberingStyleById("List1").numId, null);
96
+ });
97
+
98
+ test('numbering style has numId read from paragraph properties', function() {
99
+ var styles = readStylesXml(
100
+ new XmlElement("w:styles", {}, [
101
+ new XmlElement("w:style", {"w:type": "numbering", "w:styleId": "List1"}, [
102
+ new XmlElement("w:pPr", {}, [
103
+ new XmlElement("w:numPr", {}, [
104
+ new XmlElement("w:numId", {"w:val": "42"})
105
+ ])
106
+ ])
107
+ ])
108
+ ])
109
+ );
110
+ assert.equal(styles.findNumberingStyleById("List1").numId, "42");
111
+ });
112
+
113
+ test('when multiple style elements have same style ID then only first element is used', function() {
114
+ var styles = readStylesXml(
115
+ new XmlElement("w:styles", {}, [
116
+ tableStyleElement("TableNormal", "Normal Table"),
117
+ tableStyleElement("TableNormal", "Table Normal")
118
+ ])
119
+ );
120
+ assert.equal(styles.findTableStyleById("TableNormal").name, "Normal Table");
121
+ });
122
+
123
+ function paragraphStyleElement(id, name) {
124
+ return styleElement("paragraph", id, name);
125
+ }
126
+
127
+ function characterStyleElement(id, name) {
128
+ return styleElement("character", id, name);
129
+ }
130
+
131
+ function tableStyleElement(id, name) {
132
+ return styleElement("table", id, name);
133
+ }
134
+
135
+ function styleElement(type, id, name) {
136
+ return new XmlElement("w:style", {"w:type": type, "w:styleId": id}, [
137
+ new XmlElement("w:name", {"w:val": name}, [])
138
+ ]);
139
+ }
140
+
141
+ function styleWithoutWNameElement(type, id) {
142
+ return new XmlElement("w:style", {"w:type": type, "w:styleId": id}, []);
143
+ }
@@ -0,0 +1,12 @@
1
+ var createBodyReader = require("../../lib/docx/body-reader").createBodyReader;
2
+ var defaultNumbering = require("../../lib/docx/numbering-xml").defaultNumbering;
3
+ var Styles = require("../../lib/docx/styles-reader").Styles;
4
+
5
+ function createBodyReaderForTests(options) {
6
+ options = Object.create(options || {});
7
+ options.styles = options.styles || new Styles({}, {});
8
+ options.numbering = options.numbering || defaultNumbering;
9
+ return createBodyReader(options);
10
+ }
11
+
12
+ exports.createBodyReaderForTests = createBodyReaderForTests;
@@ -0,0 +1,22 @@
1
+ var assert = require("assert");
2
+
3
+ var zipfile = require("../../lib/docx/uris");
4
+ var test = require("../test")(module);
5
+
6
+
7
+ test("uriToZipEntryName", {
8
+ "when path does not have leading slash then path is resolved relative to base": function() {
9
+ assert.equal(
10
+ zipfile.uriToZipEntryName("one/two", "three/four"),
11
+ "one/two/three/four"
12
+ );
13
+ },
14
+
15
+ "when path has leading slash then base is ignored": function() {
16
+ assert.equal(
17
+ zipfile.uriToZipEntryName("one/two", "/three/four"),
18
+ "three/four"
19
+ );
20
+ }
21
+ });
22
+