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