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 +1 -1
- package/scripts/build-viewer.js +13 -7
- package/src/validation/core.js +2 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slides-grab",
|
|
3
|
-
"version": "1.4.
|
|
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",
|
package/scripts/build-viewer.js
CHANGED
|
@@ -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
|
|
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.
|
|
33
|
-
//
|
|
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:
|
|
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
|
-
|
|
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
|
}
|
package/src/validation/core.js
CHANGED
|
@@ -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
|
|
439
|
+
for (let alphaIndex = 3; alphaIndex < imageData.length; alphaIndex += 4) {
|
|
441
440
|
sampledPixels += 1;
|
|
442
|
-
if (imageData[
|
|
441
|
+
if (imageData[alphaIndex] !== 0) {
|
|
443
442
|
paintedSamples += 1;
|
|
444
443
|
break;
|
|
445
444
|
}
|