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 +768 -751
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +769 -752
- package/lib/index.mjs.map +1 -1
- package/lib/mdast-to-docx.d.ts +1 -1
- package/package.json +4 -5
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
|
|
22
|
-
|
|
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
|
|
25
|
-
|
|
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
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
-
|
|
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
|
|
276
|
+
return results;
|
|
298
277
|
};
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
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
|
|
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
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
319
|
-
|
|
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
|
|
319
|
+
case 3:
|
|
320
|
+
headingLevel = docx.HeadingLevel.HEADING_2;
|
|
331
321
|
break;
|
|
332
|
-
case
|
|
322
|
+
case 4:
|
|
323
|
+
headingLevel = docx.HeadingLevel.HEADING_3;
|
|
333
324
|
break;
|
|
334
|
-
case
|
|
325
|
+
case 5:
|
|
326
|
+
headingLevel = docx.HeadingLevel.HEADING_4;
|
|
335
327
|
break;
|
|
336
|
-
case
|
|
337
|
-
|
|
338
|
-
case "verb":
|
|
328
|
+
case 6:
|
|
329
|
+
headingLevel = docx.HeadingLevel.HEADING_5;
|
|
339
330
|
break;
|
|
340
|
-
default:
|
|
341
|
-
unreachable();
|
|
342
331
|
}
|
|
343
|
-
|
|
332
|
+
const nodes = convertNodes(children, ctx);
|
|
333
|
+
return new docx.Paragraph({
|
|
334
|
+
heading: headingLevel,
|
|
335
|
+
children: nodes,
|
|
336
|
+
});
|
|
344
337
|
};
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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
|
-
|
|
553
|
-
|
|
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
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
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
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
|
773
|
+
return mapString(n.content);
|
|
609
774
|
};
|
|
610
|
-
const
|
|
611
|
-
const
|
|
612
|
-
const
|
|
613
|
-
|
|
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
|
|
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
|
|
643
|
-
|
|
644
|
-
|
|
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
|
|
649
|
-
|
|
786
|
+
case "string":
|
|
787
|
+
return [mapString(n.content)];
|
|
788
|
+
case "whitespace":
|
|
650
789
|
break;
|
|
651
|
-
case
|
|
652
|
-
headingLevel = docx.HeadingLevel.HEADING_2;
|
|
790
|
+
case "parbreak":
|
|
653
791
|
break;
|
|
654
|
-
case
|
|
655
|
-
headingLevel = docx.HeadingLevel.HEADING_3;
|
|
792
|
+
case "comment":
|
|
656
793
|
break;
|
|
657
|
-
case
|
|
658
|
-
|
|
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
|
|
661
|
-
|
|
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
|
-
|
|
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
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
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
|
|
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 = [];
|