From 2838e161b8a405045d5be94670fed911aa38f3be Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 3 Jan 2026 20:36:01 +0100 Subject: [PATCH 1/5] Update dependencies to the most recent versions --- gulpfile.mjs | 2 +- package-lock.json | 287 +++++++++++++++++++++++++++------------------- package.json | 12 +- 3 files changed, 178 insertions(+), 123 deletions(-) diff --git a/gulpfile.mjs b/gulpfile.mjs index 557dae54d862b..9cf729d9d69d6 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -2369,7 +2369,7 @@ function packageJson() { bugs: DIST_BUGS_URL, license: DIST_LICENSE, optionalDependencies: { - "@napi-rs/canvas": "^0.1.84", + "@napi-rs/canvas": "^0.1.88", }, browser: { canvas: false, diff --git a/package-lock.json b/package-lock.json index 40e07c77e7b88..3a25511a1c3f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,12 +15,12 @@ "@fluent/dom": "^0.10.2", "@metalsmith/layouts": "^3.0.0", "@metalsmith/markdown": "^1.10.0", - "@napi-rs/canvas": "^0.1.84", - "@types/node": "^25.0.1", - "autoprefixer": "^10.4.22", + "@napi-rs/canvas": "^0.1.88", + "@types/node": "^25.0.3", + "autoprefixer": "^10.4.23", "babel-loader": "^10.0.0", "cached-iterable": "^0.3.0", - "caniuse-lite": "^1.0.30001760", + "caniuse-lite": "^1.0.30001762", "core-js": "^3.47.0", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", @@ -52,7 +52,7 @@ "postcss-nesting": "^13.0.2", "postcss-values-parser": "^7.0.0", "prettier": "^3.7.4", - "puppeteer": "^24.33.0", + "puppeteer": "^24.34.0", "stylelint": "^16.26.1", "stylelint-prettier": "^5.0.3", "svglint": "^4.1.2", @@ -61,7 +61,7 @@ "ttest": "^4.0.0", "typescript": "^5.9.3", "vinyl": "^3.0.1", - "webpack": "^5.103.0", + "webpack": "^5.104.1", "webpack-stream": "^7.0.0", "yargs": "^18.0.0" }, @@ -2377,9 +2377,9 @@ } }, "node_modules/@napi-rs/canvas": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.84.tgz", - "integrity": "sha512-88FTNFs4uuiFKP0tUrPsEXhpe9dg7za9ILZJE08pGdUveMIDeana1zwfVkqRHJDPJFAmGY3dXmJ99dzsy57YnA==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.88.tgz", + "integrity": "sha512-/p08f93LEbsL5mDZFQ3DBxcPv/I4QG9EDYRRq1WNlCOXVfAHBTHMSVMwxlqG/AtnSfUr9+vgfN7MKiyDo0+Weg==", "dev": true, "license": "MIT", "workspaces": [ @@ -2388,23 +2388,28 @@ "engines": { "node": ">= 10" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, "optionalDependencies": { - "@napi-rs/canvas-android-arm64": "0.1.84", - "@napi-rs/canvas-darwin-arm64": "0.1.84", - "@napi-rs/canvas-darwin-x64": "0.1.84", - "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.84", - "@napi-rs/canvas-linux-arm64-gnu": "0.1.84", - "@napi-rs/canvas-linux-arm64-musl": "0.1.84", - "@napi-rs/canvas-linux-riscv64-gnu": "0.1.84", - "@napi-rs/canvas-linux-x64-gnu": "0.1.84", - "@napi-rs/canvas-linux-x64-musl": "0.1.84", - "@napi-rs/canvas-win32-x64-msvc": "0.1.84" + "@napi-rs/canvas-android-arm64": "0.1.88", + "@napi-rs/canvas-darwin-arm64": "0.1.88", + "@napi-rs/canvas-darwin-x64": "0.1.88", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.88", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.88", + "@napi-rs/canvas-linux-arm64-musl": "0.1.88", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.88", + "@napi-rs/canvas-linux-x64-gnu": "0.1.88", + "@napi-rs/canvas-linux-x64-musl": "0.1.88", + "@napi-rs/canvas-win32-arm64-msvc": "0.1.88", + "@napi-rs/canvas-win32-x64-msvc": "0.1.88" } }, "node_modules/@napi-rs/canvas-android-arm64": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.84.tgz", - "integrity": "sha512-pdvuqvj3qtwVryqgpAGornJLV6Ezpk39V6wT4JCnRVGy8I3Tk1au8qOalFGrx/r0Ig87hWslysPpHBxVpBMIww==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.88.tgz", + "integrity": "sha512-KEaClPnZuVxJ8smUWjV1wWFkByBO/D+vy4lN+Dm5DFH514oqwukxKGeck9xcKJhaWJGjfruGmYGiwRe//+/zQQ==", "cpu": [ "arm64" ], @@ -2416,12 +2421,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.84.tgz", - "integrity": "sha512-A8IND3Hnv0R6abc6qCcCaOCujTLMmGxtucMTZ5vbQUrEN/scxi378MyTLtyWg+MRr6bwQJ6v/orqMS9datIcww==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.88.tgz", + "integrity": "sha512-Xgywz0dDxOKSgx3eZnK85WgGMmGrQEW7ZLA/E7raZdlEE+xXCozobgqz2ZvYigpB6DJFYkqnwHjqCOTSDGlFdg==", "cpu": [ "arm64" ], @@ -2433,12 +2442,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.84.tgz", - "integrity": "sha512-AUW45lJhYWwnA74LaNeqhvqYKK/2hNnBBBl03KRdqeCD4tKneUSrxUqIv8d22CBweOvrAASyKN3W87WO2zEr/A==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.88.tgz", + "integrity": "sha512-Yz4wSCIQOUgNucgk+8NFtQxQxZV5NO8VKRl9ePKE6XoNyNVC8JDqtvhh3b3TPqKK8W5p2EQpAr1rjjm0mfBxdg==", "cpu": [ "x64" ], @@ -2450,12 +2463,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.84.tgz", - "integrity": "sha512-8zs5ZqOrdgs4FioTxSBrkl/wHZB56bJNBqaIsfPL4ZkEQCinOkrFF7xIcXiHiKp93J3wUtbIzeVrhTIaWwqk+A==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.88.tgz", + "integrity": "sha512-9gQM2SlTo76hYhxHi2XxWTAqpTOb+JtxMPEIr+H5nAhHhyEtNmTSDRtz93SP7mGd2G3Ojf2oF5tP9OdgtgXyKg==", "cpu": [ "arm" ], @@ -2467,12 +2484,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.84.tgz", - "integrity": "sha512-i204vtowOglJUpbAFWU5mqsJgH0lVpNk/Ml4mQtB4Lndd86oF+Otr6Mr5KQnZHqYGhlSIKiU2SYnUbhO28zGQA==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.88.tgz", + "integrity": "sha512-7qgaOBMXuVRk9Fzztzr3BchQKXDxGbY+nwsovD3I/Sx81e+sX0ReEDYHTItNb0Je4NHbAl7D0MKyd4SvUc04sg==", "cpu": [ "arm64" ], @@ -2484,12 +2505,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.84.tgz", - "integrity": "sha512-VyZq0EEw+OILnWk7G3ZgLLPaz1ERaPP++jLjeyLMbFOF+Tr4zHzWKiKDsEV/cT7btLPZbVoR3VX+T9/QubnURQ==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.88.tgz", + "integrity": "sha512-kYyNrUsHLkoGHBc77u4Unh067GrfiCUMbGHC2+OTxbeWfZkPt2o32UOQkhnSswKd9Fko/wSqqGkY956bIUzruA==", "cpu": [ "arm64" ], @@ -2501,12 +2526,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.84.tgz", - "integrity": "sha512-PSMTh8DiThvLRsbtc/a065I/ceZk17EXAATv9uNvHgkgo7wdEfTh2C3aveNkBMGByVO3tvnvD5v/YFtZL07cIg==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.88.tgz", + "integrity": "sha512-HVuH7QgzB0yavYdNZDRyAsn/ejoXB0hn8twwFnOqUbCCdkV+REna7RXjSR7+PdfW0qMQ2YYWsLvVBT5iL/mGpw==", "cpu": [ "riscv64" ], @@ -2518,12 +2547,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.84.tgz", - "integrity": "sha512-N1GY3noO1oqgEo3rYQIwY44kfM11vA0lDbN0orTOHfCSUZTUyiYCY0nZ197QMahZBm1aR/vYgsWpV74MMMDuNA==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.88.tgz", + "integrity": "sha512-hvcvKIcPEQrvvJtJnwD35B3qk6umFJ8dFIr8bSymfrSMem0EQsfn1ztys8ETIFndTwdNWJKWluvxztA41ivsEw==", "cpu": [ "x64" ], @@ -2535,12 +2568,16 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.84.tgz", - "integrity": "sha512-vUZmua6ADqTWyHyei81aXIt9wp0yjeNwTH0KdhdeoBb6azHmFR8uKTukZMXfLCC3bnsW0t4lW7K78KNMknmtjg==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.88.tgz", + "integrity": "sha512-eSMpGYY2xnZSQ6UxYJ6plDboxq4KeJ4zT5HaVkUnbObNN6DlbJe0Mclh3wifAmquXfrlgTZt6zhHsUgz++AK6g==", "cpu": [ "x64" ], @@ -2552,12 +2589,37 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-arm64-msvc": { + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.88.tgz", + "integrity": "sha512-qcIFfEgHrchyYqRrxsCeTQgpJZ/GqHiqPcU/Fvw/ARVlQeDX1VyFH+X+0gCR2tca6UJrq96vnW+5o7buCq+erA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@napi-rs/canvas-win32-x64-msvc": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.84.tgz", - "integrity": "sha512-YSs8ncurc1xzegUMNnQUTYrdrAuaXdPMOa+iYYyAxydOtg0ppV386hyYMsy00Yip1NlTgLCseRG4sHSnjQx6og==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.88.tgz", + "integrity": "sha512-ROVqbfS4QyZxYkqmaIBBpbz/BQvAR+05FXM5PAtTYVc0uyY8Y4BHJSMdGAaMf6TdIVRsQsiq+FG/dH9XhvWCFQ==", "cpu": [ "x64" ], @@ -2569,6 +2631,10 @@ ], "engines": { "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" } }, "node_modules/@nodelib/fs.scandir": { @@ -2857,9 +2923,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.0.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.1.tgz", - "integrity": "sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==", + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", "dev": true, "license": "MIT", "dependencies": { @@ -3726,9 +3792,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", - "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "version": "10.4.23", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.23.tgz", + "integrity": "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==", "dev": true, "funding": [ { @@ -3746,10 +3812,9 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.27.0", - "caniuse-lite": "^1.0.30001754", + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001760", "fraction.js": "^5.3.4", - "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, @@ -3986,9 +4051,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.32", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz", - "integrity": "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3996,9 +4061,9 @@ } }, "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz", + "integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==", "dev": true, "license": "MIT", "engines": { @@ -4097,9 +4162,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -4117,11 +4182,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -4307,9 +4372,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001760", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", - "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "version": "1.0.30001762", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz", + "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==", "dev": true, "funding": [ { @@ -4464,9 +4529,9 @@ } }, "node_modules/chromium-bidi": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-11.0.0.tgz", - "integrity": "sha512-cM3DI+OOb89T3wO8cpPSro80Q9eKYJ7hGVXoGS3GkDPxnYSqiv+6xwpIf6XERyJ9Tdsl09hmNmY94BkgZdVekw==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-12.0.1.tgz", + "integrity": "sha512-fGg+6jr0xjQhzpy5N4ErZxQ4wF7KLEvhGZXD6EgvZKDhu7iOhZXnZhcDxPJDcwTcrD48NPzOCo84RP2lv3Z+Cg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5312,9 +5377,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.262", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz", - "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==", + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "dev": true, "license": "ISC" }, @@ -5512,9 +5577,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, @@ -9343,16 +9408,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/now-and-later": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", @@ -10386,18 +10441,18 @@ } }, "node_modules/puppeteer": { - "version": "24.33.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.33.0.tgz", - "integrity": "sha512-nl3wsAztq5F8zybn4Tk41OCnYIzFIzGC6AN0WcF2KCUnWenajvRRPgBmS6LvNUV2HEeIzT2zRZHH0TgVxLDKew==", + "version": "24.34.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.34.0.tgz", + "integrity": "sha512-Sdpl/zsYOsagZ4ICoZJPGZw8d9gZmK5DcxVal11dXi/1/t2eIXHjCf5NfmhDg5XnG9Nye+yo/LqMzIxie2rHTw==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.11.0", - "chromium-bidi": "11.0.0", + "chromium-bidi": "12.0.1", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1534754", - "puppeteer-core": "24.33.0", + "puppeteer-core": "24.34.0", "typed-query-selector": "^2.12.0" }, "bin": { @@ -10408,18 +10463,18 @@ } }, "node_modules/puppeteer-core": { - "version": "24.33.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.33.0.tgz", - "integrity": "sha512-tPTxVg+Qdj/8av4cy6szv3GlhxeOoNhiiMZ955fjxQyvPQE/6DjCa6ZyF/x0WJrlgBZtaLSP8TQgJb7FdLDXXA==", + "version": "24.34.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.34.0.tgz", + "integrity": "sha512-24evawO+mUGW4mvS2a2ivwLdX3gk8zRLZr9HP+7+VT2vBQnm0oh9jJEZmUE3ePJhRkYlZ93i7OMpdcoi2qNCLg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.11.0", - "chromium-bidi": "11.0.0", + "chromium-bidi": "12.0.1", "debug": "^4.4.3", "devtools-protocol": "0.0.1534754", "typed-query-selector": "^2.12.0", - "webdriver-bidi-protocol": "0.3.9", + "webdriver-bidi-protocol": "0.3.10", "ws": "^8.18.3" }, "engines": { @@ -13031,9 +13086,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -13270,16 +13325,16 @@ } }, "node_modules/webdriver-bidi-protocol": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.9.tgz", - "integrity": "sha512-uIYvlRQ0PwtZR1EzHlTMol1G0lAlmOe6wPykF9a77AK3bkpvZHzIVxRE2ThOx5vjy2zISe0zhwf5rzuUfbo1PQ==", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.10.tgz", + "integrity": "sha512-5LAE43jAVLOhB/QqX4bwSiv0Hg1HBfMmOuwBSXHdvg4GMGu9Y0lIq7p4R/yySu6w74WmaR4GM4H9t2IwLW7hgw==", "dev": true, "license": "Apache-2.0" }, "node_modules/webpack": { - "version": "5.103.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz", - "integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==", + "version": "5.104.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", + "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", "dev": true, "license": "MIT", "dependencies": { @@ -13291,10 +13346,10 @@ "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", - "browserslist": "^4.26.3", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.17.4", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -13305,7 +13360,7 @@ "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.11", + "terser-webpack-plugin": "^5.3.16", "watchpack": "^2.4.4", "webpack-sources": "^3.3.3" }, diff --git a/package.json b/package.json index f6e9dffb78c4c..fda11c63b3bda 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,12 @@ "@fluent/dom": "^0.10.2", "@metalsmith/layouts": "^3.0.0", "@metalsmith/markdown": "^1.10.0", - "@napi-rs/canvas": "^0.1.84", - "@types/node": "^25.0.1", - "autoprefixer": "^10.4.22", + "@napi-rs/canvas": "^0.1.88", + "@types/node": "^25.0.3", + "autoprefixer": "^10.4.23", "babel-loader": "^10.0.0", "cached-iterable": "^0.3.0", - "caniuse-lite": "^1.0.30001760", + "caniuse-lite": "^1.0.30001762", "core-js": "^3.47.0", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", @@ -47,7 +47,7 @@ "postcss-nesting": "^13.0.2", "postcss-values-parser": "^7.0.0", "prettier": "^3.7.4", - "puppeteer": "^24.33.0", + "puppeteer": "^24.34.0", "stylelint": "^16.26.1", "stylelint-prettier": "^5.0.3", "svglint": "^4.1.2", @@ -56,7 +56,7 @@ "ttest": "^4.0.0", "typescript": "^5.9.3", "vinyl": "^3.0.1", - "webpack": "^5.103.0", + "webpack": "^5.104.1", "webpack-stream": "^7.0.0", "yargs": "^18.0.0" }, From 13e070a8a3db1b89ec27c708922d8275dacdf465 Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 3 Jan 2026 20:40:39 +0100 Subject: [PATCH 2/5] Upgrade `globals` to version 17.0.0 This is a major version bump, but the changelog at https://github.com/sindresorhus/globals/releases/v17.0.0 doesn't indicate any breaking changes that should impact us. --- package-lock.json | 21 +++++++++++++++++---- package.json | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3a25511a1c3f4..e935a792e173b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "eslint-plugin-perfectionist": "^4.15.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-unicorn": "^62.0.0", - "globals": "^16.5.0", + "globals": "^17.0.0", "gulp": "^5.0.1", "gulp-cli": "^3.1.0", "gulp-postcss": "^10.0.0", @@ -5978,6 +5978,19 @@ "eslint": ">=9.38.0" } }, + "node_modules/eslint-plugin-unicorn/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-plugin-unicorn/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -6948,9 +6961,9 @@ } }, "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.0.0.tgz", + "integrity": "sha512-gv5BeD2EssA793rlFWVPMMCqefTlpusw6/2TbAVMy0FzcG8wKJn4O+NqJ4+XWmmwrayJgw5TzrmWjFgmz1XPqw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index fda11c63b3bda..6244522db8def 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "eslint-plugin-perfectionist": "^4.15.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-unicorn": "^62.0.0", - "globals": "^16.5.0", + "globals": "^17.0.0", "gulp": "^5.0.1", "gulp-cli": "^3.1.0", "gulp-postcss": "^10.0.0", From 687cd848e0da03db03c589157a2fd6f760bfcac9 Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 3 Jan 2026 20:42:04 +0100 Subject: [PATCH 3/5] Upgrade `eslint-plugin-perfectionist` to version 5.2.0 This is a major version bump, but the changelog at https://github.com/azat-io/eslint-plugin-perfectionist/releases/v5.0.0 doesn't indicate any breaking changes that should impact us. --- package-lock.json | 144 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 96 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index e935a792e173b..1153e6f1a0e17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "eslint-plugin-jasmine": "^4.2.2", "eslint-plugin-json": "^4.0.1", "eslint-plugin-no-unsanitized": "^4.1.4", - "eslint-plugin-perfectionist": "^4.15.1", + "eslint-plugin-perfectionist": "^5.2.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-unicorn": "^62.0.0", "globals": "^17.0.0", @@ -2962,14 +2962,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", - "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", + "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.44.1", - "@typescript-eslint/types": "^8.44.1", + "@typescript-eslint/tsconfig-utils": "^8.51.0", + "@typescript-eslint/types": "^8.51.0", "debug": "^4.3.4" }, "engines": { @@ -2984,14 +2984,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", - "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", + "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1" + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3002,9 +3002,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", - "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", + "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", "dev": true, "license": "MIT", "engines": { @@ -3019,9 +3019,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", - "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.51.0.tgz", + "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", "dev": true, "license": "MIT", "engines": { @@ -3033,22 +3033,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", - "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", + "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.44.1", - "@typescript-eslint/tsconfig-utils": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/visitor-keys": "8.44.1", + "@typescript-eslint/project-service": "8.51.0", + "@typescript-eslint/tsconfig-utils": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/visitor-keys": "8.51.0", "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3088,9 +3087,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", "bin": { @@ -3101,16 +3100,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", - "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.51.0.tgz", + "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.44.1", - "@typescript-eslint/types": "8.44.1", - "@typescript-eslint/typescript-estree": "8.44.1" + "@typescript-eslint/scope-manager": "8.51.0", + "@typescript-eslint/types": "8.51.0", + "@typescript-eslint/typescript-estree": "8.51.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3125,13 +3124,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.44.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", - "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", + "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/types": "8.51.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -5894,18 +5893,17 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.1.tgz", - "integrity": "sha512-MHF0cBoOG0XyBf7G0EAFCuJJu4I18wy0zAoT1OHfx2o6EOx1EFTIzr2HGeuZa1kDcusoX0xJ9V7oZmaeFd773Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-5.2.0.tgz", + "integrity": "sha512-rLD4VyA6sxcCPlG/koqjp0D46JTNRURSDs22Jr1JeVbOiu1BoeRdROnJoqDoGESuXbwxvGEnMSqClX/Q3HSMig==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.38.0", - "@typescript-eslint/utils": "^8.38.0", + "@typescript-eslint/utils": "^8.51.0", "natural-orderby": "^5.0.0" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.0.0 || >=22.0.0" }, "peerDependencies": { "eslint": ">=8.45.0" @@ -12711,6 +12709,54 @@ "node": ">=0.10.0" } }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -12748,9 +12794,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 6244522db8def..1f8daf412e1f6 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "eslint-plugin-jasmine": "^4.2.2", "eslint-plugin-json": "^4.0.1", "eslint-plugin-no-unsanitized": "^4.1.4", - "eslint-plugin-perfectionist": "^4.15.1", + "eslint-plugin-perfectionist": "^5.2.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-unicorn": "^62.0.0", "globals": "^17.0.0", From 5c06beae070b9f9ab898fa21adb20f89a06785cd Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 3 Jan 2026 20:43:08 +0100 Subject: [PATCH 4/5] Update translations to the most recent versions --- l10n/dsb/viewer.ftl | 10 +++++----- l10n/fur/viewer.ftl | 5 +++++ l10n/kk/viewer.ftl | 28 ++++++++++++++++++++++++++++ l10n/ml/viewer.ftl | 4 ++++ l10n/ru/viewer.ftl | 6 +++--- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/l10n/dsb/viewer.ftl b/l10n/dsb/viewer.ftl index 819d69e9493e1..3deccc162809c 100644 --- a/l10n/dsb/viewer.ftl +++ b/l10n/dsb/viewer.ftl @@ -167,10 +167,10 @@ pdfjs-printing-not-ready = Warnowanje: PDF njejo se za śišćanje dopołnje zac ## Tooltips and alt text for side panel toolbar buttons pdfjs-toggle-sidebar-button = - .title = Bócnicu pokazaś/schowaś + .title = Bocnicu pokazaś/schowaś pdfjs-toggle-sidebar-notification-button = .title = Bocnicu pśešaltowaś (dokument rozrědowanje/pśipiski/warstwy wopśimujo) -pdfjs-toggle-sidebar-button-label = Bócnicu pokazaś/schowaś +pdfjs-toggle-sidebar-button-label = Bocnicu pokazaś/schowaś pdfjs-document-outline-button = .title = Dokumentowe naraźenje pokazaś (dwójne kliknjenje, aby se wšykne zapiski pokazali/schowali) pdfjs-document-outline-button-label = Dokumentowa struktura @@ -389,9 +389,9 @@ pdfjs-editor-comments-sidebar-title = *[other] { $count } komentarow } pdfjs-editor-comments-sidebar-close-button = - .title = Bócnicu zacyniś - .aria-label = Bócnicu zacyniś -pdfjs-editor-comments-sidebar-close-button-label = Bócnicu zacyniś + .title = Bocnicu zacyniś + .aria-label = Bocnicu zacyniś +pdfjs-editor-comments-sidebar-close-button-label = Bocnicu zacyniś # Instructional copy to add a comment by selecting text or an annotations. pdfjs-editor-comments-sidebar-no-comments1 = Wiźiśo něco wobspomnjeśa gódnego? Wuzwigniśo to a zawóstajśo komentar. pdfjs-editor-comments-sidebar-no-comments-link = Dalšne informacije diff --git a/l10n/fur/viewer.ftl b/l10n/fur/viewer.ftl index 8f3c95a0be442..ed942244bce23 100644 --- a/l10n/fur/viewer.ftl +++ b/l10n/fur/viewer.ftl @@ -628,6 +628,11 @@ pdfjs-editor-edit-comment-dialog-text-input = .placeholder = Scomence a scrivi… pdfjs-editor-edit-comment-dialog-cancel-button = Anule +## Edit a comment button in the editor toolbar + +pdfjs-editor-add-comment-button = + .title = Zonte coment + ## Main menu for adding/removing signatures pdfjs-editor-delete-signature-button1 = diff --git a/l10n/kk/viewer.ftl b/l10n/kk/viewer.ftl index b5ae701b22f34..e5f1d05bee614 100644 --- a/l10n/kk/viewer.ftl +++ b/l10n/kk/viewer.ftl @@ -318,6 +318,12 @@ pdfjs-editor-signature-button-label = Қолтаңбаны қосу ## Default editor aria labels +# “Highlight” is a noun, the string is used on the editor for highlights. +pdfjs-editor-highlight-editor = + .aria-label = Ерекшелеу түзеткіші +# “Drawing” is a noun, the string is used on the editor for drawings. +pdfjs-editor-ink-editor = + .aria-label = Сурет салу түзеткіші # Used when a signature editor is selected/hovered. # Variables: # $description (String) - a string describing/labeling the signature. @@ -380,6 +386,8 @@ pdfjs-editor-comments-sidebar-close-button = .title = Бүйір панелін жабу .aria-label = Бүйір панелін жабу pdfjs-editor-comments-sidebar-close-button-label = Бүйір панелін жабу +# Instructional copy to add a comment by selecting text or an annotations. +pdfjs-editor-comments-sidebar-no-comments1 = Назар аударарлық бірдеңе көрдіңіз бе? Оны ерекшелеп, түсіндірме қалдырыңыз. pdfjs-editor-comments-sidebar-no-comments-link = Көбірек білу ## Alt-text dialog @@ -513,6 +521,7 @@ pdfjs-editor-alt-text-settings-close-button = Жабу ## Accessibility labels (announced by screen readers) for objects added to the editor. +pdfjs-editor-highlight-added-alert = Ерекшелеу қосылды pdfjs-editor-freetext-added-alert = Мәтін қосылды pdfjs-editor-ink-added-alert = Сызба қосылды pdfjs-editor-stamp-added-alert = Сурет қосылды @@ -586,6 +595,8 @@ pdfjs-editor-add-signature-save-checkbox = Қолтаңбаны сақтау pdfjs-editor-add-signature-save-warning-message = Сақталған 5 қолтаңбаның шегіне жеттіңіз. Көбірек сақтау үшін біреуін алып тастаңыз. pdfjs-editor-add-signature-image-upload-error-title = Суретті жүктеп жіберу мүмкін емес. pdfjs-editor-add-signature-image-upload-error-description = Желі байланысын тексеріңіз немесе басқа бейнені қолданып көріңіз. +pdfjs-editor-add-signature-image-no-data-error-title = Бұл суретті қолтаңбаға түрлендіру мүмкін емес +pdfjs-editor-add-signature-image-no-data-error-description = Басқа суретті жүктеп салып көріңіз. pdfjs-editor-add-signature-error-close-button = Жабу ## Dialog buttons @@ -594,10 +605,27 @@ pdfjs-editor-add-signature-cancel-button = Бас тарту pdfjs-editor-add-signature-add-button = Қосу pdfjs-editor-edit-signature-update-button = Жаңарту +## Comment popup + +pdfjs-editor-edit-comment-popup-button-label = Түсіндірмені түзету +pdfjs-editor-edit-comment-popup-button = + .title = Түсіндірмені түзету +pdfjs-editor-delete-comment-popup-button-label = Түсіндірмені өшіру +pdfjs-editor-delete-comment-popup-button = + .title = Түсіндірмені өшіру +pdfjs-show-comment-button = + .title = Түсіндірмені көрсету + ## Edit a comment dialog +# An existing comment is edited +pdfjs-editor-edit-comment-dialog-title-when-editing = Түсіндірмені түзету pdfjs-editor-edit-comment-dialog-save-button-when-editing = Жаңарту +# No existing comment +pdfjs-editor-edit-comment-dialog-title-when-adding = Түсіндірмені қосу pdfjs-editor-edit-comment-dialog-save-button-when-adding = Қосу +pdfjs-editor-edit-comment-dialog-text-input = + .placeholder = Теріп бастаңыз… pdfjs-editor-edit-comment-dialog-cancel-button = Бас тарту ## Edit a comment button in the editor toolbar diff --git a/l10n/ml/viewer.ftl b/l10n/ml/viewer.ftl index 59c807f232766..9476c8d489a23 100644 --- a/l10n/ml/viewer.ftl +++ b/l10n/ml/viewer.ftl @@ -309,6 +309,10 @@ pdfjs-editor-signature-add-signature-button-label = പുതിയ ഒപ്പ # $description (String) - a string describing/labeling the signature. pdfjs-editor-add-saved-signature-button = .title = കരുതിവച്ച ഒപ്പു് : { $description } +pdfjs-editor-comments-sidebar-close-button = + .title = അണിവക്കം അടയ്ക്കുക + .aria-label = അണിവക്കം അടയ്ക്കുക +pdfjs-editor-comments-sidebar-close-button-label = അണിവക്കം അടയ്ക്കുക ## Alt-text dialog diff --git a/l10n/ru/viewer.ftl b/l10n/ru/viewer.ftl index 23bd1ab4df94d..1632adab26697 100644 --- a/l10n/ru/viewer.ftl +++ b/l10n/ru/viewer.ftl @@ -70,10 +70,10 @@ pdfjs-page-rotate-ccw-button = .title = Повернуть против часовой стрелки pdfjs-page-rotate-ccw-button-label = Повернуть против часовой стрелки pdfjs-cursor-text-select-tool-button = - .title = Включить Инструмент «Выделение текста» + .title = Включить инструмент «Выделение текста» pdfjs-cursor-text-select-tool-button-label = Инструмент «Выделение текста» pdfjs-cursor-hand-tool-button = - .title = Включить Инструмент «Рука» + .title = Включить инструмент «Рука» pdfjs-cursor-hand-tool-button-label = Инструмент «Рука» pdfjs-scroll-page-button = .title = Использовать прокрутку страниц @@ -363,7 +363,7 @@ pdfjs-editor-free-highlight-thickness-input = Толщина pdfjs-editor-free-highlight-thickness-title = .title = Изменить толщину при выделении элементов, кроме текста pdfjs-editor-add-signature-container = - .aria-label = Управление подписями и сохраненные подписи + .aria-label = Управление подписями и сохранённые подписи pdfjs-editor-signature-add-signature-button = .title = Добавить новую подпись pdfjs-editor-signature-add-signature-button-label = Добавить новую подпись From 98c1955bd4302de6de3fec95e41b97451c773408 Mon Sep 17 00:00:00 2001 From: calixteman Date: Sat, 3 Jan 2026 14:00:13 +0100 Subject: [PATCH 5/5] Use the PDFium JBig2 decoder compiled into wasm The decoder is ~4x faster than the JS decoder on large images. --- eslint.config.mjs | 1 + external/jbig2/LICENSE_JBIG2 | 196 +++++++++++++++++++++++++++++ external/jbig2/LICENSE_PDFJS_JBIG2 | 13 ++ external/jbig2/README.md | 12 ++ external/jbig2/jbig2.js | 3 + external/jbig2/jbig2.wasm | Bin 0 -> 104822 bytes gulpfile.mjs | 7 +- src/core/image.js | 2 +- src/core/jbig2_stream.js | 38 +++++- src/core/jbig2_wasm.js | 127 +++++++++++++++++++ src/core/pdf_manager.js | 2 + test/pdfs/JBIG2Globals.pdf.link | 1 + test/test_manifest.json | 8 ++ 13 files changed, 406 insertions(+), 4 deletions(-) create mode 100644 external/jbig2/LICENSE_JBIG2 create mode 100644 external/jbig2/LICENSE_PDFJS_JBIG2 create mode 100644 external/jbig2/README.md create mode 100644 external/jbig2/jbig2.js create mode 100644 external/jbig2/jbig2.wasm create mode 100644 src/core/jbig2_wasm.js create mode 100644 test/pdfs/JBIG2Globals.pdf.link diff --git a/eslint.config.mjs b/eslint.config.mjs index 277475fad3b4d..07cb66e14ee91 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -35,6 +35,7 @@ export default [ "external/builder/fixtures_babel/", "external/openjpeg/", "external/qcms/", + "external/jbig2/", "external/quickjs/", "test/stats/results/", "test/tmp/", diff --git a/external/jbig2/LICENSE_JBIG2 b/external/jbig2/LICENSE_JBIG2 new file mode 100644 index 0000000000000..37a329c636c65 --- /dev/null +++ b/external/jbig2/LICENSE_JBIG2 @@ -0,0 +1,196 @@ +// Copyright 2014 The PDFium Authors +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + 1. Definitions. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + END OF TERMS AND CONDITIONS + APPENDIX: How to apply the Apache License to your work. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + Copyright [yyyy] [name of copyright owner] + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/external/jbig2/LICENSE_PDFJS_JBIG2 b/external/jbig2/LICENSE_PDFJS_JBIG2 new file mode 100644 index 0000000000000..f1845baf6613d --- /dev/null +++ b/external/jbig2/LICENSE_PDFJS_JBIG2 @@ -0,0 +1,13 @@ +Copyright 2026 Mozilla Foundation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/external/jbig2/README.md b/external/jbig2/README.md new file mode 100644 index 0000000000000..3736c91ee70e5 --- /dev/null +++ b/external/jbig2/README.md @@ -0,0 +1,12 @@ +## Build + +In order to generate the file `jbig2.js`: +* git clone https://github.com/mozilla/pdf.js.jbig2/ +* the build requires to have a [Docker](https://www.docker.com/) setup and then: + * `node build.js -C` to build the Docker image + * `node build.js -co /pdf.js/external/jbig2/` to compile the decoder + +## Licensing + +[PDFium](https://pdfium.googlesource.com/pdfium/) is under [Apache-2.0](https://pdfium.googlesource.com/pdfium/+/main/LICENSE) +and [pdf.js.jbig2](https://github.com/mozilla/pdf.js.jbig2/) is released under [Apache-2.0](https://github.com/mozilla/pdf.js.jbig2/blob/main/LICENSE) license so `jbig2.js` is released under [Apache-2.0](https://github.com/mozilla/pdf.js.jbig2/blob/main/LICENSE) license too. diff --git a/external/jbig2/jbig2.js b/external/jbig2/jbig2.js new file mode 100644 index 0000000000000..ab95ecb0fdf5d --- /dev/null +++ b/external/jbig2/jbig2.js @@ -0,0 +1,3 @@ +/* THIS FILE IS GENERATED - DO NOT EDIT */ +async function JBig2(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var _scriptName=import.meta.url;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports["i"]()}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module["locateFile"]){return locateFile("jbig2.wasm")}return new URL("jbig2.wasm",import.meta.url).href}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var __abort_js=()=>abort("");var runtimeKeepaliveCounter=0;var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var _emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};function _setImageData(array_ptr,pitch8,pitch32,height){if(pitch32===pitch8){Module.imageData=new Uint8ClampedArray(HEAPU8.subarray(array_ptr,array_ptr+pitch32*height));return}const destSize=pitch8*height;const imageData=Module.imageData=new Uint8ClampedArray(destSize);for(let srcStart=array_ptr,destStart=0;destStart{HEAP8.set(array,buffer)};{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}Module["writeArrayToMemory"]=writeArrayToMemory;var _malloc,_free,_jbig2_decode,__emscripten_timeout,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_malloc=Module["_malloc"]=wasmExports["j"];_free=Module["_free"]=wasmExports["k"];_jbig2_decode=Module["_jbig2_decode"]=wasmExports["l"];__emscripten_timeout=wasmExports["m"];memory=wasmMemory=wasmExports["h"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={a:___cxa_throw,f:__abort_js,c:__emscripten_runtime_keepalive_clear,d:__setitimer_js,e:_emscripten_resize_heap,b:_proc_exit,g:_setImageData};function run(){preRun();function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +;return moduleRtn}export default JBig2; diff --git a/external/jbig2/jbig2.wasm b/external/jbig2/jbig2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ab3c9fcd217688adab8b67738bd869393e810feb GIT binary patch literal 104822 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 0; const computedLength = ((width + 7) >> 3) * height; - const imgArray = image.getBytes(computedLength); + const imgArray = await image.getImageData(computedLength); const isSingleOpaquePixel = width === 1 && diff --git a/src/core/jbig2_stream.js b/src/core/jbig2_stream.js index 126669c811c45..0fdda06ae1a93 100644 --- a/src/core/jbig2_stream.js +++ b/src/core/jbig2_stream.js @@ -13,11 +13,12 @@ * limitations under the License. */ +import { shadow, warn } from "../shared/util.js"; import { BaseStream } from "./base_stream.js"; import { DecodeStream } from "./decode_stream.js"; import { Dict } from "./primitives.js"; import { Jbig2Image } from "./jbig2.js"; -import { shadow } from "../shared/util.js"; +import { JBig2WasmImage } from "./jbig2_wasm.js"; /** * For JBIG2's we use a library to decode these images and @@ -47,7 +48,40 @@ class Jbig2Stream extends DecodeStream { this.decodeImage(); } - decodeImage(bytes) { + get isAsyncDecoder() { + return true; + } + + async decodeImage(bytes, _decoderOptions) { + if (this.eof) { + return this.buffer; + } + bytes ||= this.bytes; + try { + let globals = null; + if (this.params instanceof Dict) { + const globalsStream = this.params.get("JBIG2Globals"); + if (globalsStream instanceof BaseStream) { + globals = globalsStream.getBytes(); + } + } + this.buffer = await JBig2WasmImage.decode( + bytes, + this.dict.get("Width"), + this.dict.get("Height"), + globals + ); + } catch { + warn("Jbig2Stream: Falling back to JS JBIG2 decoder."); + return this.decodeImageFallback(bytes); + } + this.bufferLength = this.buffer.length; + this.eof = true; + + return this.buffer; + } + + async decodeImageFallback(bytes) { if (this.eof) { return this.buffer; } diff --git a/src/core/jbig2_wasm.js b/src/core/jbig2_wasm.js new file mode 100644 index 0000000000000..2e5dca66231bb --- /dev/null +++ b/src/core/jbig2_wasm.js @@ -0,0 +1,127 @@ +/* Copyright 2026 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseException, warn } from "../shared/util.js"; +import { fetchBinaryData } from "./core_utils.js"; +import JBig2 from "../../external/jbig2/jbig2.js"; + +class JBig2Error extends BaseException { + constructor(msg) { + super(msg, "Jbig2Error"); + } +} + +class JBig2WasmImage { + static #buffer = null; + + static #handler = null; + + static #modulePromise = null; + + static #useWasm = true; + + static #useWorkerFetch = true; + + static #wasmUrl = null; + + static setOptions({ handler, useWasm, useWorkerFetch, wasmUrl }) { + this.#useWasm = useWasm; + this.#useWorkerFetch = useWorkerFetch; + this.#wasmUrl = wasmUrl; + + if (!useWorkerFetch) { + this.#handler = handler; + } + } + + static async #instantiateWasm(fallbackCallback, imports, successCallback) { + const filename = "jbig2.wasm"; + try { + if (!this.#buffer) { + if (this.#useWorkerFetch) { + this.#buffer = await fetchBinaryData(`${this.#wasmUrl}${filename}`); + } else { + this.#buffer = await this.#handler.sendWithPromise( + "FetchBinaryData", + { type: "wasmFactory", filename } + ); + } + } + const results = await WebAssembly.instantiate(this.#buffer, imports); + return successCallback(results.instance); + } catch (reason) { + warn(`JBig2Image#instantiateWasm: ${reason}`); + return null; + } finally { + this.#handler = null; + } + } + + static async decode(bytes, width, height, globals) { + if (!this.#modulePromise) { + const { promise, resolve } = Promise.withResolvers(); + const promises = [promise]; + if (this.#useWasm) { + promises.push( + JBig2({ + warn, + instantiateWasm: this.#instantiateWasm.bind(this, resolve), + }) + ); + } else { + resolve(null); + } + this.#modulePromise = Promise.race(promises); + } + const module = await this.#modulePromise; + if (!module) { + throw new JBig2Error("JBig2 failed to initialize"); + } + let ptr, globalsPtr; + + try { + const size = bytes.length; + ptr = module._malloc(size); + module.writeArrayToMemory(bytes, ptr); + const globalsSize = globals ? globals.length : 0; + if (globalsSize > 0) { + globalsPtr = module._malloc(globalsSize); + module.writeArrayToMemory(globals, globalsPtr); + } + + module._jbig2_decode(ptr, size, width, height, globalsPtr, globalsSize); + if (!module.imageData) { + throw new JBig2Error("Unknown error"); + } + const { imageData } = module; + module.imageData = null; + + return imageData; + } finally { + if (ptr) { + module._free(ptr); + } + if (globalsPtr) { + module._free(globalsPtr); + } + } + } + + static cleanup() { + this.#modulePromise = null; + } +} + +export { JBig2Error, JBig2WasmImage }; diff --git a/src/core/pdf_manager.js b/src/core/pdf_manager.js index 9ee866cdbfda2..3c4255efbeb60 100644 --- a/src/core/pdf_manager.js +++ b/src/core/pdf_manager.js @@ -22,6 +22,7 @@ import { } from "../shared/util.js"; import { ChunkedStreamManager } from "./chunked_stream.js"; import { ImageResizer } from "./image_resizer.js"; +import { JBig2WasmImage } from "./jbig2_wasm.js"; import { JpegStream } from "./jpeg_stream.js"; import { JpxImage } from "./jpx.js"; import { MissingDataException } from "./core_utils.js"; @@ -81,6 +82,7 @@ class BasePdfManager { JpxImage.setOptions(options); IccColorSpace.setOptions(options); CmykICCBasedCS.setOptions(options); + JBig2WasmImage.setOptions(options); } get docId() { diff --git a/test/pdfs/JBIG2Globals.pdf.link b/test/pdfs/JBIG2Globals.pdf.link new file mode 100644 index 0000000000000..a4aa000f55bcc --- /dev/null +++ b/test/pdfs/JBIG2Globals.pdf.link @@ -0,0 +1 @@ +https://github.com/pdfminer/pdfminer.six/files/8399364/64.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 860497c72ebc9..22b144a415cba 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -13131,5 +13131,13 @@ "rounds": 1, "link": true, "type": "eq" + }, + { + "id": "JBIG2Globals", + "file": "pdfs/JBIG2Globals.pdf", + "md5": "78ee015a604678a4efbdcd993e0d77aa", + "rounds": 1, + "link": true, + "type": "eq" } ]