diff --git a/external/color_utils.mjs b/external/color_utils.mjs new file mode 100644 index 0000000000000..739e83689623f --- /dev/null +++ b/external/color_utils.mjs @@ -0,0 +1,25 @@ +/* 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 kleur from "kleur"; + +// Kleur has one global switch, so use stdout for automatic TTY detection. +kleur.enabled = + !process.env.NO_COLOR && + (!!process.stdout.isTTY || + !!process.env.FORCE_COLOR || + process.env.GITHUB_ACTIONS === "true"); + +export { kleur }; diff --git a/gulpfile.mjs b/gulpfile.mjs index e7e40af8d91c6..535889aaa0a86 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -25,15 +25,16 @@ import { parseCoverageFormats, } from "./external/ccov/coverage_format.mjs"; import { exec, execSync, spawn, spawnSync } from "child_process"; +import { finished, pipeline as runPipeline } from "stream/promises"; import autoprefixer from "autoprefixer"; import { buildPrefsSchema } from "./external/chromium/prefs.mjs"; import crypto from "crypto"; -import { finished } from "stream/promises"; import fs from "fs"; import gulp from "gulp"; import hljs from "highlight.js"; import istanbulCoverage from "istanbul-lib-coverage"; import istanbulReportGenerator from "istanbul-reports"; +import { kleur } from "./external/color_utils.mjs"; import layouts from "@metalsmith/layouts"; import libReport from "istanbul-lib-report"; import markdown from "@metalsmith/markdown"; @@ -76,6 +77,11 @@ const TYPES_DIR = BUILD_DIR + "types/"; const TMP_DIR = BUILD_DIR + "tmp/"; const PREFSTEST_DIR = BUILD_DIR + "prefstest/"; const TYPESTEST_DIR = BUILD_DIR + "typestest/"; +const MOZCENTRAL_DIR = BUILD_DIR + "mozcentral/"; +const MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + "browser/extensions/pdfjs/"; +const MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + "content/"; +const MOZCENTRAL_L10N_DIR = MOZCENTRAL_DIR + "browser/locales/en-US/pdfviewer/"; +const CHROMIUM_DIR = BUILD_DIR + "chromium/"; const COMMON_WEB_FILES = [ "web/images/*.{png,svg,gif}", "web/debugger.{css,mjs}", @@ -104,7 +110,7 @@ const BABEL_TARGETS = ENV_TARGETS.join(", "); const BABEL_COREJS_OPTS = Object.freeze({ method: "usage-global", - version: "3.49.0", + version: "3.50.0", exclude: ["web.structured-clone"], shippedProposals: true, }); @@ -276,6 +282,35 @@ function createWebpackAlias(defines) { return alias; } +/** + * Webpack's file and missing dependencies, keyed by output filename. + * @type {Map>} + */ +const webpackFileDeps = new Map(); + +/** Return a Webpack plugin that records dependencies for `filename`. */ +function recordFileDeps(filename) { + return { + /** @param {import('webpack').Compiler} compiler */ + apply(compiler) { + compiler.hooks.done.tap("RecordFileDependencies", ({ compilation }) => { + const dependencies = new Set([ + ...compilation.fileDependencies, + ...compilation.missingDependencies, + ]); + + // Preserve known dependencies after a failed compilation. + if (compilation.errors.length > 0) { + for (const dependency of webpackFileDeps.get(filename) ?? []) { + dependencies.add(dependency); + } + } + webpackFileDeps.set(filename, dependencies); + }); + }, + }; +} + function createWebpackConfig( defines, output, @@ -351,7 +386,7 @@ function createWebpackConfig( }) ); } - plugins.push({ + plugins.push(recordFileDeps(output.filename), { /** @param {import('webpack').Compiler} compiler */ apply(compiler) { const errors = []; @@ -452,6 +487,46 @@ function webpack2Stream(webpackConfig) { return webpackStream(webpackConfig, webpack2); } +/** Write a Vinyl stream to `dest` and wait for completion. */ +function writeToDirectory(readable, dest) { + return runPipeline( + readable, + gulp.dest(dest), + // Drain `gulp.dest`'s readable side to prevent backpressure. + new stream.Writable({ + objectMode: true, + write(_file, _encoding, callback) { + callback(); + }, + }) + ); +} + +function getErrorMessages(error) { + if (error instanceof AggregateError) { + return error.errors.flatMap(getErrorMessages); + } + if (error?.plugin === "webpack-stream") { + // Avoid repeating webpack-stream's compilation diagnostics. + return []; + } + return [ + error instanceof Error ? error.stack || error.message : String(error), + ]; +} + +function reportBuildFailure(error) { + console.error(kleur.red(`\n### ${error?.message || "Build failed"}`)); + for (const message of getErrorMessages(error)) { + console.error(kleur.red(message)); + } +} + +/** Return a repository-relative path with POSIX separators. */ +function repoPath(filePath) { + return path.relative(__dirname, filePath).split(path.sep).join("/"); +} + function getVersionJSON() { return JSON.parse(fs.readFileSync(BUILD_DIR + "version.json").toString()); } @@ -1175,7 +1250,7 @@ function createBuildNumber(done) { ); } -function buildDefaultPreferences(defines, dir) { +function createDefaultPreferencesBundle(defines, dir) { console.log(`\n### Building default preferences (${dir})`); const bundleDefines = { @@ -1198,20 +1273,29 @@ function buildDefaultPreferences(defines, dir) { ); return gulp .src("web/app_options.js", { encoding: false }) - .pipe(webpack2Stream(defaultPreferencesConfig)) - .pipe(gulp.dest(DEFAULT_PREFERENCES_DIR + dir)); + .pipe(webpack2Stream(defaultPreferencesConfig)); } -function getDefaultPreferences(dir) { - console.log(`\n### Parsing default preferences (${dir})`); +function buildDefaultPreferences(defines, dir) { + return createDefaultPreferencesBundle(defines, dir).pipe( + gulp.dest(DEFAULT_PREFERENCES_DIR + dir) + ); +} + +let defaultPreferencesId = 0; - const require = process - .getBuiltinModule("module") - .createRequire(import.meta.url); +async function getDefaultPreferences(dir) { + console.log(`\n### Parsing default preferences (${dir})`); - const { AppOptions, OptionKind } = require( - "./" + DEFAULT_PREFERENCES_DIR + dir + "app_options.mjs" + const url = new URL( + `${DEFAULT_PREFERENCES_DIR}${dir}app_options.mjs`, + import.meta.url ); + // Node caches ES modules by URL; vary it to reload this bundle in watch mode. + url.searchParams.set("id", defaultPreferencesId++); + + // eslint-disable-next-line no-unsanitized/method + const { AppOptions, OptionKind } = await import(url.href); const prefs = AppOptions.getAll( OptionKind.PREFERENCE, @@ -1550,7 +1634,7 @@ gulp.task( ) ); -function createDefaultPrefsFile() { +async function createDefaultPrefsFile() { console.log("\n### Building mozilla-central preferences file"); const defaultFileName = "PdfJsDefaultPrefs.js", @@ -1561,7 +1645,7 @@ function createDefaultPrefsFile() { "// THIS FILE IS GENERATED AUTOMATICALLY, DO NOT EDIT MANUALLY!\n//\n" + `// Any overrides should be placed in \`${overrideFileName}\`.\n`; - const prefs = getDefaultPreferences("mozcentral/"); + const prefs = await getDefaultPreferences("mozcentral/"); const buf = []; for (const name in prefs) { @@ -1579,104 +1663,203 @@ function createDefaultPrefsFile() { return createStringSource(defaultFileName, buf.join("\n")); } -gulp.task( - "mozcentral", - gulp.series( - createBuildNumber, - function scriptingMozcentral() { - const defines = { ...DEFINES, MOZCENTRAL: true }; - return buildDefaultPreferences(defines, "mozcentral/"); - }, - function createMozcentral() { - console.log("\n### Building mozilla-central extension"); - const defines = { ...DEFINES, MOZCENTRAL: true }; - const gvDefines = { ...defines, GECKOVIEW: true }; +/** + * Build the mozilla-central staging tree. + * @param {Set|null} [changedFiles] - Absolute changed paths. Omit for + * a full build. + * @returns {Promise} Whether any output was built. + */ +async function buildMozcentral(changedFiles = null) { + console.log("\n### Building mozilla-central extension"); + const defines = { ...DEFINES, MOZCENTRAL: true }; + const gvDefines = { ...defines, GECKOVIEW: true }; - const MOZCENTRAL_DIR = BUILD_DIR + "mozcentral/", - MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + "browser/extensions/pdfjs/", - MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + "content/", - MOZCENTRAL_L10N_DIR = - MOZCENTRAL_DIR + "browser/locales/en-US/pdfviewer/"; + const MOZCENTRAL_BUILD_DIR = MOZCENTRAL_CONTENT_DIR + "build", + MOZCENTRAL_WEB_DIR = MOZCENTRAL_CONTENT_DIR + "web"; - const MOZCENTRAL_WEB_FILES = [ - ...COMMON_WEB_FILES, - "!web/images/toolbarButton-openFile.svg", - ]; - const MOZCENTRAL_AUTOPREFIXER_CONFIG = { - overrideBrowserslist: ["last 1 firefox versions"], - }; + const MOZCENTRAL_WEB_FILES = [ + ...COMMON_WEB_FILES, + "!web/images/toolbarButton-openFile.svg", + ]; + const MOZCENTRAL_AUTOPREFIXER_CONFIG = { + overrideBrowserslist: ["last 1 firefox versions"], + }; - // Clear out everything in the firefox extension build directory - fs.rmSync(MOZCENTRAL_DIR, { recursive: true, force: true }); + const fullBuild = !changedFiles; + const changedPaths = fullBuild ? [] : [...changedFiles].map(repoPath); - return ordered([ - createMainBundle(defines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "build") - ), - createScriptingBundle(defines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "build") - ), - createSandboxExternal(defines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "build") - ), - createWorkerBundle(defines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "build") - ), - createWebBundle(defines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web") - ), - createGVWebBundle(gvDefines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web") - ), - gulp - .src(MOZCENTRAL_WEB_FILES, { base: "web/", encoding: false }) - .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")), - createCMapBundle().pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/cmaps") - ), - createICCBundle().pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/iccs")), - createStandardFontBundle().pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/standard_fonts") - ), - createWasmBundle({ includeQuickJS: false }).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/wasm") - ), + if (fullBuild) { + // Clear the staging tree before a full build. + fs.rmSync(MOZCENTRAL_DIR, { recursive: true, force: true }); + } - preprocessHTML("web/viewer.html", defines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web") + // Rebuild bundles with unknown or changed Webpack dependencies. + function bundleChanged(filename) { + const deps = webpackFileDeps.get(filename); + return !deps || [...changedFiles].some(file => deps.has(file)); + } + // Match changed paths for non-Webpack outputs. + function sourceChanged(regExp) { + return changedPaths.some(p => regExp.test(p)); + } + + // Map outputs to their builders and watch dependencies. + const units = [ + { bundle: "pdf.mjs", create: () => createMainBundle(defines) }, + { + bundle: "pdf.scripting.mjs", + create: () => createScriptingBundle(defines), + }, + { bundle: "pdf.worker.mjs", create: () => createWorkerBundle(defines) }, + { + files: /^src\/pdf\.sandbox\.external\.js$/, + create: () => createSandboxExternal(defines), + }, + { + bundle: "viewer.mjs", + dest: MOZCENTRAL_WEB_DIR, + create: () => createWebBundle(defines), + }, + { + bundle: "viewer-geckoview.mjs", + dest: MOZCENTRAL_WEB_DIR, + create: () => createGVWebBundle(gvDefines), + }, + { + files: /^web\/(images\/|debugger\.)/, + dest: MOZCENTRAL_WEB_DIR, + create: () => + gulp.src(MOZCENTRAL_WEB_FILES, { base: "web/", encoding: false }), + }, + { + files: /^external\/bcmaps\//, + dest: MOZCENTRAL_WEB_DIR + "/cmaps", + create: createCMapBundle, + }, + { + files: /^external\/iccs\//, + dest: MOZCENTRAL_WEB_DIR + "/iccs", + create: createICCBundle, + }, + { + files: /^external\/standard_fonts\//, + dest: MOZCENTRAL_WEB_DIR + "/standard_fonts", + create: createStandardFontBundle, + }, + { + files: /^external\/(jbig2|openjpeg|qcms)\//, + dest: MOZCENTRAL_WEB_DIR + "/wasm", + create: () => createWasmBundle({ includeQuickJS: false }), + }, + // HTML includes and CSS imports aren't tracked individually; a top-level + // HTML or CSS change rebuilds both corresponding variants. + { + files: /^web\/[^/]+\.html$/, + dest: MOZCENTRAL_WEB_DIR, + create: () => preprocessHTML("web/viewer.html", defines), + }, + { + files: /^web\/[^/]+\.html$/, + dest: MOZCENTRAL_WEB_DIR, + create: () => preprocessHTML("web/viewer-geckoview.html", gvDefines), + }, + { + files: /^web\/[^/]+\.css$/, + dest: MOZCENTRAL_WEB_DIR, + create: () => + preprocessCSS("web/viewer.css", defines).pipe( + postcss([ + discardCommentsCSS(), + autoprefixer(MOZCENTRAL_AUTOPREFIXER_CONFIG), + ]) ), - preprocessHTML("web/viewer-geckoview.html", gvDefines).pipe( - gulp.dest(MOZCENTRAL_CONTENT_DIR + "web") + }, + { + files: /^web\/[^/]+\.css$/, + dest: MOZCENTRAL_WEB_DIR, + create: () => + preprocessCSS("web/viewer-geckoview.css", gvDefines).pipe( + postcss([ + discardCommentsCSS(), + autoprefixer(MOZCENTRAL_AUTOPREFIXER_CONFIG), + ]) ), + }, + { + files: /^l10n\/en-US\/[^/]+\.ftl$/, + dest: MOZCENTRAL_L10N_DIR, + create: () => gulp.src("l10n/en-US/*.ftl", { encoding: false }), + }, + { + files: /^LICENSE$/, + dest: MOZCENTRAL_EXTENSION_DIR, + create: () => gulp.src("LICENSE", { encoding: false }), + }, + // PdfJsDefaultPrefs.js is generated from this bundle. + { + bundle: "app_options.mjs", + dest: DEFAULT_PREFERENCES_DIR + "mozcentral/", + create: () => createDefaultPreferencesBundle(defines, "mozcentral/"), + }, + ]; - preprocessCSS("web/viewer.css", defines) - .pipe( - postcss([ - discardCommentsCSS(), - autoprefixer(MOZCENTRAL_AUTOPREFIXER_CONFIG), - ]) - ) - .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")), + const builds = []; + let prefsBuildIndex = -1; - preprocessCSS("web/viewer-geckoview.css", gvDefines) - .pipe( - postcss([ - discardCommentsCSS(), - autoprefixer(MOZCENTRAL_AUTOPREFIXER_CONFIG), - ]) - ) - .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")), + for (const { bundle, files, dest = MOZCENTRAL_BUILD_DIR, create } of units) { + if (fullBuild || (bundle ? bundleChanged(bundle) : sourceChanged(files))) { + if (bundle === "app_options.mjs") { + prefsBuildIndex = builds.length; + } + builds.push( + // Convert synchronous builder errors to rejections so all units settle. + (async () => { + await writeToDirectory(create(), dest); + })() + ); + } + } - gulp - .src("l10n/en-US/*.ftl", { encoding: false }) - .pipe(gulp.dest(MOZCENTRAL_L10N_DIR)), - gulp - .src("LICENSE", { encoding: false }) - .pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)), - createDefaultPrefsFile().pipe(gulp.dest(MOZCENTRAL_EXTENSION_DIR)), - ]); + if (builds.length === 0) { + console.log("Nothing to rebuild."); + return false; + } + + // Even after a failure, wait for every unit before the next watch build. + const results = await Promise.allSettled(builds); + const errors = results + .filter(({ status }) => status === "rejected") + .map(({ reason }) => reason); + + // Generate preferences after their bundle succeeds, even if another unit + // failed: the next build may reuse this bundle before synchronizing. + if (prefsBuildIndex >= 0 && results[prefsBuildIndex].status === "fulfilled") { + try { + await writeToDirectory( + await createDefaultPrefsFile(), + MOZCENTRAL_EXTENSION_DIR + ); + } catch (error) { + errors.push(error); } - ) + } + + if (errors.length > 0) { + throw new AggregateError(errors, "The mozilla-central build failed."); + } + return true; +} + +gulp.task( + "mozcentral", + gulp.series(createBuildNumber, async function createMozcentral() { + try { + return await buildMozcentral(); + } catch (error) { + reportBuildFailure(error); + throw error; + } + }) ); function getGeckoDirs() { @@ -1799,16 +1982,10 @@ function hasWatchArg() { return process.argv.includes("-w"); } -function updateMozcentral(done) { +function syncMozcentral() { const { rootDir, pdfjsDir, l10nDir } = getGeckoDirs(); console.log(`\n### Updating PDF.js in "${rootDir}"`); - const MOZCENTRAL_EXTENSION_DIR = - BUILD_DIR + "mozcentral/browser/extensions/pdfjs/", - MOZCENTRAL_CONTENT_DIR = MOZCENTRAL_EXTENSION_DIR + "content/", - MOZCENTRAL_L10N_DIR = - BUILD_DIR + "mozcentral/browser/locales/en-US/pdfviewer/"; - const stats = { updated: [], removed: [], unchanged: 0 }; // Mirror `build` and `web`; preserve other `content` entries. @@ -1842,53 +2019,93 @@ function updateMozcentral(done) { console.log(` deleted: ${filePath}`); } for (const filePath of stats.updated) { - console.log(` updated: ${filePath}`); + console.log(kleur.green(` updated: ${filePath}`)); } console.log( `\n${stats.updated.length} file(s) updated, ` + `${stats.removed.length} file(s) deleted, ` + `${stats.unchanged} file(s) unchanged.` ); +} + +function watchMozcentral(done) { + if (!hasWatchArg()) { + done(); + return; + } + const MOZCENTRAL_SOURCE_FILES = [ + "src/**", + "web/**", + "!web/locale/**", // Generated by the `locale` task. + "!web/wasm/**", // Generated by the `dev-wasm` task. + "l10n/en-US/*.ftl", + "external/bcmaps/*", + "external/iccs/*", + "external/jbig2/*", + "external/openjpeg/*", + "external/qcms/*", + "external/standard_fonts/*", + "LICENSE", + ]; + + console.log("\n### Watching for changes; press Ctrl+C to stop"); + + const changedFiles = new Set(); + let timeoutId = null, + building = false; + + async function rebuild() { + timeoutId = null; + if (building) { + return; // The active rebuild will consume these changes. + } + building = true; + + while (changedFiles.size > 0) { + const files = new Set(changedFiles); + changedFiles.clear(); + + console.log( + `\n### Changed: ${[...files].map(repoPath).sort().join(", ")}` + ); + try { + if (await buildMozcentral(files)) { + syncMozcentral(); + } + } catch (error) { + // Keep watching so a later edit can fix the error. + reportBuildFailure(error); + } + } + building = false; + } + + gulp.watch(MOZCENTRAL_SOURCE_FILES).on("all", (event, filePath) => { + changedFiles.add(path.resolve(filePath)); + // Coalesce event bursts such as branch switches. + clearTimeout(timeoutId); + timeoutId = setTimeout(rebuild, 100); + }); done(); } gulp.task( "firefox", - gulp.series("mozcentral", updateMozcentral, function watchMozcentral(done) { - if (!hasWatchArg()) { + gulp.series( + "mozcentral", + function updateMozcentral(done) { + syncMozcentral(); done(); - return; - } - const MOZCENTRAL_SOURCE_FILES = [ - "src/**", - "web/**", - "!web/locale/**", // Generated by the `locale` task. - "!web/wasm/**", // Generated by the `dev-wasm` task. - "l10n/en-US/*.ftl", - "external/bcmaps/*", - "external/iccs/*", - "external/jbig2/*", - "external/openjpeg/*", - "external/qcms/*", - "external/standard_fonts/*", - "LICENSE", - ]; - - console.log("\n### Watching for changes; press Ctrl+C to stop"); - - gulp.watch( - MOZCENTRAL_SOURCE_FILES, - gulp.series("mozcentral", updateMozcentral) - ); - done(); - }) + }, + watchMozcentral + ) ); -function createChromiumPrefsSchema() { +async function createChromiumPrefsSchema() { console.log("\n### Building Chromium preferences file"); - const prefs = getDefaultPreferences("chromium/"); + const prefs = await getDefaultPreferences("chromium/"); const chromiumPrefs = buildPrefsSchema(prefs); return createStringSource( @@ -1913,8 +2130,7 @@ gulp.task( console.log("\n### Building Chromium extension"); const defines = { ...DEFINES, CHROME: true, SKIP_BABEL: false }; - const CHROME_BUILD_DIR = BUILD_DIR + "/chromium/", - CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + "/content/"; + const CHROME_BUILD_CONTENT_DIR = CHROMIUM_DIR + "content/"; const CHROME_WEB_FILES = [ ...COMMON_WEB_FILES, @@ -1922,7 +2138,7 @@ gulp.task( ]; // Clear out everything in the chrome extension build directory - fs.rmSync(CHROME_BUILD_DIR, { recursive: true, force: true }); + fs.rmSync(CHROMIUM_DIR, { recursive: true, force: true }); const version = getVersionJSON().version; @@ -1971,21 +2187,21 @@ gulp.task( ) .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + "web")), - gulp - .src("LICENSE", { encoding: false }) - .pipe(gulp.dest(CHROME_BUILD_DIR)), + gulp.src("LICENSE", { encoding: false }).pipe(gulp.dest(CHROMIUM_DIR)), gulp .src("extensions/chromium/manifest.json", { encoding: false }) .pipe(replace(/\bPDFJSSCRIPT_VERSION\b/g, version)) - .pipe(gulp.dest(CHROME_BUILD_DIR)), + .pipe(gulp.dest(CHROMIUM_DIR)), gulp .src(["extensions/chromium/**/*.{html,js,css,png}"], { base: "extensions/chromium/", encoding: false, }) - .pipe(gulp.dest(CHROME_BUILD_DIR)), - createChromiumPrefsSchema().pipe(gulp.dest(CHROME_BUILD_DIR)), + .pipe(gulp.dest(CHROMIUM_DIR)), ]); + }, + async function prefsSchemaChromium() { + return writeToDirectory(await createChromiumPrefsSchema(), CHROMIUM_DIR); } ) ); @@ -2375,7 +2591,7 @@ gulp.task( const defines = { ...DEFINES, MOZCENTRAL: true }; return buildDefaultPreferences(defines, "mozcentral/"); }, - function checkPrefs() { + async function checkPrefs() { console.log("\n### Checking preference generation"); // Check that the preferences were correctly generated, @@ -2386,14 +2602,12 @@ gulp.task( "chromium/", "mozcentral/", ]) { - getDefaultPreferences(dir); + await getDefaultPreferences(dir); } // Check that all the relevant files can be generated. - return ordered([ - createChromiumPrefsSchema().pipe(gulp.dest(PREFSTEST_DIR)), - createDefaultPrefsFile().pipe(gulp.dest(PREFSTEST_DIR)), - ]); + await writeToDirectory(await createChromiumPrefsSchema(), PREFSTEST_DIR); + await writeToDirectory(await createDefaultPrefsFile(), PREFSTEST_DIR); } ) ); diff --git a/package-lock.json b/package-lock.json index 7c2b22515ef00..c40c675d83d49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,32 +15,32 @@ "@fluent/dom": "^0.10.2", "@metalsmith/layouts": "^3.0.0", "@metalsmith/markdown": "^1.10.0", - "@napi-rs/canvas": "^1.0.3", - "@types/node": "^26.1.2", + "@napi-rs/canvas": "^1.0.6", + "@types/node": "^26.2.0", "autoprefixer": "^10.5.4", "babel-loader": "^10.1.1", "babel-plugin-istanbul": "^8.0.2", "babel-plugin-polyfill-corejs3": "^1.0.0", "cached-iterable": "^0.3.0", - "caniuse-lite": "^1.0.30001806", - "core-js": "^3.49.0", - "eslint": "^10.8.0", + "caniuse-lite": "^1.0.30001809", + "core-js": "^3.50.0", + "eslint": "^10.8.1", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import-x": "^4.17.1", "eslint-plugin-jasmine": "^4.2.2", "eslint-plugin-no-unsanitized": "^4.1.5", - "eslint-plugin-perfectionist": "^5.10.0", + "eslint-plugin-perfectionist": "^5.10.1", "eslint-plugin-prettier": "^5.5.6", - "eslint-plugin-regexp": "^3.1.1", - "eslint-plugin-unicorn": "^72.0.0", - "globals": "^17.8.0", + "eslint-plugin-regexp": "^3.2.0", + "eslint-plugin-unicorn": "^73.0.0", + "globals": "^17.11.0", "gulp": "^5.0.1", "gulp-cli": "^3.1.0", "gulp-postcss": "^10.0.0", "gulp-rename": "^2.1.0", "gulp-replace": "^1.1.4", "gulp-zip": "^6.1.0", - "highlight.js": "^11.11.1", + "highlight.js": "^11.12.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", @@ -52,11 +52,11 @@ "metalsmith-html-relative": "^2.0.13", "ordered-read-streams": "^2.0.0", "pngjs": "^7.0.0", - "postcss": "^8.5.25", - "postcss-discard-comments": "^8.0.1", + "postcss": "^8.5.26", + "postcss-discard-comments": "^8.0.3", "postcss-values-parser": "^8.0.0", "prettier": "^3.9.6", - "puppeteer": "^25.4.0", + "puppeteer": "^25.7.0", "stylelint": "^17.14.1", "stylelint-prettier": "^5.0.3", "svglint": "^4.2.1", @@ -3669,9 +3669,9 @@ } }, "node_modules/@napi-rs/canvas": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-1.0.3.tgz", - "integrity": "sha512-OlI657a5XXvKGFX7kNeIzJ8rO7IXt87Mqu2H8rXE46viAuOfum/JA7ysX7+eBhxNKznT+RCZh418mndlcFX3+w==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-1.0.6.tgz", + "integrity": "sha512-Ud4d0jLr9vSaakvfOTIjgP3hoY8kMIYgHC4mtE4L0bP3St9lf6TyCVsInvFIOEofzcUeMfDydHDy8Fs2WuWz+A==", "dev": true, "license": "MIT", "workspaces": [ @@ -3685,23 +3685,23 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "optionalDependencies": { - "@napi-rs/canvas-android-arm64": "1.0.3", - "@napi-rs/canvas-darwin-arm64": "1.0.3", - "@napi-rs/canvas-darwin-x64": "1.0.3", - "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.3", - "@napi-rs/canvas-linux-arm64-gnu": "1.0.3", - "@napi-rs/canvas-linux-arm64-musl": "1.0.3", - "@napi-rs/canvas-linux-riscv64-gnu": "1.0.3", - "@napi-rs/canvas-linux-x64-gnu": "1.0.3", - "@napi-rs/canvas-linux-x64-musl": "1.0.3", - "@napi-rs/canvas-win32-arm64-msvc": "1.0.3", - "@napi-rs/canvas-win32-x64-msvc": "1.0.3" + "@napi-rs/canvas-android-arm64": "1.0.6", + "@napi-rs/canvas-darwin-arm64": "1.0.6", + "@napi-rs/canvas-darwin-x64": "1.0.6", + "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.6", + "@napi-rs/canvas-linux-arm64-gnu": "1.0.6", + "@napi-rs/canvas-linux-arm64-musl": "1.0.6", + "@napi-rs/canvas-linux-riscv64-gnu": "1.0.6", + "@napi-rs/canvas-linux-x64-gnu": "1.0.6", + "@napi-rs/canvas-linux-x64-musl": "1.0.6", + "@napi-rs/canvas-win32-arm64-msvc": "1.0.6", + "@napi-rs/canvas-win32-x64-msvc": "1.0.6" } }, "node_modules/@napi-rs/canvas-android-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-1.0.3.tgz", - "integrity": "sha512-7kSCdUhoXiO+AaIMXdBGdtp6EctZNkmF62Rea/BmVQlwKaM3bBhOzyGUzxyxz9dv5vdBfpyAaxhSRSJF4kqK4A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-1.0.6.tgz", + "integrity": "sha512-CZUmZEyN/cmSN1OhRJ44vBE6xyb5ekBbsIF8dqNgizbnAiHSFNi8eAA4oyyIAe5KzJ72K16OKC2lAynZLhv32Q==", "cpu": [ "arm64" ], @@ -3720,9 +3720,9 @@ } }, "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-1.0.3.tgz", - "integrity": "sha512-ds14V1BPagLszQyaDTeggny5fNeTCqsUQ5QhFj9VDxSEfzrVxXtdbR0LoFyKa0Siaaw8KvqSk4t7k/WoZJwvbg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-1.0.6.tgz", + "integrity": "sha512-FGJsIngRfS9LDaX4t/lFthqn2Km6b61ONzjJFC6+yuabL1NgaK7x0fwrj8276OQFkjCvSpJZ7+CeZWgcy03F2w==", "cpu": [ "arm64" ], @@ -3741,9 +3741,9 @@ } }, "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-1.0.3.tgz", - "integrity": "sha512-qof3LRAAycmkV2I1izZo9RoSHF8kCQr5O05sFwv0jK8rSdYV6KHVwimo6Qb7RxZj40WHKbLHm5JDaUF0o5XUAA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-1.0.6.tgz", + "integrity": "sha512-wLDrtfX9V4bu6O55/WwGvPVCjfunL2bEm59lzIFk9ZQOt7oJrPzdx/ytZiQr6bMZ9XOFwvXujszYtpoCK7yUbg==", "cpu": [ "x64" ], @@ -3762,9 +3762,9 @@ } }, "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-1.0.3.tgz", - "integrity": "sha512-FU2kKZLmolHA9+KcUA+l1+xH3WTLUUTQDU/kLv9SEUr2TrRPu94aytOeizFJDHPs/QBcw4QL1mCQhetQXYBbag==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-1.0.6.tgz", + "integrity": "sha512-8TllEP/9UPDVxrBN/tnbGBsxxwG8Eo2tgyW8wDy+Gi9rm9si2I6MsDv9MlfI3a7JOuzkBcurHYDHZxwLgzAIdA==", "cpu": [ "arm" ], @@ -3783,9 +3783,9 @@ } }, "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-1.0.3.tgz", - "integrity": "sha512-GVSjntxKeA+/y/ZKf1F+cmUw1WeIkE5aMRPqnZUlBTBvBcrvgWccJAWuYCKPX4QJQwZILIIwhgdAbl51yj6fpA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-1.0.6.tgz", + "integrity": "sha512-YF15AKoGrgU7aoA03CR+cATCRPQcVt6L14Lb/a9hqK7pT7/DhIkqh4qyl+a2GLfqx++yIIJfBuZ3sHM3zlXM1Q==", "cpu": [ "arm64" ], @@ -3807,9 +3807,9 @@ } }, "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-1.0.3.tgz", - "integrity": "sha512-J51oK/axyZ13kxycumSMfLiDZMdWdOVvqDFI28BpuViZHE3A0bQfr8B5vg8YnPEnqLD3BSn1hkdlh2buspEcNQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-1.0.6.tgz", + "integrity": "sha512-zXeVWNFpj720HZln0bfAs+1/nP3Wy6Z5hUw60UJu+cvgips5jZtuX2+EjDHFk98q3BY35GaE1TQLwE9S244vPA==", "cpu": [ "arm64" ], @@ -3831,9 +3831,9 @@ } }, "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-1.0.3.tgz", - "integrity": "sha512-CtQgQjoVTX67jS9XuCTtJ40Sl7wRLMguoFnnGnfDmCWf7kzKFZVwj5ynqUOIGKFMSB61ZCuQlwPvVNxYTTseaw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-1.0.6.tgz", + "integrity": "sha512-kvy1Ypq4ODEI2WRNGvs588qTMcWCjlEIuZRyW8JXpiBnMUirgxQukIDFVDQEcrLlHP5cqZ9cvvfOkBJ7koOktA==", "cpu": [ "riscv64" ], @@ -3855,9 +3855,9 @@ } }, "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-1.0.3.tgz", - "integrity": "sha512-jtfzAHFp+FRaR7zGT4jyCe6wUgAG/dVb5A4Apd8FY9jKarntDfUAlJXscugiH7ZF5kKnu7/lHFk9LaDPcrGEVQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-1.0.6.tgz", + "integrity": "sha512-czHnfLgSCl48iluS6bNrytGYhsbSTUuIvMucAwO0mPEj1uhkHk6SUiRI0xoqv0PSFzpGFfSnQvFpm7vV+tDO+A==", "cpu": [ "x64" ], @@ -3879,9 +3879,9 @@ } }, "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-1.0.3.tgz", - "integrity": "sha512-xTzaUCKUHTY4bCGadeeRZggbRVbGUT1petg7Z8r9AJR2+D9Bqu6nQAgqBGC6D47tA70LjaaaLTrJ7wNY1T74dg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-1.0.6.tgz", + "integrity": "sha512-afsg6GyfUx8qZzjsywjimXUEWcSWETY5F80hmMb2FWVSXkRbor8IpftY2gXnasq+Y42Xug/76qTHwqvti7HRTw==", "cpu": [ "x64" ], @@ -3903,9 +3903,9 @@ } }, "node_modules/@napi-rs/canvas-win32-arm64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-1.0.3.tgz", - "integrity": "sha512-ktVLuBkI6QVOm5BwO/WbdGwxgeetAMJa7TTmR8qBarXF0OU2NKjvjUtPJAl2y8t+zBRczJl/1VOl9gua6WcK2g==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-1.0.6.tgz", + "integrity": "sha512-byzha357piy0wgK6IZOQtU4plpt94f6CxHFS7LhJpWYrDWWT/AitQNxRMfCNNaQHZXUB3BwNhQSfH2RpiZ0WaQ==", "cpu": [ "arm64" ], @@ -3924,9 +3924,9 @@ } }, "node_modules/@napi-rs/canvas-win32-x64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-1.0.3.tgz", - "integrity": "sha512-SGhlQ8bDjL1Cz2KnsKMasr/5sTcwG/SZkB6WCJxLsmSm/3aS2C+3p39bA7iZ2/94+NkVDySZfbiGoaSZSFHYxA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-1.0.6.tgz", + "integrity": "sha512-gWLOgKGZz3hZhzg49q2PJIURwy2pCWh1zvNFXmLO1yineOPhEpoL3EV6/VIjOiKa1l2P6ieP12Eo385u1MLLVQ==", "cpu": [ "x64" ], @@ -4033,13 +4033,13 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.6.tgz", - "integrity": "sha512-B/gKoqlFkzhvzsI6jo9K1cZz9o5ypviVv/xu8CwA4grZzyVwN+XfkT+tu8T1zrauuEXv6VhS2oGX+6NL95WcKA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.2.0.tgz", + "integrity": "sha512-LlBrE8oqGfU7b1Nk2d5Q1SbuPhZxTj0cJEMDPEws28OjNMELlflekmPPuf4FnK03x0ZRjKaYwJElUcKK4kyqJA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "modern-tar": "^0.7.6", + "modern-tar": "^0.8.0", "yargs": "^18.0.0" }, "bin": { @@ -4100,9 +4100,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -4160,9 +4160,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.1.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", - "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", + "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", "dev": true, "license": "MIT", "dependencies": { @@ -4181,14 +4181,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.63.0.tgz", - "integrity": "sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", + "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.63.0", - "@typescript-eslint/types": "^8.63.0", + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", "debug": "^4.4.3" }, "engines": { @@ -4203,14 +4203,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz", - "integrity": "sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", + "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/visitor-keys": "8.63.0" + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4221,9 +4221,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz", - "integrity": "sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", + "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", "dev": true, "license": "MIT", "engines": { @@ -4238,9 +4238,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.63.0.tgz", - "integrity": "sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", + "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", "dev": true, "license": "MIT", "engines": { @@ -4252,16 +4252,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz", - "integrity": "sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", + "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.63.0", - "@typescript-eslint/tsconfig-utils": "8.63.0", - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/visitor-keys": "8.63.0", + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -4293,16 +4293,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.63.0.tgz", - "integrity": "sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", + "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.63.0", - "@typescript-eslint/types": "8.63.0", - "@typescript-eslint/typescript-estree": "8.63.0" + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4317,13 +4317,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.63.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz", - "integrity": "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==", + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", + "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/types": "8.67.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -5331,9 +5331,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", - "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { @@ -5490,9 +5490,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001806", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", - "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", "dev": true, "funding": [ { @@ -5711,9 +5711,9 @@ } }, "node_modules/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", "dev": true, "license": "MIT", "engines": { @@ -5902,12 +5902,15 @@ } }, "node_modules/core-js": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", - "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==", "dev": true, "hasInstallScript": true, "license": "MIT", + "engines": { + "node": "*" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -5969,9 +5972,9 @@ "license": "Python-2.0" }, "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { @@ -6132,9 +6135,9 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1653615", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1653615.tgz", - "integrity": "sha512-pGVkY3T/qXxAp2nFPodwYqOevk6ncNMSmvL8QfRCx5ZWGd6Vor7AFNmyaA8Zs6uJyP1QAfjuLandCgvSix1BNA==", + "version": "0.0.1666840", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1666840.tgz", + "integrity": "sha512-gCcO42XCHKEs7Ag0S7aGYsnJ7hlgrO3qderYqeiY0Eqk+0GFfuvT13IA0hHreJTa2KCdDVyGMeOhdMNmrrTjVg==", "dev": true, "license": "BSD-3-Clause" }, @@ -6423,9 +6426,9 @@ } }, "node_modules/eslint": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz", - "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==", + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz", + "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==", "dev": true, "license": "MIT", "workspaces": [ @@ -6594,13 +6597,13 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-5.10.0.tgz", - "integrity": "sha512-HiqpDrUDbGrMC6iHQbemgDyHJ0366Vyz/qRWmxQcSAkmG25cXr8BdRgx8yAhOKhEfBXn8Rnf/mTCsV4EqUJSxg==", + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-5.10.1.tgz", + "integrity": "sha512-Kprsp9Us0GqAesYaAIzUViw57xYp5WBqzXrcE0Mtww++E5fexWXYBipMuuD7yvyH4vvpBH0+oJ+OMAmZ0oYXkw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.62.1", + "@typescript-eslint/utils": "^8.65.0", "natural-orderby": "^5.0.0" }, "engines": { @@ -6642,16 +6645,16 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-3.1.1.tgz", - "integrity": "sha512-MxR5nqoQCtVWmJwia0D2+NlXX1xzdpkslsVOZLEYQ4PQWEaL65PCZXURxaBc3lPnkNFpNxzMIRmYVxdl8giXRA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-3.2.0.tgz", + "integrity": "sha512-4yq47CnLxyfHFKJEo5kvNaiJ0aDtBxSJWk4M2LiamplUXdWxdlzDYqImb/ZVCp+2BqkQjBAmw4Xc07Q8SXVDZg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "comment-parser": "^1.4.0", - "jsdoc-type-pratt-parser": "^7.0.0", + "jsdoc-type-pratt-parser": "^9.0.0", "refa": "^0.12.1", "regexp-ast-analysis": "^0.7.1", "scslre": "^0.3.0" @@ -6664,9 +6667,9 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "72.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-72.0.0.tgz", - "integrity": "sha512-hqO6ksoOHO+ZhdseTuKRVQbx9U7PRO/cv8qAR1mctwzdVO2hYud8uS9luAhp43RJgziYgHAph8eHyipT8GL0ng==", + "version": "73.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-73.0.0.tgz", + "integrity": "sha512-V0YatLe9nkGhXEXKe2Qljb1EY0sJHwDV0HUF1NKFwtsHh/fU7qGHDgv+6fchzZcgU2/7noHo2gdjnmo0P2uDPw==", "dev": true, "license": "MIT", "dependencies": { @@ -7448,9 +7451,9 @@ } }, "node_modules/globals": { - "version": "17.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.8.0.tgz", - "integrity": "sha512-Zz/LMDZScFmkakeL2cTHzf+PbWKdpU3uclqkZT7TjDG58j5WPt0PpA+n9uPI24fZtlw07q0OtEi84K+umsRzqQ==", + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz", + "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==", "dev": true, "license": "MIT", "engines": { @@ -7793,9 +7796,9 @@ } }, "node_modules/highlight.js": { - "version": "11.11.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", - "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.12.0.tgz", + "integrity": "sha512-nbfWpyRMcMrPMmDwJB+dhX/eiaPKtc2RB+0QZskqJ3WjRA/FDS0e9hZrx8EC/lbEv8gXy98FcDbNa/dspAaJMg==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -8667,9 +8670,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", - "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", + "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", "dev": true, "license": "MIT", "dependencies": { @@ -8721,13 +8724,16 @@ } }, "node_modules/jsdoc-type-pratt-parser": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz", - "integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-9.1.1.tgz", + "integrity": "sha512-kojSbQb9iQM2bk2PmHiKa3reG0U4v2gN9U8D8+eCQq+4KM5ZXBUyBVeF8KmR0RiwqyrW4+uVWYWTOLnpsavnkw==", "dev": true, "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.9" + }, "engines": { - "node": ">=20.0.0" + "node": "^22.22.2 || >=24.15.0" } }, "node_modules/jsdoc/node_modules/escape-string-regexp": { @@ -9471,9 +9477,9 @@ } }, "node_modules/modern-tar": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.7.tgz", - "integrity": "sha512-t9VmxaqrmANnEOBhpSDI6HD192Ge48k8vmWqQQL7hSFEqHEYwZbbsu49+aKLWZeRvFs3j1pMhXOqqF4kPlvjkQ==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.8.4.tgz", + "integrity": "sha512-gN54ddmyzEg10orwZ2u4OOv+bjpMWdIl5jIkodK97bMq8QBSL5c0D7YX0lT1Ooz+99S7+PvFbnxzdjgHo1r41g==", "dev": true, "license": "MIT", "engines": { @@ -9512,9 +9518,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -10104,9 +10110,9 @@ } }, "node_modules/postcss": { - "version": "8.5.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", - "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -10124,7 +10130,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.16", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10133,19 +10139,19 @@ } }, "node_modules/postcss-discard-comments": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-8.0.1.tgz", - "integrity": "sha512-FDvzm3tXlEsQBO2XQgnta5ugsAqwBrgWH+j5QgXpegEIDYA0VPnZg2aP7LtmWtC49POskeIhXesFiU/k3NyFHA==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-8.0.3.tgz", + "integrity": "sha512-oDe4ITEfp1/113ebPi/ujyfWX2E9+vbHhY0dPnypgHwIgw8LBQ7MczmtAbccw8gUs+Zlmgt80qtTKS0t8eCi+Q==", "dev": true, "license": "MIT", "dependencies": { - "postcss-selector-parser": "^7.1.2" + "postcss-selector-parser": "^7.1.5" }, "engines": { "node": "^22.11.0 || ^24.11.0 || >=26.0" }, "peerDependencies": { - "postcss": "^8.5.15" + "postcss": "^8.5.26" } }, "node_modules/postcss-load-config": { @@ -10216,9 +10222,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz", - "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", "dev": true, "license": "MIT", "dependencies": { @@ -10339,18 +10345,18 @@ } }, "node_modules/puppeteer": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.4.0.tgz", - "integrity": "sha512-xfQp8dFBcGaLc1hEMaVr7s+oW4ZkAurr8Y9H81ilKhu6QoLfSTkZjU7IavnyJ/VWpB9ni3KNJUQHUatslLWyGw==", + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.7.0.tgz", + "integrity": "sha512-zLBIYuW66SGwY7JNqGmiqeKiM92CYOs6xPibSRBPIeYGIfM1nE/8VCE8G0fGot2EfXENC4PbhktxLrQ0EK5Thg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "3.0.6", + "@puppeteer/browsers": "3.2.0", "chromium-bidi": "17.0.2", - "devtools-protocol": "0.0.1653615", + "devtools-protocol": "0.0.1666840", "lilconfig": "^3.1.3", - "puppeteer-core": "25.4.0", + "puppeteer-core": "25.7.0", "typed-query-selector": "^2.12.2" }, "bin": { @@ -10361,15 +10367,15 @@ } }, "node_modules/puppeteer-core": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.4.0.tgz", - "integrity": "sha512-K1plkLOdeoUnGeT1OvdqF3qxl33v+Ra/uH5VyPEhXdMcpvGiEskHzxxEU3fgpccJpJLIipB/rPUsvkZRWeKqOA==", + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.7.0.tgz", + "integrity": "sha512-wgBBj7dU5ceGyoT2PCrJpkYOhxPY8mDOmcSKZP92Cj5GgqQ3kv/UxzawnOLxiYuupe4bDf/yiQm3bzs/1nI0rQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "3.0.6", + "@puppeteer/browsers": "3.2.0", "chromium-bidi": "17.0.2", - "devtools-protocol": "0.0.1653615", + "devtools-protocol": "0.0.1666840", "typed-query-selector": "^2.12.2", "webdriver-bidi-protocol": "0.4.2", "ws": "^8.21.1" @@ -13162,9 +13168,9 @@ } }, "node_modules/ws": { - "version": "8.21.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", - "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "dev": true, "license": "MIT", "engines": { @@ -13268,9 +13274,9 @@ } }, "node_modules/yargs/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 5e97c4f7a274b..a1ca59d96483e 100644 --- a/package.json +++ b/package.json @@ -10,32 +10,32 @@ "@fluent/dom": "^0.10.2", "@metalsmith/layouts": "^3.0.0", "@metalsmith/markdown": "^1.10.0", - "@napi-rs/canvas": "^1.0.3", - "@types/node": "^26.1.2", + "@napi-rs/canvas": "^1.0.6", + "@types/node": "^26.2.0", "autoprefixer": "^10.5.4", "babel-loader": "^10.1.1", "babel-plugin-istanbul": "^8.0.2", "babel-plugin-polyfill-corejs3": "^1.0.0", "cached-iterable": "^0.3.0", - "caniuse-lite": "^1.0.30001806", - "core-js": "^3.49.0", - "eslint": "^10.8.0", + "caniuse-lite": "^1.0.30001809", + "core-js": "^3.50.0", + "eslint": "^10.8.1", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import-x": "^4.17.1", "eslint-plugin-jasmine": "^4.2.2", "eslint-plugin-no-unsanitized": "^4.1.5", - "eslint-plugin-perfectionist": "^5.10.0", + "eslint-plugin-perfectionist": "^5.10.1", "eslint-plugin-prettier": "^5.5.6", - "eslint-plugin-regexp": "^3.1.1", - "eslint-plugin-unicorn": "^72.0.0", - "globals": "^17.8.0", + "eslint-plugin-regexp": "^3.2.0", + "eslint-plugin-unicorn": "^73.0.0", + "globals": "^17.11.0", "gulp": "^5.0.1", "gulp-cli": "^3.1.0", "gulp-postcss": "^10.0.0", "gulp-rename": "^2.1.0", "gulp-replace": "^1.1.4", "gulp-zip": "^6.1.0", - "highlight.js": "^11.11.1", + "highlight.js": "^11.12.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", @@ -47,11 +47,11 @@ "metalsmith-html-relative": "^2.0.13", "ordered-read-streams": "^2.0.0", "pngjs": "^7.0.0", - "postcss": "^8.5.25", - "postcss-discard-comments": "^8.0.1", + "postcss": "^8.5.26", + "postcss-discard-comments": "^8.0.3", "postcss-values-parser": "^8.0.0", "prettier": "^3.9.6", - "puppeteer": "^25.4.0", + "puppeteer": "^25.7.0", "stylelint": "^17.14.1", "stylelint-prettier": "^5.0.3", "svglint": "^4.2.1", diff --git a/test/color_utils.mjs b/test/color_utils.mjs index b684b8d5fa924..2438d4245bf85 100644 --- a/test/color_utils.mjs +++ b/test/color_utils.mjs @@ -13,13 +13,7 @@ * limitations under the License. */ -import kleur from "kleur"; - -kleur.enabled = - !process.env.NO_COLOR && - (!!process.stdout.isTTY || - !!process.env.FORCE_COLOR || - process.env.GITHUB_ACTIONS === "true"); +import { kleur } from "../external/color_utils.mjs"; const TEST_PASSED = kleur.green("TEST-PASS"); const TEST_UNEXPECTED_FAIL = kleur.red().bold("TEST-UNEXPECTED-FAIL"); diff --git a/test/integration/cursor_tools_spec.mjs b/test/integration/cursor_tools_spec.mjs index d7f453252fe3a..f7881e360e007 100644 --- a/test/integration/cursor_tools_spec.mjs +++ b/test/integration/cursor_tools_spec.mjs @@ -102,28 +102,37 @@ describe("Cursor tools", () => { pages.map(async ([browserName, page]) => { await enableHandTool(page); - const pageHeight = await page.evaluate( - () => - document.querySelector(`.page[data-page-number="1"]`).offsetHeight + const viewerRect = await getRect(page, "#viewerContainer"); + const x = Math.floor(viewerRect.x + viewerRect.width / 2), + startY = Math.floor(viewerRect.y + (3 * viewerRect.height) / 4), + endY = Math.floor(viewerRect.y + viewerRect.height / 4), + steps = 10; + const initialScrollTop = await page.evaluate( + () => document.getElementById("viewerContainer").scrollTop ); - const steps = 10, - delta = Math.floor(pageHeight / steps); - const spanRect = await getRect( - page, - `.page[data-page-number="1"] > .textLayer > span` - ); - const x = spanRect.x + 1, - y = spanRect.y + spanRect.height / 2; - - for (let i = 0; i < steps; i++) { - await page.mouse.move(x, y); - await page.mouse.down(); - await page.mouse.move(x, y - delta); - await page.mouse.up(); + await page.mouse.move(x, startY); + await page.mouse.down(); + // Puppeteer's `steps` option generates fractional intermediate + // positions, which Firefox doesn't support. + for (let i = 1; i <= steps; i++) { + await page.mouse.move( + x, + Math.round(startY + ((endY - startY) * i) / steps) + ); } - // Ensure that the second page is visible. - await page.waitForFunction("window.PDFViewerApplication.page === 2"); + await page.mouse.up(); + + const scrollTop = await page.evaluate( + () => document.getElementById("viewerContainer").scrollTop + ); + const scrollDelta = scrollTop - initialScrollTop, + expectedScrollDelta = startY - endY; + expect(Math.abs(scrollDelta - expectedScrollDelta)) + .withContext( + `Expected a scroll delta of ${expectedScrollDelta}, got ${scrollDelta}, in ${browserName}` + ) + .toBeLessThan(1); // Finally, disable the hand tool. await enableSelectTool(page);