diff --git a/README.md b/README.md
index 67e2c53418..f37e719bcd 100644
--- a/README.md
+++ b/README.md
@@ -303,8 +303,9 @@ npm run check
## Check images
Every image needs to have alt text for accessibility and must use markdown syntax. To avoid changing the styling of the images, the use of the `` HTML tag is not allowed. The lint job in CI will fail if images do not have alt text defined or if an `` tag is found.
+We also require raster images (PNG, JPEG) to be converted to AVIF format to save space and make the website faster for users. You can convert images to AVIF using [ImageMagick](https://imagemagick.org/index.php).
-You can check it locally by running:
+You can check images locally by running:
```bash
# Only check images
diff --git a/scripts/js/lib/api/processHtml.ts b/scripts/js/lib/api/processHtml.ts
index 3742fd4ee3..f7b4c1f89e 100644
--- a/scripts/js/lib/api/processHtml.ts
+++ b/scripts/js/lib/api/processHtml.ts
@@ -10,6 +10,8 @@
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.
+import path from "node:path";
+
import { CheerioAPI, Cheerio, load, Element } from "cheerio";
import { Image } from "./HtmlToMdResult.js";
@@ -94,8 +96,16 @@ export function loadImages(
const $img = $(img);
const fileName = $img.attr("src")!.split("/").pop()!;
+ const fileExtension = path.extname(fileName);
+
+ // We convert PNG and JPG to AVIF for reduced file size. The image-copying
+ // logic detects changed extensions and converts the files.
+ // Remove `false &&` when ready to switch to AVIF
+ let dest =
+ false && [".png", ".jpg", ".jpeg"].includes(fileExtension)
+ ? `${imageDestination}/${path.basename(fileName, fileExtension)}.avif`
+ : `${imageDestination}/${fileName}`;
- let dest = `${imageDestination}/${fileName}`;
if (isReleaseNotes && !hasSeparateReleaseNotes) {
// If the Pkg only has a single release notes file for all versions,
// then the images should point to the current version.
diff --git a/scripts/js/lib/api/saveImages.ts b/scripts/js/lib/api/saveImages.ts
index 8dc53228d3..1f7f73e285 100644
--- a/scripts/js/lib/api/saveImages.ts
+++ b/scripts/js/lib/api/saveImages.ts
@@ -10,12 +10,15 @@
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.
-import { mkdirp } from "mkdirp";
-import pMap from "p-map";
import { copyFile } from "fs/promises";
+import { extname } from "node:path";
+
+import pMap from "p-map";
+import { $ } from "zx";
+import { mkdirp } from "mkdirp";
-import { Pkg } from "./Pkg.js";
import { Image } from "./HtmlToMdResult.js";
+import { Pkg } from "./Pkg.js";
import { pathExists } from "../fs.js";
function skipReleaseNote(imgFileName: string, pkg: Pkg): boolean {
@@ -54,10 +57,20 @@ export async function saveImages(
if (skipReleaseNote(img.fileName, pkg)) {
return;
}
+ const source = `${originalImagesFolderPath}/${img.fileName}`;
+ const dest = `${publicBaseFolder}/${img.dest}`;
- await copyFile(
- `${originalImagesFolderPath}/${img.fileName}`,
- `${publicBaseFolder}/${img.dest}`,
- );
+ if (extname(source) === extname(dest)) {
+ await copyFile(source, dest);
+ } else {
+ try {
+ await $`magick ${source} ${dest}`;
+ } catch (err) {
+ console.error(
+ "Image conversion failed, make sure you have ImageMagick installed (https://imagemagick.org/index.php)",
+ );
+ throw err;
+ }
+ }
});
}