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; + } + } }); }