headroom-cms 0.1.1
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/README.md +282 -0
- package/admin/assets/AdminsPage-CnrQqwKA.js +1 -0
- package/admin/assets/AllContentPage-ByN1h3PP.js +1 -0
- package/admin/assets/ApiKeysPage-FgNHZPBS.js +1 -0
- package/admin/assets/AuditPage-DAPpo-sj.js +1 -0
- package/admin/assets/BlockEditor-CZTwex-o.js +179 -0
- package/admin/assets/BlockEditor-Cp_wZ2xN.css +1 -0
- package/admin/assets/BlockTypeEditPage-Buuwbx1P.js +1 -0
- package/admin/assets/BlockTypesPage-Dj0qmsqX.js +1 -0
- package/admin/assets/BulkActionBar-BMcUBJSH.js +1 -0
- package/admin/assets/CollectionEditPage-CLgQu2HS.js +1 -0
- package/admin/assets/CollectionsPage-BnCaxALz.js +1 -0
- package/admin/assets/ContentCreatePage-CJI326o-.js +1 -0
- package/admin/assets/ContentEditPage-A4i8P2Jd.js +3 -0
- package/admin/assets/ContentListPage-Bc4mBIkB.js +1 -0
- package/admin/assets/CustomBlockPreview-CCssn6vF.js +479 -0
- package/admin/assets/FieldBuilder-YJGSk0nY.js +3 -0
- package/admin/assets/LoginPage-Jrne8-Wr.js +1 -0
- package/admin/assets/MediaPage-DfPQBmNf.css +1 -0
- package/admin/assets/MediaPage-_qNXqsZg.js +1 -0
- package/admin/assets/SiteSettingsPage-CoZnavij.js +1 -0
- package/admin/assets/SitesPage-ETqFT3nO.js +1 -0
- package/admin/assets/TagsPage-BGpp0XZM.js +1 -0
- package/admin/assets/UsersPage-CKRJpAb6.js +1 -0
- package/admin/assets/WebhookEditPage-BOcLe5OJ.js +1 -0
- package/admin/assets/WebhooksPage-Czco583Y.js +1 -0
- package/admin/assets/badge-0Z1nL6DI.js +1 -0
- package/admin/assets/card-D1-S-QZ6.js +1 -0
- package/admin/assets/check-BGA0ADyt.js +1 -0
- package/admin/assets/checkbox-BPqrj_XS.js +1 -0
- package/admin/assets/command-ChD319uJ.js +1 -0
- package/admin/assets/contentStatus-DfWHjFVB.js +1 -0
- package/admin/assets/copy-BqH9rXYM.js +1 -0
- package/admin/assets/core.esm-Csvubn5Q.js +5 -0
- package/admin/assets/format-CZ9bpk32.js +1 -0
- package/admin/assets/index-DOqKbrpW.css +1 -0
- package/admin/assets/index-Ds50UTAc.js +18 -0
- package/admin/assets/lib-BrI1UB_t.js +38 -0
- package/admin/assets/media-url-DIg_vSyf.js +1 -0
- package/admin/assets/module-RjUF93sV.js +716 -0
- package/admin/assets/native-48B9X9Wg.js +1 -0
- package/admin/assets/plus-BgHSYWJN.js +1 -0
- package/admin/assets/radix-DQ3amgxj.js +51 -0
- package/admin/assets/react-vendor-DNVhVxD7.js +4 -0
- package/admin/assets/search-DIzcfCVh.js +1 -0
- package/admin/assets/select-CJXZv4wv.js +1 -0
- package/admin/assets/sortable.esm-Zh-9QRSf.js +1 -0
- package/admin/assets/table-B3EHrN_H.js +1 -0
- package/admin/assets/tanstack-BO6c-AOu.js +1 -0
- package/admin/assets/trash-2-Gny2Upn-.js +1 -0
- package/admin/assets/useAdminResolver-BsQc_N4z.js +1 -0
- package/admin/assets/useContent-CSobIico.js +1 -0
- package/admin/assets/useDebouncedValue-Bf8UizjU.js +1 -0
- package/admin/assets/useMedia-CQnmMz4N.js +1 -0
- package/admin/assets/useTags-CYqbj5cK.js +1 -0
- package/admin/assets/useWebhooks-DXgtQ3aU.js +1 -0
- package/admin/index.html +21 -0
- package/admin/vite.svg +1 -0
- package/dist/admin-site.d.ts +30 -0
- package/dist/admin-site.d.ts.map +1 -0
- package/dist/admin-site.js +80 -0
- package/dist/admin-site.js.map +1 -0
- package/dist/api.d.ts +26 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +91 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +27 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +86 -0
- package/dist/auth.js.map +1 -0
- package/dist/cdn.d.ts +27 -0
- package/dist/cdn.d.ts.map +1 -0
- package/dist/cdn.js +382 -0
- package/dist/cdn.js.map +1 -0
- package/dist/image.d.ts +21 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +48 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +124 -0
- package/dist/index.js.map +1 -0
- package/dist/storage.d.ts +21 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +125 -0
- package/dist/storage.js.map +1 -0
- package/dist/webhooks.d.ts +23 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +91 -0
- package/dist/webhooks.js.map +1 -0
- package/lambda/api/bootstrap +0 -0
- package/lambda/api/resource.enc +0 -0
- package/lambda/functions/custom-message/index.mjs +112 -0
- package/lambda/functions/custom-message/resource.enc +1 -0
- package/lambda/image-lambda/index.mjs +188 -0
- package/lambda/image-lambda/node_modules/.package-lock.json +160 -0
- package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/README.md +46 -0
- package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/lib/glib-2.0/include/glibconfig.h +220 -0
- package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/lib/index.js +1 -0
- package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/lib/libvips-cpp.so.42 +0 -0
- package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/package.json +42 -0
- package/lambda/image-lambda/node_modules/@img/sharp-libvips-linux-arm64/versions.json +30 -0
- package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/LICENSE +191 -0
- package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/README.md +18 -0
- package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/lib/sharp-linux-arm64.node +0 -0
- package/lambda/image-lambda/node_modules/@img/sharp-linux-arm64/package.json +46 -0
- package/lambda/image-lambda/node_modules/color/LICENSE +21 -0
- package/lambda/image-lambda/node_modules/color/README.md +123 -0
- package/lambda/image-lambda/node_modules/color/index.js +496 -0
- package/lambda/image-lambda/node_modules/color/package.json +47 -0
- package/lambda/image-lambda/node_modules/color-convert/CHANGELOG.md +54 -0
- package/lambda/image-lambda/node_modules/color-convert/LICENSE +21 -0
- package/lambda/image-lambda/node_modules/color-convert/README.md +68 -0
- package/lambda/image-lambda/node_modules/color-convert/conversions.js +839 -0
- package/lambda/image-lambda/node_modules/color-convert/index.js +81 -0
- package/lambda/image-lambda/node_modules/color-convert/package.json +48 -0
- package/lambda/image-lambda/node_modules/color-convert/route.js +97 -0
- package/lambda/image-lambda/node_modules/color-name/LICENSE +8 -0
- package/lambda/image-lambda/node_modules/color-name/README.md +11 -0
- package/lambda/image-lambda/node_modules/color-name/index.js +152 -0
- package/lambda/image-lambda/node_modules/color-name/package.json +28 -0
- package/lambda/image-lambda/node_modules/color-string/LICENSE +21 -0
- package/lambda/image-lambda/node_modules/color-string/README.md +62 -0
- package/lambda/image-lambda/node_modules/color-string/index.js +242 -0
- package/lambda/image-lambda/node_modules/color-string/package.json +39 -0
- package/lambda/image-lambda/node_modules/detect-libc/LICENSE +201 -0
- package/lambda/image-lambda/node_modules/detect-libc/README.md +163 -0
- package/lambda/image-lambda/node_modules/detect-libc/index.d.ts +14 -0
- package/lambda/image-lambda/node_modules/detect-libc/lib/detect-libc.js +313 -0
- package/lambda/image-lambda/node_modules/detect-libc/lib/elf.js +39 -0
- package/lambda/image-lambda/node_modules/detect-libc/lib/filesystem.js +51 -0
- package/lambda/image-lambda/node_modules/detect-libc/lib/process.js +24 -0
- package/lambda/image-lambda/node_modules/detect-libc/package.json +44 -0
- package/lambda/image-lambda/node_modules/is-arrayish/LICENSE +21 -0
- package/lambda/image-lambda/node_modules/is-arrayish/README.md +16 -0
- package/lambda/image-lambda/node_modules/is-arrayish/index.js +9 -0
- package/lambda/image-lambda/node_modules/is-arrayish/package.json +45 -0
- package/lambda/image-lambda/node_modules/semver/LICENSE +15 -0
- package/lambda/image-lambda/node_modules/semver/README.md +665 -0
- package/lambda/image-lambda/node_modules/semver/bin/semver.js +191 -0
- package/lambda/image-lambda/node_modules/semver/classes/comparator.js +143 -0
- package/lambda/image-lambda/node_modules/semver/classes/index.js +7 -0
- package/lambda/image-lambda/node_modules/semver/classes/range.js +557 -0
- package/lambda/image-lambda/node_modules/semver/classes/semver.js +333 -0
- package/lambda/image-lambda/node_modules/semver/functions/clean.js +8 -0
- package/lambda/image-lambda/node_modules/semver/functions/cmp.js +54 -0
- package/lambda/image-lambda/node_modules/semver/functions/coerce.js +62 -0
- package/lambda/image-lambda/node_modules/semver/functions/compare-build.js +9 -0
- package/lambda/image-lambda/node_modules/semver/functions/compare-loose.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/compare.js +7 -0
- package/lambda/image-lambda/node_modules/semver/functions/diff.js +60 -0
- package/lambda/image-lambda/node_modules/semver/functions/eq.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/gt.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/gte.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/inc.js +21 -0
- package/lambda/image-lambda/node_modules/semver/functions/lt.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/lte.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/major.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/minor.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/neq.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/parse.js +18 -0
- package/lambda/image-lambda/node_modules/semver/functions/patch.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/prerelease.js +8 -0
- package/lambda/image-lambda/node_modules/semver/functions/rcompare.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/rsort.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/satisfies.js +12 -0
- package/lambda/image-lambda/node_modules/semver/functions/sort.js +5 -0
- package/lambda/image-lambda/node_modules/semver/functions/valid.js +8 -0
- package/lambda/image-lambda/node_modules/semver/index.js +91 -0
- package/lambda/image-lambda/node_modules/semver/internal/constants.js +37 -0
- package/lambda/image-lambda/node_modules/semver/internal/debug.js +11 -0
- package/lambda/image-lambda/node_modules/semver/internal/identifiers.js +29 -0
- package/lambda/image-lambda/node_modules/semver/internal/lrucache.js +42 -0
- package/lambda/image-lambda/node_modules/semver/internal/parse-options.js +17 -0
- package/lambda/image-lambda/node_modules/semver/internal/re.js +223 -0
- package/lambda/image-lambda/node_modules/semver/package.json +78 -0
- package/lambda/image-lambda/node_modules/semver/preload.js +4 -0
- package/lambda/image-lambda/node_modules/semver/range.bnf +16 -0
- package/lambda/image-lambda/node_modules/semver/ranges/gtr.js +6 -0
- package/lambda/image-lambda/node_modules/semver/ranges/intersects.js +9 -0
- package/lambda/image-lambda/node_modules/semver/ranges/ltr.js +6 -0
- package/lambda/image-lambda/node_modules/semver/ranges/max-satisfying.js +27 -0
- package/lambda/image-lambda/node_modules/semver/ranges/min-satisfying.js +26 -0
- package/lambda/image-lambda/node_modules/semver/ranges/min-version.js +63 -0
- package/lambda/image-lambda/node_modules/semver/ranges/outside.js +82 -0
- package/lambda/image-lambda/node_modules/semver/ranges/simplify.js +49 -0
- package/lambda/image-lambda/node_modules/semver/ranges/subset.js +249 -0
- package/lambda/image-lambda/node_modules/semver/ranges/to-comparators.js +10 -0
- package/lambda/image-lambda/node_modules/semver/ranges/valid.js +13 -0
- package/lambda/image-lambda/node_modules/sharp/LICENSE +191 -0
- package/lambda/image-lambda/node_modules/sharp/README.md +118 -0
- package/lambda/image-lambda/node_modules/sharp/install/check.js +41 -0
- package/lambda/image-lambda/node_modules/sharp/lib/channel.js +174 -0
- package/lambda/image-lambda/node_modules/sharp/lib/colour.js +180 -0
- package/lambda/image-lambda/node_modules/sharp/lib/composite.js +210 -0
- package/lambda/image-lambda/node_modules/sharp/lib/constructor.js +452 -0
- package/lambda/image-lambda/node_modules/sharp/lib/index.d.ts +1754 -0
- package/lambda/image-lambda/node_modules/sharp/lib/index.js +16 -0
- package/lambda/image-lambda/node_modules/sharp/lib/input.js +658 -0
- package/lambda/image-lambda/node_modules/sharp/lib/is.js +169 -0
- package/lambda/image-lambda/node_modules/sharp/lib/libvips.js +203 -0
- package/lambda/image-lambda/node_modules/sharp/lib/operation.js +958 -0
- package/lambda/image-lambda/node_modules/sharp/lib/output.js +1587 -0
- package/lambda/image-lambda/node_modules/sharp/lib/resize.js +587 -0
- package/lambda/image-lambda/node_modules/sharp/lib/sharp.js +114 -0
- package/lambda/image-lambda/node_modules/sharp/lib/utility.js +296 -0
- package/lambda/image-lambda/node_modules/sharp/package.json +222 -0
- package/lambda/image-lambda/node_modules/sharp/src/binding.gyp +280 -0
- package/lambda/image-lambda/node_modules/sharp/src/common.cc +1091 -0
- package/lambda/image-lambda/node_modules/sharp/src/common.h +393 -0
- package/lambda/image-lambda/node_modules/sharp/src/metadata.cc +320 -0
- package/lambda/image-lambda/node_modules/sharp/src/metadata.h +85 -0
- package/lambda/image-lambda/node_modules/sharp/src/operations.cc +475 -0
- package/lambda/image-lambda/node_modules/sharp/src/operations.h +125 -0
- package/lambda/image-lambda/node_modules/sharp/src/pipeline.cc +1758 -0
- package/lambda/image-lambda/node_modules/sharp/src/pipeline.h +393 -0
- package/lambda/image-lambda/node_modules/sharp/src/sharp.cc +40 -0
- package/lambda/image-lambda/node_modules/sharp/src/stats.cc +183 -0
- package/lambda/image-lambda/node_modules/sharp/src/stats.h +59 -0
- package/lambda/image-lambda/node_modules/sharp/src/utilities.cc +269 -0
- package/lambda/image-lambda/node_modules/sharp/src/utilities.h +19 -0
- package/lambda/image-lambda/node_modules/simple-swizzle/LICENSE +21 -0
- package/lambda/image-lambda/node_modules/simple-swizzle/README.md +43 -0
- package/lambda/image-lambda/node_modules/simple-swizzle/index.js +29 -0
- package/lambda/image-lambda/node_modules/simple-swizzle/package.json +36 -0
- package/lambda/webhook-worker/bootstrap +0 -0
- package/lambda/webhook-worker/resource.enc +0 -0
- package/package.json +50 -0
- package/src/admin-site.ts +108 -0
- package/src/api.ts +113 -0
- package/src/auth.ts +110 -0
- package/src/cdn.ts +449 -0
- package/src/image.ts +62 -0
- package/src/index.ts +216 -0
- package/src/sst-env.d.ts +143 -0
- package/src/storage.ts +138 -0
- package/src/webhooks.ts +114 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// ../functions/custom-message.ts
|
|
2
|
+
function escapeHtml(str) {
|
|
3
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4
|
+
}
|
|
5
|
+
async function handler(event) {
|
|
6
|
+
if (event.triggerSource !== "CustomMessage_AdminCreateUser") {
|
|
7
|
+
return event;
|
|
8
|
+
}
|
|
9
|
+
const inviterEmail = event.request.clientMetadata?.inviterEmail ?? "an administrator";
|
|
10
|
+
const adminUrl = event.request.clientMetadata?.adminUrl ?? "";
|
|
11
|
+
const siteHost = event.request.clientMetadata?.siteHost ?? "";
|
|
12
|
+
const tempPassword = event.request.codeParameter;
|
|
13
|
+
const userEmail = event.request.usernameParameter;
|
|
14
|
+
const loginLink = adminUrl ? `${adminUrl}/login` : "";
|
|
15
|
+
event.response.emailSubject = "You've been invited to Headroom CMS";
|
|
16
|
+
event.response.emailMessage = buildEmailHtml({
|
|
17
|
+
userEmail,
|
|
18
|
+
inviterEmail,
|
|
19
|
+
tempPassword,
|
|
20
|
+
loginLink,
|
|
21
|
+
siteHost
|
|
22
|
+
});
|
|
23
|
+
return event;
|
|
24
|
+
}
|
|
25
|
+
function buildEmailHtml(params) {
|
|
26
|
+
const { userEmail, tempPassword } = params;
|
|
27
|
+
const safeInviterEmail = escapeHtml(params.inviterEmail);
|
|
28
|
+
const safeSiteHost = escapeHtml(params.siteHost);
|
|
29
|
+
const safeLoginLink = escapeHtml(params.loginLink);
|
|
30
|
+
const loginSection = safeLoginLink ? `<tr>
|
|
31
|
+
<td style="padding: 0 0 16px 0;">
|
|
32
|
+
<a href="${safeLoginLink}" style="display: inline-block; background-color: #18181b; color: #ffffff; padding: 12px 24px; border-radius: 6px; text-decoration: none; font-weight: 500; font-size: 14px;">Sign in to Headroom</a>
|
|
33
|
+
</td>
|
|
34
|
+
</tr>
|
|
35
|
+
<tr>
|
|
36
|
+
<td style="padding: 0 0 24px 0;">
|
|
37
|
+
<p style="margin: 0; font-size: 13px; color: #71717a;">Or copy this link:</p>
|
|
38
|
+
<p style="margin: 4px 0 0 0; font-size: 13px; color: #3f3f46; word-break: break-all;">
|
|
39
|
+
<a href="${safeLoginLink}" style="color: #2563eb; text-decoration: underline;">${safeLoginLink}</a>
|
|
40
|
+
</p>
|
|
41
|
+
</td>
|
|
42
|
+
</tr>` : "";
|
|
43
|
+
return `<!DOCTYPE html>
|
|
44
|
+
<html>
|
|
45
|
+
<head>
|
|
46
|
+
<meta charset="utf-8">
|
|
47
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
48
|
+
</head>
|
|
49
|
+
<body style="margin: 0; padding: 0; background-color: #f4f4f5; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
|
|
50
|
+
<table role="presentation" style="width: 100%; border-collapse: collapse;">
|
|
51
|
+
<tr>
|
|
52
|
+
<td style="padding: 40px 20px;">
|
|
53
|
+
<table role="presentation" style="max-width: 480px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
|
|
54
|
+
|
|
55
|
+
<!-- Header -->
|
|
56
|
+
<tr>
|
|
57
|
+
<td style="padding: 32px 32px 0 32px;">
|
|
58
|
+
<h1 style="margin: 0 0 4px 0; font-size: 20px; font-weight: 600; color: #18181b;">Headroom CMS</h1>
|
|
59
|
+
<p style="margin: 0; font-size: 13px; color: #71717a;">Content Management System</p>
|
|
60
|
+
</td>
|
|
61
|
+
</tr>
|
|
62
|
+
|
|
63
|
+
<!-- Body -->
|
|
64
|
+
<tr>
|
|
65
|
+
<td style="padding: 24px 32px;">
|
|
66
|
+
<p style="margin: 0 0 16px 0; font-size: 14px; line-height: 1.6; color: #3f3f46;">
|
|
67
|
+
<strong>${safeInviterEmail}</strong> has invited you to ${safeSiteHost ? `manage content on <strong>${safeSiteHost}</strong> using Headroom CMS` : "join Headroom CMS"}.
|
|
68
|
+
</p>
|
|
69
|
+
<p style="margin: 0 0 16px 0; font-size: 14px; line-height: 1.6; color: #3f3f46;">
|
|
70
|
+
Your account has been created with the following credentials:
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
<!-- Credentials -->
|
|
74
|
+
<table role="presentation" style="width: 100%; border-collapse: collapse; margin: 0 0 24px 0; background-color: #f4f4f5; border-radius: 6px;">
|
|
75
|
+
<tr>
|
|
76
|
+
<td style="padding: 16px;">
|
|
77
|
+
<p style="margin: 0 0 8px 0; font-size: 13px; color: #71717a;">Email</p>
|
|
78
|
+
<p style="margin: 0 0 12px 0; font-size: 14px; font-weight: 500; color: #18181b;">${userEmail}</p>
|
|
79
|
+
<p style="margin: 0 0 8px 0; font-size: 13px; color: #71717a;">Temporary password</p>
|
|
80
|
+
<p style="margin: 0; font-size: 14px; font-weight: 500; font-family: 'SFMono-Regular', Consolas, monospace; color: #18181b; word-break: break-all;">${tempPassword}</p>
|
|
81
|
+
</td>
|
|
82
|
+
</tr>
|
|
83
|
+
</table>
|
|
84
|
+
|
|
85
|
+
${loginSection}
|
|
86
|
+
|
|
87
|
+
<p style="margin: 0; font-size: 13px; line-height: 1.5; color: #71717a;">
|
|
88
|
+
You will be asked to set a new password when you sign in for the first time.
|
|
89
|
+
This temporary password expires in 7 days.
|
|
90
|
+
</p>
|
|
91
|
+
</td>
|
|
92
|
+
</tr>
|
|
93
|
+
|
|
94
|
+
<!-- Footer -->
|
|
95
|
+
<tr>
|
|
96
|
+
<td style="padding: 16px 32px; border-top: 1px solid #e4e4e7;">
|
|
97
|
+
<p style="margin: 0; font-size: 12px; color: #a1a1aa;">
|
|
98
|
+
This is an automated message from Headroom CMS. If you didn't expect this invitation, you can ignore this email.
|
|
99
|
+
</p>
|
|
100
|
+
</td>
|
|
101
|
+
</tr>
|
|
102
|
+
|
|
103
|
+
</table>
|
|
104
|
+
</td>
|
|
105
|
+
</tr>
|
|
106
|
+
</table>
|
|
107
|
+
</body>
|
|
108
|
+
</html>`;
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
handler
|
|
112
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ب�ׄ":X�b����
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// ../image-lambda/index.mjs
|
|
2
|
+
import sharp from "sharp";
|
|
3
|
+
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
|
|
4
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
5
|
+
var s3 = new S3Client({});
|
|
6
|
+
var BUCKET = process.env.CONTENT_BUCKET;
|
|
7
|
+
var SIGNING_SECRET = process.env.IMAGE_SIGNING_SECRET;
|
|
8
|
+
var MAX_WIDTH = 2048;
|
|
9
|
+
var MAX_HEIGHT = 2048;
|
|
10
|
+
var MAX_PIXELS = 4e6;
|
|
11
|
+
var ALLOWED_FORMATS = ["jpeg", "png", "webp", "avif", "gif"];
|
|
12
|
+
var ALLOWED_FIT = ["cover", "contain", "fill", "inside", "outside"];
|
|
13
|
+
var DEFAULT_QUALITY = 80;
|
|
14
|
+
var SHARP_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
15
|
+
"image/jpeg",
|
|
16
|
+
"image/png",
|
|
17
|
+
"image/gif",
|
|
18
|
+
"image/webp",
|
|
19
|
+
"image/avif",
|
|
20
|
+
"image/tiff"
|
|
21
|
+
]);
|
|
22
|
+
var PATH_REGEX = /^\/img\/([a-zA-Z0-9._-]+)\/([A-Z0-9]+)\/original(\.[a-z0-9]+)$/i;
|
|
23
|
+
async function handler(event) {
|
|
24
|
+
const method = event.requestContext?.http?.method ?? event.httpMethod;
|
|
25
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
26
|
+
return { statusCode: 405, body: "Method not allowed" };
|
|
27
|
+
}
|
|
28
|
+
const rawPath = event.rawPath ?? event.path;
|
|
29
|
+
const rawQuery = event.rawQueryString ?? "";
|
|
30
|
+
const match = rawPath.match(PATH_REGEX);
|
|
31
|
+
if (!match) {
|
|
32
|
+
return { statusCode: 400, body: "Invalid image path" };
|
|
33
|
+
}
|
|
34
|
+
const params = new URLSearchParams(rawQuery);
|
|
35
|
+
const sig = params.get("sig");
|
|
36
|
+
if (!sig) {
|
|
37
|
+
return { statusCode: 403, body: "Missing signature" };
|
|
38
|
+
}
|
|
39
|
+
if (sig.length !== 32) {
|
|
40
|
+
return { statusCode: 403, body: "Invalid signature" };
|
|
41
|
+
}
|
|
42
|
+
params.delete("sig");
|
|
43
|
+
const hasTransform = params.has("w") || params.has("h") || params.has("format") || params.has("fit") || params.has("q") || params.has("cx");
|
|
44
|
+
if (!hasTransform) {
|
|
45
|
+
return { statusCode: 400, body: "No transform requested. Use /media/ path for originals." };
|
|
46
|
+
}
|
|
47
|
+
const expectedSig = computeSignature(rawPath, params);
|
|
48
|
+
if (!timingSafeEqual(Buffer.from(sig), Buffer.from(expectedSig))) {
|
|
49
|
+
return { statusCode: 403, body: "Invalid signature" };
|
|
50
|
+
}
|
|
51
|
+
const [, site, mediaId, ext] = match;
|
|
52
|
+
const s3Key = `sites/${site}/media/${mediaId}/original${ext}`;
|
|
53
|
+
const w = clamp(parseInt(params.get("w")) || null, 1, MAX_WIDTH);
|
|
54
|
+
const h = clamp(parseInt(params.get("h")) || null, 1, MAX_HEIGHT);
|
|
55
|
+
const fit = ALLOWED_FIT.includes(params.get("fit")) ? params.get("fit") : "cover";
|
|
56
|
+
const format = ALLOWED_FORMATS.includes(params.get("format")) ? params.get("format") : null;
|
|
57
|
+
const quality = clamp(
|
|
58
|
+
parseInt(params.get("q")) || DEFAULT_QUALITY,
|
|
59
|
+
1,
|
|
60
|
+
100
|
|
61
|
+
);
|
|
62
|
+
const cxRaw = params.get("cx");
|
|
63
|
+
const cyRaw = params.get("cy");
|
|
64
|
+
const cwRaw = params.get("cw");
|
|
65
|
+
const chRaw = params.get("ch");
|
|
66
|
+
const cx = cxRaw != null ? clamp(parseInt(cxRaw), 0, MAX_WIDTH) : null;
|
|
67
|
+
const cy = cyRaw != null ? clamp(parseInt(cyRaw), 0, MAX_HEIGHT) : null;
|
|
68
|
+
const cw = cwRaw != null ? clamp(parseInt(cwRaw), 1, MAX_WIDTH) : null;
|
|
69
|
+
const ch = chRaw != null ? clamp(parseInt(chRaw), 1, MAX_HEIGHT) : null;
|
|
70
|
+
const cropCount = [cx, cy, cw, ch].filter((v) => v != null).length;
|
|
71
|
+
if (cropCount > 0 && cropCount < 4) {
|
|
72
|
+
return { statusCode: 400, body: "All crop parameters (cx, cy, cw, ch) must be provided together" };
|
|
73
|
+
}
|
|
74
|
+
const hasCrop = cropCount === 4;
|
|
75
|
+
const outputKey = params.get("output");
|
|
76
|
+
const effectiveW = w || (hasCrop ? cw : null);
|
|
77
|
+
const effectiveH = h || (hasCrop ? ch : null);
|
|
78
|
+
if (effectiveW && effectiveH && effectiveW * effectiveH > MAX_PIXELS) {
|
|
79
|
+
return { statusCode: 400, body: "Requested dimensions too large" };
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const s3Response = await s3.send(
|
|
83
|
+
new GetObjectCommand({ Bucket: BUCKET, Key: s3Key })
|
|
84
|
+
);
|
|
85
|
+
if (!SHARP_MIME_TYPES.has(s3Response.ContentType)) {
|
|
86
|
+
return { statusCode: 400, body: "Unsupported content type for transformation" };
|
|
87
|
+
}
|
|
88
|
+
const inputBuffer = Buffer.from(
|
|
89
|
+
await s3Response.Body.transformToByteArray()
|
|
90
|
+
);
|
|
91
|
+
let pipeline = sharp(inputBuffer);
|
|
92
|
+
if (hasCrop) {
|
|
93
|
+
pipeline = pipeline.extract({ left: cx, top: cy, width: cw, height: ch });
|
|
94
|
+
}
|
|
95
|
+
if (w || h) {
|
|
96
|
+
pipeline = pipeline.resize(w, h, {
|
|
97
|
+
fit,
|
|
98
|
+
withoutEnlargement: true
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const outputFormat = format ?? extToFormat(ext);
|
|
102
|
+
pipeline = pipeline.toFormat(outputFormat, { quality });
|
|
103
|
+
if (outputKey) {
|
|
104
|
+
const result = await pipeline.toBuffer({ resolveWithObject: true });
|
|
105
|
+
await s3.send(new PutObjectCommand({
|
|
106
|
+
Bucket: BUCKET,
|
|
107
|
+
Key: outputKey,
|
|
108
|
+
Body: result.data,
|
|
109
|
+
ContentType: formatToMime(result.info.format)
|
|
110
|
+
}));
|
|
111
|
+
return {
|
|
112
|
+
statusCode: 200,
|
|
113
|
+
headers: { "Content-Type": "application/json" },
|
|
114
|
+
body: JSON.stringify({
|
|
115
|
+
key: outputKey,
|
|
116
|
+
width: result.info.width,
|
|
117
|
+
height: result.info.height,
|
|
118
|
+
size: result.info.size,
|
|
119
|
+
format: result.info.format
|
|
120
|
+
})
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const outputBuffer = await pipeline.toBuffer();
|
|
124
|
+
return {
|
|
125
|
+
statusCode: 200,
|
|
126
|
+
headers: {
|
|
127
|
+
"content-type": formatToMime(outputFormat),
|
|
128
|
+
"cache-control": "public, max-age=31536000, immutable",
|
|
129
|
+
"content-length": String(outputBuffer.length)
|
|
130
|
+
},
|
|
131
|
+
body: outputBuffer.toString("base64"),
|
|
132
|
+
isBase64Encoded: true
|
|
133
|
+
};
|
|
134
|
+
} catch (err) {
|
|
135
|
+
if (err.name === "NoSuchKey") {
|
|
136
|
+
return { statusCode: 404, body: "Image not found" };
|
|
137
|
+
}
|
|
138
|
+
console.error("Image processing error:", err);
|
|
139
|
+
return { statusCode: 500, body: "Image processing failed" };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function computeSignature(path, params) {
|
|
143
|
+
const sorted = new URLSearchParams([...params.entries()].sort());
|
|
144
|
+
const qs = sorted.toString();
|
|
145
|
+
const canonical = qs ? `${path}?${qs}` : path;
|
|
146
|
+
return createHmac("sha256", SIGNING_SECRET).update(canonical).digest("hex").substring(0, 32);
|
|
147
|
+
}
|
|
148
|
+
function clamp(val, min, max) {
|
|
149
|
+
if (val == null) return null;
|
|
150
|
+
return Math.min(Math.max(val, min), max);
|
|
151
|
+
}
|
|
152
|
+
function extToFormat(ext) {
|
|
153
|
+
const map = {
|
|
154
|
+
".jpg": "jpeg",
|
|
155
|
+
".jpeg": "jpeg",
|
|
156
|
+
".png": "png",
|
|
157
|
+
".gif": "gif",
|
|
158
|
+
".webp": "webp",
|
|
159
|
+
".avif": "avif",
|
|
160
|
+
".tiff": "tiff"
|
|
161
|
+
};
|
|
162
|
+
return map[ext.toLowerCase()] ?? "jpeg";
|
|
163
|
+
}
|
|
164
|
+
function formatToMime(format) {
|
|
165
|
+
const map = {
|
|
166
|
+
jpeg: "image/jpeg",
|
|
167
|
+
png: "image/png",
|
|
168
|
+
gif: "image/gif",
|
|
169
|
+
webp: "image/webp",
|
|
170
|
+
avif: "image/avif",
|
|
171
|
+
tiff: "image/tiff"
|
|
172
|
+
};
|
|
173
|
+
return map[format] ?? "application/octet-stream";
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
ALLOWED_FIT,
|
|
177
|
+
ALLOWED_FORMATS,
|
|
178
|
+
MAX_HEIGHT,
|
|
179
|
+
MAX_PIXELS,
|
|
180
|
+
MAX_WIDTH,
|
|
181
|
+
PATH_REGEX,
|
|
182
|
+
SHARP_MIME_TYPES,
|
|
183
|
+
clamp,
|
|
184
|
+
computeSignature,
|
|
185
|
+
extToFormat,
|
|
186
|
+
formatToMime,
|
|
187
|
+
handler
|
|
188
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 3,
|
|
3
|
+
"requires": true,
|
|
4
|
+
"packages": {
|
|
5
|
+
"node_modules/@img/sharp-libvips-linux-arm64": {
|
|
6
|
+
"version": "1.0.4",
|
|
7
|
+
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
|
|
8
|
+
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
|
|
9
|
+
"cpu": [
|
|
10
|
+
"arm64"
|
|
11
|
+
],
|
|
12
|
+
"license": "LGPL-3.0-or-later",
|
|
13
|
+
"optional": true,
|
|
14
|
+
"os": [
|
|
15
|
+
"linux"
|
|
16
|
+
],
|
|
17
|
+
"funding": {
|
|
18
|
+
"url": "https://opencollective.com/libvips"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"node_modules/@img/sharp-linux-arm64": {
|
|
22
|
+
"version": "0.33.5",
|
|
23
|
+
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
|
|
24
|
+
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
|
|
25
|
+
"cpu": [
|
|
26
|
+
"arm64"
|
|
27
|
+
],
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"optional": true,
|
|
30
|
+
"os": [
|
|
31
|
+
"linux"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
|
35
|
+
},
|
|
36
|
+
"funding": {
|
|
37
|
+
"url": "https://opencollective.com/libvips"
|
|
38
|
+
},
|
|
39
|
+
"optionalDependencies": {
|
|
40
|
+
"@img/sharp-libvips-linux-arm64": "1.0.4"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"node_modules/color": {
|
|
44
|
+
"version": "4.2.3",
|
|
45
|
+
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
|
46
|
+
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"color-convert": "^2.0.1",
|
|
50
|
+
"color-string": "^1.9.0"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=12.5.0"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"node_modules/color-convert": {
|
|
57
|
+
"version": "2.0.1",
|
|
58
|
+
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
59
|
+
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
60
|
+
"license": "MIT",
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"color-name": "~1.1.4"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=7.0.0"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"node_modules/color-name": {
|
|
69
|
+
"version": "1.1.4",
|
|
70
|
+
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
|
71
|
+
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
|
72
|
+
"license": "MIT"
|
|
73
|
+
},
|
|
74
|
+
"node_modules/color-string": {
|
|
75
|
+
"version": "1.9.1",
|
|
76
|
+
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
|
77
|
+
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
|
78
|
+
"license": "MIT",
|
|
79
|
+
"dependencies": {
|
|
80
|
+
"color-name": "^1.0.0",
|
|
81
|
+
"simple-swizzle": "^0.2.2"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"node_modules/detect-libc": {
|
|
85
|
+
"version": "2.1.2",
|
|
86
|
+
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
|
87
|
+
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
|
88
|
+
"license": "Apache-2.0",
|
|
89
|
+
"engines": {
|
|
90
|
+
"node": ">=8"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"node_modules/is-arrayish": {
|
|
94
|
+
"version": "0.3.4",
|
|
95
|
+
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
|
|
96
|
+
"integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
|
|
97
|
+
"license": "MIT"
|
|
98
|
+
},
|
|
99
|
+
"node_modules/semver": {
|
|
100
|
+
"version": "7.7.4",
|
|
101
|
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
|
102
|
+
"integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
|
|
103
|
+
"license": "ISC",
|
|
104
|
+
"bin": {
|
|
105
|
+
"semver": "bin/semver.js"
|
|
106
|
+
},
|
|
107
|
+
"engines": {
|
|
108
|
+
"node": ">=10"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"node_modules/sharp": {
|
|
112
|
+
"version": "0.33.5",
|
|
113
|
+
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
|
|
114
|
+
"integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
|
|
115
|
+
"hasInstallScript": true,
|
|
116
|
+
"license": "Apache-2.0",
|
|
117
|
+
"dependencies": {
|
|
118
|
+
"color": "^4.2.3",
|
|
119
|
+
"detect-libc": "^2.0.3",
|
|
120
|
+
"semver": "^7.6.3"
|
|
121
|
+
},
|
|
122
|
+
"engines": {
|
|
123
|
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
|
124
|
+
},
|
|
125
|
+
"funding": {
|
|
126
|
+
"url": "https://opencollective.com/libvips"
|
|
127
|
+
},
|
|
128
|
+
"optionalDependencies": {
|
|
129
|
+
"@img/sharp-darwin-arm64": "0.33.5",
|
|
130
|
+
"@img/sharp-darwin-x64": "0.33.5",
|
|
131
|
+
"@img/sharp-libvips-darwin-arm64": "1.0.4",
|
|
132
|
+
"@img/sharp-libvips-darwin-x64": "1.0.4",
|
|
133
|
+
"@img/sharp-libvips-linux-arm": "1.0.5",
|
|
134
|
+
"@img/sharp-libvips-linux-arm64": "1.0.4",
|
|
135
|
+
"@img/sharp-libvips-linux-s390x": "1.0.4",
|
|
136
|
+
"@img/sharp-libvips-linux-x64": "1.0.4",
|
|
137
|
+
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
|
|
138
|
+
"@img/sharp-libvips-linuxmusl-x64": "1.0.4",
|
|
139
|
+
"@img/sharp-linux-arm": "0.33.5",
|
|
140
|
+
"@img/sharp-linux-arm64": "0.33.5",
|
|
141
|
+
"@img/sharp-linux-s390x": "0.33.5",
|
|
142
|
+
"@img/sharp-linux-x64": "0.33.5",
|
|
143
|
+
"@img/sharp-linuxmusl-arm64": "0.33.5",
|
|
144
|
+
"@img/sharp-linuxmusl-x64": "0.33.5",
|
|
145
|
+
"@img/sharp-wasm32": "0.33.5",
|
|
146
|
+
"@img/sharp-win32-ia32": "0.33.5",
|
|
147
|
+
"@img/sharp-win32-x64": "0.33.5"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"node_modules/simple-swizzle": {
|
|
151
|
+
"version": "0.2.4",
|
|
152
|
+
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
|
|
153
|
+
"integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==",
|
|
154
|
+
"license": "MIT",
|
|
155
|
+
"dependencies": {
|
|
156
|
+
"is-arrayish": "^0.3.1"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# `@img/sharp-libvips-linux-arm64`
|
|
2
|
+
|
|
3
|
+
Prebuilt libvips and dependencies for use with sharp on Linux (glibc) 64-bit ARM.
|
|
4
|
+
|
|
5
|
+
## Licensing
|
|
6
|
+
|
|
7
|
+
This software contains third-party libraries
|
|
8
|
+
used under the terms of the following licences:
|
|
9
|
+
|
|
10
|
+
| Library | Used under the terms of |
|
|
11
|
+
|---------------|-----------------------------------------------------------------------------------------------------------|
|
|
12
|
+
| aom | BSD 2-Clause + [Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/) |
|
|
13
|
+
| cairo | Mozilla Public License 2.0 |
|
|
14
|
+
| cgif | MIT Licence |
|
|
15
|
+
| expat | MIT Licence |
|
|
16
|
+
| fontconfig | [fontconfig Licence](https://gitlab.freedesktop.org/fontconfig/fontconfig/blob/main/COPYING) (BSD-like) |
|
|
17
|
+
| freetype | [freetype Licence](https://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT) (BSD-like) |
|
|
18
|
+
| fribidi | LGPLv3 |
|
|
19
|
+
| glib | LGPLv3 |
|
|
20
|
+
| harfbuzz | MIT Licence |
|
|
21
|
+
| highway | Apache-2.0 License, BSD 3-Clause |
|
|
22
|
+
| lcms | MIT Licence |
|
|
23
|
+
| libarchive | BSD 2-Clause |
|
|
24
|
+
| libexif | LGPLv3 |
|
|
25
|
+
| libffi | MIT Licence |
|
|
26
|
+
| libheif | LGPLv3 |
|
|
27
|
+
| libimagequant | [BSD 2-Clause](https://github.com/lovell/libimagequant/blob/main/COPYRIGHT) |
|
|
28
|
+
| libnsgif | MIT Licence |
|
|
29
|
+
| libpng | [libpng License](https://github.com/pnggroup/libpng/blob/master/LICENSE) |
|
|
30
|
+
| librsvg | LGPLv3 |
|
|
31
|
+
| libspng | [BSD 2-Clause, libpng License](https://github.com/randy408/libspng/blob/master/LICENSE) |
|
|
32
|
+
| libtiff | [libtiff License](https://gitlab.com/libtiff/libtiff/blob/master/LICENSE.md) (BSD-like) |
|
|
33
|
+
| libvips | LGPLv3 |
|
|
34
|
+
| libwebp | New BSD License |
|
|
35
|
+
| libxml2 | MIT Licence |
|
|
36
|
+
| mozjpeg | [zlib License, IJG License, BSD-3-Clause](https://github.com/mozilla/mozjpeg/blob/master/LICENSE.md) |
|
|
37
|
+
| pango | LGPLv3 |
|
|
38
|
+
| pixman | MIT Licence |
|
|
39
|
+
| proxy-libintl | LGPLv3 |
|
|
40
|
+
| zlib-ng | [zlib Licence](https://github.com/zlib-ng/zlib-ng/blob/develop/LICENSE.md) |
|
|
41
|
+
|
|
42
|
+
Use of libraries under the terms of the LGPLv3 is via the
|
|
43
|
+
"any later version" clause of the LGPLv2 or LGPLv2.1.
|
|
44
|
+
|
|
45
|
+
Please report any errors or omissions via
|
|
46
|
+
https://github.com/lovell/sharp-libvips/issues/new
|