node-pptx-templater 1.0.1 → 1.0.2
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 +6 -6
- package/src/cli/commands/build.js +8 -6
- package/src/cli/commands/debug.js +7 -6
- package/src/cli/commands/extract.js +8 -6
- package/src/cli/commands/inspect.js +7 -5
- package/src/cli/commands/validate.js +7 -5
- package/src/cli/index.js +20 -21
- package/src/core/OutputWriter.js +9 -7
- package/src/core/PPTXTemplater.js +18 -16
- package/src/core/TemplateEngine.js +4 -2
- package/src/index.js +38 -15
- package/src/managers/ChartManager.js +8 -6
- package/src/managers/ContentTypesManager.js +5 -3
- package/src/managers/HyperlinkManager.js +6 -4
- package/src/managers/MediaManager.js +8 -6
- package/src/managers/RelationshipManager.js +7 -5
- package/src/managers/SlideManager.js +10 -8
- package/src/managers/TableManager.js +5 -3
- package/src/managers/ZipManager.js +8 -6
- package/src/managers/charts/ChartCacheGenerator.js +5 -3
- package/src/managers/charts/ChartParser.js +4 -2
- package/src/managers/charts/ChartRelationshipManager.js +4 -2
- package/src/managers/charts/ChartWorkbookUpdater.js +5 -3
- package/src/parsers/XMLParser.js +8 -4
- package/src/templates/blankPptx.js +2 -1
- package/src/templates/slideTemplate.js +8 -3
- package/src/utils/contentTypesHelper.js +4 -2
- package/src/utils/errors.js +17 -7
- package/src/utils/idUtils.js +10 -4
- package/src/utils/logger.js +5 -1
- package/src/utils/relationshipUtils.js +11 -4
- package/src/utils/xmlUtils.js +14 -6
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
* </p:sp>
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const { generateUniqueId } = require('../utils/idUtils.js');
|
|
42
|
+
const { PPTXError } = require('../utils/errors.js');
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* OpenXML namespace declarations used in slide XML.
|
|
@@ -69,7 +69,7 @@ const EMU = {
|
|
|
69
69
|
* @param {number} slideIndex - 1-based slide index (for unique IDs).
|
|
70
70
|
* @returns {string} Complete slide XML string.
|
|
71
71
|
*/
|
|
72
|
-
|
|
72
|
+
function buildNewSlideXml(options, slideIndex) {
|
|
73
73
|
const { title = '', elements = [], layout = 'blank', _rawXml } = options;
|
|
74
74
|
|
|
75
75
|
// If raw XML is provided, use it directly (for clone/export operations)
|
|
@@ -312,3 +312,8 @@ function escapeXml(str) {
|
|
|
312
312
|
.replace(/"/g, '"')
|
|
313
313
|
.replace(/'/g, ''');
|
|
314
314
|
}
|
|
315
|
+
|
|
316
|
+
module.exports = {
|
|
317
|
+
buildNewSlideXml,
|
|
318
|
+
EMU
|
|
319
|
+
};
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* </Types>
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const { createLogger } = require('./logger.js');
|
|
21
21
|
|
|
22
22
|
const logger = createLogger('ContentTypes');
|
|
23
23
|
|
|
@@ -146,4 +146,6 @@ class ContentTypesHelper {
|
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
module.exports = {
|
|
150
|
+
contentTypesHelper: new ContentTypesHelper()
|
|
151
|
+
};
|
package/src/utils/errors.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* @description Base error class for all node-pptx-templater errors.
|
|
19
19
|
* @extends Error
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
class PPTXError extends Error {
|
|
22
22
|
/**
|
|
23
23
|
* @param {string} message - Human-readable error description.
|
|
24
24
|
* @param {Error} [cause] - Original underlying error (for error chaining).
|
|
@@ -40,7 +40,7 @@ export class PPTXError extends Error {
|
|
|
40
40
|
* @description Thrown when a slide reference cannot be resolved.
|
|
41
41
|
* @extends PPTXError
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
class SlideNotFoundError extends PPTXError {
|
|
44
44
|
/**
|
|
45
45
|
* @param {string} message
|
|
46
46
|
*/
|
|
@@ -55,7 +55,7 @@ export class SlideNotFoundError extends PPTXError {
|
|
|
55
55
|
* @description Thrown when a chart cannot be located in a slide.
|
|
56
56
|
* @extends PPTXError
|
|
57
57
|
*/
|
|
58
|
-
|
|
58
|
+
class ChartNotFoundError extends PPTXError {
|
|
59
59
|
/**
|
|
60
60
|
* @param {string} message
|
|
61
61
|
*/
|
|
@@ -70,7 +70,7 @@ export class ChartNotFoundError extends PPTXError {
|
|
|
70
70
|
* @description Thrown when a table cannot be located in a slide.
|
|
71
71
|
* @extends PPTXError
|
|
72
72
|
*/
|
|
73
|
-
|
|
73
|
+
class TableNotFoundError extends PPTXError {
|
|
74
74
|
/**
|
|
75
75
|
* @param {string} message
|
|
76
76
|
*/
|
|
@@ -85,7 +85,7 @@ export class TableNotFoundError extends PPTXError {
|
|
|
85
85
|
* @description Thrown when XML parsing or building fails.
|
|
86
86
|
* @extends PPTXError
|
|
87
87
|
*/
|
|
88
|
-
|
|
88
|
+
class XMLParseError extends PPTXError {
|
|
89
89
|
/**
|
|
90
90
|
* @param {string} message
|
|
91
91
|
* @param {Error} [cause]
|
|
@@ -101,7 +101,7 @@ export class XMLParseError extends PPTXError {
|
|
|
101
101
|
* @description Thrown when a PPTX file has an invalid or unsupported structure.
|
|
102
102
|
* @extends PPTXError
|
|
103
103
|
*/
|
|
104
|
-
|
|
104
|
+
class InvalidTemplateError extends PPTXError {
|
|
105
105
|
/**
|
|
106
106
|
* @param {string} message
|
|
107
107
|
* @param {Error} [cause]
|
|
@@ -117,7 +117,7 @@ export class InvalidTemplateError extends PPTXError {
|
|
|
117
117
|
* @description Thrown when a media file cannot be embedded.
|
|
118
118
|
* @extends PPTXError
|
|
119
119
|
*/
|
|
120
|
-
|
|
120
|
+
class MediaEmbedError extends PPTXError {
|
|
121
121
|
/**
|
|
122
122
|
* @param {string} message
|
|
123
123
|
* @param {Error} [cause]
|
|
@@ -127,3 +127,13 @@ export class MediaEmbedError extends PPTXError {
|
|
|
127
127
|
this.name = 'MediaEmbedError';
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
PPTXError,
|
|
133
|
+
SlideNotFoundError,
|
|
134
|
+
ChartNotFoundError,
|
|
135
|
+
TableNotFoundError,
|
|
136
|
+
XMLParseError,
|
|
137
|
+
InvalidTemplateError,
|
|
138
|
+
MediaEmbedError
|
|
139
|
+
};
|
package/src/utils/idUtils.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Used for generating shape IDs, slide IDs, etc. in OpenXML.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const { randomBytes } = require('crypto');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Generates a unique integer ID for use as a shape or slide ID.
|
|
@@ -12,7 +12,7 @@ import { randomBytes } from 'crypto';
|
|
|
12
12
|
* @param {number[]} [existingIds] - Array of existing IDs to avoid.
|
|
13
13
|
* @returns {number} Unique positive integer.
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
function generateUniqueId(existingIds = []) {
|
|
16
16
|
const maxId = existingIds.length > 0 ? Math.max(...existingIds) : 0;
|
|
17
17
|
return maxId + 1;
|
|
18
18
|
}
|
|
@@ -23,7 +23,7 @@ export function generateUniqueId(existingIds = []) {
|
|
|
23
23
|
*
|
|
24
24
|
* @returns {string} UUID v4 string (e.g., '{A1B2C3D4-E5F6-...}')
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
function generateGuid() {
|
|
27
27
|
const bytes = randomBytes(16);
|
|
28
28
|
bytes[6] = (bytes[6] & 0x0f) | 0x40; // Version 4
|
|
29
29
|
bytes[8] = (bytes[8] & 0x3f) | 0x80; // Variant RFC4122
|
|
@@ -47,8 +47,14 @@ export function generateGuid() {
|
|
|
47
47
|
* @param {string[]} [existingSlideIds] - Existing slide ID strings.
|
|
48
48
|
* @returns {string} New slide ID string.
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
function generateSlideId(existingSlideIds = []) {
|
|
51
51
|
const existingNums = existingSlideIds.map(id => parseInt(id, 10)).filter(n => !isNaN(n));
|
|
52
52
|
const maxId = existingNums.length > 0 ? Math.max(...existingNums) : 255;
|
|
53
53
|
return String(maxId + 1);
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
module.exports = {
|
|
57
|
+
generateUniqueId,
|
|
58
|
+
generateGuid,
|
|
59
|
+
generateSlideId
|
|
60
|
+
};
|
package/src/utils/logger.js
CHANGED
|
@@ -66,7 +66,7 @@ function timestamp() {
|
|
|
66
66
|
* const logger = createLogger('SlideManager');
|
|
67
67
|
* logger.info('Loaded 5 slides');
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
function createLogger(moduleName) {
|
|
70
70
|
const isTTY = process.stdout.isTTY;
|
|
71
71
|
|
|
72
72
|
const log = (level, levelNum, color, message, ...args) => {
|
|
@@ -111,3 +111,7 @@ export function createLogger(moduleName) {
|
|
|
111
111
|
error: (message, ...args) => log('error', LOG_LEVELS.error, COLORS.red, message, ...args),
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
|
+
|
|
115
|
+
module.exports = {
|
|
116
|
+
createLogger
|
|
117
|
+
};
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* generateRelationshipId(['rId1', 'rId3']) // → 'rId4'
|
|
19
19
|
* generateRelationshipId([]) // → 'rId1'
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
function generateRelationshipId(existingIds) {
|
|
22
22
|
if (!existingIds || existingIds.length === 0) return 'rId1';
|
|
23
23
|
|
|
24
24
|
const maxNum = existingIds.reduce((max, id) => {
|
|
@@ -40,7 +40,7 @@ export function generateRelationshipId(existingIds) {
|
|
|
40
40
|
* parseRelationshipId('rId5') // → 5
|
|
41
41
|
* parseRelationshipId('foo') // → -1
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
function parseRelationshipId(rId) {
|
|
44
44
|
const match = /^rId(\d+)$/.exec(rId);
|
|
45
45
|
return match ? parseInt(match[1], 10) : -1;
|
|
46
46
|
}
|
|
@@ -51,7 +51,7 @@ export function parseRelationshipId(rId) {
|
|
|
51
51
|
* @param {string} str
|
|
52
52
|
* @returns {boolean}
|
|
53
53
|
*/
|
|
54
|
-
|
|
54
|
+
function isValidRelationshipId(str) {
|
|
55
55
|
return /^rId\d+$/.test(str);
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -66,7 +66,7 @@ export function isValidRelationshipId(str) {
|
|
|
66
66
|
* @example
|
|
67
67
|
* remapRelationshipIds(xml, new Map([['rId1', 'rId5'], ['rId2', 'rId6']]));
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
function remapRelationshipIds(xml, idMap) {
|
|
70
70
|
let updated = xml;
|
|
71
71
|
|
|
72
72
|
// Sort by length descending to avoid partial replacements (e.g., rId1 replacing part of rId10)
|
|
@@ -87,3 +87,10 @@ export function remapRelationshipIds(xml, idMap) {
|
|
|
87
87
|
|
|
88
88
|
return updated;
|
|
89
89
|
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
generateRelationshipId,
|
|
93
|
+
parseRelationshipId,
|
|
94
|
+
isValidRelationshipId,
|
|
95
|
+
remapRelationshipIds
|
|
96
|
+
};
|
package/src/utils/xmlUtils.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* attempt automatic repairs for common PPTX corruption issues.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const { XMLParser } = require('../parsers/XMLParser.js');
|
|
9
9
|
|
|
10
10
|
const parser = new XMLParser();
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ const parser = new XMLParser();
|
|
|
19
19
|
* const { valid, error } = validateXML(xml);
|
|
20
20
|
* if (!valid) console.error('XML error:', error);
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
function validateXML(xmlString) {
|
|
23
23
|
return parser.validate(xmlString);
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -38,7 +38,7 @@ export function validateXML(xmlString) {
|
|
|
38
38
|
* const { xml, repaired, changes } = repairXML(brokenXml);
|
|
39
39
|
* if (repaired) console.log('Repaired:', changes);
|
|
40
40
|
*/
|
|
41
|
-
|
|
41
|
+
function repairXML(xmlString) {
|
|
42
42
|
const changes = [];
|
|
43
43
|
let xml = xmlString;
|
|
44
44
|
|
|
@@ -81,7 +81,7 @@ export function repairXML(xmlString) {
|
|
|
81
81
|
* @param {string} elementName - Element tag name (e.g., 'a:tbl').
|
|
82
82
|
* @returns {boolean}
|
|
83
83
|
*/
|
|
84
|
-
|
|
84
|
+
function xmlContainsElement(xmlString, elementName) {
|
|
85
85
|
return xmlString.includes(`<${elementName}`) || xmlString.includes(`<${elementName}>`);
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -92,7 +92,7 @@ export function xmlContainsElement(xmlString, elementName) {
|
|
|
92
92
|
* @param {string} elementName
|
|
93
93
|
* @returns {number}
|
|
94
94
|
*/
|
|
95
|
-
|
|
95
|
+
function countElements(xmlString, elementName) {
|
|
96
96
|
const pattern = new RegExp(`<${elementName}[\\s>/]`, 'g');
|
|
97
97
|
return (xmlString.match(pattern) || []).length;
|
|
98
98
|
}
|
|
@@ -104,7 +104,7 @@ export function countElements(xmlString, elementName) {
|
|
|
104
104
|
* @param {string} attrName - Attribute name (e.g., 'r:id', 'name').
|
|
105
105
|
* @returns {string[]} Array of attribute values found.
|
|
106
106
|
*/
|
|
107
|
-
|
|
107
|
+
function extractAttributeValues(xmlString, attrName) {
|
|
108
108
|
const pattern = new RegExp(`${attrName.replace(':', '\\:')}="([^"]*)"`, 'g');
|
|
109
109
|
const values = [];
|
|
110
110
|
let match;
|
|
@@ -113,3 +113,11 @@ export function extractAttributeValues(xmlString, attrName) {
|
|
|
113
113
|
}
|
|
114
114
|
return values;
|
|
115
115
|
}
|
|
116
|
+
|
|
117
|
+
module.exports = {
|
|
118
|
+
validateXML,
|
|
119
|
+
repairXML,
|
|
120
|
+
xmlContainsElement,
|
|
121
|
+
countElements,
|
|
122
|
+
extractAttributeValues
|
|
123
|
+
};
|