@mcpcn/markdown-converter-mcp 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +17 -0
- package/.prettierrc.json +8 -0
- package/README.md +214 -0
- package/dist/config/word.d.ts +67 -0
- package/dist/config/word.d.ts.map +1 -0
- package/dist/config/word.js +86 -0
- package/dist/config/word.js.map +1 -0
- package/dist/core/BaseConverter.d.ts +104 -0
- package/dist/core/BaseConverter.d.ts.map +1 -0
- package/dist/core/BaseConverter.js +203 -0
- package/dist/core/BaseConverter.js.map +1 -0
- package/dist/core/BrowserPool.d.ts +25 -0
- package/dist/core/BrowserPool.d.ts.map +1 -0
- package/dist/core/BrowserPool.js +152 -0
- package/dist/core/BrowserPool.js.map +1 -0
- package/dist/core/CacheManager.d.ts +26 -0
- package/dist/core/CacheManager.d.ts.map +1 -0
- package/dist/core/CacheManager.js +74 -0
- package/dist/core/CacheManager.js.map +1 -0
- package/dist/core/EnhancedConverter.d.ts +78 -0
- package/dist/core/EnhancedConverter.d.ts.map +1 -0
- package/dist/core/EnhancedConverter.js +227 -0
- package/dist/core/EnhancedConverter.js.map +1 -0
- package/dist/core/MarkdownRenderer.d.ts +19 -0
- package/dist/core/MarkdownRenderer.d.ts.map +1 -0
- package/dist/core/MarkdownRenderer.js +160 -0
- package/dist/core/MarkdownRenderer.js.map +1 -0
- package/dist/core/PDFConverter.d.ts +81 -0
- package/dist/core/PDFConverter.d.ts.map +1 -0
- package/dist/core/PDFConverter.js +284 -0
- package/dist/core/PDFConverter.js.map +1 -0
- package/dist/core/PDFGenerator.d.ts +32 -0
- package/dist/core/PDFGenerator.d.ts.map +1 -0
- package/dist/core/PDFGenerator.js +352 -0
- package/dist/core/PDFGenerator.js.map +1 -0
- package/dist/core/TemplateManager.d.ts +16 -0
- package/dist/core/TemplateManager.d.ts.map +1 -0
- package/dist/core/TemplateManager.js +321 -0
- package/dist/core/TemplateManager.js.map +1 -0
- package/dist/core/WordConverter.d.ts +43 -0
- package/dist/core/WordConverter.d.ts.map +1 -0
- package/dist/core/WordConverter.js +398 -0
- package/dist/core/WordConverter.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +334 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +69 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +66 -0
- package/src/config/word.ts +164 -0
- package/src/core/BaseConverter.ts +275 -0
- package/src/core/BrowserPool.ts +176 -0
- package/src/core/CacheManager.ts +88 -0
- package/src/core/MarkdownRenderer.ts +211 -0
- package/src/core/PDFConverter.ts +374 -0
- package/src/core/PDFGenerator.ts +428 -0
- package/src/core/TemplateManager.ts +331 -0
- package/src/core/WordConverter.ts +470 -0
- package/src/index.ts +419 -0
- package/src/types/index.ts +75 -0
- package/src/types/remarkable.d.ts +8 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Word转换器
|
|
3
|
+
* 基于md-to-word-mcp项目的成功实现,继承BaseConverter
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { writeFile } from 'fs/promises';
|
|
7
|
+
import { createRequire } from 'module';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
|
|
10
|
+
const docx = require('docx');
|
|
11
|
+
const {
|
|
12
|
+
Document,
|
|
13
|
+
Paragraph,
|
|
14
|
+
TextRun,
|
|
15
|
+
Packer,
|
|
16
|
+
AlignmentType,
|
|
17
|
+
BorderStyle,
|
|
18
|
+
Footer,
|
|
19
|
+
PageNumber,
|
|
20
|
+
PageOrientation
|
|
21
|
+
} = docx;
|
|
22
|
+
|
|
23
|
+
// 类型定义
|
|
24
|
+
type ParagraphType = any;
|
|
25
|
+
type TextRunType = any;
|
|
26
|
+
|
|
27
|
+
import { BaseConverter, ConversionResult, BaseConversionOptions } from './BaseConverter.js';
|
|
28
|
+
import {
|
|
29
|
+
WordStyleConfig,
|
|
30
|
+
CodeBlockTheme,
|
|
31
|
+
WordConversionOptions,
|
|
32
|
+
defaultWordStyleConfig,
|
|
33
|
+
codeBlockThemes
|
|
34
|
+
} from '../config/word.js';
|
|
35
|
+
|
|
36
|
+
export class WordConverter extends BaseConverter {
|
|
37
|
+
private styleConfig: WordStyleConfig;
|
|
38
|
+
private codeBlockTheme: CodeBlockTheme;
|
|
39
|
+
|
|
40
|
+
constructor(options: WordConversionOptions & { cacheEnabled?: boolean; cacheDir?: string } = {}) {
|
|
41
|
+
super(options);
|
|
42
|
+
|
|
43
|
+
// 合并样式配置
|
|
44
|
+
this.styleConfig = { ...defaultWordStyleConfig, ...options.styleConfig };
|
|
45
|
+
|
|
46
|
+
// 设置代码块主题
|
|
47
|
+
if (typeof options.codeBlockTheme === 'string') {
|
|
48
|
+
this.codeBlockTheme = codeBlockThemes[options.codeBlockTheme] || codeBlockThemes.default;
|
|
49
|
+
} else if (options.codeBlockTheme) {
|
|
50
|
+
this.codeBlockTheme = options.codeBlockTheme;
|
|
51
|
+
} else {
|
|
52
|
+
this.codeBlockTheme = codeBlockThemes.default;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 转换Markdown为Word文档
|
|
58
|
+
*/
|
|
59
|
+
async convert(
|
|
60
|
+
markdownContent: string,
|
|
61
|
+
outputPath: string,
|
|
62
|
+
options: BaseConversionOptions & WordConversionOptions = {}
|
|
63
|
+
): Promise<ConversionResult> {
|
|
64
|
+
const startTime = Date.now();
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
// 检查缓存
|
|
68
|
+
const cacheKey = this.generateCacheKey(markdownContent, options);
|
|
69
|
+
const cachedResult = await this.loadFromCache(cacheKey, 'docx');
|
|
70
|
+
|
|
71
|
+
if (cachedResult) {
|
|
72
|
+
this.reportProgress({
|
|
73
|
+
stage: 'complete',
|
|
74
|
+
progress: 100,
|
|
75
|
+
message: '使用缓存结果'
|
|
76
|
+
}, options.progress);
|
|
77
|
+
|
|
78
|
+
await this.ensureOutputDir(outputPath);
|
|
79
|
+
await writeFile(outputPath, cachedResult);
|
|
80
|
+
|
|
81
|
+
const fileSize = await this.getFileSize(outputPath);
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
filePath: outputPath,
|
|
85
|
+
fileSize,
|
|
86
|
+
stats: {
|
|
87
|
+
processingTime: Date.now() - startTime,
|
|
88
|
+
headings: 0,
|
|
89
|
+
codeBlocks: 0,
|
|
90
|
+
paragraphs: 0,
|
|
91
|
+
tables: 0,
|
|
92
|
+
fileSize
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.reportProgress({
|
|
98
|
+
stage: 'parsing',
|
|
99
|
+
progress: 10,
|
|
100
|
+
message: '解析Markdown内容'
|
|
101
|
+
}, options.progress);
|
|
102
|
+
|
|
103
|
+
// 解析内容并获取统计信息
|
|
104
|
+
const { content, stats: parseStats } = this.parseMarkdown(markdownContent);
|
|
105
|
+
|
|
106
|
+
this.reportProgress({
|
|
107
|
+
stage: 'converting',
|
|
108
|
+
progress: 30,
|
|
109
|
+
message: '转换为Word文档'
|
|
110
|
+
}, options.progress);
|
|
111
|
+
|
|
112
|
+
// 转换为Word文档
|
|
113
|
+
const docChildren = this.processMarkdownToWord(content);
|
|
114
|
+
const doc = this.createDocument(docChildren, options);
|
|
115
|
+
|
|
116
|
+
this.reportProgress({
|
|
117
|
+
stage: 'saving',
|
|
118
|
+
progress: 80,
|
|
119
|
+
message: '生成Word文件'
|
|
120
|
+
}, options.progress);
|
|
121
|
+
|
|
122
|
+
// 生成文件
|
|
123
|
+
const buffer = await Packer.toBuffer(doc);
|
|
124
|
+
|
|
125
|
+
// 保存文件
|
|
126
|
+
await this.ensureOutputDir(outputPath);
|
|
127
|
+
await writeFile(outputPath, buffer);
|
|
128
|
+
|
|
129
|
+
// 保存到缓存
|
|
130
|
+
await this.saveToCache(cacheKey, 'docx', buffer);
|
|
131
|
+
|
|
132
|
+
const fileSize = await this.getFileSize(outputPath);
|
|
133
|
+
const processingTime = Date.now() - startTime;
|
|
134
|
+
|
|
135
|
+
this.reportProgress({
|
|
136
|
+
stage: 'complete',
|
|
137
|
+
progress: 100,
|
|
138
|
+
message: `转换完成: ${this.formatFileSize(fileSize)}`
|
|
139
|
+
}, options.progress);
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
success: true,
|
|
143
|
+
filePath: outputPath,
|
|
144
|
+
fileSize,
|
|
145
|
+
stats: {
|
|
146
|
+
processingTime,
|
|
147
|
+
headings: parseStats.headings || 0,
|
|
148
|
+
codeBlocks: parseStats.codeBlocks || 0,
|
|
149
|
+
paragraphs: parseStats.paragraphs || 0,
|
|
150
|
+
tables: parseStats.tables || 0,
|
|
151
|
+
fileSize
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error('Word转换失败:', error);
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
error: error instanceof Error ? error.message : String(error)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 处理Markdown内容转换为Word段落
|
|
166
|
+
*/
|
|
167
|
+
private processMarkdownToWord(markdownContent: string): any[] {
|
|
168
|
+
const lines = markdownContent.split('\n');
|
|
169
|
+
const docChildren: any[] = [];
|
|
170
|
+
|
|
171
|
+
let inCodeBlock = false;
|
|
172
|
+
let codeBlockContent = '';
|
|
173
|
+
let codeBlockLanguage = '';
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i < lines.length; i++) {
|
|
176
|
+
const line = lines[i];
|
|
177
|
+
const trimmedLine = line.trim();
|
|
178
|
+
|
|
179
|
+
// 处理代码块开始/结束
|
|
180
|
+
if (trimmedLine.startsWith('```')) {
|
|
181
|
+
if (!inCodeBlock) {
|
|
182
|
+
// 代码块开始
|
|
183
|
+
inCodeBlock = true;
|
|
184
|
+
codeBlockLanguage = trimmedLine.substring(3).trim();
|
|
185
|
+
codeBlockContent = '';
|
|
186
|
+
} else {
|
|
187
|
+
// 代码块结束
|
|
188
|
+
inCodeBlock = false;
|
|
189
|
+
|
|
190
|
+
// 创建优化的代码块
|
|
191
|
+
const codeBlockParagraphs = this.createOptimizedCodeBlock(
|
|
192
|
+
codeBlockContent,
|
|
193
|
+
codeBlockLanguage
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
docChildren.push(...codeBlockParagraphs);
|
|
197
|
+
|
|
198
|
+
// 在代码块后添加分隔段落
|
|
199
|
+
docChildren.push(new Paragraph({ text: '' }));
|
|
200
|
+
|
|
201
|
+
codeBlockContent = '';
|
|
202
|
+
codeBlockLanguage = '';
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (inCodeBlock) {
|
|
208
|
+
// 收集代码块内容
|
|
209
|
+
codeBlockContent += (codeBlockContent ? '\n' : '') + line;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 处理标题
|
|
214
|
+
if (trimmedLine.startsWith('#')) {
|
|
215
|
+
const match = trimmedLine.match(/^#+/);
|
|
216
|
+
if (match) {
|
|
217
|
+
const level = match[0].length;
|
|
218
|
+
const headingText = trimmedLine.substring(level).trim();
|
|
219
|
+
|
|
220
|
+
if (level >= 1 && level <= 6) {
|
|
221
|
+
docChildren.push(this.createHeading(headingText, level));
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 处理普通段落
|
|
228
|
+
if (trimmedLine) {
|
|
229
|
+
docChildren.push(this.createParagraph(trimmedLine));
|
|
230
|
+
} else {
|
|
231
|
+
// 空行
|
|
232
|
+
docChildren.push(new Paragraph({ text: '' }));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return docChildren;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 创建优化的代码块 - 基于成功的实现
|
|
241
|
+
*/
|
|
242
|
+
private createOptimizedCodeBlock(code: string, language?: string): any[] {
|
|
243
|
+
const lines = code.split('\n');
|
|
244
|
+
const paragraphs: any[] = [];
|
|
245
|
+
|
|
246
|
+
// 如果有语言标识,添加语言标签段落
|
|
247
|
+
if (language && this.codeBlockTheme.showLanguage) {
|
|
248
|
+
paragraphs.push(
|
|
249
|
+
new Paragraph({
|
|
250
|
+
children: [
|
|
251
|
+
new TextRun({
|
|
252
|
+
text: `语言: ${language}`,
|
|
253
|
+
font: this.codeBlockTheme.fontFamily,
|
|
254
|
+
size: this.codeBlockTheme.fontSize - 4, // 稍微小一点
|
|
255
|
+
bold: true,
|
|
256
|
+
color: '666666',
|
|
257
|
+
shading: { fill: 'E8E8E8' }
|
|
258
|
+
})
|
|
259
|
+
],
|
|
260
|
+
spacing: { before: this.styleConfig.spacing.codeBlock / 2, after: 60 },
|
|
261
|
+
shading: { fill: 'E8E8E8' },
|
|
262
|
+
border: {
|
|
263
|
+
top: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border },
|
|
264
|
+
bottom: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border },
|
|
265
|
+
left: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border },
|
|
266
|
+
right: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border },
|
|
267
|
+
},
|
|
268
|
+
indent: { left: this.styleConfig.margins.codeBlock.left }
|
|
269
|
+
})
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 为每一行代码创建单独的段落 - 这是关键的成功因素
|
|
274
|
+
lines.forEach((line, index) => {
|
|
275
|
+
// 处理空行
|
|
276
|
+
const displayText = line.trim() === '' ? ' ' : line;
|
|
277
|
+
|
|
278
|
+
// 保持原有的缩进
|
|
279
|
+
const leadingSpaces = line.match(/^(\s*)/)?.[1] || '';
|
|
280
|
+
const indentLevel = leadingSpaces.length * 50; // 每个空格50单位缩进
|
|
281
|
+
|
|
282
|
+
paragraphs.push(
|
|
283
|
+
new Paragraph({
|
|
284
|
+
children: [
|
|
285
|
+
new TextRun({
|
|
286
|
+
text: displayText,
|
|
287
|
+
font: this.codeBlockTheme.fontFamily,
|
|
288
|
+
size: this.codeBlockTheme.fontSize,
|
|
289
|
+
color: this.codeBlockTheme.textColor
|
|
290
|
+
})
|
|
291
|
+
],
|
|
292
|
+
spacing: {
|
|
293
|
+
line: this.styleConfig.spacing.line, // 固定行高
|
|
294
|
+
lineRule: 'exact'
|
|
295
|
+
},
|
|
296
|
+
shading: { fill: this.codeBlockTheme.background },
|
|
297
|
+
border: {
|
|
298
|
+
left: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border },
|
|
299
|
+
right: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border },
|
|
300
|
+
...(index === 0 && !this.codeBlockTheme.showLanguage ?
|
|
301
|
+
{ top: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border } } : {}),
|
|
302
|
+
...(index === lines.length - 1 ?
|
|
303
|
+
{ bottom: { style: BorderStyle.SINGLE, size: 1, color: this.codeBlockTheme.border } } : {})
|
|
304
|
+
},
|
|
305
|
+
indent: {
|
|
306
|
+
left: this.styleConfig.margins.codeBlock.left + indentLevel
|
|
307
|
+
}
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
return paragraphs;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* 创建标题段落
|
|
317
|
+
*/
|
|
318
|
+
private createHeading(text: string, level: number): any {
|
|
319
|
+
let fontSize: number;
|
|
320
|
+
|
|
321
|
+
switch (level) {
|
|
322
|
+
case 1: fontSize = this.styleConfig.fontSizes.heading1; break;
|
|
323
|
+
case 2: fontSize = this.styleConfig.fontSizes.heading2; break;
|
|
324
|
+
case 3: fontSize = this.styleConfig.fontSizes.heading3; break;
|
|
325
|
+
case 4: fontSize = this.styleConfig.fontSizes.heading4; break;
|
|
326
|
+
case 5: fontSize = this.styleConfig.fontSizes.heading5; break;
|
|
327
|
+
default: fontSize = this.styleConfig.fontSizes.heading5; break;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return new Paragraph({
|
|
331
|
+
children: [
|
|
332
|
+
new TextRun({
|
|
333
|
+
text: text,
|
|
334
|
+
font: this.styleConfig.fonts.heading,
|
|
335
|
+
size: fontSize,
|
|
336
|
+
bold: true,
|
|
337
|
+
color: this.styleConfig.colors.heading
|
|
338
|
+
})
|
|
339
|
+
],
|
|
340
|
+
heading: `Heading${Math.min(level, 6)}` as any,
|
|
341
|
+
spacing: {
|
|
342
|
+
before: this.styleConfig.spacing.heading,
|
|
343
|
+
after: this.styleConfig.spacing.paragraph
|
|
344
|
+
},
|
|
345
|
+
alignment: level === 1 ? AlignmentType.CENTER : AlignmentType.LEFT
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* 创建普通段落
|
|
351
|
+
*/
|
|
352
|
+
private createParagraph(text: string): any {
|
|
353
|
+
// 清理和标准化文本 - 修复乱码问题
|
|
354
|
+
const cleanedText = this.cleanText(text);
|
|
355
|
+
|
|
356
|
+
// 处理内联代码和其他Markdown语法
|
|
357
|
+
const children = this.processInlineMarkdown(cleanedText);
|
|
358
|
+
|
|
359
|
+
return new Paragraph({
|
|
360
|
+
children,
|
|
361
|
+
spacing: { after: this.styleConfig.spacing.paragraph }
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* 处理行内Markdown语法
|
|
367
|
+
*/
|
|
368
|
+
private processInlineMarkdown(text: string): any[] {
|
|
369
|
+
const runs: any[] = [];
|
|
370
|
+
const codeRegex = /`([^`]+)`/g;
|
|
371
|
+
let lastIndex = 0;
|
|
372
|
+
let match;
|
|
373
|
+
|
|
374
|
+
// 处理内联代码
|
|
375
|
+
while ((match = codeRegex.exec(text)) !== null) {
|
|
376
|
+
// 添加代码前的普通文本
|
|
377
|
+
if (match.index > lastIndex) {
|
|
378
|
+
const normalText = text.substring(lastIndex, match.index);
|
|
379
|
+
if (normalText.trim()) {
|
|
380
|
+
runs.push(new TextRun({
|
|
381
|
+
text: normalText,
|
|
382
|
+
font: this.styleConfig.fonts.default,
|
|
383
|
+
size: this.styleConfig.fontSizes.paragraph,
|
|
384
|
+
color: this.styleConfig.colors.text
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// 添加代码文本
|
|
390
|
+
runs.push(new TextRun({
|
|
391
|
+
text: match[1],
|
|
392
|
+
font: this.styleConfig.fonts.code,
|
|
393
|
+
size: this.styleConfig.fontSizes.code,
|
|
394
|
+
color: this.styleConfig.colors.code,
|
|
395
|
+
shading: { fill: this.styleConfig.colors.codeBackground },
|
|
396
|
+
border: {
|
|
397
|
+
style: BorderStyle.SINGLE,
|
|
398
|
+
size: 1,
|
|
399
|
+
color: this.styleConfig.colors.codeBorder
|
|
400
|
+
}
|
|
401
|
+
}));
|
|
402
|
+
|
|
403
|
+
lastIndex = codeRegex.lastIndex;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// 添加剩余的普通文本
|
|
407
|
+
if (lastIndex < text.length) {
|
|
408
|
+
const remainingText = text.substring(lastIndex);
|
|
409
|
+
if (remainingText.trim()) {
|
|
410
|
+
runs.push(new TextRun({
|
|
411
|
+
text: remainingText,
|
|
412
|
+
font: this.styleConfig.fonts.default,
|
|
413
|
+
size: this.styleConfig.fontSizes.paragraph,
|
|
414
|
+
color: this.styleConfig.colors.text
|
|
415
|
+
}));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// 如果没有找到任何特殊格式,返回普通文本
|
|
420
|
+
if (runs.length === 0) {
|
|
421
|
+
runs.push(new TextRun({
|
|
422
|
+
text: text,
|
|
423
|
+
font: this.styleConfig.fonts.default,
|
|
424
|
+
size: this.styleConfig.fontSizes.paragraph,
|
|
425
|
+
color: this.styleConfig.colors.text
|
|
426
|
+
}));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return runs;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* 创建Word文档
|
|
434
|
+
*/
|
|
435
|
+
private createDocument(children: any[], options: WordConversionOptions): any {
|
|
436
|
+
const docOptions: any = {
|
|
437
|
+
sections: [{
|
|
438
|
+
properties: {
|
|
439
|
+
page: {
|
|
440
|
+
margin: this.styleConfig.margins.page,
|
|
441
|
+
size: {
|
|
442
|
+
orientation: PageOrientation.PORTRAIT,
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
children,
|
|
447
|
+
}],
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
// 添加页脚(页码)
|
|
451
|
+
if (options.addFooter !== false) {
|
|
452
|
+
docOptions.sections[0].footers = {
|
|
453
|
+
default: new Footer({
|
|
454
|
+
children: [
|
|
455
|
+
new Paragraph({
|
|
456
|
+
alignment: AlignmentType.CENTER,
|
|
457
|
+
children: [
|
|
458
|
+
new TextRun({
|
|
459
|
+
children: [PageNumber.CURRENT],
|
|
460
|
+
}),
|
|
461
|
+
],
|
|
462
|
+
}),
|
|
463
|
+
],
|
|
464
|
+
}),
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return new Document(docOptions);
|
|
469
|
+
}
|
|
470
|
+
}
|