@datawheel/bespoke 0.6.0-rc.4 → 0.6.0-rc.5
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/server.js +25 -144
- package/package.json +2 -3
package/dist/server.js
CHANGED
|
@@ -26,8 +26,7 @@ import * as allIcons from '@tabler/icons-react';
|
|
|
26
26
|
import NextCors from 'nextjs-cors';
|
|
27
27
|
import imageType from 'image-type';
|
|
28
28
|
import formidable from 'formidable';
|
|
29
|
-
import
|
|
30
|
-
import puppeteer2 from 'puppeteer';
|
|
29
|
+
import { chromium } from 'playwright-chromium';
|
|
31
30
|
import DomParser from 'dom-parser';
|
|
32
31
|
import path from 'path';
|
|
33
32
|
import axiosRetry from 'axios-retry';
|
|
@@ -4221,114 +4220,6 @@ function endpointUpdateMyDataFactory(operations) {
|
|
|
4221
4220
|
}
|
|
4222
4221
|
}, []);
|
|
4223
4222
|
}
|
|
4224
|
-
async function generatePDF(path2) {
|
|
4225
|
-
const width = 1920;
|
|
4226
|
-
const height = 1080;
|
|
4227
|
-
const maxTimeoutPerPage = 0;
|
|
4228
|
-
try {
|
|
4229
|
-
const browser = await puppeteer.launch({
|
|
4230
|
-
args: [
|
|
4231
|
-
`--window-size=${width},${height}`,
|
|
4232
|
-
"--start-fullscreen"
|
|
4233
|
-
],
|
|
4234
|
-
defaultViewport: { width, height },
|
|
4235
|
-
headless: "shell",
|
|
4236
|
-
ignoreHTTPSErrors: true
|
|
4237
|
-
});
|
|
4238
|
-
const url = new URL(path2);
|
|
4239
|
-
const searchParams = new URLSearchParams(url.search);
|
|
4240
|
-
searchParams.set("print", "true");
|
|
4241
|
-
url.search = searchParams.toString();
|
|
4242
|
-
const page = await browser.newPage();
|
|
4243
|
-
await page.goto(url.toString(), { waitUntil: "networkidle0", timeout: maxTimeoutPerPage });
|
|
4244
|
-
await page.waitForSelector("#bespoke-report", { timeout: maxTimeoutPerPage });
|
|
4245
|
-
await page.evaluate(async () => {
|
|
4246
|
-
await new Promise((resolve) => {
|
|
4247
|
-
const scrollInterval = setInterval(() => {
|
|
4248
|
-
window.scrollBy(0, window.innerHeight);
|
|
4249
|
-
}, 100);
|
|
4250
|
-
const checkNetworkActivity = () => {
|
|
4251
|
-
const activeRequests = performance.getEntriesByType("resource").filter((entry) => entry.duration === 0);
|
|
4252
|
-
return activeRequests.length === 0;
|
|
4253
|
-
};
|
|
4254
|
-
const checkInterval = setInterval(() => {
|
|
4255
|
-
if (checkNetworkActivity()) {
|
|
4256
|
-
clearInterval(scrollInterval);
|
|
4257
|
-
clearInterval(checkInterval);
|
|
4258
|
-
resolve();
|
|
4259
|
-
}
|
|
4260
|
-
}, 1e3);
|
|
4261
|
-
});
|
|
4262
|
-
});
|
|
4263
|
-
const pdf = await page.pdf({
|
|
4264
|
-
displayHeaderFooter: true,
|
|
4265
|
-
footerTemplate: `
|
|
4266
|
-
<div
|
|
4267
|
-
style="
|
|
4268
|
-
color: lightgray; border-top: solid lightgray 1px; font-size: 10px;
|
|
4269
|
-
padding-top: 5px; text-align: center; width: 100%;
|
|
4270
|
-
"
|
|
4271
|
-
>
|
|
4272
|
-
<p>Page <span class="pageNumber" /> of <span class="totalPages" /></p>
|
|
4273
|
-
</div>`,
|
|
4274
|
-
format: "A4",
|
|
4275
|
-
// Letter,Legal,Tabloid,Ledger,A0,A1,A2,A3,A4,A5,A6
|
|
4276
|
-
headerTemplate: `
|
|
4277
|
-
<div
|
|
4278
|
-
style="
|
|
4279
|
-
color: lightgray; border-bottom: solid lightgray 1px; font-size: 10px;
|
|
4280
|
-
padding-bottom: 5px; text-align: center; width: 100%;
|
|
4281
|
-
"
|
|
4282
|
-
>
|
|
4283
|
-
<p class="url" />
|
|
4284
|
-
</div>`,
|
|
4285
|
-
// height: `${height}px`,
|
|
4286
|
-
landscape: false,
|
|
4287
|
-
margin: {
|
|
4288
|
-
bottom: 70,
|
|
4289
|
-
// minimum required for footer msg to display
|
|
4290
|
-
left: 20,
|
|
4291
|
-
right: 20,
|
|
4292
|
-
top: 70
|
|
4293
|
-
// minimum required for header msg to display
|
|
4294
|
-
},
|
|
4295
|
-
omitBackground: true,
|
|
4296
|
-
pageRanges: "",
|
|
4297
|
-
// All
|
|
4298
|
-
// path: "./test.pdf" // Path to save the file
|
|
4299
|
-
preferCSSPageSize: false,
|
|
4300
|
-
// Give any CSS @page size declared in the page priority over what is declared in the width or height or format option.
|
|
4301
|
-
printBackground: true,
|
|
4302
|
-
scale: 1,
|
|
4303
|
-
// From 0.1 to 2
|
|
4304
|
-
tagged: false,
|
|
4305
|
-
// Generate tagged (accessible) PDF.
|
|
4306
|
-
timeout: 0
|
|
4307
|
-
// width: `${width}px`,
|
|
4308
|
-
});
|
|
4309
|
-
await browser.close();
|
|
4310
|
-
return pdf.toString("base64");
|
|
4311
|
-
} catch (error) {
|
|
4312
|
-
console.error("Error generating PDF:", error);
|
|
4313
|
-
throw error;
|
|
4314
|
-
}
|
|
4315
|
-
}
|
|
4316
|
-
function endpointDownloadReport() {
|
|
4317
|
-
return endpoint("POST", "pdf", async (req, res) => {
|
|
4318
|
-
const { slugs, path: path2 } = req.body;
|
|
4319
|
-
if (!slugs || !path2) {
|
|
4320
|
-
throw new BackendError(400, "Missing path parameter in request.");
|
|
4321
|
-
} else {
|
|
4322
|
-
const url = new URL(path2, req.headers["origin"]);
|
|
4323
|
-
const pdf = await generatePDF(url);
|
|
4324
|
-
return {
|
|
4325
|
-
ok: true,
|
|
4326
|
-
status: 200,
|
|
4327
|
-
data: pdf
|
|
4328
|
-
};
|
|
4329
|
-
}
|
|
4330
|
-
});
|
|
4331
|
-
}
|
|
4332
4223
|
var minimal_args = [
|
|
4333
4224
|
"--autoplay-policy=user-gesture-required",
|
|
4334
4225
|
"--disable-background-networking",
|
|
@@ -4368,56 +4259,46 @@ var minimal_args = [
|
|
|
4368
4259
|
"--disable-dev-shm-usage",
|
|
4369
4260
|
"--no-sandbox"
|
|
4370
4261
|
];
|
|
4371
|
-
var
|
|
4372
|
-
"google-analytics.com",
|
|
4373
|
-
"googletagmanager.com"
|
|
4374
|
-
];
|
|
4262
|
+
var TIME = "playwright";
|
|
4375
4263
|
async function generateImage(path2, section, format = "png", transparent = false) {
|
|
4376
4264
|
const width = 1366;
|
|
4377
4265
|
const height = 768;
|
|
4378
4266
|
const maxTimeoutPerPage = 0;
|
|
4379
|
-
console.time(
|
|
4267
|
+
console.time(TIME);
|
|
4380
4268
|
try {
|
|
4381
|
-
const browser = await
|
|
4269
|
+
const browser = await chromium.launch({
|
|
4382
4270
|
args: [
|
|
4383
4271
|
`--window-size=${width},${height}`,
|
|
4384
4272
|
...minimal_args
|
|
4385
|
-
]
|
|
4386
|
-
defaultViewport: { width, height, deviceScaleFactor: 2 },
|
|
4387
|
-
ignoreHTTPSErrors: true,
|
|
4388
|
-
headless: true
|
|
4273
|
+
]
|
|
4389
4274
|
});
|
|
4390
|
-
|
|
4275
|
+
const context = await browser.newContext({
|
|
4276
|
+
viewport: { width, height },
|
|
4277
|
+
deviceScaleFactor: 2
|
|
4278
|
+
});
|
|
4279
|
+
console.timeLog(TIME, "Browser started");
|
|
4391
4280
|
const url = new URL(path2);
|
|
4392
4281
|
const searchParams = new URLSearchParams(url.search);
|
|
4393
4282
|
url.search = searchParams.toString();
|
|
4394
|
-
const page = await
|
|
4395
|
-
console.timeLog(
|
|
4283
|
+
const page = await context.newPage();
|
|
4284
|
+
console.timeLog(TIME, "Creating page");
|
|
4396
4285
|
await page.addStyleTag({ content: ".bespoke-Section-container{ padding: 1rem !important }" });
|
|
4397
|
-
|
|
4398
|
-
page.
|
|
4399
|
-
|
|
4400
|
-
if (blocked_domains.some((domain) => url2.includes(domain))) {
|
|
4401
|
-
request.abort();
|
|
4402
|
-
} else {
|
|
4403
|
-
request.continue();
|
|
4404
|
-
}
|
|
4405
|
-
});
|
|
4406
|
-
console.timeLog("puppeteer", "Setting request interceptor");
|
|
4407
|
-
await page.goto(url.toString(), { waitUntil: "networkidle0", timeout: maxTimeoutPerPage });
|
|
4408
|
-
console.timeLog("puppeteer", "Navigated to page");
|
|
4286
|
+
console.timeLog(TIME, "Setting request interceptor");
|
|
4287
|
+
await page.goto(url.toString(), { timeout: maxTimeoutPerPage });
|
|
4288
|
+
console.timeLog(TIME, "Navigated to page");
|
|
4409
4289
|
await page.waitForSelector("#bespoke-report", { timeout: maxTimeoutPerPage });
|
|
4410
|
-
console.timeLog(
|
|
4290
|
+
console.timeLog(TIME, "Selector detected");
|
|
4291
|
+
await page.waitForLoadState("networkidle");
|
|
4411
4292
|
if (transparent) {
|
|
4412
4293
|
await page.$eval(`.bespoke-Section-${section}`, (el) => el["style"].background = "transparent");
|
|
4413
4294
|
await page.evaluate(() => document.body.style.background = "transparent");
|
|
4414
|
-
console.timeLog(
|
|
4295
|
+
console.timeLog(TIME, "Added transparent background");
|
|
4415
4296
|
}
|
|
4416
4297
|
if (format === "svg") {
|
|
4417
4298
|
const element = await page.$(".d3plus-viz");
|
|
4418
4299
|
const svg = await element?.evaluate((el) => el.outerHTML);
|
|
4419
|
-
console.timeLog(
|
|
4420
|
-
console.timeEnd(
|
|
4300
|
+
console.timeLog(TIME, "Finishing SVG");
|
|
4301
|
+
console.timeEnd(TIME);
|
|
4421
4302
|
await browser.close();
|
|
4422
4303
|
return svg?.replace(/ {4}|[\t\n\r]/gm, "");
|
|
4423
4304
|
} else {
|
|
@@ -4426,15 +4307,15 @@ async function generateImage(path2, section, format = "png", transparent = false
|
|
|
4426
4307
|
type: "png",
|
|
4427
4308
|
omitBackground: true
|
|
4428
4309
|
});
|
|
4429
|
-
console.timeLog(
|
|
4430
|
-
console.timeEnd(
|
|
4310
|
+
console.timeLog(TIME, "Finishing PNG");
|
|
4311
|
+
console.timeEnd(TIME);
|
|
4431
4312
|
await browser.close();
|
|
4432
4313
|
return screenshot;
|
|
4433
4314
|
}
|
|
4434
4315
|
} catch (error) {
|
|
4435
4316
|
console.error("Error generating Image:", error);
|
|
4436
|
-
console.timeLog(
|
|
4437
|
-
console.timeEnd(
|
|
4317
|
+
console.timeLog(TIME, "Finishing with error");
|
|
4318
|
+
console.timeEnd(TIME);
|
|
4438
4319
|
throw error;
|
|
4439
4320
|
}
|
|
4440
4321
|
}
|
|
@@ -4560,7 +4441,7 @@ function getEndpointMap(db) {
|
|
|
4560
4441
|
endpointRevalidateReportFactory(api),
|
|
4561
4442
|
endpointRevalidateUrlFactory(),
|
|
4562
4443
|
endpointReadPrivateBlocksFactory(api),
|
|
4563
|
-
endpointDownloadReport(),
|
|
4444
|
+
// endpointDownloadReport(),
|
|
4564
4445
|
endpointExportImage(),
|
|
4565
4446
|
endpointListIconsFactory(api, "tabler"),
|
|
4566
4447
|
endpointReadIconFactory(api, "tabler"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datawheel/bespoke",
|
|
3
|
-
"version": "0.6.0-rc.
|
|
3
|
+
"version": "0.6.0-rc.5",
|
|
4
4
|
"description": "Content management system for creating automated data reports",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -103,9 +103,8 @@
|
|
|
103
103
|
"nextjs-cors": "^2.1.1",
|
|
104
104
|
"normalizr": "^3.6.2",
|
|
105
105
|
"pg": "^8.7.3",
|
|
106
|
+
"playwright-chromium": "^1.44.1",
|
|
106
107
|
"pretty-format": "^28.1.1",
|
|
107
|
-
"puppeteer": "^22.10.0",
|
|
108
|
-
"puppeteer-core": "^22.10.0",
|
|
109
108
|
"react": "^18.2.0",
|
|
110
109
|
"react-clipboard.js": "^2.0.16",
|
|
111
110
|
"react-dom": "^18.2.0",
|