@8btc/ppt-generator-mcp 0.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.
Files changed (39) hide show
  1. package/README.md +129 -0
  2. package/dist/export-pptx.d.ts +6 -0
  3. package/dist/export-pptx.js +876 -0
  4. package/dist/generate-ppt-slides.d.ts +10 -0
  5. package/dist/generate-ppt-slides.js +581 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +161 -0
  8. package/dist/ppt-generator.d.ts +39 -0
  9. package/dist/ppt-generator.js +110 -0
  10. package/dist/tpls/imgs.json +482 -0
  11. package/dist/tpls/tpl-1.json +7649 -0
  12. package/dist/tpls/tpl-2.json +7455 -0
  13. package/dist/tpls/tpl-3.json +8184 -0
  14. package/dist/tpls/tpl-4.json +8352 -0
  15. package/dist/types/outline.d.ts +36 -0
  16. package/dist/types/outline.js +2 -0
  17. package/dist/types/slide.d.ts +696 -0
  18. package/dist/types/slide.js +2 -0
  19. package/dist/utils/element.d.ts +94 -0
  20. package/dist/utils/element.js +239 -0
  21. package/dist/utils/htmlParser/format.d.ts +3 -0
  22. package/dist/utils/htmlParser/format.js +47 -0
  23. package/dist/utils/htmlParser/index.d.ts +4 -0
  24. package/dist/utils/htmlParser/index.js +15 -0
  25. package/dist/utils/htmlParser/lexer.d.ts +2 -0
  26. package/dist/utils/htmlParser/lexer.js +245 -0
  27. package/dist/utils/htmlParser/parser.d.ts +15 -0
  28. package/dist/utils/htmlParser/parser.js +117 -0
  29. package/dist/utils/htmlParser/stringify.d.ts +3 -0
  30. package/dist/utils/htmlParser/stringify.js +32 -0
  31. package/dist/utils/htmlParser/tags.d.ts +8 -0
  32. package/dist/utils/htmlParser/tags.js +50 -0
  33. package/dist/utils/htmlParser/types.d.ts +55 -0
  34. package/dist/utils/htmlParser/types.js +2 -0
  35. package/dist/utils/svg2Base64.d.ts +1 -0
  36. package/dist/utils/svg2Base64.js +58 -0
  37. package/dist/utils/svgPathParser.d.ts +120 -0
  38. package/dist/utils/svgPathParser.js +145 -0
  39. package/package.json +59 -0
