pptx-glimpse 0.8.0 → 0.10.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 +155 -65
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +153 -64
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DEFAULT_FONT_MAPPING: () => DEFAULT_FONT_MAPPING,
|
|
24
|
+
clearFontCache: () => clearFontCache,
|
|
24
25
|
collectUsedFonts: () => collectUsedFonts,
|
|
25
26
|
convertPptxToPng: () => convertPptxToPng,
|
|
26
27
|
convertPptxToSvg: () => convertPptxToSvg,
|
|
@@ -1043,12 +1044,109 @@ function measureTextWidth(text, fontSizePt, bold, fontFamily, fontFamilyEa) {
|
|
|
1043
1044
|
return totalWidth;
|
|
1044
1045
|
}
|
|
1045
1046
|
|
|
1047
|
+
// src/warning-logger.ts
|
|
1048
|
+
var PREFIX = "[pptx-glimpse]";
|
|
1049
|
+
var currentLevel = "off";
|
|
1050
|
+
var entries = [];
|
|
1051
|
+
var featureCounts = /* @__PURE__ */ new Map();
|
|
1052
|
+
function initWarningLogger(level) {
|
|
1053
|
+
currentLevel = level;
|
|
1054
|
+
entries = [];
|
|
1055
|
+
featureCounts.clear();
|
|
1056
|
+
}
|
|
1057
|
+
function warn(feature, message, context) {
|
|
1058
|
+
if (currentLevel === "off") return;
|
|
1059
|
+
entries.push({ feature, message, ...context !== void 0 && { context } });
|
|
1060
|
+
const existing = featureCounts.get(feature);
|
|
1061
|
+
if (existing) {
|
|
1062
|
+
existing.count++;
|
|
1063
|
+
} else {
|
|
1064
|
+
featureCounts.set(feature, { message, count: 1 });
|
|
1065
|
+
}
|
|
1066
|
+
if (currentLevel === "debug") {
|
|
1067
|
+
const ctx = context ? ` (${context})` : "";
|
|
1068
|
+
console.warn(`${PREFIX} SKIP: ${feature} - ${message}${ctx}`);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
function debug(feature, message, context) {
|
|
1072
|
+
if (currentLevel !== "debug") return;
|
|
1073
|
+
entries.push({ feature, message, ...context !== void 0 && { context } });
|
|
1074
|
+
const existing = featureCounts.get(feature);
|
|
1075
|
+
if (existing) {
|
|
1076
|
+
existing.count++;
|
|
1077
|
+
} else {
|
|
1078
|
+
featureCounts.set(feature, { message, count: 1 });
|
|
1079
|
+
}
|
|
1080
|
+
const ctx = context ? ` (${context})` : "";
|
|
1081
|
+
console.warn(`${PREFIX} DEBUG: ${feature} - ${message}${ctx}`);
|
|
1082
|
+
}
|
|
1083
|
+
function getWarningSummary() {
|
|
1084
|
+
const features = [];
|
|
1085
|
+
for (const [feature, { message, count }] of featureCounts) {
|
|
1086
|
+
features.push({ feature, message, count });
|
|
1087
|
+
}
|
|
1088
|
+
return { totalCount: entries.length, features };
|
|
1089
|
+
}
|
|
1090
|
+
function flushWarnings() {
|
|
1091
|
+
const summary = getWarningSummary();
|
|
1092
|
+
if (currentLevel !== "off" && summary.features.length > 0) {
|
|
1093
|
+
console.warn(`${PREFIX} Summary: ${summary.features.length} unsupported feature(s) detected`);
|
|
1094
|
+
for (const { feature, count } of summary.features) {
|
|
1095
|
+
console.warn(` - ${feature}: ${count} occurrence(s)`);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
entries = [];
|
|
1099
|
+
featureCounts.clear();
|
|
1100
|
+
return summary;
|
|
1101
|
+
}
|
|
1102
|
+
function getWarningEntries() {
|
|
1103
|
+
return entries;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// src/font/cjk-font-fallback.ts
|
|
1107
|
+
var import_node_os = require("os");
|
|
1108
|
+
var MACOS_FALLBACKS = {
|
|
1109
|
+
// ゴシック系
|
|
1110
|
+
"Noto Sans JP": ["Hiragino Sans", "Hiragino Kaku Gothic ProN"],
|
|
1111
|
+
"Noto Sans CJK JP": ["Hiragino Sans", "Hiragino Kaku Gothic ProN"],
|
|
1112
|
+
// 明朝系
|
|
1113
|
+
"Noto Serif CJK JP": ["Hiragino Mincho ProN"]
|
|
1114
|
+
};
|
|
1115
|
+
var WINDOWS_FALLBACKS = {
|
|
1116
|
+
// ゴシック系
|
|
1117
|
+
"Noto Sans JP": ["Yu Gothic", "Meiryo", "MS Gothic"],
|
|
1118
|
+
"Noto Sans CJK JP": ["Yu Gothic", "Meiryo", "MS Gothic"],
|
|
1119
|
+
// 明朝系
|
|
1120
|
+
"Noto Serif CJK JP": ["Yu Mincho", "MS Mincho"]
|
|
1121
|
+
};
|
|
1122
|
+
var EMPTY = [];
|
|
1123
|
+
var cachedFallbacks = null;
|
|
1124
|
+
function getFallbackMap() {
|
|
1125
|
+
if (cachedFallbacks) return cachedFallbacks;
|
|
1126
|
+
const os = (0, import_node_os.platform)();
|
|
1127
|
+
switch (os) {
|
|
1128
|
+
case "darwin":
|
|
1129
|
+
cachedFallbacks = MACOS_FALLBACKS;
|
|
1130
|
+
break;
|
|
1131
|
+
case "win32":
|
|
1132
|
+
cachedFallbacks = WINDOWS_FALLBACKS;
|
|
1133
|
+
break;
|
|
1134
|
+
default:
|
|
1135
|
+
cachedFallbacks = {};
|
|
1136
|
+
}
|
|
1137
|
+
return cachedFallbacks;
|
|
1138
|
+
}
|
|
1139
|
+
function getCjkFallbackFonts(mappedFontName) {
|
|
1140
|
+
return getFallbackMap()[mappedFontName] ?? EMPTY;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1046
1143
|
// src/font/opentype-text-measurer.ts
|
|
1047
1144
|
var PX_PER_PT2 = 96 / 72;
|
|
1048
1145
|
var BOLD_FACTOR2 = 1.05;
|
|
1049
1146
|
var OpentypeTextMeasurer = class {
|
|
1050
1147
|
fonts;
|
|
1051
1148
|
defaultFont;
|
|
1149
|
+
warnedFonts = /* @__PURE__ */ new Set();
|
|
1052
1150
|
/**
|
|
1053
1151
|
* @param fonts - フォント名 → opentype.js Font オブジェクトのマップ
|
|
1054
1152
|
* @param defaultFont - フォールバックフォント(省略可)
|
|
@@ -1098,6 +1196,14 @@ var OpentypeTextMeasurer = class {
|
|
|
1098
1196
|
if (mapped) {
|
|
1099
1197
|
const mappedFont = this.fonts.get(mapped);
|
|
1100
1198
|
if (mappedFont) return mappedFont;
|
|
1199
|
+
for (const fallback of getCjkFallbackFonts(mapped)) {
|
|
1200
|
+
const fallbackFont = this.fonts.get(fallback);
|
|
1201
|
+
if (fallbackFont) return fallbackFont;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
if (!this.warnedFonts.has(name)) {
|
|
1205
|
+
this.warnedFonts.add(name);
|
|
1206
|
+
warn("font.notFound", `Font not found: "${name}"`);
|
|
1101
1207
|
}
|
|
1102
1208
|
return null;
|
|
1103
1209
|
}
|
|
@@ -1105,19 +1211,31 @@ var OpentypeTextMeasurer = class {
|
|
|
1105
1211
|
|
|
1106
1212
|
// src/font/system-font-loader.ts
|
|
1107
1213
|
var import_node_fs = require("fs");
|
|
1108
|
-
var
|
|
1214
|
+
var import_node_os2 = require("os");
|
|
1109
1215
|
var import_node_path = require("path");
|
|
1110
1216
|
var FONT_EXTENSIONS = /* @__PURE__ */ new Set([".ttf", ".otf"]);
|
|
1111
|
-
var CJK_TTC_PATTERNS = [
|
|
1217
|
+
var CJK_TTC_PATTERNS = [
|
|
1218
|
+
"NotoSansCJK",
|
|
1219
|
+
"NotoSerifCJK",
|
|
1220
|
+
// macOS
|
|
1221
|
+
"Hiragino",
|
|
1222
|
+
"\u30D2\u30E9\u30AE\u30CE",
|
|
1223
|
+
// Windows
|
|
1224
|
+
"YuGoth",
|
|
1225
|
+
"YuMin",
|
|
1226
|
+
"meiryo",
|
|
1227
|
+
"msgothic",
|
|
1228
|
+
"msmincho"
|
|
1229
|
+
];
|
|
1112
1230
|
var cachedPaths = null;
|
|
1113
1231
|
var cachedAdditionalDirs = null;
|
|
1114
1232
|
function getSystemFontDirs() {
|
|
1115
|
-
const os = (0,
|
|
1233
|
+
const os = (0, import_node_os2.platform)();
|
|
1116
1234
|
switch (os) {
|
|
1117
1235
|
case "linux":
|
|
1118
1236
|
return ["/usr/share/fonts", "/usr/local/share/fonts"];
|
|
1119
1237
|
case "darwin":
|
|
1120
|
-
return ["/System/Library/Fonts", "/Library/Fonts", (0, import_node_path.join)((0,
|
|
1238
|
+
return ["/System/Library/Fonts", "/Library/Fonts", (0, import_node_path.join)((0, import_node_os2.homedir)(), "Library/Fonts")];
|
|
1121
1239
|
case "win32":
|
|
1122
1240
|
return ["C:\\Windows\\Fonts"];
|
|
1123
1241
|
default:
|
|
@@ -1125,7 +1243,7 @@ function getSystemFontDirs() {
|
|
|
1125
1243
|
}
|
|
1126
1244
|
}
|
|
1127
1245
|
function isCjkTtc(name) {
|
|
1128
|
-
const lower = name.toLowerCase();
|
|
1246
|
+
const lower = name.normalize("NFC").toLowerCase();
|
|
1129
1247
|
return lower.endsWith(".ttc") && CJK_TTC_PATTERNS.some((p) => lower.includes(p.toLowerCase()));
|
|
1130
1248
|
}
|
|
1131
1249
|
function walk(dir, result) {
|
|
@@ -1163,6 +1281,7 @@ function collectFontFilePaths(additionalDirs) {
|
|
|
1163
1281
|
var DefaultTextPathFontResolver = class {
|
|
1164
1282
|
fonts;
|
|
1165
1283
|
defaultFont;
|
|
1284
|
+
warnedFonts = /* @__PURE__ */ new Set();
|
|
1166
1285
|
constructor(fonts, defaultFont) {
|
|
1167
1286
|
this.fonts = fonts;
|
|
1168
1287
|
this.defaultFont = defaultFont ?? null;
|
|
@@ -1180,6 +1299,12 @@ var DefaultTextPathFontResolver = class {
|
|
|
1180
1299
|
const font = this.findFont(jpanFallback);
|
|
1181
1300
|
if (font) return font;
|
|
1182
1301
|
}
|
|
1302
|
+
for (const name of [fontFamily, fontFamilyEa, jpanFallback]) {
|
|
1303
|
+
if (name && !this.warnedFonts.has(name)) {
|
|
1304
|
+
this.warnedFonts.add(name);
|
|
1305
|
+
warn("font.notFound", `Font not found: "${name}"`);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1183
1308
|
return this.defaultFont;
|
|
1184
1309
|
}
|
|
1185
1310
|
findFont(name) {
|
|
@@ -1189,6 +1314,10 @@ var DefaultTextPathFontResolver = class {
|
|
|
1189
1314
|
if (mapped) {
|
|
1190
1315
|
const mappedFont = this.fonts.get(mapped);
|
|
1191
1316
|
if (mappedFont) return mappedFont;
|
|
1317
|
+
for (const fallback of getCjkFallbackFonts(mapped)) {
|
|
1318
|
+
const fallbackFont = this.fonts.get(fallback);
|
|
1319
|
+
if (fallbackFont) return fallbackFont;
|
|
1320
|
+
}
|
|
1192
1321
|
}
|
|
1193
1322
|
return null;
|
|
1194
1323
|
}
|
|
@@ -1416,7 +1545,23 @@ function collectFontNames(font) {
|
|
|
1416
1545
|
}
|
|
1417
1546
|
return names;
|
|
1418
1547
|
}
|
|
1548
|
+
function buildCacheKey(additionalFontDirs, fontMapping) {
|
|
1549
|
+
const dirsKey = additionalFontDirs ? [...additionalFontDirs].sort().join("\0") : "";
|
|
1550
|
+
const mappingKey = fontMapping ? JSON.stringify(fontMapping, Object.keys(fontMapping).sort()) : "";
|
|
1551
|
+
return `${dirsKey}
|
|
1552
|
+
${mappingKey}`;
|
|
1553
|
+
}
|
|
1554
|
+
var cachedSetup = null;
|
|
1555
|
+
var cachedSetupKey = null;
|
|
1556
|
+
function clearFontCache() {
|
|
1557
|
+
cachedSetup = null;
|
|
1558
|
+
cachedSetupKey = null;
|
|
1559
|
+
}
|
|
1419
1560
|
async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping) {
|
|
1561
|
+
const key = buildCacheKey(additionalFontDirs, fontMapping);
|
|
1562
|
+
if (cachedSetup && cachedSetupKey === key) {
|
|
1563
|
+
return cachedSetup;
|
|
1564
|
+
}
|
|
1420
1565
|
const opentype = await tryLoadOpentype();
|
|
1421
1566
|
if (!opentype) return null;
|
|
1422
1567
|
const fontFilePaths = collectFontFilePaths(additionalFontDirs);
|
|
@@ -1448,7 +1593,10 @@ async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping) {
|
|
|
1448
1593
|
resolverFonts,
|
|
1449
1594
|
firstResolverFont ?? void 0
|
|
1450
1595
|
);
|
|
1451
|
-
|
|
1596
|
+
const setup = { measurer, fontResolver };
|
|
1597
|
+
cachedSetup = setup;
|
|
1598
|
+
cachedSetupKey = key;
|
|
1599
|
+
return setup;
|
|
1452
1600
|
}
|
|
1453
1601
|
|
|
1454
1602
|
// src/font/script-font-context.ts
|
|
@@ -1621,65 +1769,6 @@ async function svgToPng(svgString, options) {
|
|
|
1621
1769
|
};
|
|
1622
1770
|
}
|
|
1623
1771
|
|
|
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
1772
|
// src/color/color-transforms.ts
|
|
1684
1773
|
function applyColorTransforms(color, node) {
|
|
1685
1774
|
let { hex, alpha } = color;
|
|
@@ -8935,6 +9024,7 @@ function collectFontsFromTextBody(textBody, fonts) {
|
|
|
8935
9024
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8936
9025
|
0 && (module.exports = {
|
|
8937
9026
|
DEFAULT_FONT_MAPPING,
|
|
9027
|
+
clearFontCache,
|
|
8938
9028
|
collectUsedFonts,
|
|
8939
9029
|
convertPptxToPng,
|
|
8940
9030
|
convertPptxToSvg,
|
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 - フォールバックフォント(省略可)
|
|
@@ -176,6 +177,12 @@ interface OpentypeSetup {
|
|
|
176
177
|
* 同じ Font オブジェクトを measurer と fontResolver の両方に渡す。
|
|
177
178
|
*/
|
|
178
179
|
declare function createOpentypeSetupFromBuffers(fontBuffers: FontBuffer[], fontMapping?: FontMapping): Promise<OpentypeSetup | null>;
|
|
180
|
+
/**
|
|
181
|
+
* フォントオブジェクトキャッシュをクリアする。
|
|
182
|
+
* 通常は呼び出す必要はないが、フォントのインストール/アンインストール後に
|
|
183
|
+
* 強制的に再読み込みしたい場合に使用する。
|
|
184
|
+
*/
|
|
185
|
+
declare function clearFontCache(): void;
|
|
179
186
|
|
|
180
187
|
/**
|
|
181
188
|
* resvg-wasm の WASM モジュールを初期化する。
|
|
@@ -184,4 +191,4 @@ declare function createOpentypeSetupFromBuffers(fontBuffers: FontBuffer[], fontM
|
|
|
184
191
|
*/
|
|
185
192
|
declare function initResvgWasm(): Promise<void>;
|
|
186
193
|
|
|
187
|
-
export { type ConvertOptions, DEFAULT_FONT_MAPPING, type FontBuffer, type FontMapping, type LogLevel, type OpentypeSetup, type SlideImage, type SlideSvg, type UsedFonts, type WarningEntry, type WarningSummary, collectUsedFonts, convertPptxToPng, convertPptxToSvg, createFontMapping, createOpentypeSetupFromBuffers, createOpentypeTextMeasurerFromBuffers, getMappedFont, getWarningEntries, getWarningSummary, initResvgWasm };
|
|
194
|
+
export { type ConvertOptions, DEFAULT_FONT_MAPPING, type FontBuffer, type FontMapping, type LogLevel, type OpentypeSetup, type SlideImage, type SlideSvg, type UsedFonts, type WarningEntry, type WarningSummary, clearFontCache, collectUsedFonts, convertPptxToPng, convertPptxToSvg, createFontMapping, createOpentypeSetupFromBuffers, createOpentypeTextMeasurerFromBuffers, getMappedFont, getWarningEntries, getWarningSummary, initResvgWasm };
|
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 - フォールバックフォント(省略可)
|
|
@@ -176,6 +177,12 @@ interface OpentypeSetup {
|
|
|
176
177
|
* 同じ Font オブジェクトを measurer と fontResolver の両方に渡す。
|
|
177
178
|
*/
|
|
178
179
|
declare function createOpentypeSetupFromBuffers(fontBuffers: FontBuffer[], fontMapping?: FontMapping): Promise<OpentypeSetup | null>;
|
|
180
|
+
/**
|
|
181
|
+
* フォントオブジェクトキャッシュをクリアする。
|
|
182
|
+
* 通常は呼び出す必要はないが、フォントのインストール/アンインストール後に
|
|
183
|
+
* 強制的に再読み込みしたい場合に使用する。
|
|
184
|
+
*/
|
|
185
|
+
declare function clearFontCache(): void;
|
|
179
186
|
|
|
180
187
|
/**
|
|
181
188
|
* resvg-wasm の WASM モジュールを初期化する。
|
|
@@ -184,4 +191,4 @@ declare function createOpentypeSetupFromBuffers(fontBuffers: FontBuffer[], fontM
|
|
|
184
191
|
*/
|
|
185
192
|
declare function initResvgWasm(): Promise<void>;
|
|
186
193
|
|
|
187
|
-
export { type ConvertOptions, DEFAULT_FONT_MAPPING, type FontBuffer, type FontMapping, type LogLevel, type OpentypeSetup, type SlideImage, type SlideSvg, type UsedFonts, type WarningEntry, type WarningSummary, collectUsedFonts, convertPptxToPng, convertPptxToSvg, createFontMapping, createOpentypeSetupFromBuffers, createOpentypeTextMeasurerFromBuffers, getMappedFont, getWarningEntries, getWarningSummary, initResvgWasm };
|
|
194
|
+
export { type ConvertOptions, DEFAULT_FONT_MAPPING, type FontBuffer, type FontMapping, type LogLevel, type OpentypeSetup, type SlideImage, type SlideSvg, type UsedFonts, type WarningEntry, type WarningSummary, clearFontCache, collectUsedFonts, convertPptxToPng, convertPptxToSvg, createFontMapping, createOpentypeSetupFromBuffers, createOpentypeTextMeasurerFromBuffers, getMappedFont, getWarningEntries, getWarningSummary, initResvgWasm };
|
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 = [
|
|
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 =
|
|
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
|
}
|
|
@@ -1380,7 +1508,23 @@ function collectFontNames(font) {
|
|
|
1380
1508
|
}
|
|
1381
1509
|
return names;
|
|
1382
1510
|
}
|
|
1511
|
+
function buildCacheKey(additionalFontDirs, fontMapping) {
|
|
1512
|
+
const dirsKey = additionalFontDirs ? [...additionalFontDirs].sort().join("\0") : "";
|
|
1513
|
+
const mappingKey = fontMapping ? JSON.stringify(fontMapping, Object.keys(fontMapping).sort()) : "";
|
|
1514
|
+
return `${dirsKey}
|
|
1515
|
+
${mappingKey}`;
|
|
1516
|
+
}
|
|
1517
|
+
var cachedSetup = null;
|
|
1518
|
+
var cachedSetupKey = null;
|
|
1519
|
+
function clearFontCache() {
|
|
1520
|
+
cachedSetup = null;
|
|
1521
|
+
cachedSetupKey = null;
|
|
1522
|
+
}
|
|
1383
1523
|
async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping) {
|
|
1524
|
+
const key = buildCacheKey(additionalFontDirs, fontMapping);
|
|
1525
|
+
if (cachedSetup && cachedSetupKey === key) {
|
|
1526
|
+
return cachedSetup;
|
|
1527
|
+
}
|
|
1384
1528
|
const opentype = await tryLoadOpentype();
|
|
1385
1529
|
if (!opentype) return null;
|
|
1386
1530
|
const fontFilePaths = collectFontFilePaths(additionalFontDirs);
|
|
@@ -1412,7 +1556,10 @@ async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping) {
|
|
|
1412
1556
|
resolverFonts,
|
|
1413
1557
|
firstResolverFont ?? void 0
|
|
1414
1558
|
);
|
|
1415
|
-
|
|
1559
|
+
const setup = { measurer, fontResolver };
|
|
1560
|
+
cachedSetup = setup;
|
|
1561
|
+
cachedSetupKey = key;
|
|
1562
|
+
return setup;
|
|
1416
1563
|
}
|
|
1417
1564
|
|
|
1418
1565
|
// src/font/script-font-context.ts
|
|
@@ -1584,65 +1731,6 @@ async function svgToPng(svgString, options) {
|
|
|
1584
1731
|
};
|
|
1585
1732
|
}
|
|
1586
1733
|
|
|
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
1734
|
// src/color/color-transforms.ts
|
|
1647
1735
|
function applyColorTransforms(color, node) {
|
|
1648
1736
|
let { hex, alpha } = color;
|
|
@@ -8897,6 +8985,7 @@ function collectFontsFromTextBody(textBody, fonts) {
|
|
|
8897
8985
|
}
|
|
8898
8986
|
export {
|
|
8899
8987
|
DEFAULT_FONT_MAPPING,
|
|
8988
|
+
clearFontCache,
|
|
8900
8989
|
collectUsedFonts,
|
|
8901
8990
|
convertPptxToPng,
|
|
8902
8991
|
convertPptxToSvg,
|
package/package.json
CHANGED