diff --git a/bin/html2pptx.js b/bin/html2pptx.js
index d2ea7b0..7d78f42 100644
--- a/bin/html2pptx.js
+++ b/bin/html2pptx.js
@@ -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, {