remark-docx 0.1.8 → 0.1.9

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/lib/index.js CHANGED
@@ -18,813 +18,830 @@ function invariant(cond, message) {
18
18
  throw new Error(message);
19
19
  }
20
20
 
21
- const hasSquareBrackets = (arg) => {
22
- return !!arg && arg.openMark === "[" && arg.closeMark === "]";
21
+ const ORDERED_LIST_REF = "ordered";
22
+ const INDENT = 0.5;
23
+ const DEFAULT_NUMBERINGS = [
24
+ {
25
+ level: 0,
26
+ format: docx.LevelFormat.DECIMAL,
27
+ text: "%1.",
28
+ alignment: docx.AlignmentType.START,
29
+ },
30
+ {
31
+ level: 1,
32
+ format: docx.LevelFormat.DECIMAL,
33
+ text: "%2.",
34
+ alignment: docx.AlignmentType.START,
35
+ style: {
36
+ paragraph: {
37
+ indent: { start: docx.convertInchesToTwip(INDENT * 1) },
38
+ },
39
+ },
40
+ },
41
+ {
42
+ level: 2,
43
+ format: docx.LevelFormat.DECIMAL,
44
+ text: "%3.",
45
+ alignment: docx.AlignmentType.START,
46
+ style: {
47
+ paragraph: {
48
+ indent: { start: docx.convertInchesToTwip(INDENT * 2) },
49
+ },
50
+ },
51
+ },
52
+ {
53
+ level: 3,
54
+ format: docx.LevelFormat.DECIMAL,
55
+ text: "%4.",
56
+ alignment: docx.AlignmentType.START,
57
+ style: {
58
+ paragraph: {
59
+ indent: { start: docx.convertInchesToTwip(INDENT * 3) },
60
+ },
61
+ },
62
+ },
63
+ {
64
+ level: 4,
65
+ format: docx.LevelFormat.DECIMAL,
66
+ text: "%5.",
67
+ alignment: docx.AlignmentType.START,
68
+ style: {
69
+ paragraph: {
70
+ indent: { start: docx.convertInchesToTwip(INDENT * 4) },
71
+ },
72
+ },
73
+ },
74
+ {
75
+ level: 5,
76
+ format: docx.LevelFormat.DECIMAL,
77
+ text: "%6.",
78
+ alignment: docx.AlignmentType.START,
79
+ style: {
80
+ paragraph: {
81
+ indent: { start: docx.convertInchesToTwip(INDENT * 5) },
82
+ },
83
+ },
84
+ },
85
+ ];
86
+ const createFootnoteRegistry = () => {
87
+ const idToInternalId = new Map();
88
+ const defs = new Map();
89
+ const getId = (id) => {
90
+ let internalId = idToInternalId.get(id);
91
+ if (internalId == null) {
92
+ idToInternalId.set(id, (internalId = idToInternalId.size + 1));
93
+ }
94
+ return internalId;
95
+ };
96
+ return {
97
+ ref: (id) => {
98
+ return getId(id);
99
+ },
100
+ def: (id, def) => {
101
+ const internalId = getId(id);
102
+ defs.set(internalId, def);
103
+ },
104
+ footnotes: () => {
105
+ return defs.entries().reduce((acc, [key, def]) => {
106
+ acc[key] = def;
107
+ return acc;
108
+ }, {});
109
+ },
110
+ };
23
111
  };
24
- const hasCurlyBrackets = (arg) => {
25
- return !!arg && arg.openMark === "{" && arg.closeMark === "}";
112
+ const createNumberingRegistry = () => {
113
+ let counter = 1;
114
+ return {
115
+ create: () => {
116
+ return `${ORDERED_LIST_REF}-${counter++}`;
117
+ },
118
+ getAll: () => {
119
+ return Array.from({ length: counter }, (_, i) => ({
120
+ reference: `${ORDERED_LIST_REF}-${i}`,
121
+ levels: DEFAULT_NUMBERINGS,
122
+ }));
123
+ },
124
+ };
26
125
  };
27
- const mapString = (s) => new docx.MathRun(s);
28
- const mapMacro = (n, runs) => {
29
- var _a, _b, _c, _d, _e, _f, _g, _h;
30
- switch (n.content) {
31
- case "#":
32
- return mapString("#");
33
- case "$":
34
- return mapString("$");
35
- case "%":
36
- return mapString("%");
37
- case "&":
38
- return mapString("&");
39
- case "textasciitilde":
40
- return mapString("~");
41
- case "textasciicircum":
42
- return mapString("^");
43
- case "textbackslash":
44
- return mapString("∖");
45
- case "{":
46
- return mapString("{");
47
- case "}":
48
- return mapString("}");
49
- case "textbar":
50
- return mapString("|");
51
- case "textless":
52
- return mapString("<");
53
- case "textgreater":
54
- return mapString(">");
55
- case "neq":
56
- return mapString("≠");
57
- case "sim":
58
- return mapString("∼");
59
- case "simeq":
60
- return mapString("");
61
- case "approx":
62
- return mapString("≈");
63
- case "fallingdotseq":
64
- return mapString("≒");
65
- case "risingdotseq":
66
- return mapString("");
67
- case "equiv":
68
- return mapString("≡");
69
- case "geq":
70
- return mapString("≥");
71
- case "geqq":
72
- return mapString("≧");
73
- case "leq":
74
- return mapString("");
75
- case "leqq":
76
- return mapString("≦");
77
- case "gg":
78
- return mapString("≫");
79
- case "ll":
80
- return mapString("≪");
81
- case "times":
82
- return mapString("×");
83
- case "div":
84
- return mapString("÷");
85
- case "pm":
86
- return mapString("±");
87
- case "mp":
88
- return mapString("∓");
89
- case "oplus":
90
- return mapString("⊕");
91
- case "ominus":
92
- return mapString("⊖");
93
- case "otimes":
94
- return mapString("⊗");
95
- case "oslash":
96
- return mapString("⊘");
97
- case "circ":
98
- return mapString("∘");
99
- case "cdot":
100
- return mapString("⋅");
101
- case "bullet":
102
- return mapString("∙");
103
- case "ltimes":
104
- return mapString("⋉");
105
- case "rtimes":
106
- return mapString("⋊");
107
- case "in":
108
- return mapString("∈");
109
- case "ni":
110
- return mapString("∋");
111
- case "notin":
112
- return mapString("∉");
113
- case "subset":
114
- return mapString("⊂");
115
- case "supset":
116
- return mapString("⊃");
117
- case "subseteq":
118
- return mapString("⊆");
119
- case "supseteq":
120
- return mapString("⊇");
121
- case "nsubseteq":
122
- return mapString("⊈");
123
- case "nsupseteq":
124
- return mapString("⊉");
125
- case "subsetneq":
126
- return mapString("⊊");
127
- case "supsetneq":
128
- return mapString("⊋");
129
- case "cap":
130
- return mapString("∩");
131
- case "cup":
132
- return mapString("∪");
133
- case "emptyset":
134
- return mapString("∅");
135
- case "infty":
136
- return mapString("∞");
137
- case "partial":
138
- return mapString("∂");
139
- case "aleph":
140
- return mapString("ℵ");
141
- case "hbar":
142
- return mapString("ℏ");
143
- case "wp":
144
- return mapString("℘");
145
- case "Re":
146
- return mapString("ℜ");
147
- case "Im":
148
- return mapString("ℑ");
149
- case "alpha":
150
- return mapString("α");
151
- case "beta":
152
- return mapString("β");
153
- case "gamma":
154
- return mapString("γ");
155
- case "delta":
156
- return mapString("δ");
157
- case "epsilon":
158
- return mapString("ϵ");
159
- case "zeta":
160
- return mapString("ζ");
161
- case "eta":
162
- return mapString("η");
163
- case "theta":
164
- return mapString("θ");
165
- case "iota":
166
- return mapString("ι");
167
- case "kappa":
168
- return mapString("κ");
169
- case "lambda":
170
- return mapString("λ");
171
- case "eta":
172
- return mapString("η");
173
- case "mu":
174
- return mapString("μ");
175
- case "nu":
176
- return mapString("ν");
177
- case "xi":
178
- return mapString("ξ");
179
- case "pi":
180
- return mapString("π");
181
- case "rho":
182
- return mapString("ρ");
183
- case "sigma":
184
- return mapString("σ");
185
- case "tau":
186
- return mapString("τ");
187
- case "upsilon":
188
- return mapString("υ");
189
- case "phi":
190
- return mapString("ϕ");
191
- case "chi":
192
- return mapString("χ");
193
- case "psi":
194
- return mapString("ψ");
195
- case "omega":
196
- return mapString("ω");
197
- case "varepsilon":
198
- return mapString("ε");
199
- case "vartheta":
200
- return mapString("ϑ");
201
- case "varrho":
202
- return mapString("ϱ");
203
- case "varsigma":
204
- return mapString("ς");
205
- case "varphi":
206
- return mapString("φ");
207
- case "Gamma":
208
- return mapString("Γ");
209
- case "Delta":
210
- return mapString("Δ");
211
- case "Theta":
212
- return mapString("Θ");
213
- case "Lambda":
214
- return mapString("Λ");
215
- case "Xi":
216
- return mapString("Ξ");
217
- case "Pi":
218
- return mapString("Π");
219
- case "Sigma":
220
- return mapString("Σ");
221
- case "Upsilon":
222
- return mapString("Υ");
223
- case "Phi":
224
- return mapString("Φ");
225
- case "Psi":
226
- return mapString("Ψ");
227
- case "Omega":
228
- return mapString("Ω");
229
- case "newline":
230
- case "\\":
231
- // line break
232
- return false;
233
- case "^": {
234
- const prev = runs.pop();
235
- if (!prev)
126
+ const mdastToDocx = async (node, { output = "buffer", title, subject, creator, keywords, description, lastModifiedBy, revision, styles, background, }, images, latex) => {
127
+ const definition = {};
128
+ unistUtilVisit.visit(node, "definition", (node) => {
129
+ definition[node.identifier] = node.url;
130
+ });
131
+ const footnote = createFootnoteRegistry();
132
+ const numbering = createNumberingRegistry();
133
+ const nodes = convertNodes(node.children, {
134
+ deco: {},
135
+ images,
136
+ indent: 0,
137
+ def: definition,
138
+ footnote,
139
+ numbering,
140
+ latex,
141
+ });
142
+ const doc = new docx.Document({
143
+ title,
144
+ subject,
145
+ creator,
146
+ keywords,
147
+ description,
148
+ lastModifiedBy,
149
+ revision,
150
+ styles,
151
+ background,
152
+ footnotes: footnote.footnotes(),
153
+ sections: [{ children: nodes }],
154
+ numbering: {
155
+ config: numbering.getAll(),
156
+ },
157
+ });
158
+ switch (output) {
159
+ case "buffer":
160
+ const bufOut = await docx.Packer.toBuffer(doc);
161
+ // feature detection instead of environment detection, but if Buffer exists
162
+ // it's probably Node. If not, return the Uint8Array that JSZip returns
163
+ // when it doesn't detect a Node environment.
164
+ return typeof Buffer === "function" ? Buffer.from(bufOut) : bufOut;
165
+ case "blob":
166
+ return docx.Packer.toBlob(doc);
167
+ }
168
+ };
169
+ const convertNodes = (nodes, ctx) => {
170
+ const results = [];
171
+ for (const node of nodes) {
172
+ switch (node.type) {
173
+ case "paragraph": {
174
+ results.push(buildParagraph(node, ctx));
236
175
  break;
237
- return new docx.MathSuperScript({
238
- children: [prev],
239
- superScript: mapGroup((_c = (_b = (_a = n.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) !== null && _c !== void 0 ? _c : []),
240
- });
241
- }
242
- case "_": {
243
- const prev = runs.pop();
244
- if (!prev)
176
+ }
177
+ case "heading": {
178
+ results.push(buildHeading(node, ctx));
245
179
  break;
246
- return new docx.MathSubScript({
247
- children: [prev],
248
- subScript: mapGroup((_f = (_e = (_d = n.args) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content) !== null && _f !== void 0 ? _f : []),
249
- });
250
- }
251
- case "hat":
252
- // TODO: implement
253
- break;
254
- case "widehat":
255
- // TODO: implement
256
- break;
257
- case "sum": {
258
- // TODO: support superscript and subscript
259
- return new docx.MathSum({
260
- children: [],
261
- });
262
- }
263
- case "int":
264
- return mapString("");
265
- case "frac":
266
- case "tfrac":
267
- case "dfrac": {
268
- const args = (_g = n.args) !== null && _g !== void 0 ? _g : [];
269
- if (args.length === 2 &&
270
- hasCurlyBrackets(args[0]) &&
271
- hasCurlyBrackets(args[1])) {
272
- return new docx.MathFraction({
273
- numerator: mapGroup(args[0].content),
274
- denominator: mapGroup(args[1].content),
180
+ }
181
+ case "thematicBreak":
182
+ results.push(buildThematicBreak());
183
+ break;
184
+ case "blockquote": {
185
+ results.push(...buildBlockquote(node, ctx));
186
+ break;
187
+ }
188
+ case "list": {
189
+ results.push(...buildList(node, ctx));
190
+ break;
191
+ }
192
+ case "listItem":
193
+ invariant(false, "unreachable");
194
+ case "table":
195
+ results.push(buildTable(node, ctx));
196
+ break;
197
+ case "tableRow":
198
+ invariant(false, "unreachable");
199
+ case "tableCell":
200
+ invariant(false, "unreachable");
201
+ case "html":
202
+ results.push(buildHtml(node));
203
+ break;
204
+ case "code":
205
+ results.push(buildCode(node));
206
+ break;
207
+ case "yaml":
208
+ // FIXME: unimplemented
209
+ break;
210
+ case "toml":
211
+ // FIXME: unimplemented
212
+ break;
213
+ case "definition":
214
+ // noop
215
+ break;
216
+ case "footnoteDefinition": {
217
+ registerFootnoteDefinition(node, ctx);
218
+ break;
219
+ }
220
+ case "text":
221
+ results.push(buildText(node.value, ctx.deco));
222
+ break;
223
+ case "emphasis":
224
+ case "strong":
225
+ case "delete": {
226
+ const { type, children } = node;
227
+ const nodes = convertNodes(children, {
228
+ ...ctx,
229
+ deco: { ...ctx.deco, [type]: true },
275
230
  });
231
+ results.push(...nodes);
232
+ break;
233
+ }
234
+ case "inlineCode":
235
+ // FIXME: transform to text for now
236
+ results.push(buildText(node.value, ctx.deco));
237
+ break;
238
+ case "break":
239
+ results.push(buildBreak());
240
+ break;
241
+ case "link": {
242
+ results.push(buildLink(node, ctx));
243
+ break;
276
244
  }
277
- break;
278
- }
279
- case "sqrt": {
280
- const args = (_h = n.args) !== null && _h !== void 0 ? _h : [];
281
- if (args.length === 1 && hasCurlyBrackets(args[0])) {
282
- return new docx.MathRadical({
283
- children: mapGroup(args[0].content),
284
- });
245
+ case "image":
246
+ results.push(buildImage(node, ctx.images));
247
+ break;
248
+ case "linkReference":
249
+ results.push(...buildLinkReference(node, ctx));
250
+ break;
251
+ case "imageReference": {
252
+ const image = buildImageReference(node, ctx);
253
+ if (image) {
254
+ results.push(image);
255
+ }
256
+ break;
285
257
  }
286
- if (args.length === 2 &&
287
- hasSquareBrackets(args[0]) &&
288
- hasCurlyBrackets(args[1])) {
289
- return new docx.MathRadical({
290
- children: mapGroup(args[1].content),
291
- degree: mapGroup(args[0].content),
292
- });
258
+ case "footnote": {
259
+ // inline footnote was removed in mdast v5
260
+ break;
293
261
  }
294
- break;
262
+ case "footnoteReference":
263
+ results.push(buildFootnoteReference(node, ctx));
264
+ break;
265
+ case "math":
266
+ results.push(...buildMath(node, ctx));
267
+ break;
268
+ case "inlineMath":
269
+ results.push(buildInlineMath(node, ctx));
270
+ break;
271
+ default:
272
+ unreachable();
273
+ break;
295
274
  }
296
275
  }
297
- return mapString(n.content);
276
+ return results;
298
277
  };
299
- const mapGroup = (nodes) => {
300
- const group = [];
301
- for (const c of nodes) {
302
- group.push(...(mapNode(c, group) || []));
278
+ const buildParagraph = ({ children }, ctx) => {
279
+ const list = ctx.list;
280
+ const nodes = convertNodes(children, ctx);
281
+ if (list && list.checked != null) {
282
+ nodes.unshift(new docx.CheckBox({
283
+ checked: list.checked,
284
+ checkedState: { value: "2611" },
285
+ uncheckedState: { value: "2610" },
286
+ }));
303
287
  }
304
- return group;
288
+ return new docx.Paragraph({
289
+ children: nodes,
290
+ indent: ctx.indent > 0
291
+ ? {
292
+ start: docx.convertInchesToTwip(INDENT * ctx.indent),
293
+ }
294
+ : undefined,
295
+ ...(list &&
296
+ (list.ordered
297
+ ? {
298
+ numbering: {
299
+ reference: list.reference,
300
+ level: list.level,
301
+ },
302
+ }
303
+ : {
304
+ bullet: {
305
+ level: list.level,
306
+ },
307
+ })),
308
+ });
305
309
  };
306
- const mapNode = (n, runs) => {
307
- switch (n.type) {
308
- case "root":
309
- break;
310
- case "string":
311
- return [mapString(n.content)];
312
- case "whitespace":
313
- break;
314
- case "parbreak":
315
- break;
316
- case "comment":
310
+ const buildHeading = ({ children, depth }, ctx) => {
311
+ let headingLevel;
312
+ switch (depth) {
313
+ case 1:
314
+ headingLevel = docx.HeadingLevel.TITLE;
317
315
  break;
318
- case "macro":
319
- const run = mapMacro(n, runs);
320
- if (!run) {
321
- // line break
322
- return false;
323
- }
324
- else {
325
- return [run];
326
- }
327
- case "environment":
328
- case "mathenv":
316
+ case 2:
317
+ headingLevel = docx.HeadingLevel.HEADING_1;
329
318
  break;
330
- case "verbatim":
319
+ case 3:
320
+ headingLevel = docx.HeadingLevel.HEADING_2;
331
321
  break;
332
- case "inlinemath":
322
+ case 4:
323
+ headingLevel = docx.HeadingLevel.HEADING_3;
333
324
  break;
334
- case "displaymath":
325
+ case 5:
326
+ headingLevel = docx.HeadingLevel.HEADING_4;
335
327
  break;
336
- case "group":
337
- return mapGroup(n.content);
338
- case "verb":
328
+ case 6:
329
+ headingLevel = docx.HeadingLevel.HEADING_5;
339
330
  break;
340
- default:
341
- unreachable();
342
331
  }
343
- return [];
332
+ const nodes = convertNodes(children, ctx);
333
+ return new docx.Paragraph({
334
+ heading: headingLevel,
335
+ children: nodes,
336
+ });
344
337
  };
345
- /**
346
- * @internal
347
- */
348
- const parseLatex = (value) => {
349
- const parsed = unifiedLatexUtilParse.parseMath(value);
350
- const paragraphs = [[]];
351
- let runs = paragraphs[0];
352
- for (const n of parsed) {
353
- const res = mapNode(n, runs);
354
- if (!res) {
355
- // line break
356
- paragraphs.push((runs = []));
357
- }
358
- else {
359
- runs.push(...res);
360
- }
361
- }
362
- return paragraphs;
338
+ const buildThematicBreak = (_) => {
339
+ return new docx.Paragraph({
340
+ thematicBreak: true,
341
+ });
363
342
  };
364
-
365
- const ORDERED_LIST_REF = "ordered";
366
- const INDENT = 0.5;
367
- const DEFAULT_NUMBERINGS = [
368
- {
369
- level: 0,
370
- format: docx.LevelFormat.DECIMAL,
371
- text: "%1.",
372
- alignment: docx.AlignmentType.START,
373
- },
374
- {
375
- level: 1,
376
- format: docx.LevelFormat.DECIMAL,
377
- text: "%2.",
378
- alignment: docx.AlignmentType.START,
379
- style: {
380
- paragraph: {
381
- indent: { start: docx.convertInchesToTwip(INDENT * 1) },
382
- },
383
- },
384
- },
385
- {
386
- level: 2,
387
- format: docx.LevelFormat.DECIMAL,
388
- text: "%3.",
389
- alignment: docx.AlignmentType.START,
390
- style: {
391
- paragraph: {
392
- indent: { start: docx.convertInchesToTwip(INDENT * 2) },
393
- },
394
- },
395
- },
396
- {
397
- level: 3,
398
- format: docx.LevelFormat.DECIMAL,
399
- text: "%4.",
400
- alignment: docx.AlignmentType.START,
401
- style: {
402
- paragraph: {
403
- indent: { start: docx.convertInchesToTwip(INDENT * 3) },
404
- },
405
- },
406
- },
407
- {
408
- level: 4,
409
- format: docx.LevelFormat.DECIMAL,
410
- text: "%5.",
411
- alignment: docx.AlignmentType.START,
412
- style: {
413
- paragraph: {
414
- indent: { start: docx.convertInchesToTwip(INDENT * 4) },
415
- },
416
- },
417
- },
418
- {
419
- level: 5,
420
- format: docx.LevelFormat.DECIMAL,
421
- text: "%6.",
422
- alignment: docx.AlignmentType.START,
423
- style: {
424
- paragraph: {
425
- indent: { start: docx.convertInchesToTwip(INDENT * 5) },
426
- },
427
- },
428
- },
429
- ];
430
- const createFootnoteRegistry = () => {
431
- const idToInternalId = new Map();
432
- const defs = new Map();
433
- const getId = (id) => {
434
- let internalId = idToInternalId.get(id);
435
- if (internalId == null) {
436
- idToInternalId.set(id, (internalId = idToInternalId.size + 1));
343
+ const buildBlockquote = ({ children }, ctx) => {
344
+ return convertNodes(children, {
345
+ ...ctx,
346
+ indent: ctx.indent + 1,
347
+ });
348
+ };
349
+ const buildList = ({ children, ordered, start: _start, spread: _spread }, ctx) => {
350
+ var _a;
351
+ const isTopLevel = !ctx.list;
352
+ const list = {
353
+ level: ctx.list ? ctx.list.level + 1 : 0,
354
+ ordered: !!ordered,
355
+ reference: isTopLevel && ordered
356
+ ? ctx.numbering.create()
357
+ : ((_a = ctx.list) === null || _a === void 0 ? void 0 : _a.reference) || ORDERED_LIST_REF,
358
+ };
359
+ return children.flatMap((item) => {
360
+ return buildListItem(item, {
361
+ ...ctx,
362
+ list,
363
+ });
364
+ });
365
+ };
366
+ const buildListItem = ({ children, checked, spread: _spread }, ctx) => {
367
+ return convertNodes(children, {
368
+ ...ctx,
369
+ ...(ctx.list && { list: { ...ctx.list, checked: checked !== null && checked !== void 0 ? checked : undefined } }),
370
+ });
371
+ };
372
+ const buildTable = ({ children, align }, ctx) => {
373
+ const cellAligns = align === null || align === void 0 ? void 0 : align.map((a) => {
374
+ switch (a) {
375
+ case "left":
376
+ return docx.AlignmentType.LEFT;
377
+ case "right":
378
+ return docx.AlignmentType.RIGHT;
379
+ case "center":
380
+ return docx.AlignmentType.CENTER;
381
+ default:
382
+ return docx.AlignmentType.LEFT;
437
383
  }
438
- return internalId;
439
- };
440
- return {
441
- ref: (id) => {
442
- return getId(id);
443
- },
444
- def: (id, def) => {
445
- const internalId = getId(id);
446
- defs.set(internalId, def);
447
- },
448
- footnotes: () => {
449
- return defs.entries().reduce((acc, [key, def]) => {
450
- acc[key] = def;
451
- return acc;
452
- }, {});
453
- },
454
- };
384
+ });
385
+ return new docx.Table({
386
+ rows: children.map((r) => {
387
+ return buildTableRow(r, ctx, cellAligns);
388
+ }),
389
+ });
455
390
  };
456
- const mdastToDocx = async (node, { output = "buffer", title, subject, creator, keywords, description, lastModifiedBy, revision, styles, background, }, images) => {
457
- const definition = {};
458
- unistUtilVisit.visit(node, "definition", (node) => {
459
- definition[node.identifier] = node.url;
391
+ const buildTableRow = ({ children }, ctx, cellAligns) => {
392
+ return new docx.TableRow({
393
+ children: children.map((c, i) => {
394
+ return buildTableCell(c, ctx, cellAligns === null || cellAligns === void 0 ? void 0 : cellAligns[i]);
395
+ }),
460
396
  });
461
- const footnote = createFootnoteRegistry();
462
- const nodes = convertNodes(node.children, {
463
- deco: {},
464
- images,
465
- indent: 0,
466
- def: definition,
467
- footnote,
397
+ };
398
+ const buildTableCell = ({ children }, ctx, align) => {
399
+ const nodes = convertNodes(children, ctx);
400
+ return new docx.TableCell({
401
+ children: [
402
+ new docx.Paragraph({
403
+ alignment: align,
404
+ children: nodes,
405
+ }),
406
+ ],
468
407
  });
469
- const doc = new docx.Document({
470
- title,
471
- subject,
472
- creator,
473
- keywords,
474
- description,
475
- lastModifiedBy,
476
- revision,
477
- styles,
478
- background,
479
- footnotes: footnote.footnotes(),
480
- sections: [{ children: nodes }],
481
- numbering: {
482
- config: [
483
- {
484
- reference: ORDERED_LIST_REF,
485
- levels: DEFAULT_NUMBERINGS,
486
- },
487
- ],
408
+ };
409
+ const buildHtml = ({ value }) => {
410
+ // FIXME: transform to text for now
411
+ return new docx.Paragraph({
412
+ children: [buildText(value, {})],
413
+ });
414
+ };
415
+ const buildCode = ({ value, lang: _lang, meta: _meta, }) => {
416
+ // FIXME: transform to text for now
417
+ return new docx.Paragraph({
418
+ children: [buildText(value, {})],
419
+ });
420
+ };
421
+ const buildMath = ({ value }, ctx) => {
422
+ return ctx.latex(value).map((runs) => new docx.Paragraph({
423
+ children: [
424
+ new docx.Math({
425
+ children: runs,
426
+ }),
427
+ ],
428
+ }));
429
+ };
430
+ const buildInlineMath = ({ value }, ctx) => {
431
+ return new docx.Math({
432
+ children: ctx.latex(value).flatMap((runs) => runs),
433
+ });
434
+ };
435
+ const buildText = (text, deco) => {
436
+ return new docx.TextRun({
437
+ text,
438
+ bold: deco.strong,
439
+ italics: deco.emphasis,
440
+ strike: deco.delete,
441
+ });
442
+ };
443
+ const buildBreak = (_) => {
444
+ return new docx.TextRun({ text: "", break: 1 });
445
+ };
446
+ const buildLink = ({ children, url }, ctx) => {
447
+ const nodes = convertNodes(children, ctx);
448
+ return new docx.ExternalHyperlink({
449
+ link: url,
450
+ children: nodes,
451
+ });
452
+ };
453
+ const buildImage = ({ url }, images) => {
454
+ const img = images[url];
455
+ invariant(img, `Fetch image was failed: ${url}`);
456
+ const { image, width, height } = img;
457
+ return new docx.ImageRun({
458
+ data: image,
459
+ transformation: {
460
+ width,
461
+ height,
488
462
  },
489
463
  });
490
- switch (output) {
491
- case "buffer":
492
- const bufOut = await docx.Packer.toBuffer(doc);
493
- // feature detection instead of environment detection, but if Buffer exists
494
- // it's probably Node. If not, return the Uint8Array that JSZip returns
495
- // when it doesn't detect a Node environment.
496
- return typeof Buffer === "function" ? Buffer.from(bufOut) : bufOut;
497
- case "blob":
498
- return docx.Packer.toBlob(doc);
464
+ };
465
+ const buildLinkReference = ({ children, identifier }, ctx) => {
466
+ const def = ctx.def[identifier];
467
+ if (def == null) {
468
+ return convertNodes(children, ctx);
499
469
  }
470
+ return [buildLink({ children, url: def }, ctx)];
500
471
  };
501
- const convertNodes = (nodes, ctx) => {
502
- const results = [];
503
- for (const node of nodes) {
504
- switch (node.type) {
505
- case "paragraph": {
506
- results.push(buildParagraph(node, ctx));
507
- break;
508
- }
509
- case "heading": {
510
- results.push(buildHeading(node, ctx));
511
- break;
512
- }
513
- case "thematicBreak":
514
- results.push(buildThematicBreak());
515
- break;
516
- case "blockquote": {
517
- results.push(...buildBlockquote(node, ctx));
518
- break;
519
- }
520
- case "list": {
521
- results.push(...buildList(node, ctx));
522
- break;
472
+ const buildImageReference = ({ identifier }, ctx) => {
473
+ const def = ctx.def[identifier];
474
+ if (def == null) {
475
+ return;
476
+ }
477
+ return buildImage({ url: def }, ctx.images);
478
+ };
479
+ const registerFootnoteDefinition = ({ children, identifier }, ctx) => {
480
+ const definition = {
481
+ children: children.map((node) => {
482
+ // Convert each node and extract the first result as a paragraph
483
+ const nodes = convertNodes([node], ctx);
484
+ if (nodes[0] instanceof docx.Paragraph) {
485
+ return nodes[0];
523
486
  }
524
- case "listItem":
525
- invariant(false, "unreachable");
526
- case "table":
527
- results.push(buildTable(node, ctx));
528
- break;
529
- case "tableRow":
530
- invariant(false, "unreachable");
531
- case "tableCell":
532
- invariant(false, "unreachable");
533
- case "html":
534
- results.push(buildHtml(node));
535
- break;
536
- case "code":
537
- results.push(buildCode(node));
538
- break;
539
- case "yaml":
540
- // FIXME: unimplemented
541
- break;
542
- case "toml":
543
- // FIXME: unimplemented
544
- break;
545
- case "definition":
546
- // noop
547
- break;
548
- case "footnoteDefinition": {
549
- registerFootnoteDefinition(node, ctx);
487
+ // For non-paragraph content, wrap in a paragraph
488
+ return new docx.Paragraph({ children: nodes });
489
+ }),
490
+ };
491
+ ctx.footnote.def(identifier, definition);
492
+ };
493
+ const buildFootnoteReference = ({ identifier }, ctx) => {
494
+ return new docx.FootnoteReferenceRun(ctx.footnote.ref(identifier));
495
+ };
496
+
497
+ const hasSquareBrackets = (arg) => {
498
+ return !!arg && arg.openMark === "[" && arg.closeMark === "]";
499
+ };
500
+ const hasCurlyBrackets = (arg) => {
501
+ return !!arg && arg.openMark === "{" && arg.closeMark === "}";
502
+ };
503
+ const mapString = (s) => new docx.MathRun(s);
504
+ const mapMacro = (n, runs) => {
505
+ var _a, _b, _c, _d, _e, _f, _g, _h;
506
+ switch (n.content) {
507
+ case "#":
508
+ return mapString("#");
509
+ case "$":
510
+ return mapString("$");
511
+ case "%":
512
+ return mapString("%");
513
+ case "&":
514
+ return mapString("&");
515
+ case "textasciitilde":
516
+ return mapString("~");
517
+ case "textasciicircum":
518
+ return mapString("^");
519
+ case "textbackslash":
520
+ return mapString("∖");
521
+ case "{":
522
+ return mapString("{");
523
+ case "}":
524
+ return mapString("}");
525
+ case "textbar":
526
+ return mapString("|");
527
+ case "textless":
528
+ return mapString("<");
529
+ case "textgreater":
530
+ return mapString(">");
531
+ case "neq":
532
+ return mapString("≠");
533
+ case "sim":
534
+ return mapString("∼");
535
+ case "simeq":
536
+ return mapString("≃");
537
+ case "approx":
538
+ return mapString("≈");
539
+ case "fallingdotseq":
540
+ return mapString("≒");
541
+ case "risingdotseq":
542
+ return mapString("≓");
543
+ case "equiv":
544
+ return mapString("≡");
545
+ case "geq":
546
+ return mapString("≥");
547
+ case "geqq":
548
+ return mapString("≧");
549
+ case "leq":
550
+ return mapString("≤");
551
+ case "leqq":
552
+ return mapString("≦");
553
+ case "gg":
554
+ return mapString("≫");
555
+ case "ll":
556
+ return mapString("≪");
557
+ case "times":
558
+ return mapString("×");
559
+ case "div":
560
+ return mapString("÷");
561
+ case "pm":
562
+ return mapString("±");
563
+ case "mp":
564
+ return mapString("∓");
565
+ case "oplus":
566
+ return mapString("⊕");
567
+ case "ominus":
568
+ return mapString("⊖");
569
+ case "otimes":
570
+ return mapString("⊗");
571
+ case "oslash":
572
+ return mapString("⊘");
573
+ case "circ":
574
+ return mapString("∘");
575
+ case "cdot":
576
+ return mapString("⋅");
577
+ case "bullet":
578
+ return mapString("∙");
579
+ case "ltimes":
580
+ return mapString("⋉");
581
+ case "rtimes":
582
+ return mapString("⋊");
583
+ case "in":
584
+ return mapString("∈");
585
+ case "ni":
586
+ return mapString("∋");
587
+ case "notin":
588
+ return mapString("∉");
589
+ case "subset":
590
+ return mapString("⊂");
591
+ case "supset":
592
+ return mapString("⊃");
593
+ case "subseteq":
594
+ return mapString("⊆");
595
+ case "supseteq":
596
+ return mapString("⊇");
597
+ case "nsubseteq":
598
+ return mapString("⊈");
599
+ case "nsupseteq":
600
+ return mapString("⊉");
601
+ case "subsetneq":
602
+ return mapString("⊊");
603
+ case "supsetneq":
604
+ return mapString("⊋");
605
+ case "cap":
606
+ return mapString("∩");
607
+ case "cup":
608
+ return mapString("∪");
609
+ case "emptyset":
610
+ return mapString("∅");
611
+ case "infty":
612
+ return mapString("∞");
613
+ case "partial":
614
+ return mapString("∂");
615
+ case "aleph":
616
+ return mapString("ℵ");
617
+ case "hbar":
618
+ return mapString("ℏ");
619
+ case "wp":
620
+ return mapString("℘");
621
+ case "Re":
622
+ return mapString("ℜ");
623
+ case "Im":
624
+ return mapString("ℑ");
625
+ case "alpha":
626
+ return mapString("α");
627
+ case "beta":
628
+ return mapString("β");
629
+ case "gamma":
630
+ return mapString("γ");
631
+ case "delta":
632
+ return mapString("δ");
633
+ case "epsilon":
634
+ return mapString("ϵ");
635
+ case "zeta":
636
+ return mapString("ζ");
637
+ case "eta":
638
+ return mapString("η");
639
+ case "theta":
640
+ return mapString("θ");
641
+ case "iota":
642
+ return mapString("ι");
643
+ case "kappa":
644
+ return mapString("κ");
645
+ case "lambda":
646
+ return mapString("λ");
647
+ case "eta":
648
+ return mapString("η");
649
+ case "mu":
650
+ return mapString("μ");
651
+ case "nu":
652
+ return mapString("ν");
653
+ case "xi":
654
+ return mapString("ξ");
655
+ case "pi":
656
+ return mapString("π");
657
+ case "rho":
658
+ return mapString("ρ");
659
+ case "sigma":
660
+ return mapString("σ");
661
+ case "tau":
662
+ return mapString("τ");
663
+ case "upsilon":
664
+ return mapString("υ");
665
+ case "phi":
666
+ return mapString("ϕ");
667
+ case "chi":
668
+ return mapString("χ");
669
+ case "psi":
670
+ return mapString("ψ");
671
+ case "omega":
672
+ return mapString("ω");
673
+ case "varepsilon":
674
+ return mapString("ε");
675
+ case "vartheta":
676
+ return mapString("ϑ");
677
+ case "varrho":
678
+ return mapString("ϱ");
679
+ case "varsigma":
680
+ return mapString("ς");
681
+ case "varphi":
682
+ return mapString("φ");
683
+ case "Gamma":
684
+ return mapString("Γ");
685
+ case "Delta":
686
+ return mapString("Δ");
687
+ case "Theta":
688
+ return mapString("Θ");
689
+ case "Lambda":
690
+ return mapString("Λ");
691
+ case "Xi":
692
+ return mapString("Ξ");
693
+ case "Pi":
694
+ return mapString("Π");
695
+ case "Sigma":
696
+ return mapString("Σ");
697
+ case "Upsilon":
698
+ return mapString("Υ");
699
+ case "Phi":
700
+ return mapString("Φ");
701
+ case "Psi":
702
+ return mapString("Ψ");
703
+ case "Omega":
704
+ return mapString("Ω");
705
+ case "newline":
706
+ case "\\":
707
+ // line break
708
+ return false;
709
+ case "^": {
710
+ const prev = runs.pop();
711
+ if (!prev)
550
712
  break;
551
- }
552
- case "text":
553
- results.push(buildText(node.value, ctx.deco));
713
+ return new docx.MathSuperScript({
714
+ children: [prev],
715
+ superScript: mapGroup((_c = (_b = (_a = n.args) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content) !== null && _c !== void 0 ? _c : []),
716
+ });
717
+ }
718
+ case "_": {
719
+ const prev = runs.pop();
720
+ if (!prev)
554
721
  break;
555
- case "emphasis":
556
- case "strong":
557
- case "delete": {
558
- const { type, children } = node;
559
- const nodes = convertNodes(children, {
560
- ...ctx,
561
- deco: { ...ctx.deco, [type]: true },
722
+ return new docx.MathSubScript({
723
+ children: [prev],
724
+ subScript: mapGroup((_f = (_e = (_d = n.args) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.content) !== null && _f !== void 0 ? _f : []),
725
+ });
726
+ }
727
+ case "hat":
728
+ // TODO: implement
729
+ break;
730
+ case "widehat":
731
+ // TODO: implement
732
+ break;
733
+ case "sum": {
734
+ // TODO: support superscript and subscript
735
+ return new docx.MathSum({
736
+ children: [],
737
+ });
738
+ }
739
+ case "int":
740
+ return mapString("∫");
741
+ case "frac":
742
+ case "tfrac":
743
+ case "dfrac": {
744
+ const args = (_g = n.args) !== null && _g !== void 0 ? _g : [];
745
+ if (args.length === 2 &&
746
+ hasCurlyBrackets(args[0]) &&
747
+ hasCurlyBrackets(args[1])) {
748
+ return new docx.MathFraction({
749
+ numerator: mapGroup(args[0].content),
750
+ denominator: mapGroup(args[1].content),
562
751
  });
563
- results.push(...nodes);
564
- break;
565
- }
566
- case "inlineCode":
567
- // FIXME: transform to text for now
568
- results.push(buildText(node.value, ctx.deco));
569
- break;
570
- case "break":
571
- results.push(buildBreak());
572
- break;
573
- case "link": {
574
- results.push(buildLink(node, ctx));
575
- break;
576
- }
577
- case "image":
578
- results.push(buildImage(node, ctx.images));
579
- break;
580
- case "linkReference":
581
- results.push(...buildLinkReference(node, ctx));
582
- break;
583
- case "imageReference": {
584
- const image = buildImageReference(node, ctx);
585
- if (image) {
586
- results.push(image);
587
- }
588
- break;
589
752
  }
590
- case "footnote": {
591
- // inline footnote was removed in mdast v5
592
- break;
753
+ break;
754
+ }
755
+ case "sqrt": {
756
+ const args = (_h = n.args) !== null && _h !== void 0 ? _h : [];
757
+ if (args.length === 1 && hasCurlyBrackets(args[0])) {
758
+ return new docx.MathRadical({
759
+ children: mapGroup(args[0].content),
760
+ });
593
761
  }
594
- case "footnoteReference":
595
- results.push(buildFootnoteReference(node, ctx));
596
- break;
597
- case "math":
598
- results.push(...buildMath(node));
599
- break;
600
- case "inlineMath":
601
- results.push(buildInlineMath(node));
602
- break;
603
- default:
604
- unreachable();
605
- break;
762
+ if (args.length === 2 &&
763
+ hasSquareBrackets(args[0]) &&
764
+ hasCurlyBrackets(args[1])) {
765
+ return new docx.MathRadical({
766
+ children: mapGroup(args[1].content),
767
+ degree: mapGroup(args[0].content),
768
+ });
769
+ }
770
+ break;
606
771
  }
607
772
  }
608
- return results;
773
+ return mapString(n.content);
609
774
  };
610
- const buildParagraph = ({ children }, ctx) => {
611
- const list = ctx.list;
612
- const nodes = convertNodes(children, ctx);
613
- if (list && list.checked != null) {
614
- nodes.unshift(new docx.CheckBox({
615
- checked: list.checked,
616
- checkedState: { value: "2611" },
617
- uncheckedState: { value: "2610" },
618
- }));
775
+ const mapGroup = (nodes) => {
776
+ const group = [];
777
+ for (const c of nodes) {
778
+ group.push(...(mapNode(c, group) || []));
619
779
  }
620
- return new docx.Paragraph({
621
- children: nodes,
622
- indent: ctx.indent > 0
623
- ? {
624
- start: docx.convertInchesToTwip(INDENT * ctx.indent),
625
- }
626
- : undefined,
627
- ...(list &&
628
- (list.ordered
629
- ? {
630
- numbering: {
631
- reference: ORDERED_LIST_REF,
632
- level: list.level,
633
- },
634
- }
635
- : {
636
- bullet: {
637
- level: list.level,
638
- },
639
- })),
640
- });
780
+ return group;
641
781
  };
642
- const buildHeading = ({ children, depth }, ctx) => {
643
- let headingLevel;
644
- switch (depth) {
645
- case 1:
646
- headingLevel = docx.HeadingLevel.TITLE;
782
+ const mapNode = (n, runs) => {
783
+ switch (n.type) {
784
+ case "root":
647
785
  break;
648
- case 2:
649
- headingLevel = docx.HeadingLevel.HEADING_1;
786
+ case "string":
787
+ return [mapString(n.content)];
788
+ case "whitespace":
650
789
  break;
651
- case 3:
652
- headingLevel = docx.HeadingLevel.HEADING_2;
790
+ case "parbreak":
653
791
  break;
654
- case 4:
655
- headingLevel = docx.HeadingLevel.HEADING_3;
792
+ case "comment":
656
793
  break;
657
- case 5:
658
- headingLevel = docx.HeadingLevel.HEADING_4;
794
+ case "macro":
795
+ const run = mapMacro(n, runs);
796
+ if (!run) {
797
+ // line break
798
+ return false;
799
+ }
800
+ else {
801
+ return [run];
802
+ }
803
+ case "environment":
804
+ case "mathenv":
659
805
  break;
660
- case 6:
661
- headingLevel = docx.HeadingLevel.HEADING_5;
806
+ case "verbatim":
807
+ break;
808
+ case "inlinemath":
662
809
  break;
810
+ case "displaymath":
811
+ break;
812
+ case "group":
813
+ return mapGroup(n.content);
814
+ case "verb":
815
+ break;
816
+ default:
817
+ unreachable();
663
818
  }
664
- const nodes = convertNodes(children, ctx);
665
- return new docx.Paragraph({
666
- heading: headingLevel,
667
- children: nodes,
668
- });
669
- };
670
- const buildThematicBreak = (_) => {
671
- return new docx.Paragraph({
672
- thematicBreak: true,
673
- });
674
- };
675
- const buildBlockquote = ({ children }, ctx) => {
676
- return convertNodes(children, {
677
- ...ctx,
678
- indent: ctx.indent + 1,
679
- });
680
- };
681
- const buildList = ({ children, ordered, start: _start, spread: _spread }, ctx) => {
682
- const list = {
683
- level: ctx.list ? ctx.list.level + 1 : 0,
684
- ordered: !!ordered,
685
- };
686
- return children.flatMap((item) => {
687
- return buildListItem(item, {
688
- ...ctx,
689
- list,
690
- });
691
- });
692
- };
693
- const buildListItem = ({ children, checked, spread: _spread }, ctx) => {
694
- return convertNodes(children, {
695
- ...ctx,
696
- ...(ctx.list && { list: { ...ctx.list, checked: checked !== null && checked !== void 0 ? checked : undefined } }),
697
- });
819
+ return [];
698
820
  };
699
- const buildTable = ({ children, align }, ctx) => {
700
- const cellAligns = align === null || align === void 0 ? void 0 : align.map((a) => {
701
- switch (a) {
702
- case "left":
703
- return docx.AlignmentType.LEFT;
704
- case "right":
705
- return docx.AlignmentType.RIGHT;
706
- case "center":
707
- return docx.AlignmentType.CENTER;
708
- default:
709
- return docx.AlignmentType.LEFT;
821
+ /**
822
+ * @internal
823
+ */
824
+ const parseLatex = (value) => {
825
+ const parsed = unifiedLatexUtilParse.parseMath(value);
826
+ const paragraphs = [[]];
827
+ let runs = paragraphs[0];
828
+ for (const n of parsed) {
829
+ const res = mapNode(n, runs);
830
+ if (!res) {
831
+ // line break
832
+ paragraphs.push((runs = []));
833
+ }
834
+ else {
835
+ runs.push(...res);
710
836
  }
711
- });
712
- return new docx.Table({
713
- rows: children.map((r) => {
714
- return buildTableRow(r, ctx, cellAligns);
715
- }),
716
- });
717
- };
718
- const buildTableRow = ({ children }, ctx, cellAligns) => {
719
- return new docx.TableRow({
720
- children: children.map((c, i) => {
721
- return buildTableCell(c, ctx, cellAligns === null || cellAligns === void 0 ? void 0 : cellAligns[i]);
722
- }),
723
- });
724
- };
725
- const buildTableCell = ({ children }, ctx, align) => {
726
- const nodes = convertNodes(children, ctx);
727
- return new docx.TableCell({
728
- children: [
729
- new docx.Paragraph({
730
- alignment: align,
731
- children: nodes,
732
- }),
733
- ],
734
- });
735
- };
736
- const buildHtml = ({ value }) => {
737
- // FIXME: transform to text for now
738
- return new docx.Paragraph({
739
- children: [buildText(value, {})],
740
- });
741
- };
742
- const buildCode = ({ value, lang: _lang, meta: _meta, }) => {
743
- // FIXME: transform to text for now
744
- return new docx.Paragraph({
745
- children: [buildText(value, {})],
746
- });
747
- };
748
- const buildMath = ({ value }) => {
749
- return parseLatex(value).map((runs) => new docx.Paragraph({
750
- children: [
751
- new docx.Math({
752
- children: runs,
753
- }),
754
- ],
755
- }));
756
- };
757
- const buildInlineMath = ({ value }) => {
758
- return new docx.Math({
759
- children: parseLatex(value).flatMap((runs) => runs),
760
- });
761
- };
762
- const buildText = (text, deco) => {
763
- return new docx.TextRun({
764
- text,
765
- bold: deco.strong,
766
- italics: deco.emphasis,
767
- strike: deco.delete,
768
- });
769
- };
770
- const buildBreak = (_) => {
771
- return new docx.TextRun({ text: "", break: 1 });
772
- };
773
- const buildLink = ({ children, url }, ctx) => {
774
- const nodes = convertNodes(children, ctx);
775
- return new docx.ExternalHyperlink({
776
- link: url,
777
- children: nodes,
778
- });
779
- };
780
- const buildImage = ({ url }, images) => {
781
- const img = images[url];
782
- invariant(img, `Fetch image was failed: ${url}`);
783
- const { image, width, height } = img;
784
- return new docx.ImageRun({
785
- data: image,
786
- transformation: {
787
- width,
788
- height,
789
- },
790
- });
791
- };
792
- const buildLinkReference = ({ children, identifier }, ctx) => {
793
- const def = ctx.def[identifier];
794
- if (def == null) {
795
- return convertNodes(children, ctx);
796
- }
797
- return [buildLink({ children, url: def }, ctx)];
798
- };
799
- const buildImageReference = ({ identifier }, ctx) => {
800
- const def = ctx.def[identifier];
801
- if (def == null) {
802
- return;
803
837
  }
804
- return buildImage({ url: def }, ctx.images);
805
- };
806
- const registerFootnoteDefinition = ({ children, identifier }, ctx) => {
807
- const definition = {
808
- children: children.map((node) => {
809
- // Convert each node and extract the first result as a paragraph
810
- const nodes = convertNodes([node], ctx);
811
- if (nodes[0] instanceof docx.Paragraph) {
812
- return nodes[0];
813
- }
814
- // For non-paragraph content, wrap in a paragraph
815
- return new docx.Paragraph({ children: nodes });
816
- }),
817
- };
818
- ctx.footnote.def(identifier, definition);
819
- };
820
- const buildFootnoteReference = ({ identifier }, ctx) => {
821
- return new docx.FootnoteReferenceRun(ctx.footnote.ref(identifier));
838
+ return paragraphs;
822
839
  };
823
840
 
824
841
  const plugin = function (opts = {}) {
825
842
  let images = {};
826
843
  this.Compiler = (node) => {
827
- return mdastToDocx(node, opts, images);
844
+ return mdastToDocx(node, opts, images, parseLatex);
828
845
  };
829
846
  return async (node) => {
830
847
  const imageList = [];