@@ -0,0 +1,10 @@
1
+ import { Outline } from "./types/outline";
2
+ import { Slide } from "./types/slide";
3
+ interface ImgPoolItem {
4
+ id: string;
5
+ src: string;
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export declare const generatePPTSlides: (templateSlides: Slide[], outlineList: Outline[], imgs?: ImgPoolItem[]) => Slide[];
10
+ export {};
@@ -0,0 +1,581 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generatePPTSlides = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const canvas_1 = require("@napi-rs/canvas");
6
+ // Node.js环境DOM支持
7
+ if (typeof window === "undefined") {
8
+ const { JSDOM } = require("jsdom");
9
+ const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
10
+ global.DOMParser = dom.window.DOMParser;
11
+ global.document = dom.window.document;
12
+ global.NodeFilter = dom.window.NodeFilter;
13
+ }
14
+ // 生成随机ID的函数
15
+ const nanoid = (length = 10) => {
16
+ return (0, crypto_1.randomBytes)(Math.ceil(length / 2))
17
+ .toString("hex")
18
+ .slice(0, length);
19
+ };
20
+ const generatePPTSlides = (templateSlides, outlineList, imgs = []) => {
21
+ const slides = [];
22
+ const coverTemplates = [];
23
+ const contentsTemplates = [];
24
+ const transitionTemplates = [];
25
+ const contentTemplates = [];
26
+ const endTemplates = [];
27
+ templateSlides.forEach((slide) => {
28
+ if (slide.type === "cover")
29
+ coverTemplates.push(slide);
30
+ else if (slide.type === "contents")
31
+ contentsTemplates.push(slide);
32
+ else if (slide.type === "transition")
33
+ transitionTemplates.push(slide);
34
+ else if (slide.type === "content")
35
+ contentTemplates.push(slide);
36
+ else if (slide.type === "end")
37
+ endTemplates.push(slide);
38
+ });
39
+ const normalizedOutlineList = formatOutlineList(outlineList, contentsTemplates);
40
+ let transitionIndex = 1;
41
+ // 章节过渡页模板
42
+ const transitionTemplate = transitionTemplates[Math.floor(Math.random() * transitionTemplates.length)];
43
+ for (const outlineItem of normalizedOutlineList) {
44
+ if (outlineItem.type === "cover") {
45
+ const coverSlide = generateCover(outlineItem, imgs, coverTemplates);
46
+ slides.push(coverSlide);
47
+ }
48
+ else if (outlineItem.type === "contents") {
49
+ const contentsSlide = generateContents(outlineItem, imgs, contentsTemplates);
50
+ slides.push(contentsSlide);
51
+ }
52
+ else if (outlineItem.type === "transition") {
53
+ const transitionSlide = generateTransition(outlineItem, imgs, transitionTemplate, transitionIndex);
54
+ slides.push(transitionSlide);
55
+ transitionIndex += 1;
56
+ }
57
+ else if (outlineItem.type === "content") {
58
+ const contentSlide = generateContent(outlineItem, imgs, contentTemplates);
59
+ slides.push(contentSlide);
60
+ }
61
+ else if (outlineItem.type === "end") {
62
+ const endSlide = generateEnd(outlineItem, imgs, endTemplates);
63
+ slides.push(endSlide);
64
+ }
65
+ }
66
+ return slides;
67
+ };
68
+ exports.generatePPTSlides = generatePPTSlides;
69
+ const formatOutlineList = (outlineList, contentsTemplates) => {
70
+ const normalizedOutlineList = [];
71
+ const maxContentsCount = contentsTemplates.reduce((acc, cur) => {
72
+ const count = cur.elements.filter((el) => checkTextType(el, "item")).length;
73
+ acc = Math.max(acc, count);
74
+ return acc;
75
+ }, 0);
76
+ for (const outlineItem of outlineList) {
77
+ if (outlineItem.type === "content") {
78
+ const items = outlineItem.data.items;
79
+ if (items.length === 5 || items.length === 6) {
80
+ const items1 = items.slice(0, 3);
81
+ const items2 = items.slice(3);
82
+ normalizedOutlineList.push({
83
+ ...outlineItem,
84
+ data: { ...outlineItem.data, items: items1 },
85
+ });
86
+ normalizedOutlineList.push({
87
+ ...outlineItem,
88
+ data: { ...outlineItem.data, items: items2 },
89
+ offset: 3,
90
+ });
91
+ }
92
+ else if (items.length === 7 || items.length === 8) {
93
+ const items1 = items.slice(0, 4);
94
+ const items2 = items.slice(4);
95
+ normalizedOutlineList.push({
96
+ ...outlineItem,
97
+ data: { ...outlineItem.data, items: items1 },
98
+ });
99
+ normalizedOutlineList.push({
100
+ ...outlineItem,
101
+ data: { ...outlineItem.data, items: items2 },
102
+ offset: 4,
103
+ });
104
+ }
105
+ else if (items.length === 9 || items.length === 10) {
106
+ const items1 = items.slice(0, 3);
107
+ const items2 = items.slice(3, 6);
108
+ const items3 = items.slice(6);
109
+ normalizedOutlineList.push({
110
+ ...outlineItem,
111
+ data: { ...outlineItem.data, items: items1 },
112
+ });
113
+ normalizedOutlineList.push({
114
+ ...outlineItem,
115
+ data: { ...outlineItem.data, items: items2 },
116
+ offset: 3,
117
+ });
118
+ normalizedOutlineList.push({
119
+ ...outlineItem,
120
+ data: { ...outlineItem.data, items: items3 },
121
+ offset: 6,
122
+ });
123
+ }
124
+ else if (items.length > 10) {
125
+ const items1 = items.slice(0, 4);
126
+ const items2 = items.slice(4, 8);
127
+ const items3 = items.slice(8);
128
+ normalizedOutlineList.push({
129
+ ...outlineItem,
130
+ data: { ...outlineItem.data, items: items1 },
131
+ });
132
+ normalizedOutlineList.push({
133
+ ...outlineItem,
134
+ data: { ...outlineItem.data, items: items2 },
135
+ offset: 4,
136
+ });
137
+ normalizedOutlineList.push({
138
+ ...outlineItem,
139
+ data: { ...outlineItem.data, items: items3 },
140
+ offset: 8,
141
+ });
142
+ }
143
+ else {
144
+ normalizedOutlineList.push(outlineItem);
145
+ }
146
+ }
147
+ else if (outlineItem.type === "contents") {
148
+ const items = outlineItem.data.items;
149
+ if (items.length > maxContentsCount) {
150
+ const loop = Math.ceil(items.length / maxContentsCount);
151
+ for (let i = 0; i < loop; i++) {
152
+ const items1 = items.slice(i * maxContentsCount, (i + 1) * maxContentsCount);
153
+ normalizedOutlineList.push({
154
+ ...outlineItem,
155
+ data: { ...outlineItem.data, items: items1 },
156
+ offset: i * maxContentsCount,
157
+ });
158
+ }
159
+ }
160
+ else {
161
+ normalizedOutlineList.push(outlineItem);
162
+ }
163
+ }
164
+ else
165
+ normalizedOutlineList.push(outlineItem);
166
+ }
167
+ return normalizedOutlineList;
168
+ };
169
+ const generateCover = (outlineItem, imgs, coverTemplates) => {
170
+ const coverTemplate = coverTemplates[Math.floor(Math.random() * coverTemplates.length)];
171
+ const elements = coverTemplate.elements.map((el) => {
172
+ if (el.type === "image")
173
+ return getNewImgElement(el, imgs);
174
+ if (el.type !== "text" && el.type !== "shape")
175
+ return el;
176
+ if (checkTextType(el, "title") && outlineItem.data.title) {
177
+ return getNewTextElement({
178
+ el,
179
+ text: outlineItem.data.title,
180
+ maxLine: 1,
181
+ });
182
+ }
183
+ if (checkTextType(el, "content") && outlineItem.data.text) {
184
+ return getNewTextElement({
185
+ el,
186
+ text: outlineItem.data.text,
187
+ maxLine: 3,
188
+ });
189
+ }
190
+ return el;
191
+ });
192
+ return {
193
+ ...coverTemplate,
194
+ id: `${coverTemplate.id}-${nanoid(10)}`,
195
+ elements,
196
+ };
197
+ };
198
+ const generateContents = (outlineItem, imgs, contentsTemplates) => {
199
+ const _contentsTemplates = getUseableTemplates(contentsTemplates, outlineItem.data.items.length, "item");
200
+ const contentsTemplate = _contentsTemplates[Math.floor(Math.random() * _contentsTemplates.length)];
201
+ const sortedNumberItems = contentsTemplate.elements.filter((el) => checkTextType(el, "itemNumber"));
202
+ const sortedNumberItemIds = sortedNumberItems
203
+ .sort((a, b) => {
204
+ if (sortedNumberItems.length > 6) {
205
+ let aContent = "";
206
+ let bContent = "";
207
+ if (a.type === "text")
208
+ aContent = a.content;
209
+ if (a.type === "shape")
210
+ aContent = a.text.content;
211
+ if (b.type === "text")
212
+ bContent = b.content;
213
+ if (b.type === "shape")
214
+ bContent = b.text.content;
215
+ if (aContent && bContent) {
216
+ const aIndex = parseInt(aContent);
217
+ const bIndex = parseInt(bContent);
218
+ return aIndex - bIndex;
219
+ }
220
+ }
221
+ const aIndex = a.left + a.top * 2;
222
+ const bIndex = b.left + b.top * 2;
223
+ return aIndex - bIndex;
224
+ })
225
+ .map((el) => el.id);
226
+ const sortedItems = contentsTemplate.elements.filter((el) => checkTextType(el, "item"));
227
+ const sortedItemIds = sortedItems
228
+ .sort((a, b) => {
229
+ if (sortedItems.length > 6) {
230
+ const aItemNumber = sortedNumberItems.find((item) => item.groupId === a.groupId);
231
+ const bItemNumber = sortedNumberItems.find((item) => item.groupId === b.groupId);
232
+ if (aItemNumber && bItemNumber) {
233
+ return (sortedNumberItemIds.indexOf(aItemNumber.id) -
234
+ sortedNumberItemIds.indexOf(bItemNumber.id));
235
+ }
236
+ }
237
+ const aIndex = a.left + a.top * 2;
238
+ const bIndex = b.left + b.top * 2;
239
+ return aIndex - bIndex;
240
+ })
241
+ .map((el) => el.id);
242
+ const longestText = outlineItem.data.items.reduce((longest, current) => (current.length > longest.length ? current : longest), "");
243
+ const unusedElIds = [];
244
+ const unusedGroupIds = [];
245
+ const elements = contentsTemplate.elements
246
+ .map((el) => {
247
+ if (el.type === "image" && el.imageType)
248
+ return getNewImgElement(el, imgs);
249
+ if (el.type !== "text" && el.type !== "shape")
250
+ return el;
251
+ if (checkTextType(el, "item")) {
252
+ const index = sortedItemIds.findIndex((id) => id === el.id);
253
+ const itemTitle = outlineItem.data.items[index];
254
+ if (itemTitle)
255
+ return getNewTextElement({
256
+ el,
257
+ text: itemTitle,
258
+ maxLine: 1,
259
+ longestText,
260
+ });
261
+ unusedElIds.push(el.id);
262
+ if (el.groupId)
263
+ unusedGroupIds.push(el.groupId);
264
+ }
265
+ if (checkTextType(el, "itemNumber")) {
266
+ const index = sortedNumberItemIds.findIndex((id) => id === el.id);
267
+ const offset = outlineItem.offset || 0;
268
+ return getNewTextElement({
269
+ el,
270
+ text: index + offset + 1 + "",
271
+ maxLine: 1,
272
+ digitPadding: true,
273
+ });
274
+ }
275
+ return el;
276
+ })
277
+ .filter((el) => !unusedElIds.includes(el.id) &&
278
+ !(el.groupId && unusedGroupIds.includes(el.groupId)));
279
+ return {
280
+ ...contentsTemplate,
281
+ id: `${contentsTemplate.id}-${nanoid(10)}`,
282
+ elements,
283
+ };
284
+ };
285
+ const generateTransition = (outlineItem, imgs, transitionTemplate, transitionIndex) => {
286
+ const elements = transitionTemplate.elements.map((el) => {
287
+ if (el.type === "image" && el.imageType)
288
+ return getNewImgElement(el, imgs);
289
+ if (el.type !== "text" && el.type !== "shape")
290
+ return el;
291
+ if (checkTextType(el, "title") && outlineItem.data.title) {
292
+ return getNewTextElement({
293
+ el,
294
+ text: outlineItem.data.title,
295
+ maxLine: 1,
296
+ });
297
+ }
298
+ if (checkTextType(el, "content") && outlineItem.data.text) {
299
+ return getNewTextElement({
300
+ el,
301
+ text: outlineItem.data.text,
302
+ maxLine: 3,
303
+ });
304
+ }
305
+ if (checkTextType(el, "partNumber")) {
306
+ return getNewTextElement({
307
+ el,
308
+ text: transitionIndex + "",
309
+ maxLine: 1,
310
+ digitPadding: true,
311
+ });
312
+ }
313
+ return el;
314
+ });
315
+ return {
316
+ ...transitionTemplate,
317
+ id: `${transitionTemplate.id}-${nanoid(10)}`,
318
+ elements,
319
+ };
320
+ };
321
+ const generateContent = (outlineItem, imgs, contentTemplates) => {
322
+ const _contentTemplates = getUseableTemplates(contentTemplates, outlineItem.data.items.length, "item");
323
+ const contentTemplate = _contentTemplates[Math.floor(Math.random() * _contentTemplates.length)];
324
+ const sortedTitleItemIds = contentTemplate.elements
325
+ .filter((el) => checkTextType(el, "itemTitle"))
326
+ .sort((a, b) => {
327
+ const aIndex = a.left + a.top * 2;
328
+ const bIndex = b.left + b.top * 2;
329
+ return aIndex - bIndex;
330
+ })
331
+ .map((el) => el.id);
332
+ const sortedTextItemIds = contentTemplate.elements
333
+ .filter((el) => checkTextType(el, "item"))
334
+ .sort((a, b) => {
335
+ const aIndex = a.left + a.top * 2;
336
+ const bIndex = b.left + b.top * 2;
337
+ return aIndex - bIndex;
338
+ })
339
+ .map((el) => el.id);
340
+ const sortedNumberItemIds = contentTemplate.elements
341
+ .filter((el) => checkTextType(el, "itemNumber"))
342
+ .sort((a, b) => {
343
+ const aIndex = a.left + a.top * 2;
344
+ const bIndex = b.left + b.top * 2;
345
+ return aIndex - bIndex;
346
+ })
347
+ .map((el) => el.id);
348
+ const itemTitles = [];
349
+ const itemTexts = [];
350
+ for (const _item of outlineItem.data.items) {
351
+ if (_item.title)
352
+ itemTitles.push(_item.title);
353
+ if (_item.text)
354
+ itemTexts.push(_item.text);
355
+ }
356
+ const longestTitle = itemTitles.reduce((longest, current) => (current.length > longest.length ? current : longest), "");
357
+ const longestText = itemTexts.reduce((longest, current) => (current.length > longest.length ? current : longest), "");
358
+ const elements = contentTemplate.elements.map((el) => {
359
+ if (el.type === "image" && el.imageType)
360
+ return getNewImgElement(el, imgs);
361
+ if (el.type !== "text" && el.type !== "shape")
362
+ return el;
363
+ if (outlineItem.data.items.length === 1) {
364
+ const contentItem = outlineItem.data.items[0];
365
+ if (checkTextType(el, "content") && contentItem.text) {
366
+ return getNewTextElement({
367
+ el,
368
+ text: contentItem.text,
369
+ maxLine: 6,
370
+ });
371
+ }
372
+ }
373
+ else {
374
+ if (checkTextType(el, "itemTitle")) {
375
+ const index = sortedTitleItemIds.findIndex((id) => id === el.id);
376
+ const contentItem = outlineItem.data.items[index];
377
+ if (contentItem && contentItem.title) {
378
+ return getNewTextElement({
379
+ el,
380
+ text: contentItem.title,
381
+ longestText: longestTitle,
382
+ maxLine: 1,
383
+ });
384
+ }
385
+ }
386
+ if (checkTextType(el, "item")) {
387
+ const index = sortedTextItemIds.findIndex((id) => id === el.id);
388
+ const contentItem = outlineItem.data.items[index];
389
+ if (contentItem && contentItem.text) {
390
+ return getNewTextElement({
391
+ el,
392
+ text: contentItem.text,
393
+ longestText,
394
+ maxLine: 4,
395
+ });
396
+ }
397
+ }
398
+ if (checkTextType(el, "itemNumber")) {
399
+ const index = sortedNumberItemIds.findIndex((id) => id === el.id);
400
+ const offset = outlineItem.offset || 0;
401
+ return getNewTextElement({
402
+ el,
403
+ text: index + offset + 1 + "",
404
+ maxLine: 1,
405
+ digitPadding: true,
406
+ });
407
+ }
408
+ }
409
+ if (checkTextType(el, "title") && outlineItem.data.title) {
410
+ return getNewTextElement({
411
+ el,
412
+ text: outlineItem.data.title,
413
+ maxLine: 1,
414
+ });
415
+ }
416
+ return el;
417
+ });
418
+ return {
419
+ ...contentTemplate,
420
+ id: `${contentTemplate.id}-${nanoid(10)}`,
421
+ elements,
422
+ };
423
+ };
424
+ const generateEnd = (outlineItem, imgs, endTemplates) => {
425
+ const endTemplate = endTemplates[Math.floor(Math.random() * endTemplates.length)];
426
+ const elements = endTemplate.elements.map((el) => {
427
+ if (el.type === "image" && el.imageType)
428
+ return getNewImgElement(el, imgs);
429
+ return el;
430
+ });
431
+ return {
432
+ ...endTemplate,
433
+ id: `${endTemplate.id}-${nanoid(10)}`,
434
+ elements,
435
+ };
436
+ };
437
+ const getAdaptedFontsize = ({ text, fontSize, fontFamily, width, height, lineHeight, maxLine, }) => {
438
+ const canvas = new canvas_1.Canvas(width, height);
439
+ const context = canvas.getContext("2d");
440
+ let newFontSize = fontSize;
441
+ const minFontSize = 10;
442
+ while (newFontSize >= minFontSize) {
443
+ context.font = `${newFontSize}px ${fontFamily}`;
444
+ const textWidth = context.measureText(text).width;
445
+ const line = Math.ceil(textWidth / width);
446
+ if (maxLine > 1 && height) {
447
+ const heightOfLine = Math.max(newFontSize, 16) * (newFontSize < 15 ? 1.2 : lineHeight) * 1.2;
448
+ const totalHeight = line * heightOfLine;
449
+ if (totalHeight <= height)
450
+ return newFontSize;
451
+ }
452
+ if (line <= maxLine)
453
+ return newFontSize;
454
+ const step = newFontSize <= 22 ? 1 : 2;
455
+ newFontSize = newFontSize - step;
456
+ }
457
+ return minFontSize;
458
+ };
459
+ const getFontInfo = (htmlString) => {
460
+ const fontSizeRegex = /font-size:\s*(\d+(?:\.\d+)?)\s*px/i;
461
+ const fontFamilyRegex = /font-family:\s*['"]?([^'";]+)['"]?\s*(?=;|>|$)/i;
462
+ const defaultInfo = {
463
+ fontSize: 16,
464
+ fontFamily: "PingFang SC, Microsoft Yahei",
465
+ };
466
+ const fontSizeMatch = htmlString.match(fontSizeRegex);
467
+ const fontFamilyMatch = htmlString.match(fontFamilyRegex);
468
+ return {
469
+ fontSize: fontSizeMatch ? +fontSizeMatch[1].trim() : defaultInfo.fontSize,
470
+ fontFamily: fontFamilyMatch
471
+ ? fontFamilyMatch[1].trim()
472
+ : defaultInfo.fontFamily,
473
+ };
474
+ };
475
+ // 创建新图片元素函数
476
+ const getNewImgElement = (el, imgs) => {
477
+ if (imgs.length === 0)
478
+ return el;
479
+ const randomImg = imgs[Math.floor(Math.random() * imgs.length)];
480
+ return {
481
+ ...el,
482
+ src: randomImg.src,
483
+ width: randomImg.width,
484
+ height: randomImg.height,
485
+ };
486
+ };
487
+ const checkTextType = (el, type) => {
488
+ return ((el.type === "text" && el.textType === type) ||
489
+ (el.type === "shape" && el.text && el.text.type === type));
490
+ };
491
+ const getUseableTemplates = (templates, n, type) => {
492
+ if (n === 1) {
493
+ const list = templates.filter((slide) => {
494
+ const items = slide.elements.filter((el) => checkTextType(el, type));
495
+ const titles = slide.elements.filter((el) => checkTextType(el, "title"));
496
+ const texts = slide.elements.filter((el) => checkTextType(el, "content"));
497
+ return !items.length && titles.length === 1 && texts.length === 1;
498
+ });
499
+ if (list.length)
500
+ return list;
501
+ }
502
+ let target = null;
503
+ const list = templates.filter((slide) => {
504
+ const len = slide.elements.filter((el) => checkTextType(el, type)).length;
505
+ return len >= n;
506
+ });
507
+ if (list.length === 0) {
508
+ const sorted = templates.sort((a, b) => {
509
+ const aLen = a.elements.filter((el) => checkTextType(el, type)).length;
510
+ const bLen = b.elements.filter((el) => checkTextType(el, type)).length;
511
+ return aLen - bLen;
512
+ });
513
+ target = sorted[sorted.length - 1];
514
+ }
515
+ else {
516
+ target = list.reduce((closest, current) => {
517
+ const currentLen = current.elements.filter((el) => checkTextType(el, type)).length;
518
+ const closestLen = closest.elements.filter((el) => checkTextType(el, type)).length;
519
+ return currentLen - n <= closestLen - n ? current : closest;
520
+ });
521
+ }
522
+ return templates.filter((slide) => {
523
+ const len = slide.elements.filter((el) => checkTextType(el, type)).length;
524
+ const targetLen = target.elements.filter((el) => checkTextType(el, type)).length;
525
+ return len === targetLen;
526
+ });
527
+ };
528
+ const getNewTextElement = ({ el, text, maxLine, longestText, digitPadding, }) => {
529
+ const padding = 10;
530
+ const width = el.width - padding * 2 - 2;
531
+ const height = el.height - padding * 2 - 2;
532
+ const lineHeight = el.type === "text" ? el.lineHeight || 1.5 : 1.2;
533
+ let content = el.type === "text" ? el.content : el.text.content;
534
+ const fontInfo = getFontInfo(content);
535
+ const size = getAdaptedFontsize({
536
+ text: longestText || text,
537
+ fontSize: fontInfo.fontSize,
538
+ fontFamily: fontInfo.fontFamily,
539
+ width,
540
+ height,
541
+ lineHeight,
542
+ maxLine,
543
+ });
544
+ const parser = new DOMParser();
545
+ const doc = parser.parseFromString(content, "text/html");
546
+ const treeWalker = document.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
547
+ const firstTextNode = treeWalker.nextNode();
548
+ if (firstTextNode) {
549
+ if (digitPadding &&
550
+ firstTextNode.textContent &&
551
+ firstTextNode.textContent.length === 2 &&
552
+ text.length === 1) {
553
+ firstTextNode.textContent = "0" + text;
554
+ }
555
+ else if (
556
+ // 处理 1. 1: 1:
557
+ digitPadding &&
558
+ firstTextNode.textContent &&
559
+ firstTextNode.textContent.length === 3 &&
560
+ [".", ":", ":"].includes(firstTextNode.textContent.slice(-1)) &&
561
+ text.length === 1) {
562
+ firstTextNode.textContent =
563
+ "0" + text + firstTextNode.textContent.slice(-1);
564
+ }
565
+ else
566
+ firstTextNode.textContent = text;
567
+ let node;
568
+ while ((node = treeWalker.nextNode())) {
569
+ node.parentNode?.removeChild(node);
570
+ }
571
+ }
572
+ if (doc.body.innerHTML.indexOf("font-size") === -1) {
573
+ const p = doc.querySelector("p");
574
+ if (p)
575
+ p.style.fontSize = "16px";
576
+ }
577
+ content = doc.body.innerHTML.replace(/font-size:(.+?)px/g, `font-size: ${size}px`);
578
+ return el.type === "text"
579
+ ? { ...el, content, lineHeight: size < 15 ? 1.2 : el.lineHeight }
580
+ : { ...el, text: { ...el.text, content } };
581
+ };
@@ -0,0 +1 @@
1
+ export {};