diff --git a/package.json b/package.json index 7d2874c8..95972745 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "scripts": { + "icons:generate": "node tools/generate_apple_touch_icons.js", "links:refresh": "node tools/check_external_links.js", "stats:generate": "node tools/generate_stats.js" }, diff --git a/static/apple-touch-icon-precomposed.png b/static/apple-touch-icon-precomposed.png new file mode 100644 index 00000000..449e77aa Binary files /dev/null and b/static/apple-touch-icon-precomposed.png differ diff --git a/static/apple-touch-icon.png b/static/apple-touch-icon.png new file mode 100644 index 00000000..449e77aa Binary files /dev/null and b/static/apple-touch-icon.png differ diff --git a/themes/2026/layouts/_partials/head.html b/themes/2026/layouts/_partials/head.html index d62618cc..ea2d474e 100644 --- a/themes/2026/layouts/_partials/head.html +++ b/themes/2026/layouts/_partials/head.html @@ -11,4 +11,5 @@ + {{ partialCached "head/css.html" . }} diff --git a/themes/42/layouts/_partials/head.html b/themes/42/layouts/_partials/head.html index a73074ee..5b9cef15 100644 --- a/themes/42/layouts/_partials/head.html +++ b/themes/42/layouts/_partials/head.html @@ -4,4 +4,5 @@ + {{ partialCached "head/css.html" . }} diff --git a/tools/generate_apple_touch_icons.js b/tools/generate_apple_touch_icons.js new file mode 100644 index 00000000..001c805b --- /dev/null +++ b/tools/generate_apple_touch_icons.js @@ -0,0 +1,53 @@ +#!/usr/bin/env node + +const fs = require("fs"); +const path = require("path"); +const sharp = require("sharp"); + +const PROJECT_ROOT = path.resolve(__dirname, ".."); +const SOURCE_ICON_PATH = path.join(PROJECT_ROOT, "static", "favicon.png"); +const APPLE_TOUCH_ICON_SIZE = 180; +const APPLE_TOUCH_ICON_BACKGROUND = "#060c14"; +const OUTPUT_ICON_PATHS = [ + path.join(PROJECT_ROOT, "static", "apple-touch-icon.png"), + path.join(PROJECT_ROOT, "static", "apple-touch-icon-precomposed.png"), +]; + +/** + * Génère le PNG Apple Touch à partir du favicon principal du site. + * + * L'image finale est rendue opaque sur le fond sombre du thème actif pour + * éviter les rendus incohérents des zones transparentes sur certains appareils iOS. + * + * @returns {Promise} + */ +function buildAppleTouchIconBuffer() { + return sharp(SOURCE_ICON_PATH) + .resize(APPLE_TOUCH_ICON_SIZE, APPLE_TOUCH_ICON_SIZE, { + fit: "cover", + }) + .flatten({ + background: APPLE_TOUCH_ICON_BACKGROUND, + }) + .png({ + compressionLevel: 9, + adaptiveFiltering: true, + }) + .toBuffer(); +} + +/** + * Écrit la même icône sous les deux noms historiques encore demandés par les navigateurs. + * + * @param {Buffer} iconBuffer + */ +function writeAppleTouchIcons(iconBuffer) { + for (const outputPath of OUTPUT_ICON_PATHS) { + fs.writeFileSync(outputPath, iconBuffer); + } +} + +(async function main() { + const iconBuffer = await buildAppleTouchIconBuffer(); + writeAppleTouchIcons(iconBuffer); +})();