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