@reddoorla/maintenance 0.17.0 → 0.18.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.
- package/dist/cli/bin.js +66 -8
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.js +8 -0
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +51 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -2417,9 +2417,16 @@ function commentarySection(text) {
|
|
|
2417
2417
|
</mj-column>
|
|
2418
2418
|
</mj-section>`;
|
|
2419
2419
|
}
|
|
2420
|
+
function headerImageTag(data) {
|
|
2421
|
+
const src = `cid:${data.headerImageCid}`;
|
|
2422
|
+
const alt = `${data.siteName} maintenance report`;
|
|
2423
|
+
if (data.headerWidth && data.headerHeight && data.headerBgColor) {
|
|
2424
|
+
return `<mj-image href="${data.siteUrl}" src="${src}" alt="${alt}" width="${data.headerWidth}px" height="${data.headerHeight}px" container-background-color="${data.headerBgColor}" />`;
|
|
2425
|
+
}
|
|
2426
|
+
return `<mj-image href="${data.siteUrl}" src="${src}" alt="${alt}" />`;
|
|
2427
|
+
}
|
|
2420
2428
|
function buildMjml(data) {
|
|
2421
2429
|
const isTesting = data.reportType === "Testing";
|
|
2422
|
-
const headerSrc = `cid:${data.headerImageCid}`;
|
|
2423
2430
|
const previewText = `Checked up on ${data.siteName}`;
|
|
2424
2431
|
return `<mjml>
|
|
2425
2432
|
<mj-head>
|
|
@@ -2433,7 +2440,7 @@ function buildMjml(data) {
|
|
|
2433
2440
|
<mj-body background-color="white">
|
|
2434
2441
|
<mj-section background-color="#F4F4F4" padding-top="0px" padding-bottom="0px" padding-left="0px" padding-right="0px">
|
|
2435
2442
|
<mj-column>
|
|
2436
|
-
|
|
2443
|
+
${headerImageTag(data)}
|
|
2437
2444
|
</mj-column>
|
|
2438
2445
|
</mj-section>
|
|
2439
2446
|
<mj-section background-color="white">
|
|
@@ -2647,7 +2654,7 @@ function scoresFromWebsite(siteRow) {
|
|
|
2647
2654
|
}
|
|
2648
2655
|
function daysAgo(today, n) {
|
|
2649
2656
|
const out = new Date(today);
|
|
2650
|
-
out.
|
|
2657
|
+
out.setUTCDate(out.getUTCDate() - n);
|
|
2651
2658
|
return out;
|
|
2652
2659
|
}
|
|
2653
2660
|
async function draftReportForSite(base, siteRow, reportType, options = {}) {
|
|
@@ -2733,6 +2740,38 @@ function openBase(cfg) {
|
|
|
2733
2740
|
return new Airtable({ apiKey: cfg.apiKey }).base(cfg.baseId);
|
|
2734
2741
|
}
|
|
2735
2742
|
|
|
2743
|
+
// src/reports/maintenance-email/header-image.ts
|
|
2744
|
+
import sharp from "sharp";
|
|
2745
|
+
var DEFAULT_DISPLAY_WIDTH = 600;
|
|
2746
|
+
var RETINA_SCALE = 2;
|
|
2747
|
+
var JPEG_QUALITY = 82;
|
|
2748
|
+
function channelToHex(value) {
|
|
2749
|
+
return Math.max(0, Math.min(255, Math.round(value))).toString(16).padStart(2, "0");
|
|
2750
|
+
}
|
|
2751
|
+
async function prepareHeaderImage(bytes, options = {}) {
|
|
2752
|
+
const requestedDisplayWidth = options.displayWidth ?? DEFAULT_DISPLAY_WIDTH;
|
|
2753
|
+
const input = Buffer.from(bytes);
|
|
2754
|
+
const meta = await sharp(input).metadata();
|
|
2755
|
+
const origWidth = meta.width;
|
|
2756
|
+
const origHeight = meta.height;
|
|
2757
|
+
if (!origWidth || !origHeight) {
|
|
2758
|
+
throw new Error("prepareHeaderImage: could not read source image dimensions");
|
|
2759
|
+
}
|
|
2760
|
+
const displayWidth = Math.min(requestedDisplayWidth, origWidth);
|
|
2761
|
+
const displayHeight = Math.round(displayWidth * origHeight / origWidth);
|
|
2762
|
+
const targetSourceWidth = Math.min(origWidth, displayWidth * RETINA_SCALE);
|
|
2763
|
+
const out = await sharp(input).resize({ width: targetSourceWidth, withoutEnlargement: true }).flatten({ background: "#ffffff" }).jpeg({ quality: JPEG_QUALITY }).toBuffer();
|
|
2764
|
+
const { dominant } = await sharp(out).stats();
|
|
2765
|
+
const placeholderColor = `#${channelToHex(dominant.r)}${channelToHex(dominant.g)}${channelToHex(dominant.b)}`;
|
|
2766
|
+
return {
|
|
2767
|
+
bytes: new Uint8Array(out),
|
|
2768
|
+
contentType: "image/jpeg",
|
|
2769
|
+
displayWidth,
|
|
2770
|
+
displayHeight,
|
|
2771
|
+
placeholderColor
|
|
2772
|
+
};
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2736
2775
|
// src/reports/send/resend.ts
|
|
2737
2776
|
import { Resend } from "resend";
|
|
2738
2777
|
function defaultResendClient() {
|
|
@@ -2796,7 +2835,8 @@ async function sendOne(client, base, site, report) {
|
|
|
2796
2835
|
if (!report.lighthouse) {
|
|
2797
2836
|
throw new Error(`Report ${report.reportId} has no Lighthouse scores`);
|
|
2798
2837
|
}
|
|
2799
|
-
const
|
|
2838
|
+
const original = await fetchAttachmentBytes(site.headerImage.url);
|
|
2839
|
+
const header = await prepareHeaderImage(original.bytes);
|
|
2800
2840
|
const bundled = await loadBundledImages();
|
|
2801
2841
|
const slug = siteSlug(site.name);
|
|
2802
2842
|
const cidName = `${slug}-header`;
|
|
@@ -2810,7 +2850,10 @@ async function sendOne(client, base, site, report) {
|
|
|
2810
2850
|
gaUsersPrevious: report.gaUsersPrevious ?? 0,
|
|
2811
2851
|
lastTestedDate: report.lastTestedDate ? new Date(report.lastTestedDate) : null,
|
|
2812
2852
|
commentary: report.commentary,
|
|
2813
|
-
headerImageCid: cidName
|
|
2853
|
+
headerImageCid: cidName,
|
|
2854
|
+
headerWidth: header.displayWidth,
|
|
2855
|
+
headerHeight: header.displayHeight,
|
|
2856
|
+
headerBgColor: header.placeholderColor
|
|
2814
2857
|
});
|
|
2815
2858
|
const subject = report.subjectOverride ?? `${site.name} ${report.reportType} Report`;
|
|
2816
2859
|
const explicitTo = parseAddresses(site.reportRecipientsTo);
|
|
@@ -2846,9 +2889,9 @@ async function sendOne(client, base, site, report) {
|
|
|
2846
2889
|
html,
|
|
2847
2890
|
attachments: [
|
|
2848
2891
|
{
|
|
2849
|
-
filename:
|
|
2850
|
-
content: Buffer.from(bytes).toString("base64"),
|
|
2851
|
-
contentType,
|
|
2892
|
+
filename: `${cidName}.jpg`,
|
|
2893
|
+
content: Buffer.from(header.bytes).toString("base64"),
|
|
2894
|
+
contentType: header.contentType,
|
|
2852
2895
|
inlineContentId: cidName
|
|
2853
2896
|
},
|
|
2854
2897
|
// Bundled images referenced via cid:rd-check-png / cid:rd-blurred-tests-jpg
|