@depup/mammoth 1.12.2-depup.0 → 1.13.0-depup.0

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.
package/.eslintrc.json CHANGED
@@ -68,7 +68,10 @@
68
68
  "console": true,
69
69
  "exports": true,
70
70
  "module": true,
71
+ "process": false,
72
+ "Promise": false,
71
73
  "require": false,
74
+ "setTimeout": false,
72
75
  "TextDecoder": false,
73
76
  "Uint8Array": false
74
77
  }
package/NEWS CHANGED
@@ -1,3 +1,37 @@
1
+ # 1.13.0
2
+
3
+ * Replace the use of bluebird with native promises.
4
+
5
+ This is arguably a breaking change: however, the return value of functions
6
+ such as convertToHtml() was only documented as a promise, rather than as a
7
+ bluebird promise.
8
+
9
+ The only exception is that the docs previously used .done(): therefore,
10
+ when returning promises from the API to external users, a done method is
11
+ added.
12
+
13
+ Any callers that rely on bluebird promises can convert the returned promise
14
+ into a bluebird promise using bluebird.Promise.resolve().
15
+
16
+ * Read the children of w:customXml elements.
17
+
18
+ * Handle paragraphs and runs that have been moved and tracked as a revision.
19
+
20
+ * Improve escaping in Markdown writer. This avoids some cases where source
21
+ documents could inject arbitrary HTML into the converted document.
22
+
23
+ # 1.12.3
24
+
25
+ * Avoid excessive backtracking when parsing an unterminated string with many
26
+ escape sequences. The previous behaviour would allow maliciously crafted
27
+ documents to cause a denial of service.
28
+
29
+ Note that it is still strongly recommended to process untrusted documents in
30
+ a separate thread with a timeout to avoid potential similar issues.
31
+
32
+ * Handle complex field separator and end characters without corresponding start
33
+ characters.
34
+
1
35
  # 1.12.2
2
36
 
3
37
  * Avoid prototype pollution when reading the styles defined in a document. This
package/README.md CHANGED
@@ -13,20 +13,19 @@ npm install @depup/mammoth
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [mammoth](https://www.npmjs.com/package/mammoth) @ 1.12.2 |
17
- | Processed | 2026-08-28 |
16
+ | Original | [mammoth](https://www.npmjs.com/package/mammoth) @ 1.13.0 |
17
+ | Processed | 2026-09-27 |
18
18
  | Smoke test | passed |
19
- | Deps updated | 7 |
19
+ | Deps updated | 6 |
20
20
 
21
21
  ## Dependency Changes
22
22
 
23
23
  | Dependency | From | To |
24
24
  |------------|------|-----|
25
25
  | @xmldom/xmldom | ^0.8.6 | ^0.9.12 |
26
- | argparse | ~1.0.3 | ^3.0.1 |
27
- | bluebird | ~3.4.0 | ^3.7.2 |
28
- | jszip | ^3.7.1 | ^3.10.1 |
29
- | path-is-absolute | ^1.0.0 | ^2.0.0 |
26
+ | argparse | ~1.0.3 | ^3.0.2 |
27
+ | dingbat-to-unicode | ^1.0.1 | ^1.0.2 |
28
+ | jszip | ^3.7.1 | ^3.10.2 |
30
29
  | underscore | ^1.13.1 | ^1.13.8 |
31
30
  | xmlbuilder | ^10.0.0 | ^15.1.1 |
32
31
 
package/changes.json CHANGED
@@ -6,19 +6,15 @@
6
6
  },
7
7
  "argparse": {
8
8
  "from": "~1.0.3",
9
- "to": "^3.0.1"
9
+ "to": "^3.0.2"
10
10
  },
11
- "bluebird": {
12
- "from": "~3.4.0",
13
- "to": "^3.7.2"
11
+ "dingbat-to-unicode": {
12
+ "from": "^1.0.1",
13
+ "to": "^1.0.2"
14
14
  },
15
15
  "jszip": {
16
16
  "from": "^3.7.1",
17
- "to": "^3.10.1"
18
- },
19
- "path-is-absolute": {
20
- "from": "^1.0.0",
21
- "to": "^2.0.0"
17
+ "to": "^3.10.2"
22
18
  },
23
19
  "underscore": {
24
20
  "from": "^1.13.1",
@@ -29,6 +25,6 @@
29
25
  "to": "^15.1.1"
30
26
  }
31
27
  },
32
- "timestamp": "2026-08-28T20:02:44.372Z",
33
- "totalUpdated": 7
28
+ "timestamp": "2026-09-27T01:01:10.195Z",
29
+ "totalUpdated": 6
34
30
  }
