fix: 修复slide分割/文字聚合/字号计算三个缺陷
This commit is contained in:
+35
-26
@@ -154,9 +154,17 @@ async function main() {
|
|||||||
// ------ 3. DOM extraction (in-browser) ------
|
// ------ 3. DOM extraction (in-browser) ------
|
||||||
const slidesData = await page.evaluate(() => {
|
const slidesData = await page.evaluate(() => {
|
||||||
// ----- Slide detection -----
|
// ----- Slide detection -----
|
||||||
let slides = document.querySelectorAll(
|
var slides;
|
||||||
|
// DashiAI format: .ppt-deck > .ppt-slide
|
||||||
|
var deck = document.querySelector('.ppt-deck');
|
||||||
|
if (deck) {
|
||||||
|
slides = deck.querySelectorAll('.ppt-slide');
|
||||||
|
}
|
||||||
|
if (!slides || slides.length <= 1) {
|
||||||
|
slides = document.querySelectorAll(
|
||||||
'section[data-slide], section.slide, section'
|
'section[data-slide], section.slide, section'
|
||||||
);
|
);
|
||||||
|
}
|
||||||
if (slides.length <= 1) {
|
if (slides.length <= 1) {
|
||||||
slides = document.querySelectorAll('[data-slide]');
|
slides = document.querySelectorAll('[data-slide]');
|
||||||
}
|
}
|
||||||
@@ -165,40 +173,42 @@ async function main() {
|
|||||||
return r.width > 0 && r.height > 0;
|
return r.width > 0 && r.height > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tags that are purely structural containers — skip when they have no direct text
|
// Tags whose full text content should be a single text box
|
||||||
var CONTAINER_TAGS = new Set([
|
var TEXT_BLOCK_TAGS = new Set([
|
||||||
'div', 'section', 'ul', 'ol', 'nav', 'header', 'footer',
|
'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||||
'main', 'aside', 'article', 'form', 'fieldset', 'table',
|
'li', 'td', 'th', 'blockquote', 'figcaption', 'dt', 'dd', 'caption',
|
||||||
'thead', 'tbody', 'tfoot', 'tr', 'figure',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function hasDirectText(el) {
|
|
||||||
var nodes = el.childNodes;
|
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
|
||||||
if (nodes[i].nodeType === 3 && nodes[i].textContent.trim()) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return slides.map(function (slide) {
|
return slides.map(function (slide) {
|
||||||
var slideRect = slide.getBoundingClientRect();
|
var slideRect = slide.getBoundingClientRect();
|
||||||
var allEls = slide.querySelectorAll('*');
|
|
||||||
var elements = [];
|
var elements = [];
|
||||||
|
|
||||||
for (var i = 0; i < allEls.length; i++) {
|
// Collect block-level text containers; each becomes one text box
|
||||||
var el = allEls[i];
|
var textBlocks = slide.querySelectorAll(
|
||||||
|
'p, h1, h2, h3, h4, h5, h6, li, td, th, blockquote, ' +
|
||||||
|
'figcaption, dt, dd, caption'
|
||||||
|
);
|
||||||
|
|
||||||
|
for (var i = 0; i < textBlocks.length; i++) {
|
||||||
|
var el = textBlocks[i];
|
||||||
|
// Skip if this block is nested inside another text block (e.g. li inside another li)
|
||||||
|
var parent = el.parentElement;
|
||||||
|
var skip = false;
|
||||||
|
while (parent && parent !== slide) {
|
||||||
|
if (TEXT_BLOCK_TAGS.has(parent.tagName.toLowerCase())) {
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
|
||||||
var text = (el.textContent || '').trim();
|
var text = (el.textContent || '').trim();
|
||||||
if (!text) continue;
|
if (!text) continue;
|
||||||
|
|
||||||
var rect = el.getBoundingClientRect();
|
var rect = el.getBoundingClientRect();
|
||||||
if (rect.width === 0 || rect.height === 0) continue;
|
if (rect.width === 0 || rect.height === 0) continue;
|
||||||
|
|
||||||
var tag = el.tagName.toLowerCase();
|
|
||||||
var directText = hasDirectText(el);
|
|
||||||
|
|
||||||
// Skip structural containers that have no direct text (e.g. wrapper divs)
|
|
||||||
if (CONTAINER_TAGS.has(tag) && !directText) continue;
|
|
||||||
|
|
||||||
var style = window.getComputedStyle(el);
|
var style = window.getComputedStyle(el);
|
||||||
|
|
||||||
elements.push({
|
elements.push({
|
||||||
@@ -271,9 +281,8 @@ async function main() {
|
|||||||
var w = Math.max(el.width * scaleX, 0.3);
|
var w = Math.max(el.width * scaleX, 0.3);
|
||||||
var h = Math.max(el.height * scaleY, 0.2);
|
var h = Math.max(el.height * scaleY, 0.2);
|
||||||
|
|
||||||
// Font size: proportional to slide height
|
// Font size: CSS px → pt (1pt = 1/72in, CSS 1px = 1/96in, so px × 72/96 = pt)
|
||||||
// CSS px → inches at 96dpi → scaled to PPTX slide height → pt (/72 inches per pt)
|
var fontSize = el.fontSize * 72 / 96;
|
||||||
var fontSize = el.fontSize * scaleY * 72;
|
|
||||||
fontSize = Math.max(fontSize, 8);
|
fontSize = Math.max(fontSize, 8);
|
||||||
|
|
||||||
slide.addText(t, {
|
slide.addText(t, {
|
||||||
|
|||||||
Reference in New Issue
Block a user