node-pptx-templater 1.0.21 → 1.1.0

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/src/index.js CHANGED
@@ -51,7 +51,7 @@ const {
51
51
  analyzeXmlFile,
52
52
  reportXmlComplexity,
53
53
  } = require('./utils/xmlUtils.js')
54
- const { createLogger } = require('./utils/logger.js')
54
+ const { createLogger, setGlobalLogLevel, resetLogLevel } = require('./utils/logger.js')
55
55
  const {
56
56
  PPTXError,
57
57
  SlideNotFoundError,
@@ -87,6 +87,8 @@ module.exports = {
87
87
  analyzeXmlFile,
88
88
  reportXmlComplexity,
89
89
  createLogger,
90
+ setGlobalLogLevel,
91
+ resetLogLevel,
90
92
  PPTXError,
91
93
  SlideNotFoundError,
92
94
  ChartNotFoundError,
@@ -796,8 +796,6 @@ class TableManager {
796
796
  getCellBounds(slideIndex, tableId, rowIndex, colIndex, slideManager) {
797
797
  const { tblObj, frameObj } = this.#getTableContext(slideIndex, tableId, slideManager)
798
798
 
799
- this.#calculateRowHeights(slideIndex, tableId, slideManager, tblObj)
800
-
801
799
  const xfrm = frameObj['p:xfrm']
802
800
  const tableX = xfrm?.['a:off']?.['@_x'] ? parseInt(xfrm['a:off']['@_x'], 10) : 0
803
801
  const tableY = xfrm?.['a:off']?.['@_y'] ? parseInt(xfrm['a:off']['@_y'], 10) : 0
@@ -1343,6 +1341,16 @@ class TableManager {
1343
1341
  }
1344
1342
  }
1345
1343
 
1344
+ // Scale shape down proportionally to fit inside the cell if it exceeds the cell dimensions
1345
+ if (shapeWidth > cellWidth_px || shapeHeight > cellHeight_px) {
1346
+ logger.warn(
1347
+ `Shape width (${shapeWidth}px) or height (${shapeHeight}px) exceeds cell dimensions (${cellWidth_px}px x ${cellHeight_px}px). Scaling shape to fit.`
1348
+ )
1349
+ const scale = Math.min(cellWidth_px / shapeWidth, cellHeight_px / shapeHeight)
1350
+ shapeWidth = Math.max(1, Math.floor(shapeWidth * scale))
1351
+ shapeHeight = Math.max(1, Math.floor(shapeHeight * scale))
1352
+ }
1353
+
1346
1354
  // 2. Determine alignment settings
1347
1355
  let alignX = config.alignX
1348
1356
  let alignY = config.alignY
@@ -1695,8 +1703,6 @@ class TableManager {
1695
1703
  }
1696
1704
  }
1697
1705
 
1698
- this.#calculateRowHeights(slideIndex, tableId, slideManager, tblObj)
1699
-
1700
1706
  const xfrm = frameObj['p:xfrm']
1701
1707
  const tableX = xfrm?.['a:off']?.['@_x'] ? parseInt(xfrm['a:off']['@_x'], 10) : 0
1702
1708
  const tableY = xfrm?.['a:off']?.['@_y'] ? parseInt(xfrm['a:off']['@_y'], 10) : 0
@@ -1870,8 +1876,6 @@ class TableManager {
1870
1876
  slideManager
1871
1877
  )
1872
1878
 
1873
- this.#calculateRowHeights(slideIndex, tableId, slideManager, tblObj)
1874
-
1875
1879
  const xfrm = frameObj['p:xfrm']
1876
1880
  const tableX = xfrm?.['a:off']?.['@_x'] ? parseInt(xfrm['a:off']['@_x'], 10) : 0
1877
1881
  const tableY = xfrm?.['a:off']?.['@_y'] ? parseInt(xfrm['a:off']['@_y'], 10) : 0
@@ -1955,8 +1959,6 @@ class TableManager {
1955
1959
  slideManager
1956
1960
  )
1957
1961
 
1958
- this.#calculateRowHeights(slideIndex, tableId, slideManager, tblObj)
1959
-
1960
1962
  const shapes = shapeManager.getShapes(slideIndex, slideManager)
1961
1963
  const prefix = `cellshape_${resolvedTableId}_${rowIndex}_${colIndex}_${shapeIndex}`
1962
1964
  const matchingShapes = shapes.filter(
@@ -2,10 +2,11 @@
2
2
  * @fileoverview Logger utility - lightweight structured logging.
3
3
  *
4
4
  * Provides contextual logging with module names.
5
- * Respects the PPTX_LOG_LEVEL environment variable.
5
+ * Respects the PPTX_LOG_LEVEL environment variable, or can be
6
+ * configured at runtime via setGlobalLogLevel().
6
7
  *
7
8
  * Log levels (lowest to highest severity):
8
- * debug → info → warn → error
9
+ * verbose → debug → info → warn → error → silent
9
10
  *
10
11
  * Usage:
11
12
  * const logger = createLogger('MyModule');
@@ -14,21 +15,67 @@
14
15
  * logger.warn('Watch out');
15
16
  * logger.error('Something failed');
16
17
  *
17
- * Environment:
18
- * PPTX_LOG_LEVEL=debug → show all logs
19
- * PPTX_LOG_LEVEL=info → show info, warn, error (default)
20
- * PPTX_LOG_LEVEL=warn → show warn and error only
21
- * PPTX_LOG_LEVEL=error → show only errors
22
- * PPTX_LOG_LEVEL=silent → suppress all logs
18
+ * Environment variable (set before process starts):
19
+ * PPTX_LOG_LEVEL=debug → show debug, info, warn, error
20
+ * PPTX_LOG_LEVEL=info → show info, warn, error
21
+ * PPTX_LOG_LEVEL=warn → show warn and error only (default)
22
+ * PPTX_LOG_LEVEL=error → show only errors
23
+ * PPTX_LOG_LEVEL=silent → suppress all output
24
+ *
25
+ * Runtime control (overrides env var):
26
+ * const { setGlobalLogLevel } = require('./logger');
27
+ * setGlobalLogLevel('debug');
23
28
  */
24
29
 
25
- const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3, silent: 4 }
30
+ /** @type {Object.<string, number>} */
31
+ const LOG_LEVELS = { verbose: -1, debug: 0, info: 1, warn: 2, error: 3, silent: 4 }
32
+
33
+ /** @type {number} Initial level from environment variable */
34
+ const envLevel = LOG_LEVELS[(process.env.PPTX_LOG_LEVEL || 'warn').toLowerCase()] ?? LOG_LEVELS.warn
35
+
36
+ /** @type {number|null} Runtime override — null means use envLevel */
37
+ let runtimeLevel = null
26
38
 
27
- const currentLevel =
28
- LOG_LEVELS[(process.env.PPTX_LOG_LEVEL || 'warn').toLowerCase()] ?? LOG_LEVELS.warn
39
+ /**
40
+ * Gets the current effective log level.
41
+ * @returns {number}
42
+ */
43
+ function getEffectiveLevel() {
44
+ return runtimeLevel !== null ? runtimeLevel : envLevel
45
+ }
46
+
47
+ /**
48
+ * Sets the global log level at runtime, overriding the environment variable.
49
+ * This affects all logger instances immediately.
50
+ *
51
+ * @param {string} level - One of: 'verbose', 'debug', 'info', 'warn', 'error', 'silent'
52
+ * @throws {Error} If an invalid level is provided.
53
+ *
54
+ * @example
55
+ * const { setGlobalLogLevel } = require('node-pptx-templater');
56
+ * setGlobalLogLevel('debug'); // Enable verbose output
57
+ * setGlobalLogLevel('silent'); // Suppress everything
58
+ */
59
+ function setGlobalLogLevel(level) {
60
+ const normalized = String(level).toLowerCase()
61
+ if (LOG_LEVELS[normalized] === undefined) {
62
+ throw new Error(
63
+ `Invalid log level: "${level}". Valid levels: verbose, debug, info, warn, error, silent`
64
+ )
65
+ }
66
+ runtimeLevel = LOG_LEVELS[normalized]
67
+ }
68
+
69
+ /**
70
+ * Resets the log level back to the environment variable default.
71
+ */
72
+ function resetLogLevel() {
73
+ runtimeLevel = null
74
+ }
29
75
 
30
76
  /**
31
77
  * ANSI color codes for terminal output.
78
+ * @private
32
79
  */
33
80
  const COLORS = {
34
81
  reset: '\x1b[0m',
@@ -37,6 +84,7 @@ const COLORS = {
37
84
  green: '\x1b[32m',
38
85
  yellow: '\x1b[33m',
39
86
  red: '\x1b[31m',
87
+ magenta: '\x1b[35m',
40
88
  }
41
89
 
42
90
  /**
@@ -49,6 +97,7 @@ function timestamp() {
49
97
 
50
98
  /**
51
99
  * @typedef {Object} Logger
100
+ * @property {Function} verbose - Log verbose message (most detailed).
52
101
  * @property {Function} debug - Log debug message.
53
102
  * @property {Function} info - Log info message.
54
103
  * @property {Function} warn - Log warning.
@@ -64,16 +113,17 @@ function timestamp() {
64
113
  * @example
65
114
  * const logger = createLogger('SlideManager');
66
115
  * logger.info('Loaded 5 slides');
116
+ * logger.debug('Processing slide XML...');
67
117
  */
68
118
  function createLogger(moduleName) {
69
119
  const isTTY = process.stdout.isTTY
70
120
 
71
121
  const log = (level, levelNum, color, message, ...args) => {
72
- if (levelNum < currentLevel) return
122
+ if (levelNum < getEffectiveLevel()) return
73
123
 
74
124
  const prefix = isTTY
75
- ? `${COLORS.dim}${timestamp()}${COLORS.reset} ${color}[${level.toUpperCase().padEnd(5)}]${COLORS.reset} ${COLORS.cyan}[${moduleName}]${COLORS.reset}`
76
- : `${timestamp()} [${level.toUpperCase().padEnd(5)}] [${moduleName}]`
125
+ ? `${COLORS.dim}${timestamp()}${COLORS.reset} ${color}[${level.toUpperCase().padEnd(7)}]${COLORS.reset} ${COLORS.cyan}[${moduleName}]${COLORS.reset}`
126
+ : `${timestamp()} [${level.toUpperCase().padEnd(7)}] [${moduleName}]`
77
127
 
78
128
  const output =
79
129
  args.length > 0
@@ -85,7 +135,15 @@ function createLogger(moduleName) {
85
135
 
86
136
  return {
87
137
  /**
88
- * Logs a debug-level message. Only shown when PPTX_LOG_LEVEL=debug.
138
+ * Logs a verbose-level message. Only shown when level=verbose.
139
+ * @param {string} message
140
+ * @param {...*} args
141
+ */
142
+ verbose: (message, ...args) =>
143
+ log('verbose', LOG_LEVELS.verbose, COLORS.magenta, message, ...args),
144
+
145
+ /**
146
+ * Logs a debug-level message. Only shown when level=debug or lower.
89
147
  * @param {string} message
90
148
  * @param {...*} args
91
149
  */
@@ -116,4 +174,7 @@ function createLogger(moduleName) {
116
174
 
117
175
  module.exports = {
118
176
  createLogger,
177
+ setGlobalLogLevel,
178
+ resetLogLevel,
179
+ LOG_LEVELS,
119
180
  }