@@ -51,7 +51,7 @@ function DocumentConversion(options, comments) {
51
51
  }
52
52
  });
53
53
  var deferredValues = Object.create(null);
54
- return promises.mapSeries(deferredNodes, function(deferred) {
54
+ return promises.forEachSeries(deferredNodes, function(deferred) {
55
55
  return deferred.value().then(function(value) {
56
56
  deferredValues[deferred.id] = value;
57
57
  });
@@ -80,27 +80,27 @@ function DocumentConversion(options, comments) {
80
80
  });
81
81
  }
82
82
 
83
- function convertElements(elements, messages, options) {
83
+ function convertElements(elements, messages, context) {
84
84
  return flatMap(elements, function(element) {
85
- return elementToHtml(element, messages, options);
85
+ return elementToHtml(element, messages, context);
86
86
  });
87
87
  }
88
88
 
89
- function elementToHtml(element, messages, options) {
90
- if (!options) {
91
- throw new Error("options not set");
89
+ function elementToHtml(element, messages, context) {
90
+ if (!context) {
91
+ throw new Error("context not set");
92
92
  }
93
93
  var handler = elementConverters[element.type];
94
94
  if (handler) {
95
- return handler(element, messages, options);
95
+ return handler(element, messages, context);
96
96
  } else {
97
97
  return [];
98
98
  }
99
99
  }
100
100
 
101
- function convertParagraph(element, messages, options) {
101
+ function convertParagraph(element, messages, context) {
102
102
  return htmlPathForParagraph(element, messages).wrap(function() {
103
- var content = convertElements(element.children, messages, options);
103
+ var content = convertElements(element.children, messages, context);
104
104
  if (ignoreEmptyParagraphs) {
105
105
  return content;
106
106
  } else {
@@ -122,9 +122,9 @@ function DocumentConversion(options, comments) {
122
122
  }
123
123
  }
124
124
 
125
- function convertRun(run, messages, options) {
125
+ function convertRun(run, messages, context) {
126
126
  var nodes = function() {
127
- return convertElements(run.children, messages, options);
127
+ return convertElements(run.children, messages, context);
128
128
  };
129
129
  var paths = [];
130
130
  if (run.highlight !== null) {
@@ -199,9 +199,9 @@ function DocumentConversion(options, comments) {
199
199
 
200
200
  function recoveringConvertImage(convertImage) {
201
201
  return function(image, messages) {
202
- return promises.attempt(function() {
202
+ return promises.try(function() {
203
203
  return convertImage(image, messages);
204
- }).caught(function(error) {
204
+ }).catch(function(error) {
205
205
  messages.push(results.error(error));
206
206
  return [];
207
207
  });
@@ -232,13 +232,13 @@ function DocumentConversion(options, comments) {
232
232
  htmlPaths.element("table", {}, {fresh: true})
233
233
  ]);
234
234
 
235
- function convertTable(element, messages, options) {
235
+ function convertTable(element, messages, context) {
236
236
  return findHtmlPath(element, defaultTablePath).wrap(function() {
237
- return convertTableChildren(element, messages, options);
237
+ return convertTableChildren(element, messages, context);
238
238
  });
239
239
  }
240
240
 
241
- function convertTableChildren(element, messages, options) {
241
+ function convertTableChildren(element, messages, context) {
242
242
  var bodyIndex = _.findIndex(element.children, function(child) {
243
243
  return !child.type === documents.types.tableRow || !child.isHeader;
244
244
  });
@@ -250,18 +250,18 @@ function DocumentConversion(options, comments) {
250
250
  children = convertElements(
251
251
  element.children,
252
252
  messages,
253
- _.extend({}, options, {isTableHeader: false})
253
+ _.extend({}, context, {isTableHeader: false})
254
254
  );
255
255
  } else {
256
256
  var headRows = convertElements(
257
257
  element.children.slice(0, bodyIndex),
258
258
  messages,
259
- _.extend({}, options, {isTableHeader: true})
259
+ _.extend({}, context, {isTableHeader: true})
260
260
  );
261
261
  var bodyRows = convertElements(
262
262
  element.children.slice(bodyIndex),
263
263
  messages,
264
- _.extend({}, options, {isTableHeader: false})
264
+ _.extend({}, context, {isTableHeader: false})
265
265
  );
266
266
  children = [
267
267
  Html.freshElement("thead", {}, headRows),
@@ -271,16 +271,16 @@ function DocumentConversion(options, comments) {
271
271
  return [Html.forceWrite].concat(children);
272
272
  }
273
273
 
274
- function convertTableRow(element, messages, options) {
275
- var children = convertElements(element.children, messages, options);
274
+ function convertTableRow(element, messages, context) {
275
+ var children = convertElements(element.children, messages, context);
276
276
  return [
277
277
  Html.freshElement("tr", {}, [Html.forceWrite].concat(children))
278
278
  ];
279
279
  }
280
280
 
281
- function convertTableCell(element, messages, options) {
282
- var tagName = options.isTableHeader ? "th" : "td";
283
- var children = convertElements(element.children, messages, options);
281
+ function convertTableCell(element, messages, context) {
282
+ var tagName = context.isTableHeader ? "th" : "td";
283
+ var children = convertElements(element.children, messages, context);
284
284
  var attributes = {};
285
285
  if (element.colSpan !== 1) {
286
286
  attributes.colspan = element.colSpan.toString();
@@ -294,7 +294,7 @@ function DocumentConversion(options, comments) {
294
294
  ];
295
295
  }
296
296
 
297
- function convertCommentReference(reference, messages, options) {
297
+ function convertCommentReference(reference, messages, context) {
298
298
  return findHtmlPath(reference, htmlPaths.ignore).wrap(function() {
299
299
  var comment = comments[reference.commentId];
300
300
  var count = referencedComments.length + 1;
@@ -310,12 +310,12 @@ function DocumentConversion(options, comments) {
310
310
  });
311
311
  }
312
312
 
313
- function convertComment(referencedComment, messages, options) {
313
+ function convertComment(referencedComment, messages, context) {
314
314
  // TODO: remove duplication with note references
315
315
 
316
316
  var label = referencedComment.label;
317
317
  var comment = referencedComment.comment;
318
- var body = convertElements(comment.body, messages, options).concat([
318
+ var body = convertElements(comment.body, messages, context).concat([
319
319
  Html.nonFreshElement("p", {}, [
320
320
  Html.text(" "),
321
321
  Html.freshElement("a", {"href": "#" + referenceHtmlId("comment", comment.commentId)}, [
@@ -334,7 +334,7 @@ function DocumentConversion(options, comments) {
334
334
  ];
335
335
  }
336
336
 
337
- function convertBreak(element, messages, options) {
337
+ function convertBreak(element, messages, context) {
338
338
  return htmlPathForBreak(element).wrap(function() {
339
339
  return [];
340
340
  });
@@ -352,35 +352,35 @@ function DocumentConversion(options, comments) {
352
352
  }
353
353
 
354
354
  var elementConverters = {
355
- "document": function(document, messages, options) {
356
- var children = convertElements(document.children, messages, options);
355
+ "document": function(document, messages, context) {
356
+ var children = convertElements(document.children, messages, context);
357
357
  var notes = noteReferences.map(function(noteReference) {
358
358
  return document.notes.resolve(noteReference);
359
359
  });
360
- var notesNodes = convertElements(notes, messages, options);
360
+ var notesNodes = convertElements(notes, messages, context);
361
361
  return children.concat([
362
362
  Html.freshElement("ol", {}, notesNodes),
363
363
  Html.freshElement("dl", {}, flatMap(referencedComments, function(referencedComment) {
364
- return convertComment(referencedComment, messages, options);
364
+ return convertComment(referencedComment, messages, context);
365
365
  }))
366
366
  ]);
367
367
  },
368
368
  "paragraph": convertParagraph,
369
369
  "run": convertRun,
370
- "text": function(element, messages, options) {
370
+ "text": function(element, messages, context) {
371
371
  return [Html.text(element.value)];
372
372
  },
373
- "tab": function(element, messages, options) {
373
+ "tab": function(element, messages, context) {
374
374
  return [Html.text("\t")];
375
375
  },
376
- "hyperlink": function(element, messages, options) {
376
+ "hyperlink": function(element, messages, context) {
377
377
  var href = element.anchor ? "#" + htmlId(element.anchor) : element.href;
378
378
  var attributes = {href: href};
379
379
  if (element.targetFrame != null) {
380
380
  attributes.target = element.targetFrame;
381
381
  }
382
382
 
383
- var children = convertElements(element.children, messages, options);
383
+ var children = convertElements(element.children, messages, context);
384
384
  return [Html.nonFreshElement("a", attributes, children)];
385
385
  },
386
386
  "checkbox": function(element) {
@@ -390,13 +390,13 @@ function DocumentConversion(options, comments) {
390
390
  }
391
391
  return [Html.freshElement("input", attributes)];
392
392
  },
393
- "bookmarkStart": function(element, messages, options) {
393
+ "bookmarkStart": function(element, messages, context) {
394
394
  var anchor = Html.freshElement("a", {
395
395
  id: htmlId(element.name)
396
396
  }, [Html.forceWrite]);
397
397
  return [anchor];
398
398
  },
399
- "noteReference": function(element, messages, options) {
399
+ "noteReference": function(element, messages, context) {
400
400
  noteReferences.push(element);
401
401
  var anchor = Html.freshElement("a", {
402
402
  href: "#" + noteHtmlId(element),
@@ -405,8 +405,8 @@ function DocumentConversion(options, comments) {
405
405
 
406
406
  return [Html.freshElement("sup", {}, [anchor])];
407
407
  },
408
- "note": function(element, messages, options) {
409
- var children = convertElements(element.body, messages, options);
408
+ "note": function(element, messages, context) {
409
+ var children = convertElements(element.body, messages, context);
410
410
  var backLink = Html.elementWithTag(htmlPaths.element("p", {}, {fresh: false}), [
411
411
  Html.text(" "),
412
412
  Html.freshElement("a", {href: "#" + noteRefHtmlId(element)}, [Html.text("↑")])
@@ -431,13 +431,13 @@ function DocumentConversion(options, comments) {
431
431
  var deferredId = 1;
432
432
 
433
433
  function deferredConversion(func) {
434
- return function(element, messages, options) {
434
+ return function(element, messages, context) {
435
435
  return [
436
436
  {
437
437
  type: "deferred",
438
438
  id: deferredId++,
439
439
  value: function() {
440
- return func(element, messages, options);
440
+ return func(element, messages, context);
441
441
  }
442
442
  }
443
443
  ];
@@ -169,6 +169,12 @@ function BodyReader(options) {
169
169
  complexFieldStack.push({type: "begin", fldChar: element});
170
170
  currentInstrText = [];
171
171
  } else if (type === "end") {
172
+ if (complexFieldStack.length === 0) {
173
+ return emptyResultWithMessages([warning(
174
+ "Ignoring complex field end character without corresponding start character"
175
+ )]);
176
+ }
177
+
172
178
  var complexFieldEnd = complexFieldStack.pop();
173
179
  if (complexFieldEnd.type === "begin") {
174
180
  complexFieldEnd = parseCurrentInstrText(complexFieldEnd);
@@ -179,6 +185,12 @@ function BodyReader(options) {
179
185
  }));
180
186
  }
181
187
  } else if (type === "separate") {
188
+ if (complexFieldStack.length === 0) {
189
+ return emptyResultWithMessages([warning(
190
+ "Ignoring complex field separator character without corresponding start character"
191
+ )]);
192
+ }
193
+
182
194
  var complexFieldSeparate = complexFieldStack.pop();
183
195
  var complexField = parseCurrentInstrText(complexFieldSeparate);
184
196
  complexFieldStack.push(complexField);
@@ -431,7 +443,13 @@ function BodyReader(options) {
431
443
  });
432
444
  },
433
445
 
446
+ "w:customXml": readChildElements,
434
447
  "w:ins": readChildElements,
448
+ "w:moveFromRangeEnd": readChildElements,
449
+ "w:moveFromRangeStart": readChildElements,
450
+ "w:moveTo": readChildElements,
451
+ "w:moveToRangeEnd": readChildElements,
452
+ "w:moveToRangeStart": readChildElements,
435
453
  "w:object": readChildElements,
436
454
  "w:smartTag": readChildElements,
437
455
  "w:drawing": readChildElements,
@@ -711,6 +729,7 @@ var ignoreElements = {
711
729
  "w:del": true,
712
730
  "w:footnoteRef": true,
713
731
  "w:endnoteRef": true,
732
+ "w:moveFrom": true,
714
733
  "w:pPr": true,
715
734
  "w:rPr": true,
716
735
  "w:tblPr": true,
package/lib/docx/files.js CHANGED
@@ -1,10 +1,10 @@
1
- var fs = require("fs");
2
1
  var url = require("url");
3
2
  var os = require("os");
4
3
  var dirname = require("path").dirname;
4
+ var isAbsolutePath = require("path").isAbsolute;
5
5
  var resolvePath = require("path").resolve;
6
- var isAbsolutePath = require('path-is-absolute');
7
6
 
7
+ var fs = require("../fs");
8
8
  var promises = require("../promises");
9
9
 
10
10
 
@@ -26,7 +26,7 @@ function Files(options) {
26
26
 
27
27
  function read(uri, encoding) {
28
28
  return resolveUri(uri).then(function(path) {
29
- return readFile(path, encoding).caught(function(error) {
29
+ return fs.readFile(path, encoding).catch(function(error) {
30
30
  var message = "could not open external image: '" + uri + "' (document directory: '" + base + "')\n" + error.message;
31
31
  return promises.reject(new Error(message));
32
32
  });
@@ -50,9 +50,6 @@ function Files(options) {
50
50
  }
51
51
 
52
52
 
53
- var readFile = promises.promisify(fs.readFile.bind(fs));
54
-
55
-
56
53
  function uriToPath(uriString, platform) {
57
54
  if (!platform) {
58
55
  platform = os.platform();
package/lib/fs.js ADDED
@@ -0,0 +1,16 @@
1
+ var fs = require("fs");
2
+
3
+ var promises = require("./promises");
4
+
5
+ function readFile(path, options) {
6
+ return promises.resolve(fs.promises.readFile(path, options));
7
+ }
8
+
9
+ function writeFile(path, data, options) {
10
+ return promises.resolve(fs.promises.writeFile(path, data, options));
11
+ }
12
+
13
+ exports.createWriteStream = fs.createWriteStream.bind(fs);
14
+ exports.readFile = readFile;
15
+ exports.readFileSync = fs.readFileSync.bind(fs);
16
+ exports.writeFile = writeFile;
package/lib/images.js CHANGED
@@ -7,7 +7,7 @@ exports.imgElement = imgElement;
7
7
 
8
8
  function imgElement(func) {
9
9
  return function(element, messages) {
10
- return promises.when(func(element)).then(function(result) {
10
+ return promises.resolve(func(element)).then(function(result) {
11
11
  var attributes = {};
12
12
  if (element.altText) {
13
13
  attributes.alt = element.altText;
package/lib/index.js CHANGED
@@ -6,6 +6,7 @@ var DocumentConverter = require("./document-to-html").DocumentConverter;
6
6
  var convertElementToRawText = require("./raw-text").convertElementToRawText;
7
7
  var readStyle = require("./style-reader").readStyle;
8
8
  var readOptions = require("./options-reader").readOptions;
9
+ var promises = require("./promises");
9
10
  var unzip = require("./unzip");
10
11
  var Result = require("./results").Result;
11
12
 
@@ -32,10 +33,11 @@ function convertToMarkdown(input, options) {
32
33
  function convert(input, options) {
33
34
  options = readOptions(options);
34
35
 
35
- return unzip.openZip(input)
36
- .tap(function(docxFile) {
36
+ var result = unzip.openZip(input)
37
+ .then(function(docxFile) {
37
38
  return docxStyleMap.readStyleMap(docxFile).then(function(styleMap) {
38
39
  options.embeddedStyleMap = styleMap;
40
+ return docxFile;
39
41
  });
40
42
  })
41
43
  .then(function(docxFile) {
@@ -47,11 +49,15 @@ function convert(input, options) {
47
49
  return convertDocumentToHtml(documentResult, options);
48
50
  });
49
51
  });
52
+
53
+ return promises.toExternalPromise(result);
50
54
  }
51
55
 
52
56
  function readEmbeddedStyleMap(input) {
53
- return unzip.openZip(input)
57
+ var result = unzip.openZip(input)
54
58
  .then(docxStyleMap.readStyleMap);
59
+
60
+ return promises.toExternalPromise(result);
55
61
  }
56
62
 
57
63
  function convertDocumentToHtml(documentResult, options) {
@@ -79,17 +85,22 @@ function parseStyleMap(styleMap) {
79
85
 
80
86
 
81
87
  function extractRawText(input) {
82
- return unzip.openZip(input)
88
+ var result = unzip.openZip(input)
83
89
  .then(docxReader.read)
84
90
  .then(function(documentResult) {
85
91
  return documentResult.map(convertElementToRawText);
86
92
  });
93
+
94
+ return promises.toExternalPromise(result);
87
95
  }
88
96
 
89
97
  function embedStyleMap(input, styleMap) {
90
- return unzip.openZip(input)
91
- .tap(function(docxFile) {
92
- return docxStyleMap.writeStyleMap(docxFile, styleMap);
98
+ var result = unzip.openZip(input)
99
+ .then(function(docxFile) {
100
+ return docxStyleMap.writeStyleMap(docxFile, styleMap)
101
+ .then(function() {
102
+ return docxFile;
103
+ });
93
104
  })
94
105
  .then(function(docxFile) {
95
106
  return docxFile.toArrayBuffer();
@@ -104,6 +115,8 @@ function embedStyleMap(input, styleMap) {
104
115
  }
105
116
  };
106
117
  });
118
+
119
+ return promises.toExternalPromise(result);
107
120
  }
108
121
 
109
122
  exports.styleMapping = function() {
package/lib/main.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /* global process */
2
2
 
3
- var fs = require("fs");
4
3
  var path = require("path");
5
4
 
6
5
  var mammoth = require("./");
7
- var promises = require("./promises");
6
+ var fs = require("./fs");
8
7
  var images = require("./images");
8
+ var promises = require("./promises");
9
9
 
10
10
  function main(argv) {
11
11
  var docxPath = argv["docx-path"];
@@ -14,7 +14,7 @@ function main(argv) {
14
14
  var outputFormat = argv.output_format;
15
15
  var styleMapPath = argv.style_map;
16
16
 
17
- readStyleMap(styleMapPath).then(function(styleMap) {
17
+ var result = readStyleMap(styleMapPath).then(function(styleMap) {
18
18
  var options = {
19
19
  styleMap: styleMap,
20
20
  outputFormat: outputFormat
@@ -31,7 +31,7 @@ function main(argv) {
31
31
 
32
32
  return element.read().then(function(imageBuffer) {
33
33
  var imagePath = path.join(outputDir, filename);
34
- return promises.nfcall(fs.writeFile, imagePath, imageBuffer);
34
+ return fs.writeFile(imagePath, imageBuffer);
35
35
  }).then(function() {
36
36
  return {src: filename};
37
37
  });
@@ -49,12 +49,14 @@ function main(argv) {
49
49
 
50
50
  outputStream.write(result.value);
51
51
  });
52
- }).done();
52
+ });
53
+
54
+ promises.toExternalPromise(result).done();
53
55
  }
54
56
 
55
57
  function readStyleMap(styleMapPath) {
56
58
  if (styleMapPath) {
57
- return promises.nfcall(fs.readFile, styleMapPath, "utf8");
59
+ return fs.readFile(styleMapPath, "utf8");
58
60
  } else {
59
61
  return promises.resolve(null);
60
62
  }