node-pptx-templater 1.0.11 → 1.0.12
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-pptx-templater",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "High-performance, low-level PowerPoint (PPTX) OpenXML template engine for Node.js. Dynamically replace text, insert images, update charts (with Excel workbook data caching), and merge table cells without PowerPoint corruption or Repair Mode prompts.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -69,24 +69,43 @@ class ShapeManager {
|
|
|
69
69
|
throw new PPTXError(`Shape "${shapeId}" not found in slide ${slideIndex}`)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
72
|
+
if (!res.shape['p:spPr']) {
|
|
73
|
+
res.shape['p:spPr'] = {}
|
|
74
|
+
}
|
|
75
|
+
if (!res.shape['p:spPr']['a:xfrm']) {
|
|
76
|
+
res.shape['p:spPr']['a:xfrm'] = {}
|
|
77
|
+
}
|
|
78
|
+
const xfrm = res.shape['p:spPr']['a:xfrm']
|
|
79
|
+
|
|
80
|
+
if (!xfrm['a:off']) {
|
|
81
|
+
xfrm['a:off'] = {}
|
|
82
|
+
}
|
|
83
|
+
if (!xfrm['a:ext']) {
|
|
84
|
+
xfrm['a:ext'] = {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (options.x !== undefined) {
|
|
88
|
+
xfrm['a:off']['@_x'] = String(Math.round(options.x))
|
|
89
|
+
} else if (xfrm['a:off']['@_x'] === undefined) {
|
|
90
|
+
xfrm['a:off']['@_x'] = '0'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (options.y !== undefined) {
|
|
94
|
+
xfrm['a:off']['@_y'] = String(Math.round(options.y))
|
|
95
|
+
} else if (xfrm['a:off']['@_y'] === undefined) {
|
|
96
|
+
xfrm['a:off']['@_y'] = '0'
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (options.width !== undefined) {
|
|
100
|
+
xfrm['a:ext']['@_cx'] = String(Math.round(options.width))
|
|
101
|
+
} else if (xfrm['a:ext']['@_cx'] === undefined) {
|
|
102
|
+
xfrm['a:ext']['@_cx'] = '0'
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (options.height !== undefined) {
|
|
106
|
+
xfrm['a:ext']['@_cy'] = String(Math.round(options.height))
|
|
107
|
+
} else if (xfrm['a:ext']['@_cy'] === undefined) {
|
|
108
|
+
xfrm['a:ext']['@_cy'] = '0'
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
const decl = this.#xmlParser.extractDeclaration(slideXml)
|
|
@@ -293,16 +293,17 @@ class ChartCacheGenerator {
|
|
|
293
293
|
if (countMatch) pointsCount = parseInt(countMatch[1], 10)
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
|
-
if (pointsCount === 0 && options.labels) {
|
|
297
|
-
pointsCount = options.labels.length
|
|
298
|
-
}
|
|
299
296
|
|
|
300
|
-
// Parse existing styling and flags from the current <c:dLbls> block
|
|
301
297
|
let existingTxPr = ''
|
|
302
298
|
let existingDLblPos = ''
|
|
303
299
|
let existingNumFmt = ''
|
|
304
300
|
let existingSpPr = ''
|
|
301
|
+
let existingExtLst = ''
|
|
302
|
+
let existingShowLeaderLines = ''
|
|
305
303
|
const existingDLblSpPrs = {}
|
|
304
|
+
const existingDLblTxPrs = {}
|
|
305
|
+
const existingDLblLayouts = {}
|
|
306
|
+
const existingDLblPositions = {}
|
|
306
307
|
const existingShowTags = {}
|
|
307
308
|
|
|
308
309
|
const dLblsMatch = /<c:dLbls>([\s\S]*?)<\/c:dLbls>/.exec(content)
|
|
@@ -324,8 +325,16 @@ class ChartCacheGenerator {
|
|
|
324
325
|
if (spPrMatch) {
|
|
325
326
|
existingSpPr = spPrMatch[1]
|
|
326
327
|
}
|
|
328
|
+
const extLstMatch = /(<c:extLst>[\s\S]*?<\/c:extLst>)/.exec(dLblsContent)
|
|
329
|
+
if (extLstMatch) {
|
|
330
|
+
existingExtLst = extLstMatch[1]
|
|
331
|
+
}
|
|
332
|
+
const showLeaderMatch = /(<c:showLeaderLines\s+[^>]*\/>)/.exec(dLblsContent)
|
|
333
|
+
if (showLeaderMatch) {
|
|
334
|
+
existingShowLeaderLines = showLeaderMatch[1]
|
|
335
|
+
}
|
|
327
336
|
|
|
328
|
-
// Parse individual <c:dLbl>
|
|
337
|
+
// Parse individual <c:dLbl> properties: fills, text styling, layouts, and positions
|
|
329
338
|
const dLblPattern = /<c:dLbl>([\s\S]*?)<\/c:dLbl>/g
|
|
330
339
|
let dLblMatch
|
|
331
340
|
while ((dLblMatch = dLblPattern.exec(dLblsContent)) !== null) {
|
|
@@ -337,6 +346,18 @@ class ChartCacheGenerator {
|
|
|
337
346
|
if (dLblSpPrMatch) {
|
|
338
347
|
existingDLblSpPrs[idx] = dLblSpPrMatch[1]
|
|
339
348
|
}
|
|
349
|
+
const dLblTxPrMatch = /(<c:txPr>[\s\S]*?<\/c:txPr>)/.exec(dLblContent)
|
|
350
|
+
if (dLblTxPrMatch) {
|
|
351
|
+
existingDLblTxPrs[idx] = dLblTxPrMatch[1]
|
|
352
|
+
}
|
|
353
|
+
const dLblLayoutMatch = /(<c:layout>[\s\S]*?<\/c:layout>|<c:layout\/>)/.exec(dLblContent)
|
|
354
|
+
if (dLblLayoutMatch) {
|
|
355
|
+
existingDLblLayouts[idx] = dLblLayoutMatch[1]
|
|
356
|
+
}
|
|
357
|
+
const dLblPosMatch = /(<c:dLblPos\s+[^>]*\/>)/.exec(dLblContent)
|
|
358
|
+
if (dLblPosMatch) {
|
|
359
|
+
existingDLblPositions[idx] = dLblPosMatch[1]
|
|
360
|
+
}
|
|
340
361
|
}
|
|
341
362
|
}
|
|
342
363
|
|
|
@@ -367,7 +388,12 @@ class ChartCacheGenerator {
|
|
|
367
388
|
existingNumFmt,
|
|
368
389
|
existingShowTags,
|
|
369
390
|
existingSpPr,
|
|
370
|
-
existingDLblSpPrs
|
|
391
|
+
existingDLblSpPrs,
|
|
392
|
+
existingDLblTxPrs,
|
|
393
|
+
existingDLblLayouts,
|
|
394
|
+
existingDLblPositions,
|
|
395
|
+
existingExtLst,
|
|
396
|
+
existingShowLeaderLines
|
|
371
397
|
)
|
|
372
398
|
|
|
373
399
|
let updatedContent = content
|
|
@@ -397,7 +423,12 @@ class ChartCacheGenerator {
|
|
|
397
423
|
existingNumFmt = '',
|
|
398
424
|
existingShowTags = {},
|
|
399
425
|
existingSpPr = '',
|
|
400
|
-
existingDLblSpPrs = {}
|
|
426
|
+
existingDLblSpPrs = {},
|
|
427
|
+
existingDLblTxPrs = {},
|
|
428
|
+
existingDLblLayouts = {},
|
|
429
|
+
existingDLblPositions = {},
|
|
430
|
+
existingExtLst = '',
|
|
431
|
+
existingShowLeaderLines = ''
|
|
401
432
|
) {
|
|
402
433
|
const {
|
|
403
434
|
labels,
|
|
@@ -463,6 +494,11 @@ class ChartCacheGenerator {
|
|
|
463
494
|
xml += `<c:dLbl>`
|
|
464
495
|
xml += `<c:idx val="${i}"/>`
|
|
465
496
|
|
|
497
|
+
// Restore per-point layout (manual position offsets) from template
|
|
498
|
+
if (existingDLblLayouts && existingDLblLayouts[i]) {
|
|
499
|
+
xml += existingDLblLayouts[i]
|
|
500
|
+
}
|
|
501
|
+
|
|
466
502
|
if (labelsFromCells && !template) {
|
|
467
503
|
const range = ChartWorkbookUpdater.parseCellRange(labelsFromCells)
|
|
468
504
|
const startColNum = ChartWorkbookUpdater.colLetterToNum(range.startCol)
|
|
@@ -510,8 +546,9 @@ class ChartCacheGenerator {
|
|
|
510
546
|
let bodyPr = '<a:bodyPr/>'
|
|
511
547
|
let pPrXml = ''
|
|
512
548
|
let rPrXml = ''
|
|
513
|
-
|
|
514
|
-
|
|
549
|
+
const dLblTxPr = (existingDLblTxPrs && existingDLblTxPrs[i]) || existingTxPr
|
|
550
|
+
if (dLblTxPr) {
|
|
551
|
+
const extracted = this.extractTxPrParts(dLblTxPr)
|
|
515
552
|
bodyPr = extracted.bodyPr
|
|
516
553
|
pPrXml = extracted.pPrXml
|
|
517
554
|
rPrXml = extracted.rPrXml
|
|
@@ -556,12 +593,16 @@ class ChartCacheGenerator {
|
|
|
556
593
|
|
|
557
594
|
if (labelStyle) {
|
|
558
595
|
xml += this.generateTxPrXml(labelStyle)
|
|
596
|
+
} else if (existingDLblTxPrs && existingDLblTxPrs[i]) {
|
|
597
|
+
xml += existingDLblTxPrs[i]
|
|
559
598
|
} else if (existingTxPr) {
|
|
560
599
|
xml += existingTxPr
|
|
561
600
|
}
|
|
562
601
|
|
|
563
602
|
if (openxmlPos) {
|
|
564
603
|
xml += `<c:dLblPos val="${openxmlPos}"/>`
|
|
604
|
+
} else if (existingDLblPositions && existingDLblPositions[i]) {
|
|
605
|
+
xml += existingDLblPositions[i]
|
|
565
606
|
} else if (existingDLblPos) {
|
|
566
607
|
xml += existingDLblPos
|
|
567
608
|
}
|
|
@@ -648,6 +689,14 @@ class ChartCacheGenerator {
|
|
|
648
689
|
xml += `<c:showBubbleSize val="0"/>`
|
|
649
690
|
}
|
|
650
691
|
|
|
692
|
+
// Restore showLeaderLines and extension list from template
|
|
693
|
+
if (existingShowLeaderLines) {
|
|
694
|
+
xml += existingShowLeaderLines
|
|
695
|
+
}
|
|
696
|
+
if (existingExtLst) {
|
|
697
|
+
xml += existingExtLst
|
|
698
|
+
}
|
|
699
|
+
|
|
651
700
|
xml += '</c:dLbls>'
|
|
652
701
|
return xml
|
|
653
702
|
}
|