pptx-glimpse 0.10.3 → 0.11.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/README.md +2 -1
- package/dist/index.cjs +28 -13
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +28 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -81,6 +81,7 @@ const results = await convertPptxToPng(pptx, {
|
|
|
81
81
|
height: 1080, // Output height in pixels (width takes priority if both set)
|
|
82
82
|
logLevel: "warn", // Warning log level: "off" | "warn" | "debug"
|
|
83
83
|
fontDirs: ["/custom/fonts"], // Additional font directories to search
|
|
84
|
+
skipSystemFonts: true, // Skip OS system font directories; use fontDirs only
|
|
84
85
|
fontMapping: {
|
|
85
86
|
"Custom Corp Font": "Noto Sans", // Custom font name mapping
|
|
86
87
|
},
|
|
@@ -154,7 +155,7 @@ Default system font directories:
|
|
|
154
155
|
| macOS | `/System/Library/Fonts`, `/Library/Fonts`, `~/Library/Fonts` |
|
|
155
156
|
| Windows | `C:\Windows\Fonts` |
|
|
156
157
|
|
|
157
|
-
Use the `fontDirs` option to add custom font directories.
|
|
158
|
+
Use the `fontDirs` option to add custom font directories. To skip system font scanning entirely and use only `fontDirs` (useful in containers, serverless environments, or when you want to bundle specific fonts to reduce startup time), set `skipSystemFonts: true`.
|
|
158
159
|
|
|
159
160
|
### Font Mapping
|
|
160
161
|
|
package/dist/index.cjs
CHANGED
|
@@ -1229,6 +1229,7 @@ var CJK_TTC_PATTERNS = [
|
|
|
1229
1229
|
];
|
|
1230
1230
|
var cachedPaths = null;
|
|
1231
1231
|
var cachedAdditionalDirs = null;
|
|
1232
|
+
var cachedSkipSystemFonts = null;
|
|
1232
1233
|
function getSystemFontDirs() {
|
|
1233
1234
|
const os = (0, import_node_os2.platform)();
|
|
1234
1235
|
switch (os) {
|
|
@@ -1260,20 +1261,21 @@ function walk(dir, result) {
|
|
|
1260
1261
|
} catch {
|
|
1261
1262
|
}
|
|
1262
1263
|
}
|
|
1263
|
-
function collectFontFilePaths(additionalDirs) {
|
|
1264
|
+
function collectFontFilePaths(additionalDirs, skipSystemFonts = false) {
|
|
1264
1265
|
const dirs = additionalDirs ?? [];
|
|
1265
1266
|
const dirsKey = dirs.join("\0");
|
|
1266
1267
|
const cachedKey = cachedAdditionalDirs?.join("\0") ?? null;
|
|
1267
|
-
if (cachedPaths !== null && dirsKey === cachedKey) {
|
|
1268
|
+
if (cachedPaths !== null && dirsKey === cachedKey && cachedSkipSystemFonts === skipSystemFonts) {
|
|
1268
1269
|
return cachedPaths;
|
|
1269
1270
|
}
|
|
1270
|
-
const allDirs = [...getSystemFontDirs(), ...dirs];
|
|
1271
|
+
const allDirs = skipSystemFonts ? dirs : [...getSystemFontDirs(), ...dirs];
|
|
1271
1272
|
const result = [];
|
|
1272
1273
|
for (const dir of allDirs) {
|
|
1273
1274
|
walk(dir, result);
|
|
1274
1275
|
}
|
|
1275
1276
|
cachedPaths = result;
|
|
1276
1277
|
cachedAdditionalDirs = dirs;
|
|
1278
|
+
cachedSkipSystemFonts = skipSystemFonts;
|
|
1277
1279
|
return result;
|
|
1278
1280
|
}
|
|
1279
1281
|
|
|
@@ -1545,11 +1547,12 @@ function collectFontNames(font) {
|
|
|
1545
1547
|
}
|
|
1546
1548
|
return names;
|
|
1547
1549
|
}
|
|
1548
|
-
function buildCacheKey(additionalFontDirs, fontMapping) {
|
|
1550
|
+
function buildCacheKey(additionalFontDirs, fontMapping, skipSystemFonts = false) {
|
|
1549
1551
|
const dirsKey = additionalFontDirs ? [...additionalFontDirs].sort().join("\0") : "";
|
|
1550
1552
|
const mappingKey = fontMapping ? JSON.stringify(fontMapping, Object.keys(fontMapping).sort()) : "";
|
|
1551
1553
|
return `${dirsKey}
|
|
1552
|
-
${mappingKey}
|
|
1554
|
+
${mappingKey}
|
|
1555
|
+
${skipSystemFonts}`;
|
|
1553
1556
|
}
|
|
1554
1557
|
var cachedSetup = null;
|
|
1555
1558
|
var cachedSetupKey = null;
|
|
@@ -1557,14 +1560,14 @@ function clearFontCache() {
|
|
|
1557
1560
|
cachedSetup = null;
|
|
1558
1561
|
cachedSetupKey = null;
|
|
1559
1562
|
}
|
|
1560
|
-
async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping) {
|
|
1561
|
-
const key = buildCacheKey(additionalFontDirs, fontMapping);
|
|
1563
|
+
async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping, skipSystemFonts = false) {
|
|
1564
|
+
const key = buildCacheKey(additionalFontDirs, fontMapping, skipSystemFonts);
|
|
1562
1565
|
if (cachedSetup && cachedSetupKey === key) {
|
|
1563
1566
|
return cachedSetup;
|
|
1564
1567
|
}
|
|
1565
1568
|
const opentype = await tryLoadOpentype();
|
|
1566
1569
|
if (!opentype) return null;
|
|
1567
|
-
const fontFilePaths = collectFontFilePaths(additionalFontDirs);
|
|
1570
|
+
const fontFilePaths = collectFontFilePaths(additionalFontDirs, skipSystemFonts);
|
|
1568
1571
|
if (fontFilePaths.length === 0) return null;
|
|
1569
1572
|
const mapping = createFontMapping(fontMapping);
|
|
1570
1573
|
const reverseMap = buildReverseMapping(mapping);
|
|
@@ -9113,7 +9116,11 @@ function escapeXmlAttr(str) {
|
|
|
9113
9116
|
|
|
9114
9117
|
// src/converter.ts
|
|
9115
9118
|
async function convertPptxToSvg(input, options) {
|
|
9116
|
-
const setup = await createOpentypeSetupFromSystem(
|
|
9119
|
+
const setup = await createOpentypeSetupFromSystem(
|
|
9120
|
+
options?.fontDirs,
|
|
9121
|
+
options?.fontMapping,
|
|
9122
|
+
options?.skipSystemFonts
|
|
9123
|
+
);
|
|
9117
9124
|
if (setup) {
|
|
9118
9125
|
setTextMeasurer(setup.measurer);
|
|
9119
9126
|
setTextPathFontResolver(setup.fontResolver);
|
|
@@ -9165,13 +9172,21 @@ async function convertPptxToPng(input, options) {
|
|
|
9165
9172
|
return results;
|
|
9166
9173
|
}
|
|
9167
9174
|
function mergeElements(masterElements, layoutElements, slideElements) {
|
|
9168
|
-
const
|
|
9175
|
+
const filterTemplatePlaceholders = (elements) => elements.filter((el) => {
|
|
9169
9176
|
if (el.type !== "shape") return true;
|
|
9170
9177
|
return !el.placeholderType;
|
|
9171
9178
|
});
|
|
9172
|
-
const
|
|
9173
|
-
const
|
|
9174
|
-
|
|
9179
|
+
const filterEmptySlidePlaceholders = (elements) => elements.filter((el) => !(el.type === "shape" && isEmptyPlaceholder(el)));
|
|
9180
|
+
const filteredMaster = filterTemplatePlaceholders(masterElements);
|
|
9181
|
+
const filteredLayout = filterTemplatePlaceholders(layoutElements);
|
|
9182
|
+
const filteredSlide = filterEmptySlidePlaceholders(slideElements);
|
|
9183
|
+
return [...filteredMaster, ...filteredLayout, ...filteredSlide];
|
|
9184
|
+
}
|
|
9185
|
+
function isEmptyPlaceholder(shape) {
|
|
9186
|
+
if (!shape.placeholderType) return false;
|
|
9187
|
+
const paragraphs = shape.textBody?.paragraphs;
|
|
9188
|
+
if (!paragraphs || paragraphs.length === 0) return true;
|
|
9189
|
+
return !paragraphs.some((p) => p.runs.some((r) => r.text.length > 0));
|
|
9175
9190
|
}
|
|
9176
9191
|
|
|
9177
9192
|
// src/font/font-collector.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -46,6 +46,8 @@ interface ConvertOptions {
|
|
|
46
46
|
fontDirs?: string[];
|
|
47
47
|
/** PPTX フォント名 → OSS 代替フォントのカスタムマッピング。デフォルトマッピングにマージされる */
|
|
48
48
|
fontMapping?: FontMapping;
|
|
49
|
+
/** true のとき OS のシステムフォントをスキャンせず fontDirs のみを使用する */
|
|
50
|
+
skipSystemFonts?: boolean;
|
|
49
51
|
}
|
|
50
52
|
interface SlideSvg {
|
|
51
53
|
slideNumber: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ interface ConvertOptions {
|
|
|
46
46
|
fontDirs?: string[];
|
|
47
47
|
/** PPTX フォント名 → OSS 代替フォントのカスタムマッピング。デフォルトマッピングにマージされる */
|
|
48
48
|
fontMapping?: FontMapping;
|
|
49
|
+
/** true のとき OS のシステムフォントをスキャンせず fontDirs のみを使用する */
|
|
50
|
+
skipSystemFonts?: boolean;
|
|
49
51
|
}
|
|
50
52
|
interface SlideSvg {
|
|
51
53
|
slideNumber: number;
|
package/dist/index.js
CHANGED
|
@@ -1192,6 +1192,7 @@ var CJK_TTC_PATTERNS = [
|
|
|
1192
1192
|
];
|
|
1193
1193
|
var cachedPaths = null;
|
|
1194
1194
|
var cachedAdditionalDirs = null;
|
|
1195
|
+
var cachedSkipSystemFonts = null;
|
|
1195
1196
|
function getSystemFontDirs() {
|
|
1196
1197
|
const os = platform2();
|
|
1197
1198
|
switch (os) {
|
|
@@ -1223,20 +1224,21 @@ function walk(dir, result) {
|
|
|
1223
1224
|
} catch {
|
|
1224
1225
|
}
|
|
1225
1226
|
}
|
|
1226
|
-
function collectFontFilePaths(additionalDirs) {
|
|
1227
|
+
function collectFontFilePaths(additionalDirs, skipSystemFonts = false) {
|
|
1227
1228
|
const dirs = additionalDirs ?? [];
|
|
1228
1229
|
const dirsKey = dirs.join("\0");
|
|
1229
1230
|
const cachedKey = cachedAdditionalDirs?.join("\0") ?? null;
|
|
1230
|
-
if (cachedPaths !== null && dirsKey === cachedKey) {
|
|
1231
|
+
if (cachedPaths !== null && dirsKey === cachedKey && cachedSkipSystemFonts === skipSystemFonts) {
|
|
1231
1232
|
return cachedPaths;
|
|
1232
1233
|
}
|
|
1233
|
-
const allDirs = [...getSystemFontDirs(), ...dirs];
|
|
1234
|
+
const allDirs = skipSystemFonts ? dirs : [...getSystemFontDirs(), ...dirs];
|
|
1234
1235
|
const result = [];
|
|
1235
1236
|
for (const dir of allDirs) {
|
|
1236
1237
|
walk(dir, result);
|
|
1237
1238
|
}
|
|
1238
1239
|
cachedPaths = result;
|
|
1239
1240
|
cachedAdditionalDirs = dirs;
|
|
1241
|
+
cachedSkipSystemFonts = skipSystemFonts;
|
|
1240
1242
|
return result;
|
|
1241
1243
|
}
|
|
1242
1244
|
|
|
@@ -1508,11 +1510,12 @@ function collectFontNames(font) {
|
|
|
1508
1510
|
}
|
|
1509
1511
|
return names;
|
|
1510
1512
|
}
|
|
1511
|
-
function buildCacheKey(additionalFontDirs, fontMapping) {
|
|
1513
|
+
function buildCacheKey(additionalFontDirs, fontMapping, skipSystemFonts = false) {
|
|
1512
1514
|
const dirsKey = additionalFontDirs ? [...additionalFontDirs].sort().join("\0") : "";
|
|
1513
1515
|
const mappingKey = fontMapping ? JSON.stringify(fontMapping, Object.keys(fontMapping).sort()) : "";
|
|
1514
1516
|
return `${dirsKey}
|
|
1515
|
-
${mappingKey}
|
|
1517
|
+
${mappingKey}
|
|
1518
|
+
${skipSystemFonts}`;
|
|
1516
1519
|
}
|
|
1517
1520
|
var cachedSetup = null;
|
|
1518
1521
|
var cachedSetupKey = null;
|
|
@@ -1520,14 +1523,14 @@ function clearFontCache() {
|
|
|
1520
1523
|
cachedSetup = null;
|
|
1521
1524
|
cachedSetupKey = null;
|
|
1522
1525
|
}
|
|
1523
|
-
async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping) {
|
|
1524
|
-
const key = buildCacheKey(additionalFontDirs, fontMapping);
|
|
1526
|
+
async function createOpentypeSetupFromSystem(additionalFontDirs, fontMapping, skipSystemFonts = false) {
|
|
1527
|
+
const key = buildCacheKey(additionalFontDirs, fontMapping, skipSystemFonts);
|
|
1525
1528
|
if (cachedSetup && cachedSetupKey === key) {
|
|
1526
1529
|
return cachedSetup;
|
|
1527
1530
|
}
|
|
1528
1531
|
const opentype = await tryLoadOpentype();
|
|
1529
1532
|
if (!opentype) return null;
|
|
1530
|
-
const fontFilePaths = collectFontFilePaths(additionalFontDirs);
|
|
1533
|
+
const fontFilePaths = collectFontFilePaths(additionalFontDirs, skipSystemFonts);
|
|
1531
1534
|
if (fontFilePaths.length === 0) return null;
|
|
1532
1535
|
const mapping = createFontMapping(fontMapping);
|
|
1533
1536
|
const reverseMap = buildReverseMapping(mapping);
|
|
@@ -9075,7 +9078,11 @@ function escapeXmlAttr(str) {
|
|
|
9075
9078
|
|
|
9076
9079
|
// src/converter.ts
|
|
9077
9080
|
async function convertPptxToSvg(input, options) {
|
|
9078
|
-
const setup = await createOpentypeSetupFromSystem(
|
|
9081
|
+
const setup = await createOpentypeSetupFromSystem(
|
|
9082
|
+
options?.fontDirs,
|
|
9083
|
+
options?.fontMapping,
|
|
9084
|
+
options?.skipSystemFonts
|
|
9085
|
+
);
|
|
9079
9086
|
if (setup) {
|
|
9080
9087
|
setTextMeasurer(setup.measurer);
|
|
9081
9088
|
setTextPathFontResolver(setup.fontResolver);
|
|
@@ -9127,13 +9134,21 @@ async function convertPptxToPng(input, options) {
|
|
|
9127
9134
|
return results;
|
|
9128
9135
|
}
|
|
9129
9136
|
function mergeElements(masterElements, layoutElements, slideElements) {
|
|
9130
|
-
const
|
|
9137
|
+
const filterTemplatePlaceholders = (elements) => elements.filter((el) => {
|
|
9131
9138
|
if (el.type !== "shape") return true;
|
|
9132
9139
|
return !el.placeholderType;
|
|
9133
9140
|
});
|
|
9134
|
-
const
|
|
9135
|
-
const
|
|
9136
|
-
|
|
9141
|
+
const filterEmptySlidePlaceholders = (elements) => elements.filter((el) => !(el.type === "shape" && isEmptyPlaceholder(el)));
|
|
9142
|
+
const filteredMaster = filterTemplatePlaceholders(masterElements);
|
|
9143
|
+
const filteredLayout = filterTemplatePlaceholders(layoutElements);
|
|
9144
|
+
const filteredSlide = filterEmptySlidePlaceholders(slideElements);
|
|
9145
|
+
return [...filteredMaster, ...filteredLayout, ...filteredSlide];
|
|
9146
|
+
}
|
|
9147
|
+
function isEmptyPlaceholder(shape) {
|
|
9148
|
+
if (!shape.placeholderType) return false;
|
|
9149
|
+
const paragraphs = shape.textBody?.paragraphs;
|
|
9150
|
+
if (!paragraphs || paragraphs.length === 0) return true;
|
|
9151
|
+
return !paragraphs.some((p) => p.runs.some((r) => r.text.length > 0));
|
|
9137
9152
|
}
|
|
9138
9153
|
|
|
9139
9154
|
// src/font/font-collector.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptx-glimpse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"license": "MIT",
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@resvg/resvg-wasm": "^2.6.2",
|
|
68
|
-
"fast-xml-parser": "^5.3
|
|
68
|
+
"fast-xml-parser": "^5.7.3",
|
|
69
69
|
"fflate": "^0.8.2",
|
|
70
70
|
"opentype.js": "^1.3.4"
|
|
71
71
|
},
|