feat: jszip 后处理注入 type=custom + 画布高度限制140cm
- 用 jszip 原地修改 PPTX 的 sldSz,加 type=custom(WPS 识别自定义尺寸) - 画布最大高度限制 140cm(WPS 上限) - zip 命令行打包会破坏 PPTX 结构,改用 jszip 保证完整性
This commit is contained in:
+27
-2
@@ -932,16 +932,18 @@ async function convert(input) {
|
|||||||
// 第三步:组装最终 Schema
|
// 第三步:组装最终 Schema
|
||||||
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
||||||
// 画布尺寸:多 slide(PPT设计稿)用容器尺寸,单 slide(网页)用 canvas
|
// 画布尺寸:多 slide(PPT设计稿)用容器尺寸,单 slide(网页)用 canvas
|
||||||
|
// 限制最大高度 140cm(WPS 上限约140cm)
|
||||||
|
const MAX_H_IN = 55.12; // 140cm
|
||||||
let layout = 'LAYOUT_16x9';
|
let layout = 'LAYOUT_16x9';
|
||||||
var sizeSource;
|
var sizeSource;
|
||||||
if (slideGroups.length > 1) {
|
if (slideGroups.length > 1) {
|
||||||
sizeSource = slideGroups[0].slideRect;
|
sizeSource = slideGroups[0].slideRect;
|
||||||
} else {
|
} else {
|
||||||
sizeSource = { w: canvas.width || 1920, h: canvas.height || 1080 };
|
sizeSource = { w: canvas.width || 1920, h: Math.min(canvas.height || 1080, MAX_H_IN * 72) };
|
||||||
}
|
}
|
||||||
if (sizeSource.w && sizeSource.h) {
|
if (sizeSource.w && sizeSource.h) {
|
||||||
const sw = sizeSource.w / 72;
|
const sw = sizeSource.w / 72;
|
||||||
const sh = sizeSource.h / 72;
|
const sh = Math.min(sizeSource.h / 72, MAX_H_IN);
|
||||||
layout = 'CUSTOM';
|
layout = 'CUSTOM';
|
||||||
return {
|
return {
|
||||||
presentation: { layout: 'CUSTOM', slideWidth: sw, slideHeight: sh },
|
presentation: { layout: 'CUSTOM', slideWidth: sw, slideHeight: sh },
|
||||||
@@ -1046,7 +1048,30 @@ if (require.main === module) {
|
|||||||
|
|
||||||
const pptxPath = inputPath.replace(/\.json$/, '.pptx');
|
const pptxPath = inputPath.replace(/\.json$/, '.pptx');
|
||||||
pres.writeFile({ fileName: pptxPath }).then(() => {
|
pres.writeFile({ fileName: pptxPath }).then(() => {
|
||||||
|
// 后处理:给 sldSz 加 type="custom",确保 WPS 等应用识别自定义尺寸
|
||||||
|
try {
|
||||||
|
const JSZip = require('jszip');
|
||||||
|
const zipData = fs.readFileSync(pptxPath);
|
||||||
|
JSZip.loadAsync(zipData).then(function(zip) {
|
||||||
|
return zip.file('ppt/presentation.xml').async('string');
|
||||||
|
}).then(function(presXml) {
|
||||||
|
if (presXml.includes('sldSz') && !presXml.includes('type="custom"')) {
|
||||||
|
var fixed = presXml.replace(/sldSz cx="([^"]*)" cy="([^"]*)"/, 'sldSz cx="$1" cy="$2" type="custom"');
|
||||||
|
return JSZip.loadAsync(zipData).then(function(zip) {
|
||||||
|
zip.file('ppt/presentation.xml', fixed);
|
||||||
|
return zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
|
||||||
|
}).then(function(buf) {
|
||||||
|
fs.writeFileSync(pptxPath, buf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).then(function() {
|
||||||
console.log('✅ PPTX: ' + pptxPath);
|
console.log('✅ PPTX: ' + pptxPath);
|
||||||
|
}).catch(function(e) {
|
||||||
|
console.log('✅ PPTX: ' + pptxPath + ' (后处理跳过)');
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log('✅ PPTX: ' + pptxPath + ' (后处理跳过)');
|
||||||
|
}
|
||||||
}).catch(e => console.error('❌ PPTX 渲染失败:', e.message));
|
}).catch(e => console.error('❌ PPTX 渲染失败:', e.message));
|
||||||
|
|
||||||
fs.writeFileSync(outputPath, JSON.stringify(result, null, 2), 'utf8');
|
fs.writeFileSync(outputPath, JSON.stringify(result, null, 2), 'utf8');
|
||||||
|
|||||||
Reference in New Issue
Block a user