pptx-glimpse 0.7.1 → 0.9.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/dist/index.cjs CHANGED
@@ -1043,12 +1043,109 @@ function measureTextWidth(text, fontSizePt, bold, fontFamily, fontFamilyEa) {
1043
1043
  return totalWidth;
1044
1044
  }
1045
1045
 
1046
+ // src/warning-logger.ts
1047
+ var PREFIX = "[pptx-glimpse]";
1048
+ var currentLevel = "off";
1049
+ var entries = [];
1050
+ var featureCounts = /* @__PURE__ */ new Map();
1051
+ function initWarningLogger(level) {
1052
+ currentLevel = level;
1053
+ entries = [];
1054
+ featureCounts.clear();
1055
+ }
1056
+ function warn(feature, message, context) {
1057
+ if (currentLevel === "off") return;
1058
+ entries.push({ feature, message, ...context !== void 0 && { context } });
1059
+ const existing = featureCounts.get(feature);
1060
+ if (existing) {
1061
+ existing.count++;
1062
+ } else {
1063
+ featureCounts.set(feature, { message, count: 1 });
1064
+ }
1065
+ if (currentLevel === "debug") {
1066
+ const ctx = context ? ` (${context})` : "";
1067
+ console.warn(`${PREFIX} SKIP: ${feature} - ${message}${ctx}`);
1068
+ }
1069
+ }
1070
+ function debug(feature, message, context) {
1071
+ if (currentLevel !== "debug") return;
1072
+ entries.push({ feature, message, ...context !== void 0 && { context } });
1073
+ const existing = featureCounts.get(feature);
1074
+ if (existing) {
1075
+ existing.count++;
1076
+ } else {
1077
+ featureCounts.set(feature, { message, count: 1 });
1078
+ }
1079
+ const ctx = context ? ` (${context})` : "";
1080
+ console.warn(`${PREFIX} DEBUG: ${feature} - ${message}${ctx}`);
1081
+ }
1082
+ function getWarningSummary() {
1083
+ const features = [];
1084
+ for (const [feature, { message, count }] of featureCounts) {
1085
+ features.push({ feature, message, count });
1086
+ }
1087
+ return { totalCount: entries.length, features };
1088
+ }
1089
+ function flushWarnings() {
1090
+ const summary = getWarningSummary();
1091
+ if (currentLevel !== "off" && summary.features.length > 0) {
1092
+ console.warn(`${PREFIX} Summary: ${summary.features.length} unsupported feature(s) detected`);
1093
+ for (const { feature, count } of summary.features) {
1094
+ console.warn(` - ${feature}: ${count} occurrence(s)`);
1095
+ }
1096
+ }
1097
+ entries = [];
1098
+ featureCounts.clear();
1099
+ return summary;
1100
+ }
1101
+ function getWarningEntries() {
1102
+ return entries;
1103
+ }
1104
+
1105
+ // src/font/cjk-font-fallback.ts
1106
+ var import_node_os = require("os");
1107
+ var MACOS_FALLBACKS = {
1108
+ // ゴシック系
1109
+ "Noto Sans JP": ["Hiragino Sans", "Hiragino Kaku Gothic ProN"],
1110
+ "Noto Sans CJK JP": ["Hiragino Sans", "Hiragino Kaku Gothic ProN"],
1111
+ // 明朝系
1112
+ "Noto Serif CJK JP": ["Hiragino Mincho ProN"]
1113
+ };
1114
+ var WINDOWS_FALLBACKS = {
1115
+ // ゴシック系
1116
+ "Noto Sans JP": ["Yu Gothic", "Meiryo", "MS Gothic"],
1117
+ "Noto Sans CJK JP": ["Yu Gothic", "Meiryo", "MS Gothic"],
1118
+ // 明朝系
1119
+ "Noto Serif CJK JP": ["Yu Mincho", "MS Mincho"]
1120
+ };
1121
+ var EMPTY = [];
1122
+ var cachedFallbacks = null;
1123
+ function getFallbackMap() {
1124
+ if (cachedFallbacks) return cachedFallbacks;
1125
+ const os = (0, import_node_os.platform)();
1126
+ switch (os) {
1127
+ case "darwin":
1128
+ cachedFallbacks = MACOS_FALLBACKS;
1129
+ break;
1130
+ case "win32":
1131
+ cachedFallbacks = WINDOWS_FALLBACKS;
1132
+ break;
1133
+ default:
1134
+ cachedFallbacks = {};
1135
+ }
1136
+ return cachedFallbacks;
1137
+ }
1138
+ function getCjkFallbackFonts(mappedFontName) {
1139
+ return getFallbackMap()[mappedFontName] ?? EMPTY;
1140
+ }
1141
+
1046
1142
  // src/font/opentype-text-measurer.ts
