@onlook/storybook-plugin 0.4.0-beta.17 → 0.4.0-beta.19
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/dist/cli/index.js +78 -124
- package/dist/index.d.ts +1 -1
- package/dist/index.js +301 -262
- package/dist/preset/index.d.ts +1 -1
- package/dist/preset/index.js +301 -262
- package/dist/screenshot-service/index.js +78 -124
- package/dist/{storybook-onlook-plugin-BvrvMhRF.d.ts → storybook-onlook-plugin-J4qj72mN.d.ts} +7 -7
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -153,50 +153,6 @@ async function closeBrowser() {
|
|
|
153
153
|
var ONLOOK_RENDER_STATE_ATTR = "data-onlook-render-state";
|
|
154
154
|
var ONLOOK_CONTAINED_CARD_ATTR = "data-onlook-contained-card";
|
|
155
155
|
|
|
156
|
-
// src/screenshot-service/utils/capture-semaphore/capture-semaphore.ts
|
|
157
|
-
function createSemaphore(limit) {
|
|
158
|
-
const max = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : 1;
|
|
159
|
-
let active = 0;
|
|
160
|
-
const waiters = [];
|
|
161
|
-
const acquire = () => {
|
|
162
|
-
if (active < max) {
|
|
163
|
-
active += 1;
|
|
164
|
-
return Promise.resolve();
|
|
165
|
-
}
|
|
166
|
-
return new Promise((resolve3) => {
|
|
167
|
-
waiters.push(() => {
|
|
168
|
-
active += 1;
|
|
169
|
-
resolve3();
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
};
|
|
173
|
-
const release = () => {
|
|
174
|
-
active -= 1;
|
|
175
|
-
const next = waiters.shift();
|
|
176
|
-
if (next) next();
|
|
177
|
-
};
|
|
178
|
-
return {
|
|
179
|
-
async run(fn) {
|
|
180
|
-
await acquire();
|
|
181
|
-
try {
|
|
182
|
-
return await fn();
|
|
183
|
-
} finally {
|
|
184
|
-
release();
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
var DEFAULT_CAPTURE_CONCURRENCY = 3;
|
|
190
|
-
function resolveConcurrency(raw) {
|
|
191
|
-
if (!raw) return DEFAULT_CAPTURE_CONCURRENCY;
|
|
192
|
-
const parsed = Number.parseInt(raw, 10);
|
|
193
|
-
if (!Number.isInteger(parsed) || parsed < 1) return DEFAULT_CAPTURE_CONCURRENCY;
|
|
194
|
-
return parsed;
|
|
195
|
-
}
|
|
196
|
-
var captureSemaphore = createSemaphore(
|
|
197
|
-
resolveConcurrency(process.env.ONLOOK_CAPTURE_CONCURRENCY)
|
|
198
|
-
);
|
|
199
|
-
|
|
200
156
|
// src/screenshot-service/utils/screenshot/screenshot.ts
|
|
201
157
|
function classifyPreviewSnapshot(s) {
|
|
202
158
|
if (s.text.includes("Sorry, something went wrong")) return "errored";
|
|
@@ -272,89 +228,87 @@ function screenshotExists(storyId, theme) {
|
|
|
272
228
|
return fs.existsSync(screenshotPath);
|
|
273
229
|
}
|
|
274
230
|
async function captureScreenshotBuffer(storyId, theme, width = VIEWPORT_WIDTH, height = VIEWPORT_HEIGHT, storybookUrl = "http://localhost:6006", loadTimeoutMs = 9e4, renderTimeoutMs = 2e4) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
231
|
+
const browser = await getBrowser();
|
|
232
|
+
const context = await browser.newContext({
|
|
233
|
+
viewport: { width, height },
|
|
234
|
+
deviceScaleFactor: 2
|
|
235
|
+
});
|
|
236
|
+
const page = await context.newPage();
|
|
237
|
+
try {
|
|
238
|
+
const url = `${storybookUrl}/iframe.html?id=${storyId}&viewMode=story&globals=theme:${theme}`;
|
|
239
|
+
await page.goto(url, { timeout: loadTimeoutMs });
|
|
240
|
+
await page.waitForLoadState("domcontentloaded", { timeout: loadTimeoutMs });
|
|
241
|
+
await page.waitForLoadState("load", { timeout: loadTimeoutMs });
|
|
282
242
|
try {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
img.addEventListener("error", resolve3);
|
|
302
|
-
setTimeout(resolve3, 3e3);
|
|
303
|
-
});
|
|
304
|
-
})
|
|
305
|
-
);
|
|
306
|
-
});
|
|
307
|
-
} catch {
|
|
308
|
-
}
|
|
309
|
-
const contentBounds = await page.evaluate(() => {
|
|
310
|
-
const root = document.querySelector("#storybook-root");
|
|
311
|
-
if (!root) return null;
|
|
312
|
-
const children = root.querySelectorAll("*");
|
|
313
|
-
if (children.length === 0) return null;
|
|
314
|
-
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
315
|
-
children.forEach((child) => {
|
|
316
|
-
const rect = child.getBoundingClientRect();
|
|
317
|
-
if (rect.width === 0 || rect.height === 0) return;
|
|
318
|
-
minX = Math.min(minX, rect.left);
|
|
319
|
-
minY = Math.min(minY, rect.top);
|
|
320
|
-
maxX = Math.max(maxX, rect.right);
|
|
321
|
-
maxY = Math.max(maxY, rect.bottom);
|
|
322
|
-
});
|
|
323
|
-
if (minX === Infinity) return null;
|
|
324
|
-
return {
|
|
325
|
-
x: minX,
|
|
326
|
-
y: minY,
|
|
327
|
-
width: maxX - minX,
|
|
328
|
-
height: maxY - minY
|
|
329
|
-
};
|
|
243
|
+
await page.waitForLoadState("networkidle", { timeout: 5e3 });
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
246
|
+
const renderState = await detectRenderState(page, { hardCapMs: renderTimeoutMs });
|
|
247
|
+
await page.evaluate(() => document.fonts.ready);
|
|
248
|
+
try {
|
|
249
|
+
await page.evaluate(async () => {
|
|
250
|
+
const images = document.querySelectorAll("img");
|
|
251
|
+
await Promise.all(
|
|
252
|
+
Array.from(images).map((img) => {
|
|
253
|
+
if (img.complete) return Promise.resolve();
|
|
254
|
+
return new Promise((resolve3) => {
|
|
255
|
+
img.addEventListener("load", resolve3);
|
|
256
|
+
img.addEventListener("error", resolve3);
|
|
257
|
+
setTimeout(resolve3, 3e3);
|
|
258
|
+
});
|
|
259
|
+
})
|
|
260
|
+
);
|
|
330
261
|
});
|
|
331
|
-
|
|
332
|
-
let resultBoundingBox = null;
|
|
333
|
-
if (contentBounds && contentBounds.width > 0 && contentBounds.height > 0) {
|
|
334
|
-
const PADDING = 20;
|
|
335
|
-
const clippedWidth = Math.min(width, contentBounds.width + PADDING);
|
|
336
|
-
const clippedHeight = Math.min(height, contentBounds.height + PADDING);
|
|
337
|
-
resultBoundingBox = {
|
|
338
|
-
width: Math.max(MIN_COMPONENT_WIDTH, Math.round(clippedWidth)),
|
|
339
|
-
height: Math.max(MIN_COMPONENT_HEIGHT, Math.round(clippedHeight))
|
|
340
|
-
};
|
|
341
|
-
screenshotBuffer = await page.screenshot({
|
|
342
|
-
type: "png",
|
|
343
|
-
clip: {
|
|
344
|
-
x: Math.max(0, contentBounds.x - 10),
|
|
345
|
-
y: Math.max(0, contentBounds.y - 10),
|
|
346
|
-
width: clippedWidth,
|
|
347
|
-
height: clippedHeight
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
} else {
|
|
351
|
-
screenshotBuffer = await page.screenshot({ type: "png" });
|
|
352
|
-
}
|
|
353
|
-
return { buffer: screenshotBuffer, boundingBox: resultBoundingBox, renderState };
|
|
354
|
-
} finally {
|
|
355
|
-
await context.close();
|
|
262
|
+
} catch {
|
|
356
263
|
}
|
|
357
|
-
|
|
264
|
+
const contentBounds = await page.evaluate(() => {
|
|
265
|
+
const root = document.querySelector("#storybook-root");
|
|
266
|
+
if (!root) return null;
|
|
267
|
+
const children = root.querySelectorAll("*");
|
|
268
|
+
if (children.length === 0) return null;
|
|
269
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
270
|
+
children.forEach((child) => {
|
|
271
|
+
const rect = child.getBoundingClientRect();
|
|
272
|
+
if (rect.width === 0 || rect.height === 0) return;
|
|
273
|
+
minX = Math.min(minX, rect.left);
|
|
274
|
+
minY = Math.min(minY, rect.top);
|
|
275
|
+
maxX = Math.max(maxX, rect.right);
|
|
276
|
+
maxY = Math.max(maxY, rect.bottom);
|
|
277
|
+
});
|
|
278
|
+
if (minX === Infinity) return null;
|
|
279
|
+
return {
|
|
280
|
+
x: minX,
|
|
281
|
+
y: minY,
|
|
282
|
+
width: maxX - minX,
|
|
283
|
+
height: maxY - minY
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
let screenshotBuffer;
|
|
287
|
+
let resultBoundingBox = null;
|
|
288
|
+
if (contentBounds && contentBounds.width > 0 && contentBounds.height > 0) {
|
|
289
|
+
const PADDING = 20;
|
|
290
|
+
const clippedWidth = Math.min(width, contentBounds.width + PADDING);
|
|
291
|
+
const clippedHeight = Math.min(height, contentBounds.height + PADDING);
|
|
292
|
+
resultBoundingBox = {
|
|
293
|
+
width: Math.max(MIN_COMPONENT_WIDTH, Math.round(clippedWidth)),
|
|
294
|
+
height: Math.max(MIN_COMPONENT_HEIGHT, Math.round(clippedHeight))
|
|
295
|
+
};
|
|
296
|
+
screenshotBuffer = await page.screenshot({
|
|
297
|
+
type: "png",
|
|
298
|
+
clip: {
|
|
299
|
+
x: Math.max(0, contentBounds.x - 10),
|
|
300
|
+
y: Math.max(0, contentBounds.y - 10),
|
|
301
|
+
width: clippedWidth,
|
|
302
|
+
height: clippedHeight
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
} else {
|
|
306
|
+
screenshotBuffer = await page.screenshot({ type: "png" });
|
|
307
|
+
}
|
|
308
|
+
return { buffer: screenshotBuffer, boundingBox: resultBoundingBox, renderState };
|
|
309
|
+
} finally {
|
|
310
|
+
await context.close();
|
|
311
|
+
}
|
|
358
312
|
}
|
|
359
313
|
async function generateScreenshot(storyId, theme, storybookUrl = "http://localhost:6006", timeoutMs = 3e4) {
|
|
360
314
|
try {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { E as EnvContainmentOptions, a as EnvContainmentSubstitution, O as OnlookPluginOptions, e as envContainmentPlugin, s as storybookOnlookPlugin } from './storybook-onlook-plugin-
|
|
1
|
+
export { E as EnvContainmentOptions, a as EnvContainmentSubstitution, O as OnlookPluginOptions, e as envContainmentPlugin, s as storybookOnlookPlugin } from './storybook-onlook-plugin-J4qj72mN.js';
|
|
2
2
|
import { Plugin } from 'vite';
|
|
3
3
|
import { Indexer } from 'storybook/internal/types';
|
|
4
4
|
|