make-slide 2.1.1 → 2.2.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.
|
@@ -111,15 +111,16 @@ Ask the user which image approach they prefer:
|
|
|
111
111
|
|
|
112
112
|
- **Option A** → Use CSS placeholders matching the theme (emoji, SVG icons, CSS shapes)
|
|
113
113
|
- **Option B** → Mark image positions in the outline, ask user for URLs, use `<img src>` with `loading="lazy"` and descriptive `alt` text
|
|
114
|
-
- **Option C** →
|
|
115
|
-
1.
|
|
116
|
-
2.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
5.
|
|
122
|
-
6.
|
|
114
|
+
- **Option C** → Automatically search and place images, but be selective:
|
|
115
|
+
1. NOT every slide needs an image. Only add images to slides where a visual genuinely enhances understanding (e.g., concept slides, example slides, section dividers). Skip images for quote slides, code slides, data/chart slides, comparison slides, and agenda slides.
|
|
116
|
+
2. Aim for roughly 30-40% of slides having images — not all of them.
|
|
117
|
+
3. Determine a relevant English search keyword based on the slide content.
|
|
118
|
+
4. Use Unsplash direct photo URLs: `https://images.unsplash.com/photo-{PHOTO_ID}?w=800&h=600&fit=crop`
|
|
119
|
+
- To find valid photo IDs, search the web for `site:unsplash.com {keyword}` and extract the photo ID from the URL.
|
|
120
|
+
- NEVER guess or fabricate Unsplash photo IDs — every URL must come from an actual search result.
|
|
121
|
+
5. After collecting image URLs, verify each one actually returns an image (HTTP 200) before inserting. Replace any 404 URLs with CSS placeholders.
|
|
122
|
+
6. Insert as `<img src="URL" alt="description" loading="lazy">`
|
|
123
|
+
7. Inform the user that images are from Unsplash (Unsplash License, free for commercial use).
|
|
123
124
|
|
|
124
125
|
### Step 4: Generate Outline
|
|
125
126
|
Create a slide-by-slide outline with:
|
|
@@ -188,13 +189,42 @@ When the user selects PPTX output, follow this modified workflow:
|
|
|
188
189
|
Follow the standard HTML generation workflow (Steps 1-7) but with these constraints from the PPTX spec. Read `references/pptx-spec.md` for the complete PPTX conversion rules before generating HTML.
|
|
189
190
|
|
|
190
191
|
### PPTX Step 2: Convert HTML to PPTX
|
|
191
|
-
Use the
|
|
192
|
-
1. Install dependencies if not present: `npm install pptxgenjs
|
|
193
|
-
2.
|
|
194
|
-
|
|
192
|
+
Use the screenshot-based conversion pipeline with Puppeteer + PptxGenJS:
|
|
193
|
+
1. Install dependencies if not present: `npm install pptxgenjs puppeteer`
|
|
194
|
+
2. Write a conversion script that:
|
|
195
|
+
- Opens the HTML file in a headless browser with viewport 1280×720 (16:9)
|
|
196
|
+
- For EACH slide:
|
|
197
|
+
a. Navigate to that slide (set it as active, remove active class from others)
|
|
198
|
+
b. **Wait for ALL animations to complete** — add a delay of at least 1000ms after activating the slide, or better: disable all CSS animations/transitions before capturing by injecting `* { animation: none !important; transition: none !important; }`
|
|
199
|
+
c. **Hide all other slides completely** — ensure only the current slide is visible (opacity:1, display:flex) and all others are hidden (opacity:0, display:none). This prevents ghost/residue from previous slides.
|
|
200
|
+
d. Take a full-page screenshot of the viewport at **2x resolution** (deviceScaleFactor: 2) for crisp text
|
|
201
|
+
- Insert each screenshot into PPTX as a **full-slide image** covering the entire slide area (x:0, y:0, w:'100%', h:'100%')
|
|
202
|
+
- Do NOT add margins or padding around the image — it should fill the entire slide
|
|
203
|
+
3. Save as `.pptx`
|
|
204
|
+
|
|
205
|
+
**Critical: Preventing ghost slides and small content**
|
|
206
|
+
```javascript
|
|
207
|
+
// Before each screenshot, inject this CSS to disable animations
|
|
208
|
+
await page.addStyleTag({ content: '*, *::before, *::after { animation: none !important; transition: none !important; animation-delay: 0s !important; }' });
|
|
209
|
+
|
|
210
|
+
// Hide all slides, then show only current
|
|
211
|
+
await page.evaluate((idx) => {
|
|
212
|
+
document.querySelectorAll('.slide').forEach((s, i) => {
|
|
213
|
+
s.style.display = i === idx ? 'flex' : 'none';
|
|
214
|
+
s.style.opacity = i === idx ? '1' : '0';
|
|
215
|
+
s.classList.toggle('active', i === idx);
|
|
216
|
+
});
|
|
217
|
+
}, slideIndex);
|
|
218
|
+
|
|
219
|
+
// Wait for layout to settle
|
|
220
|
+
await new Promise(r => setTimeout(r, 500));
|
|
221
|
+
|
|
222
|
+
// Screenshot at 2x for crisp text
|
|
223
|
+
await page.screenshot({ path: outputPath, type: 'png' });
|
|
224
|
+
```
|
|
195
225
|
|
|
196
226
|
### PPTX Step 3: Validate and Deliver
|
|
197
|
-
-
|
|
227
|
+
- Verify the PPTX opens correctly and content fills each slide without excess margins
|
|
198
228
|
- Save as `presentation.pptx` (or user-specified filename)
|
|
199
229
|
- Offer to also generate the HTML version for preview
|
|
200
230
|
|
|
@@ -80,17 +80,64 @@ Workflow:
|
|
|
80
80
|
- `<img>` → `add_picture()`
|
|
81
81
|
4. Save as .pptx
|
|
82
82
|
|
|
83
|
-
### Method 3: Screenshot-based (
|
|
83
|
+
### Method 3: Screenshot-based (Recommended for visual fidelity)
|
|
84
84
|
```bash
|
|
85
85
|
npm install puppeteer pptxgenjs
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
This is the recommended method when using make-slide themes, because it preserves the exact visual design including custom fonts, gradients, and complex layouts.
|
|
89
|
+
|
|
88
90
|
Workflow:
|
|
89
91
|
1. Generate full HTML presentation (standard mode, no PPTX constraints needed)
|
|
90
92
|
2. Use Puppeteer to screenshot each slide as high-resolution PNG
|
|
91
93
|
3. Insert each screenshot as a full-slide image in PPTX
|
|
92
|
-
4.
|
|
93
|
-
|
|
94
|
+
4. Note: This produces image-based slides (no editable text) but preserves exact visual design
|
|
95
|
+
|
|
96
|
+
**Critical implementation details to prevent common issues:**
|
|
97
|
+
|
|
98
|
+
**Problem: Ghost/residue from previous slides appearing in screenshots**
|
|
99
|
+
```javascript
|
|
100
|
+
// BEFORE capturing, disable ALL animations and transitions
|
|
101
|
+
await page.addStyleTag({
|
|
102
|
+
content: '*, *::before, *::after { animation: none !important; transition: none !important; animation-delay: 0s !important; opacity: 1 !important; }'
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// For each slide, hide ALL others completely
|
|
106
|
+
await page.evaluate((idx) => {
|
|
107
|
+
document.querySelectorAll('.slide').forEach((s, i) => {
|
|
108
|
+
if (i === idx) {
|
|
109
|
+
s.style.display = 'flex';
|
|
110
|
+
s.style.opacity = '1';
|
|
111
|
+
s.style.visibility = 'visible';
|
|
112
|
+
s.classList.add('active');
|
|
113
|
+
} else {
|
|
114
|
+
s.style.display = 'none';
|
|
115
|
+
s.style.opacity = '0';
|
|
116
|
+
s.style.visibility = 'hidden';
|
|
117
|
+
s.classList.remove('active');
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}, slideIndex);
|
|
121
|
+
|
|
122
|
+
// Wait for layout to fully settle
|
|
123
|
+
await new Promise(r => setTimeout(r, 500));
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Problem: Content appears too small with large margins in PPTX**
|
|
127
|
+
```javascript
|
|
128
|
+
// Set viewport to exact 16:9 dimensions
|
|
129
|
+
await page.setViewport({ width: 1280, height: 720, deviceScaleFactor: 2 });
|
|
130
|
+
|
|
131
|
+
// Screenshot the full viewport
|
|
132
|
+
const screenshot = await page.screenshot({ type: 'png' });
|
|
133
|
+
|
|
134
|
+
// Insert as FULL-SLIDE image — no margins
|
|
135
|
+
slide.addImage({
|
|
136
|
+
data: `image/png;base64,${screenshot.toString('base64')}`,
|
|
137
|
+
x: 0, y: 0, w: '100%', h: '100%'
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
Do NOT use percentage-based sizing with margins. The image must cover x:0, y:0 to w:100%, h:100%.
|
|
94
141
|
|
|
95
142
|
## Design Principles for PPTX
|
|
96
143
|
|