1047
1143
  var PX_PER_PT2 = 96 / 72;
1048
1144
  var BOLD_FACTOR2 = 1.05;
1049
1145
  var OpentypeTextMeasurer = class {
1050
1146
  fonts;
1051
1147
  defaultFont;
1148
+ warnedFonts = /* @__PURE__ */ new Set();
1052
1149
  /**
1053
1150
  * @param fonts - フォント名 → opentype.js Font オブジェクトのマップ
1054
1151
  * @param defaultFont - フォールバックフォント(省略可)
@@ -1098,6 +1195,14 @@ var OpentypeTextMeasurer = class {
1098
1195
  if (mapped) {
1099
1196
  const mappedFont = this.fonts.get(mapped);
1100
1197
  if (mappedFont) return mappedFont;
1198
+ for (const fallback of getCjkFallbackFonts(mapped)) {
1199
+ const fallbackFont = this.fonts.get(fallback);
1200
+ if (fallbackFont) return fallbackFont;
1201
+ }
1202
+ }
1203
+ if (!this.warnedFonts.has(name)) {
1204
+ this.warnedFonts.add(name);
1205
+ warn("font.notFound", `Font not found: "${name}"`);
1101
1206
  }
1102
1207
  return null;
1103
1208
  }
@@ -1105,19 +1210,31 @@ var OpentypeTextMeasurer = class {
1105
1210
 
1106
1211
  // src/font/system-font-loader.ts
1107
1212
  var import_node_fs = require("fs");
1108
- var import_node_os = require("os");
1213
+ var import_node_os2 = require("os");
1109
1214
  var import_node_path = require("path");
1110
1215
  var FONT_EXTENSIONS = /* @__PURE__ */ new Set([".ttf", ".otf"]);
1111
- var CJK_TTC_PATTERNS = ["NotoSansCJK", "NotoSerifCJK"];
1216
+ var CJK_TTC_PATTERNS = [
1217
+ "NotoSansCJK",
1218
+ "NotoSerifCJK",
1219
+ // macOS
1220
+ "Hiragino",
1221
+ "\u30D2\u30E9\u30AE\u30CE",
1222
+ // Windows
1223
+ "YuGoth",
1224
+ "YuMin",
1225
+ "meiryo",
1226
+ "msgothic",
1227
+ "msmincho"
1228
+ ];
1112
1229
  var cachedPaths = null;
1113
1230
  var cachedAdditionalDirs = null;
1114
1231
  function getSystemFontDirs() {
1115
- const os = (0, import_node_os.platform)();
1232
+ const os = (0, import_node_os2.platform)();
1116
1233
  switch (os) {
1117
1234
  case "linux":
1118
1235
  return ["/usr/share/fonts", "/usr/local/share/fonts"];
1119
1236
  case "darwin":
1120
- return ["/System/Library/Fonts", "/Library/Fonts", (0, import_node_path.join)((0, import_node_os.homedir)(), "Library/Fonts")];
1237
+ return ["/System/Library/Fonts", "/Library/Fonts", (0, import_node_path.join)((0, import_node_os2.homedir)(), "Library/Fonts")];
1121
1238
  case "win32":
1122
1239
  return ["C:\\Windows\\Fonts"];
1123
1240
  default:
@@ -1125,7 +1242,7 @@ function getSystemFontDirs() {
1125
1242
  }
1126
1243
  }
1127
1244
  function isCjkTtc(name) {
1128
- const lower = name.toLowerCase();
1245
+ const lower = name.normalize("NFC").toLowerCase();
1129
1246
  return lower.endsWith(".ttc") && CJK_TTC_PATTERNS.some((p) => lower.includes(p.toLowerCase()));
1130
1247
  }
1131
1248
  function walk(dir, result) {
@@ -1163,6 +1280,7 @@ function collectFontFilePaths(additionalDirs) {
1163
1280
  var DefaultTextPathFontResolver = class {
1164
1281
  fonts;
1165
1282
  defaultFont;
1283
+ warnedFonts = /* @__PURE__ */ new Set();
1166
1284
  constructor(fonts, defaultFont) {
1167
1285
  this.fonts = fonts;
1168
1286
  this.defaultFont = defaultFont ?? null;
@@ -1180,6 +1298,12 @@ var DefaultTextPathFontResolver = class {
1180
1298
  const font = this.findFont(jpanFallback);
1181
1299
  if (font) return font;
1182
1300
  }
1301
+ for (const name of [fontFamily, fontFamilyEa, jpanFallback]) {
1302
+ if (name && !this.warnedFonts.has(name)) {
1303
+ this.warnedFonts.add(name);
1304
+ warn("font.notFound", `Font not found: "${name}"`);
1305
+ }
1306
+ }
1183
1307
  return this.defaultFont;
1184
1308
  }
1185
1309
  findFont(name) {
@@ -1189,6 +1313,10 @@ var DefaultTextPathFontResolver = class {
1189
1313
  if (mapped) {
1190
1314
  const mappedFont = this.fonts.get(mapped);
1191
1315
  if (mappedFont) return mappedFont;
1316
+ for (const fallback of getCjkFallbackFonts(mapped)) {
1317
+ const fallbackFont = this.fonts.get(fallback);
1318
+ if (fallbackFont) return fallbackFont;
1319
+ }
1192
1320
  }
1193
1321
  return null;
1194
1322
  }
@@ -1621,65 +1749,6 @@ async function svgToPng(svgString, options) {
1621
1749
  };
1622
1750
  }
1623
1751
 
1624
- // src/warning-logger.ts
1625
- var PREFIX = "[pptx-glimpse]";
1626
- var currentLevel = "off";
1627
- var entries = [];
1628
- var featureCounts = /* @__PURE__ */ new Map();
1629
- function initWarningLogger(level) {
1630
- currentLevel = level;
1631
- entries = [];
1632
- featureCounts.clear();
1633
- }
1634
- function warn(feature, message, context) {
1635
- if (currentLevel === "off") return;
1636
- entries.push({ feature, message, ...context !== void 0 && { context } });
1637
- const existing = featureCounts.get(feature);
1638
- if (existing) {
1639
- existing.count++;
1640
- } else {
1641
- featureCounts.set(feature, { message, count: 1 });
1642
- }
1643
- if (currentLevel === "debug") {
1644
- const ctx = context ? ` (${context})` : "";
1645
- console.warn(`${PREFIX} SKIP: ${feature} - ${message}${ctx}`);
1646
- }
1647
- }
1648
- function debug(feature, message, context) {
1649
- if (currentLevel !== "debug") return;
1650
- entries.push({ feature, message, ...context !== void 0 && { context } });
1651
- const existing = featureCounts.get(feature);
1652
- if (existing) {
1653
- existing.count++;
1654
- } else {
1655
- featureCounts.set(feature, { message, count: 1 });
1656
- }
1657
- const ctx = context ? ` (${context})` : "";
1658
- console.warn(`${PREFIX} DEBUG: ${feature} - ${message}${ctx}`);
1659
- }
1660
- function getWarningSummary() {
1661
- const features = [];
1662
- for (const [feature, { message, count }] of featureCounts) {
1663
- features.push({ feature, message, count });
1664
- }
1665
- return { totalCount: entries.length, features };
1666
- }
1667
- function flushWarnings() {
1668
- const summary = getWarningSummary();
1669
- if (currentLevel !== "off" && summary.features.length > 0) {
1670
- console.warn(`${PREFIX} Summary: ${summary.features.length} unsupported feature(s) detected`);
1671
- for (const { feature, count } of summary.features) {
1672
- console.warn(` - ${feature}: ${count} occurrence(s)`);
1673
- }
1674
- }
1675
- entries = [];
1676
- featureCounts.clear();
1677
- return summary;
1678
- }
1679
- function getWarningEntries() {
1680
- return entries;
1681
- }
1682
-
1683
1752
  // src/color/color-transforms.ts
1684
1753
  function applyColorTransforms(color, node) {
1685
1754
  let { hex, alpha } = color;
@@ -8813,6 +8882,9 @@ async function convertPptxToSvg(input, options) {
8813
8882
  const data = parsePptxData(input);
8814
8883
  setScriptFonts(data.theme.fontScheme.majorFontJpan, data.theme.fontScheme.minorFontJpan);
8815
8884
  const targetSlides = options?.slides ? data.slidePaths.filter((s) => options.slides.includes(s.slideNumber)) : data.slidePaths;
8885
+ if (data.slidePaths.length === 0) {
8886
+ warn("presentation.noSlides", "No slides found in the PPTX file");
8887
+ }
8816
8888
  const results = [];
8817
8889
  for (const { slideNumber, path } of targetSlides) {
8818
8890
  const parsed = parseSlideWithLayout(slideNumber, path, data);
package/dist/index.d.cts CHANGED
@@ -125,6 +125,7 @@ interface OpentypeFont {
125
125
  declare class OpentypeTextMeasurer implements TextMeasurer {
126
126
  private fonts;
127
127
  private defaultFont;
128
+ private warnedFonts;
128
129
  /**
129
130
  * @param fonts - フォント名 → opentype.js Font オブジェクトのマップ
130
131
  * @param defaultFont - フォールバックフォント(省略可)
package/dist/index.d.ts CHANGED
@@ -125,6 +125,7 @@ interface OpentypeFont {
125
125
  declare class OpentypeTextMeasurer implements TextMeasurer {
126
126
  private fonts;
127
127
  private defaultFont;
128
+ private warnedFonts;
128
129
  /**
129
130
  * @param fonts - フォント名 → opentype.js Font オブジェクトのマップ
130
131
  * @param defaultFont - フォールバックフォント(省略可)
package/dist/index.js CHANGED
@@ -1007,12 +1007,109 @@ function measureTextWidth(text, fontSizePt, bold, fontFamily, fontFamilyEa) {
1007
1007
  return totalWidth;
1008
1008
  }
1009
1009
 
1010
+ // src/warning-logger.ts
1011
+ var PREFIX = "[pptx-glimpse]";
1012
+ var currentLevel = "off";
1013
+ var entries = [];
1014
+ var featureCounts = /* @__PURE__ */ new Map();
1015
+ function initWarningLogger(level) {
1016
+ currentLevel = level;
1017
+ entries = [];
1018
+ featureCounts.clear();
1019
+ }
1020
+ function warn(feature, message, context) {
1021
+ if (currentLevel === "off") return;
1022
+ entries.push({ feature, message, ...context !== void 0 && { context } });
1023
+ const existing = featureCounts.get(feature);
1024
+ if (existing) {
1025
+ existing.count++;
1026
+ } else {
1027
+ featureCounts.set(feature, { message, count: 1 });
1028
+ }
1029
+ if (currentLevel === "debug") {
1030
+ const ctx = context ? ` (${context})` : "";
1031
+ console.warn(`${PREFIX} SKIP: ${feature} - ${message}${ctx}`);
1032
+ }
1033
+ }
1034
+ function debug(feature, message, context) {
1035
+ if (currentLevel !== "debug") return;
1036
+ entries.push({ feature, message, ...context !== void 0 && { context } });
1037
+ const existing = featureCounts.get(feature);
1038
+ if (existing) {
1039
+ existing.count++;
1040
+ } else {
1041
+ featureCounts.set(feature, { message, count: 1 });
1042
+ }
1043
+ const ctx = context ? ` (${context})` : "";
1044
+ console.warn(`${PREFIX} DEBUG: ${feature} - ${message}${ctx}`);
1045
+ }
1046
+ function getWarningSummary() {
1047
+ const features = [];
1048
+ for (const [feature, { message, count }] of featureCounts) {
1049
+ features.push({ feature, message, count });
1050
+ }
1051
+ return { totalCount: entries.length, features };
1052
+ }
1053
+ function flushWarnings() {
1054
+ const summary = getWarningSummary();
1055
+ if (currentLevel !== "off" && summary.features.length > 0) {
1056
+ console.warn(`${PREFIX} Summary: ${summary.features.length} unsupported feature(s) detected`);
1057
+ for (const { feature, count } of summary.features) {
1058
+ console.warn(` - ${feature}: ${count} occurrence(s)`);
1059
+ }
1060
+ }
1061
+ entries = [];
1062
+ featureCounts.clear();
1063
+ return summary;
1064
+ }
1065
+ function getWarningEntries() {
1066
+ return entries;
1067
+ }
1068
+
1069
+ // src/font/cjk-font-fallback.ts
1070
+ import { platform } from "os";
1071
+ var MACOS_FALLBACKS = {
1072
+ // ゴシック系
1073
+ "Noto Sans JP": ["Hiragino Sans", "Hiragino Kaku Gothic ProN"],
1074
+ "Noto Sans CJK JP": ["Hiragino Sans", "Hiragino Kaku Gothic ProN"],
1075
+ // 明朝系
1076
+ "Noto Serif CJK JP": ["Hiragino Mincho ProN"]
1077
+ };
1078
+ var WINDOWS_FALLBACKS = {
1079
+ // ゴシック系
1080
+ "Noto Sans JP": ["Yu Gothic", "Meiryo", "MS Gothic"],
1081
+ "Noto Sans CJK JP": ["Yu Gothic", "Meiryo", "MS Gothic"],
1082
+ // 明朝系
1083
+ "Noto Serif CJK JP": ["Yu Mincho", "MS Mincho"]
1084
+ };
1085
+ var EMPTY = [];
1086
+ var cachedFallbacks = null;
1087
+ function getFallbackMap() {
1088
+ if (cachedFallbacks) return cachedFallbacks;
1089
+ const os = platform();
1090
+ switch (os) {
1091
+ case "darwin":
1092
+ cachedFallbacks = MACOS_FALLBACKS;
1093
+ break;
1094
+ case "win32":
1095
+ cachedFallbacks = WINDOWS_FALLBACKS;
1096
+ break;
1097
+ default:
1098
+ cachedFallbacks = {};
1099
+ }
1100
+ return cachedFallbacks;
1101
+ }
1102
+ function getCjkFallbackFonts(mappedFontName) {
1103
+ return getFallbackMap()[mappedFontName] ?? EMPTY;
1104
+ }
1105
+
1010
1106
  // src/font/opentype-text-measurer.ts
1011
1107
  var PX_PER_PT2 = 96 / 72;
1012
1108
  var BOLD_FACTOR2 = 1.05;
1013
1109
  var OpentypeTextMeasurer = class {
1014
1110
  fonts;
1015
1111
  defaultFont;
1112
+ warnedFonts = /* @__PURE__ */ new Set();
1016
1113
  /**
1017
1114
  * @param fonts - フォント名 → opentype.js Font オブジェクトのマップ
1018
1115
  * @param defaultFont - フォールバックフォント(省略可)
@@ -1062,6 +1159,14 @@ var OpentypeTextMeasurer = class {
1062
1159
  if (mapped) {
1063
1160
  const mappedFont = this.fonts.get(mapped);
1064
1161
  if (mappedFont) return mappedFont;
1162
+ for (const fallback of getCjkFallbackFonts(mapped)) {
1163
+ const fallbackFont = this.fonts.get(fallback);
1164
+ if (fallbackFont) return fallbackFont;
1165
+ }
1166
+ }
1167
+ if (!this.warnedFonts.has(name)) {
1168
+ this.warnedFonts.add(name);
1169
+ warn("font.notFound", `Font not found: "${name}"`);
1065
1170
  }
1066
1171
  return null;
1067
1172
  }
@@ -1069,14 +1174,26 @@ var OpentypeTextMeasurer = class {
1069
1174
 
1070
1175
  // src/font/system-font-loader.ts
1071
1176
  import { existsSync, readdirSync } from "fs";
1072
- import { homedir, platform } from "os";
1177
+ import { homedir, platform as platform2 } from "os";
1073
1178
  import { extname, join } from "path";
1074
1179
  var FONT_EXTENSIONS = /* @__PURE__ */ new Set([".ttf", ".otf"]);
1075
- var CJK_TTC_PATTERNS = ["NotoSansCJK", "NotoSerifCJK"];
1180
+ var CJK_TTC_PATTERNS = [
1181
+ "NotoSansCJK",
1182
+ "NotoSerifCJK",
1183
+ // macOS
1184
+ "Hiragino",
1185
+ "\u30D2\u30E9\u30AE\u30CE",
1186
+ // Windows
1187
+ "YuGoth",
1188
+ "YuMin",
1189
+ "meiryo",
1190
+ "msgothic",
1191
+ "msmincho"
1192
+ ];
1076
1193
  var cachedPaths = null;
1077
1194
  var cachedAdditionalDirs = null;
1078
1195
  function getSystemFontDirs() {
1079
- const os = platform();
1196
+ const os = platform2();
1080
1197
  switch (os) {
1081
1198
  case "linux":
1082
1199
  return ["/usr/share/fonts", "/usr/local/share/fonts"];
@@ -1089,7 +1206,7 @@ function getSystemFontDirs() {
1089
1206
  }
1090
1207
  }
1091
1208
  function isCjkTtc(name) {
1092
- const lower = name.toLowerCase();
1209
+ const lower = name.normalize("NFC").toLowerCase();
1093
1210
  return lower.endsWith(".ttc") && CJK_TTC_PATTERNS.some((p) => lower.includes(p.toLowerCase()));
1094
1211
  }
1095
1212
  function walk(dir, result) {
@@ -1127,6 +1244,7 @@ function collectFontFilePaths(additionalDirs) {
1127
1244
  var DefaultTextPathFontResolver = class {
1128
1245
  fonts;
1129
1246
  defaultFont;
1247
+ warnedFonts = /* @__PURE__ */ new Set();
1130
1248
  constructor(fonts, defaultFont) {
1131
1249
  this.fonts = fonts;
1132
1250
  this.defaultFont = defaultFont ?? null;
@@ -1144,6 +1262,12 @@ var DefaultTextPathFontResolver = class {
1144
1262
  const font = this.findFont(jpanFallback);
1145
1263
  if (font) return font;
1146
1264
  }
1265
+ for (const name of [fontFamily, fontFamilyEa, jpanFallback]) {
1266
+ if (name && !this.warnedFonts.has(name)) {
1267
+ this.warnedFonts.add(name);
1268
+ warn("font.notFound", `Font not found: "${name}"`);
1269
+ }
1270
+ }
1147
1271
  return this.defaultFont;
1148
1272
  }
1149
1273
  findFont(name) {
@@ -1153,6 +1277,10 @@ var DefaultTextPathFontResolver = class {
1153
1277
  if (mapped) {
1154
1278
  const mappedFont = this.fonts.get(mapped);
1155
1279
  if (mappedFont) return mappedFont;
1280
+ for (const fallback of getCjkFallbackFonts(mapped)) {
1281
+ const fallbackFont = this.fonts.get(fallback);
1282
+ if (fallbackFont) return fallbackFont;
1283
+ }
1156
1284
  }
1157
1285
  return null;
1158
1286
  }
@@ -1584,65 +1712,6 @@ async function svgToPng(svgString, options) {
1584
1712
  };
1585
1713
  }
1586
1714
 
1587
- // src/warning-logger.ts
1588
- var PREFIX = "[pptx-glimpse]";
1589
- var currentLevel = "off";
1590
- var entries = [];
1591
- var featureCounts = /* @__PURE__ */ new Map();
1592
- function initWarningLogger(level) {
1593
- currentLevel = level;
1594
- entries = [];
1595
- featureCounts.clear();
1596
- }
1597
- function warn(feature, message, context) {
1598
- if (currentLevel === "off") return;
1599
- entries.push({ feature, message, ...context !== void 0 && { context } });
1600
- const existing = featureCounts.get(feature);
1601
- if (existing) {
1602
- existing.count++;
1603
- } else {
1604
- featureCounts.set(feature, { message, count: 1 });
1605
- }
1606
- if (currentLevel === "debug") {
1607
- const ctx = context ? ` (${context})` : "";
1608
- console.warn(`${PREFIX} SKIP: ${feature} - ${message}${ctx}`);
1609
- }
1610
- }
1611
- function debug(feature, message, context) {
1612
- if (currentLevel !== "debug") return;
1613
- entries.push({ feature, message, ...context !== void 0 && { context } });
1614
- const existing = featureCounts.get(feature);
1615
- if (existing) {
1616
- existing.count++;
1617
- } else {
1618
- featureCounts.set(feature, { message, count: 1 });
1619
- }
1620
- const ctx = context ? ` (${context})` : "";
1621
- console.warn(`${PREFIX} DEBUG: ${feature} - ${message}${ctx}`);
1622
- }
1623
- function getWarningSummary() {
1624
- const features = [];
1625
- for (const [feature, { message, count }] of featureCounts) {
1626
- features.push({ feature, message, count });
1627
- }
1628
- return { totalCount: entries.length, features };
1629
- }
1630
- function flushWarnings() {
1631
- const summary = getWarningSummary();
1632
- if (currentLevel !== "off" && summary.features.length > 0) {
1633
- console.warn(`${PREFIX} Summary: ${summary.features.length} unsupported feature(s) detected`);
1634
- for (const { feature, count } of summary.features) {
1635
- console.warn(` - ${feature}: ${count} occurrence(s)`);
1636
- }
1637
- }
1638
- entries = [];
1639
- featureCounts.clear();
1640
- return summary;
1641
- }
1642
- function getWarningEntries() {
1643
- return entries;
1644
- }
1645
-
1646
1715
  // src/color/color-transforms.ts
1647
1716
  function applyColorTransforms(color, node) {
1648
1717
  let { hex, alpha } = color;
@@ -8776,6 +8845,9 @@ async function convertPptxToSvg(input, options) {
8776
8845
  const data = parsePptxData(input);
8777
8846
  setScriptFonts(data.theme.fontScheme.majorFontJpan, data.theme.fontScheme.minorFontJpan);
8778
8847
  const targetSlides = options?.slides ? data.slidePaths.filter((s) => options.slides.includes(s.slideNumber)) : data.slidePaths;
8848
+ if (data.slidePaths.length === 0) {
8849
+ warn("presentation.noSlides", "No slides found in the PPTX file");
8850
+ }
8779
8851
  const results = [];
8780
8852
  for (const { slideNumber, path } of targetSlides) {
8781
8853
  const parsed = parseSlideWithLayout(slideNumber, path, data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-glimpse",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "description": "A lightweight JavaScript library for rendering PowerPoint (.pptx) files as SVG or PNG in Node.js. No LibreOffice required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",