slides-grab 1.4.1 → 1.4.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slides-grab",
3
- "version": "1.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Agent-first presentation framework — plan, design, and visually edit HTML slides with Claude Code or Codex, then export to PDF or experimental/unstable PPTX/Figma formats",
5
5
  "license": "MIT",
6
6
  "author": "vkehfdl1",
@@ -11,7 +11,7 @@
11
11
  import { readFileSync, writeFileSync, readdirSync } from 'fs';
12
12
  import { createRequire } from 'node:module';
13
13
  import { dirname, extname, join, resolve } from 'path';
14
- import { fileURLToPath, pathToFileURL } from 'url';
14
+ import { fileURLToPath } from 'url';
15
15
 
16
16
  import { buildSlideRuntimeHtml } from '../src/image-contract.js';
17
17
 
@@ -29,8 +29,8 @@ const LOCAL_ASSET_PREFIX = './assets/';
29
29
  // Deliberate sandbox decision: allow-scripts (so Chart.js and other in-slide JS
30
30
  // render in the viewer) WITHOUT allow-same-origin. Omitting allow-same-origin gives
31
31
  // each iframe an opaque origin so first-party slide content cannot reach the parent
32
- // viewer document. Because relative URLs break under an opaque origin, local
33
- // ./assets/ references are inlined as data: URLs in loadSlides()/inlineLocalAssetsForSrcdoc.
32
+ // viewer document. Small local image references are inlined for srcdoc portability;
33
+ // large media such as videos remain relative to the generated viewer file.
34
34
  const SLIDE_FRAME_SANDBOX = 'allow-scripts';
35
35
 
36
36
  const MIME_BY_EXTENSION = new Map([
@@ -38,7 +38,6 @@ const MIME_BY_EXTENSION = new Map([
38
38
  ['.gif', 'image/gif'],
39
39
  ['.jpg', 'image/jpeg'],
40
40
  ['.jpeg', 'image/jpeg'],
41
- ['.mp4', 'video/mp4'],
42
41
  ['.png', 'image/png'],
43
42
  ['.svg', 'image/svg+xml'],
44
43
  ['.webp', 'image/webp'],
@@ -146,14 +145,13 @@ export function escapeForSrcdoc(html) {
146
145
  }
147
146
 
148
147
  export function loadSlides(slidesDir) {
149
- const slideBaseHref = pathToFileURL(`${resolve(slidesDir)}/`).href;
150
148
  return findSlideFiles(slidesDir).map((file) => {
151
149
  const slidePath = join(slidesDir, file);
152
150
  const html = inlineLocalAssetsForSrcdoc(readFileSync(slidePath, 'utf-8'), slidePath);
153
151
  return {
154
152
  file,
155
153
  html: buildSlideRuntimeHtml(html, {
156
- baseHref: slideBaseHref,
154
+ baseHref: './',
157
155
  slideFile: file,
158
156
  }),
159
157
  };
@@ -169,6 +167,10 @@ function toDataUrl(filePath) {
169
167
  return `data:${getMimeType(filePath)};base64,${bytes.toString('base64')}`;
170
168
  }
171
169
 
170
+ function isInlineableAsset(filePath) {
171
+ return getMimeType(filePath).startsWith('image/');
172
+ }
173
+
172
174
  export function inlineLocalAssetsForSrcdoc(html, slidePath) {
173
175
  const resolveAsset = (source) => {
174
176
  if (!source.startsWith(LOCAL_ASSET_PREFIX)) {
@@ -176,7 +178,11 @@ export function inlineLocalAssetsForSrcdoc(html, slidePath) {
176
178
  }
177
179
 
178
180
  try {
179
- return toDataUrl(resolve(dirname(slidePath), source));
181
+ const filePath = resolve(dirname(slidePath), source);
182
+ if (!isInlineableAsset(filePath)) {
183
+ return source;
184
+ }
185
+ return toDataUrl(filePath);
180
186
  } catch {
181
187
  return source;
182
188
  }
@@ -433,13 +433,12 @@ export async function inspectSlide(page, fileName, slidesDir, slideMode = DEFAUL
433
433
  try {
434
434
  const imageData = context.getImageData(0, 0, canvas.width, canvas.height).data;
435
435
  const totalPixels = canvas.width * canvas.height;
436
- const stride = Math.max(1, Math.ceil(totalPixels / 50000));
437
436
  let sampledPixels = 0;
438
437
  let paintedSamples = 0;
439
438
 
440
- for (let pixel = 0; pixel < totalPixels; pixel += stride) {
439
+ for (let alphaIndex = 3; alphaIndex < imageData.length; alphaIndex += 4) {
441
440
  sampledPixels += 1;
442
- if (imageData[(pixel * 4) + 3] !== 0) {
441
+ if (imageData[alphaIndex] !== 0) {
443
442
  paintedSamples += 1;
444
443
  break;
445
444
  }