From 2aa2c1db2e05673ed934f2e244588cb8aa31d921 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Thu, 30 Apr 2026 16:54:43 +0200 Subject: [PATCH 01/14] Migrate to Playwright --- .gitignore | 5 +- README.md | 11 +- backstop.json | 294 ---- docs/CSS22-npm.md | 49 +- .../OEBPS/Text/Section-022.xhtml | 62 +- package-lock.json | 1445 +---------------- package.json | 7 +- playwright.config.js | 21 + tests/a11y-font.html | 20 - tests/visual.spec.js | 67 + 10 files changed, 156 insertions(+), 1825 deletions(-) delete mode 100644 backstop.json create mode 100644 playwright.config.js delete mode 100644 tests/a11y-font.html create mode 100644 tests/visual.spec.js diff --git a/.gitignore b/.gitignore index 9419a30d..3dc5e736 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ node_modules/ *.css.map -tests/backstop_data/ \ No newline at end of file +tests/backstop_data/ +tests/snapshots/ +test-results/ +playwright-report/ \ No newline at end of file diff --git a/README.md b/README.md index 4befa4ba..9a330841 100644 --- a/README.md +++ b/README.md @@ -56,12 +56,11 @@ Building and testing are relying on npm packages and scripts. To initialize your npm install ``` -In case you’re encountering an error with Puppeteer, make sure you’re using at least Node v.20.11.1 – it might work with an earlier version but only the latest LTS as of March 21, 2024 has been tested. - -Then create reference bitmaps for visual regression testing: +Then install the Playwright browser binary and generate reference screenshots for visual regression testing: ``` -npm run test:ref +npx playwright install chromium +npm run test:update ``` ### Build @@ -78,10 +77,10 @@ To test the updated styles and catch visual regression bugs: npm run test ``` -To update reference bitmaps after a bugfix: +To update reference screenshots after an intentional change: ``` -npm run test:approve +npm run test:update ``` ## Docs diff --git a/backstop.json b/backstop.json deleted file mode 100644 index 526b1699..00000000 --- a/backstop.json +++ /dev/null @@ -1,294 +0,0 @@ -{ - "id": "ReadiumCSS", - "viewports": [ - { - "label": "tablet", - "width": 1024, - "height": 768 - } - ], - "scenarios": [ - { - "label": "Paged", - "url": "http://localhost:8000/tests/base.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Paged rtl", - "url": "http://localhost:8000/tests/base-rtl.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Paged vertical", - "url": "http://localhost:8000/tests/base-vertical.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "1 column pref", - "url": "http://localhost:8000/tests/cols-1.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "2 columns pref", - "url": "http://localhost:8000/tests/cols-2.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "3 columns pref", - "url": "http://localhost:8000/tests/cols-3.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Line length pref", - "url": "http://localhost:8000/tests/line-length.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Scroll pref", - "url": "http://localhost:8000/tests/scroll.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Scroll vertical pref", - "url": "http://localhost:8000/tests/scroll-vertical.html", - "delay": 0, - "selectors": ["viewport"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Scroll padding pref", - "url": "http://localhost:8000/tests/scroll-padding.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Default colors pref", - "url": "http://localhost:8000/tests/default-colors.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Default custom colors pref", - "url": "http://localhost:8000/tests/default-custom-colors.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Theming (Reading System)", - "url": "http://localhost:8000/tests/theming.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font family pref", - "url": "http://localhost:8000/tests/font-family.html", - "delay": 500, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font size pref", - "url": "http://localhost:8000/tests/font-size.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Deprecated font size pref", - "url": "http://localhost:8000/tests/font-size-deprecated.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font size normalize pref", - "url": "http://localhost:8000/tests/font-size-normalize.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Type scale pref", - "url": "http://localhost:8000/tests/type-scale.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Text align pref", - "url": "http://localhost:8000/tests/text-align.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Hyphens pref", - "url": "http://localhost:8000/tests/hyphens.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Line height pref", - "url": "http://localhost:8000/tests/line-height.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Para spacing pref", - "url": "http://localhost:8000/tests/para-spacing.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Para spacing vertical pref", - "url": "http://localhost:8000/tests/para-spacing-vertical.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Wordspacing pref", - "url": "http://localhost:8000/tests/word-spacing.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Letterspacing pref", - "url": "http://localhost:8000/tests/letter-spacing.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Letterspacing CJK pref", - "url": "http://localhost:8000/tests/letter-spacing-cjk.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Ligatures pref", - "url": "http://localhost:8000/tests/arabic-ligatures.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Accessibility font pref", - "url": "http://localhost:8000/tests/a11y-font.html", - "delay": 500, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Accessibility normalize pref", - "url": "http://localhost:8000/tests/a11y-normalize.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Accessibility custom pref", - "url": "http://localhost:8000/tests/a11y-custom.html", - "delay": 500, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "no Ruby pref", - "url": "http://localhost:8000/tests/no-ruby.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font optical sizing pref", - "url": "http://localhost:8000/tests/font-optical-sizing.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font weight pref", - "url": "http://localhost:8000/tests/font-weight.html", - "delay": 500, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font width Keyword pref", - "url": "http://localhost:8000/tests/font-width-keyword.html", - "delay": 500, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Font width Percentage pref", - "url": "http://localhost:8000/tests/font-width-percentage.html", - "delay": 500, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Blend Filter pref", - "url": "http://localhost:8000/tests/blend-filter.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Darken Filter pref", - "url": "http://localhost:8000/tests/darken-filter.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - }, - { - "label": "Invert Filter pref", - "url": "http://localhost:8000/tests/invert-filter.html", - "delay": 0, - "selectors": ["document"], - "misMatchThreshold" : 0.1 - } - ], - "paths": { - "bitmaps_reference": "tests/backstop_data/bitmaps_reference", - "bitmaps_test": "tests/backstop_data/bitmaps_test", - "engine_scripts": "tests/backstop_data/engine_scripts", - "html_report": "tests/backstop_data/html_report", - "ci_report": "tests/backstop_data/ci_report" - }, - "report": ["browser"], - "engine": "puppeteer", - "engineOptions": { - "args": ["--no-sandbox"] - }, - "asyncCaptureLimit": 5, - "asyncCompareLimit": 50, - "debug": false, - "debugWindow": false -} diff --git a/docs/CSS22-npm.md b/docs/CSS22-npm.md index e0f9fa0c..15c25e11 100644 --- a/docs/CSS22-npm.md +++ b/docs/CSS22-npm.md @@ -21,10 +21,11 @@ This will install all dev dependencies needed and make npm scripts available to Then, once the install is finished, type: ``` -npm run test:ref +npx playwright install chromium +npm run test:update ``` -This will create reference screenshots for the CSS regression tests. +This will install the Playwright browser binary and create reference screenshots for the CSS regression tests. ## Build @@ -116,35 +117,18 @@ Here is a list of additionnal PostCSS plugins which might prove useful to implem ## Test -Once you have build `dist` stylesheets, you can run regression tests using [Backstop.js](https://github.com/garris/BackstopJS). +Once you have built `dist` stylesheets, you can run visual regression tests using [Playwright](https://playwright.dev). It helps you check if you didn’t accidentally create a breaking change when customizing stylesheets, and make sure pagination and user settings work as expected. ### Config -You will find the configuration file, `backstop.json` at the root of the project. By default, it runs those tests for a smartphone (portrait) and a tablet (landscape) viewports using Chrome, but you can customize it to fit your needs. +The test configuration lives in `playwright.config.js` at the root of the project. By default, it runs all tests at a 1024×768 tablet viewport using Chromium. You can adjust the viewport or add browsers there. -For instance, if you don’t need to support mobile, you could modify `viewports`: +If you want to run tests with WebKit (useful for iOS development), install the additional browser and update `browserName` in the config: ``` -"viewports": [ - { - "label": "desktop small", - "width": 800, - "height": 600 - }, - { - "label": "desktop large", - "width": 1600, - "height": 900 - } -] -``` - -And if you want to run tests using Webkit instead of Blink because you’re developing iOS apps: - -``` -"engine": "phantomjs" +npx playwright install webkit ``` ### Test files @@ -153,11 +137,10 @@ If you customize flags in `ReadiumCSS-config.css`, you must modify HTML files in ### Available scripts -By default, the following scripts are available: +By default, the following scripts are available: -- `test`, will run tests; -- `test:ref`, will create reference screenshots; -- `test:approve`, will update reference screenshots from the current test. +- `test`, will build stylesheets then run visual regression tests; +- `test:update`, will create or update reference screenshots. ### Usage @@ -167,16 +150,12 @@ First navigate to the `readium-css` folder if you didn’t already, then… npm run test ``` -The regression tests will run against the newly-created `dist` stylesheets, which is why you must build them beforehand. +The regression tests will run against the newly-built `dist` stylesheets and compare each page against its stored reference screenshot. -Once all scenarios are tested for the viewports you created, which can take up to a minute, a report will automatically open in your browser. - -If a unit test is marked as “failed”, it doesn’t necessarily mean the user setting failed, it just means you made a significant change which impacts rendering. Take a closer look at the diff, and if you’re happy with the result, head to the terminal and type: +If a test is marked as failed, it doesn’t necessarily mean the user setting failed — it just means you made a change that impacts rendering. Open the Playwright HTML report to inspect the diff, and if you’re happy with the result, update the references: ``` -npm run test:approve +npm run test:update ``` -This will make the current test screenshots the new reference for the next test. - -**Note:** on some occasions, an error might happen during tests and the process won’t stop. Try `ctrl + c` to stop the current process and run the test again. \ No newline at end of file +This will make the current screenshots the new reference for the next test run. \ No newline at end of file diff --git a/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml b/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml index 29c6c354..d51aaee2 100644 --- a/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml +++ b/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml @@ -30,9 +30,10 @@

Then, once the install is finished, type:

-
npm run test:ref
+
npx playwright install chromium
+npm run test:update
-

This will create reference screenshots for the CSS regression tests.

+

This will install the Playwright browser binary and create reference screenshots for the CSS regression tests.

@@ -162,73 +163,52 @@ require("postcss-alter-property-value")({

Test

-

Once you have build dist stylesheets, you can run regression tests using Backstop.js.

+

Once you have built dist stylesheets, you can run visual regression tests using Playwright.

It helps you check if you didn’t accidentally create a breaking change when customizing stylesheets, and make sure pagination and user settings work as expected.

-
-

Config

+
+

Config

-

You will find the configuration file, backstop.json at the root of the project. By default, it runs those tests for a smartphone (portrait) and a tablet (landscape) viewports using Chrome, but you can customize it to fit your needs.

+

The test configuration lives in playwright.config.js at the root of the project. By default, it runs all tests at a 1024×768 tablet viewport using Chromium. You can adjust the viewport or add browsers there.

-

For instance, if you don’t need to support mobile, you could modify viewports:

+

If you want to run tests with WebKit (useful for iOS development), install the additional browser and update browserName in the config:

-
"viewports": [ 
-  { 
-    "label": "desktop small", 
-    "width": 800, 
-    "height": 600 
-  }, 
-  { 
-    "label": "desktop large", 
-    "width": 1600, 
-    "height": 900 
-  } 
-]
- -

And if you want to run tests using Webkit instead of Blink because you’re developing iOS apps:

- -
"engine": "phantomjs"
+
npx playwright install webkit
-
-

Test files

+
+

Test files

If you customize flags in ReadiumCSS-config.css, you must modify HTML files in the tests folder; user settings are indeed set as inline styles on the html element and are using the default flags.

-
-

Available scripts

+
+

Available scripts

By default, the following scripts are available:

    -
  • test, will run tests;
  • +
  • test, will build stylesheets then run visual regression tests;
  • -
  • test:ref, will create reference screenshots;
  • - -
  • test:approve, will update reference screenshots from the current test.
  • +
  • test:update, will create or update reference screenshots.
-
-

Usage

+
+

Usage

First navigate to the readium-css folder if you didn’t already, then…

npm run test
-

The regression tests will run against the newly-created dist stylesheets, which is why you must build them beforehand.

- -

Once all scenarios are tested for the viewports you created, which can take up to a minute, a report will automatically open in your browser.

- -

If a unit test is marked as “failed”, it doesn’t necessarily mean the user setting failed, it just means you made a significant change which impacts rendering. Take a closer look at the diff, and if you’re happy with the result, head to the terminal and type:

+

The regression tests will run against the newly-built dist stylesheets and compare each page against its stored reference screenshot.

-
npm run test:approve
+

If a test is marked as failed, it doesn’t necessarily mean the user setting failed — it just means you made a change that impacts rendering. Open the Playwright HTML report to inspect the diff, and if you’re happy with the result, update the references:

-

This will make the current test screenshots the new reference for the next test.

+
npm run test:update
-

Note: on some occasions, an error might happen during tests and the process won’t stop. Try ctrl + c to stop the current process and run the test again.

+

This will make the current screenshots the new reference for the next test run.

diff --git a/package-lock.json b/package-lock.json index fe5e6fea..8297fddf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "BSD-3-Clause", "devDependencies": { "@daltontan/postcss-import-json": "^1.1.1", - "backstopjs": "^6.3.23", + "@playwright/test": "^1.52.0", "copyfiles": "^2.4.1", "express": "^4.21.1", "postcss-alter-property-value": "^1.1.3", @@ -225,16 +225,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/@mirzazeyrek/node-resemble-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@mirzazeyrek/node-resemble-js/-/node-resemble-js-1.2.1.tgz", - "integrity": "sha512-+z1c7HpC5ysdSVVyUVz67hctVLl337VlRJP/MBwpvXHkKJdlnSUVrBhlRzxgal7xpm1uDE2JeUhWbQh6wPRC4w==", - "dev": true, - "dependencies": { - "jpeg-js": "^0.4.2", - "pngjs": "^6.0.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -270,63 +260,21 @@ "node": ">= 8" } }, - "node_modules/@puppeteer/browsers": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz", - "integrity": "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==", + "node_modules/@playwright/test": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", + "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", "dev": true, "dependencies": { - "debug": "^4.3.5", - "extract-zip": "^2.0.1", - "progress": "^2.0.3", - "proxy-agent": "^6.4.0", - "semver": "^7.6.3", - "tar-fs": "^3.0.6", - "unbzip2-stream": "^1.4.3", - "yargs": "^17.7.2" + "playwright": "1.59.1" }, "bin": { - "browsers": "lib/cjs/main-cli.js" + "playwright": "cli.js" }, "engines": { "node": ">=18" } }, - "node_modules/@puppeteer/browsers/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@puppeteer/browsers/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@puppeteer/browsers/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@sindresorhus/merge-streams": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", @@ -339,32 +287,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "22.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.2.tgz", - "integrity": "sha512-yPL6DyFwY5PiMVEwymNeqUTKsDczQBJ/5T7W/46RwLU/VH+AA8aT5TZkvBviLKLbbm0hlfftEkGrNzfRk/fofQ==", - "dev": true, - "optional": true, - "dependencies": { - "undici-types": "~6.11.1" - } - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -378,54 +300,6 @@ "node": ">= 0.6" } }, - "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", @@ -503,18 +377,6 @@ "node": ">=8" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -524,167 +386,12 @@ "node": ">=8" } }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", - "dev": true - }, - "node_modules/backstopjs": { - "version": "6.3.25", - "resolved": "https://registry.npmjs.org/backstopjs/-/backstopjs-6.3.25.tgz", - "integrity": "sha512-jy0dxlk45tItXLcj9zjRTCyCa6D27M9OMK5kM8To0ELLclKhI/dWn/igUTMBBMJXe4Kql+CGyDRErMtTv2+40Q==", - "dev": true, - "dependencies": { - "@mirzazeyrek/node-resemble-js": "^1.2.1", - "chalk": "^4.1.2", - "diverged": "^0.1.3", - "fs-extra": "^11.2.0", - "jump.js": "^1.0.2", - "junit-report-builder": "^3.1.0", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "object-hash": "3.0.0", - "opn": "^6.0.0", - "os": "^0.1.2", - "p-map": "^4.0.0", - "path": "^0.12.7", - "playwright": "^1.40.1", - "portfinder": "^1.0.32", - "puppeteer": "^22.1.0", - "super-simple-web-server": "^1.1.4", - "temp": "^0.9.4" - }, - "bin": { - "backstop": "cli/index.js" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "dev": true, - "license": "Apache-2.0", - "optional": true - }, - "node_modules/bare-fs": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.2.tgz", - "integrity": "sha512-S5mmkMesiduMqnz51Bfh0Et9EX0aTCJxhsI4bvzFFLs8Z1AV8RDHadfY5CyLwdoLHgXbNBEN1gQcbEtGwuvixw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-events": "^2.5.4", - "bare-path": "^3.0.0", - "bare-stream": "^2.6.4" - }, - "engines": { - "bare": ">=1.16.0" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-os": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", - "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-stream": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", - "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "streamx": "^2.21.0" - }, - "peerDependencies": { - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/basic-ftp": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.2.tgz", - "integrity": "sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -772,39 +479,6 @@ "node": ">=8" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -854,22 +528,6 @@ "node": ">=6" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -894,29 +552,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chromium-bidi": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz", - "integrity": "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A==", - "dev": true, - "dependencies": { - "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0", - "zod": "3.23.8" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -1174,24 +809,6 @@ "node": ">=4" } }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/date-format": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", - "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1201,20 +818,6 @@ "ms": "2.0.0" } }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1243,21 +846,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/devtools-protocol": { - "version": "0.0.1312386", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", - "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", - "dev": true - }, - "node_modules/diff": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", - "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1279,27 +867,6 @@ "node": ">=8" } }, - "node_modules/diverged": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/diverged/-/diverged-0.1.3.tgz", - "integrity": "sha512-W8BLyp4Eo+YW9uQ3F5c9BXDT9ITCARA2CFQVb+v57FWYfkr0XjwNOASZacDCq+syk1i/obZ4BZ3w1qtlRO6hQw==", - "dev": true, - "dependencies": { - "diff": "^3.5.0", - "pixelmatch": "^4.0.2", - "pngjs": "^3.3.3", - "super-simple-web-server": "^1.0.0" - } - }, - "node_modules/diverged/node_modules/pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -1336,15 +903,6 @@ "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -1420,58 +978,6 @@ "node": ">=0.8.0" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1528,53 +1034,10 @@ "url": "https://opencollective.com/express" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/extract-zip/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "node_modules/fast-deep-equal": { @@ -1583,12 +1046,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -1639,15 +1096,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1831,59 +1279,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", - "dev": true, - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/get-uri/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/get-uri/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2049,78 +1444,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2133,26 +1456,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -2187,15 +1490,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2218,19 +1512,6 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -2318,15 +1599,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -2339,12 +1611,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/jpeg-js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", - "dev": true - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2364,12 +1630,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2400,27 +1660,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jump.js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jump.js/-/jump.js-1.0.2.tgz", - "integrity": "sha512-oUkJJ/Y4ATU5qjkXBntCZSKctbSyS3ewe2jrLaUu/cc9jsQiAn0fnTUxQnZz3mJdDdem1Q279zrD6h3n+Cgxtg==", - "dev": true - }, - "node_modules/junit-report-builder": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/junit-report-builder/-/junit-report-builder-3.2.1.tgz", - "integrity": "sha512-IMCp5XyDQ4YESDE4Za7im3buM0/7cMnRfe17k2X8B05FnUl9vqnaliX6cgOEmPIeWKfJrEe/gANRq/XgqttCqQ==", - "dev": true, - "dependencies": { - "date-format": "4.0.3", - "lodash": "^4.17.21", - "make-dir": "^3.1.0", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2463,43 +1702,12 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, - "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2633,33 +1841,6 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2694,15 +1875,6 @@ "node": ">= 0.6" } }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/noms": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", @@ -2722,15 +1894,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -2760,98 +1923,9 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/opn": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz", - "integrity": "sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==", - "deprecated": "The package has been renamed to `open`", - "dev": true, - "dependencies": { - "is-wsl": "^1.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/os": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/os/-/os-0.1.2.tgz", - "integrity": "sha512-ZoXJkvAnljwvc56MbvhtKVWmSkzV712k42Is2mA0+0KTSRakq5XXuXpjZjgAt9ctzl51ojhQWakQQpmOvXWfjQ==", - "dev": true - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pac-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", - "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", - "dev": true, - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.5", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/pac-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" + "dev": true, + "dependencies": { + "wrappy": "1" } }, "node_modules/parent-module": { @@ -2893,16 +1967,6 @@ "node": ">= 0.8" } }, - "node_modules/path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", - "dev": true, - "dependencies": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2936,12 +2000,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2971,34 +2029,13 @@ "node": ">=0.10.0" } }, - "node_modules/pixelmatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", - "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", - "dev": true, - "dependencies": { - "pngjs": "^3.0.0" - }, - "bin": { - "pixelmatch": "bin/pixelmatch" - } - }, - "node_modules/pixelmatch/node_modules/pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/playwright": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", - "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", + "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", "dev": true, "dependencies": { - "playwright-core": "1.56.1" + "playwright-core": "1.59.1" }, "bin": { "playwright": "cli.js" @@ -3011,9 +2048,9 @@ } }, "node_modules/playwright-core": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", - "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", + "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -3022,44 +2059,6 @@ "node": ">=18" } }, - "node_modules/pngjs": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", - "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", - "dev": true, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/portfinder": { - "version": "1.0.32", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", - "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", - "dev": true, - "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/portfinder/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/postcss": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", @@ -3325,30 +2324,12 @@ "node": ">= 0.8" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3362,122 +2343,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/puppeteer": { - "version": "22.15.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz", - "integrity": "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@puppeteer/browsers": "2.3.0", - "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1312386", - "puppeteer-core": "22.15.0" - }, - "bin": { - "puppeteer": "lib/esm/puppeteer/node/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/puppeteer-core": { - "version": "22.15.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz", - "integrity": "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==", - "dev": true, - "dependencies": { - "@puppeteer/browsers": "2.3.0", - "chromium-bidi": "0.6.3", - "debug": "^4.3.6", - "devtools-protocol": "0.0.1312386", - "ws": "^8.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/puppeteer-core/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/puppeteer-core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/qs": { "version": "6.14.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", @@ -3653,18 +2518,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3714,15 +2567,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/send": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", @@ -3900,77 +2744,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socks-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3981,12 +2754,6 @@ "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -3996,20 +2763,6 @@ "node": ">= 0.8" } }, - "node_modules/streamx": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", - "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, "node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -4190,15 +2943,6 @@ "node": ">=8" } }, - "node_modules/super-simple-web-server": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/super-simple-web-server/-/super-simple-web-server-1.1.4.tgz", - "integrity": "sha512-sQdVXz8ZDBMloocL63mifyVVzhxP55MlO2F0MiYJAJQiHTp42M2C3m2dZBIxGkcC7NUDr1/p0UhvGQvOsxZLpw==", - "dev": true, - "dependencies": { - "express": "^4.16.3" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4279,66 +3023,12 @@ "node": ">=8" } }, - "node_modules/tar-fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", - "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" - } - }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "node_modules/temp": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1", - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", - "dev": true, - "dependencies": { - "b4a": "^1.6.4" - } - }, "node_modules/thenby": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", "dev": true }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4406,12 +3096,6 @@ "node": ">=0.6" } }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -4425,23 +3109,6 @@ "node": ">= 0.6" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/undici-types": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", - "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==", - "dev": true, - "optional": true - }, "node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", @@ -4481,33 +3148,12 @@ "node": ">=8" } }, - "node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "node_modules/util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "dependencies": { - "inherits": "2.0.3" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -4595,36 +3241,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "engines": { - "node": ">=8.0" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -4681,25 +3297,6 @@ "engines": { "node": ">=12" } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/package.json b/package.json index 6d3bf2f1..091a8e07 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ ], "devDependencies": { "@daltontan/postcss-import-json": "^1.1.1", - "backstopjs": "^6.3.23", + "@playwright/test": "^1.52.0", "copyfiles": "^2.4.1", "express": "^4.21.1", "postcss-alter-property-value": "^1.1.3", @@ -54,8 +54,7 @@ "build:vertical": "postcss css/src/ReadiumCSS-before-cjk-vertical.css -o css/dist/cjk-vertical/ReadiumCSS-before.css && postcss css/src/ReadiumCSS-default-cjk-vertical.css -o css/dist/cjk-vertical/ReadiumCSS-default.css && postcss css/src/ReadiumCSS-after-cjk-vertical.css -o css/dist/cjk-vertical/ReadiumCSS-after.css", "copyPatches": "copyfiles -u 2 css/src/ReadiumCSS-ebpaj_fonts_patch.css css/dist", "start": "node \"./server.js\"", - "test": "npm run build && (npm start & for i in {1..10}; do if curl -s http://localhost:8000 >/dev/null; then backstop test; pkill -f \"node ./server.js\"; echo '\\nVisual Regression testing has been completed.\\n'; exit 0; fi; sleep 1; done; echo 'Failed to start server'; exit 1)", - "test:ref": "npm start & backstop reference && pkill -9 -f \"node ./server.js\" && echo '\nVisual Regression references have been generated.\n'", - "test:approve": "backstop approve" + "test": "npm run build && playwright test", + "test:update": "playwright test --update-snapshots" } } diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 00000000..c218d42a --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,21 @@ +const { defineConfig } = require("@playwright/test"); + +module.exports = defineConfig({ + testDir: "./tests", + snapshotPathTemplate: "tests/snapshots/{arg}{ext}", + reporter: [["html", { open: "always" }]], + use: { + baseURL: "http://localhost:8000", + viewport: { width: 1024, height: 768 }, + browserName: "chromium", + screenshot: "on", + launchOptions: { + args: ["--no-sandbox"], + }, + }, + webServer: { + command: "npm run start", + url: "http://localhost:8000/tests/base.html", + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/tests/a11y-font.html b/tests/a11y-font.html deleted file mode 100644 index 91e33d5a..00000000 --- a/tests/a11y-font.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Test - - - - - - - -

CHAPTER 1. Loomings.

- -

Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people’s hats off—then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball.[1] With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.

- -

There now is your insular city of the Manhattoes, belted round by wharves as Indian isles by coral reefs—commerce surrounds it with her surf. Right and left, the streets take you waterward. Its extreme downtown is the battery, where that noble mole is washed by waves, and cooled by breezes, which a few hours previous were out of sight of land. Look at the crowds of water-gazers there.

- -

Circumambulate the city of a dreamy Sabbath afternoon. Go from Corlears Hook to Coenties Slip, and from thence, by Whitehall, northward. What do you see?—Posted like silent sentinels all around the town, stand thousands upon thousands of mortal men fixed in ocean reveries. Some leaning against the spiles; some seated upon the pier-heads; some looking over the bulwarks of ships from China; some high aloft in the rigging, as if striving to get a still better seaward peep. But these are all landsmen; of week days pent up in lath and plaster—tied to counters, nailed to benches, clinched to desks. How then is this? Are the green fields gone? What do they here?

- - \ No newline at end of file diff --git a/tests/visual.spec.js b/tests/visual.spec.js new file mode 100644 index 00000000..15d6a345 --- /dev/null +++ b/tests/visual.spec.js @@ -0,0 +1,67 @@ +const { test, expect } = require("@playwright/test"); + +const scenarios = [ + // viewport screenshots (paged mode — content is clipped to columns) + { label: "Paged", url: "/tests/base.html" }, + { label: "Paged RTL", url: "/tests/base-rtl.html" }, + { label: "Paged vertical", url: "/tests/base-vertical.html" }, + { label: "1 column", url: "/tests/cols-1.html" }, + { label: "2 columns", url: "/tests/cols-2.html"}, + { label: "3 columns", url: "/tests/cols-3.html" }, + { label: "Line length", url: "/tests/line-length.html" }, + { label: "Scroll", url: "/tests/scroll.html", fullPage: true }, + { label: "Scroll vertical", url: "/tests/scroll-vertical.html", fullPage: true }, + { label: "Scroll padding", url: "/tests/scroll-padding.html", fullPage: true }, + { label: "Default colors", url: "/tests/default-colors.html", fullPage: true }, + { label: "Default custom colors", url: "/tests/default-custom-colors.html", fullPage: true }, + { label: "Theming", url: "/tests/theming.html", fullPage: true }, + { label: "Font family", url: "/tests/font-family.html", fullPage: true }, + { label: "Font size", url: "/tests/font-size.html", fullPage: true }, + { label: "Font size deprecated", url: "/tests/font-size-deprecated.html", fullPage: true }, + { label: "Font size normalize", url: "/tests/font-size-normalize.html", fullPage: true }, + { label: "Type scale", url: "/tests/type-scale.html", fullPage: true }, + { label: "Text align", url: "/tests/text-align.html", fullPage: true }, + { label: "Hyphens", url: "/tests/hyphens.html", fullPage: true }, + { label: "Line height", url: "/tests/line-height.html", fullPage: true }, + { label: "Para spacing", url: "/tests/para-spacing.html", fullPage: true }, + { label: "Para spacing vertical", url: "/tests/para-spacing-vertical.html", fullPage: true }, + { label: "Word spacing", url: "/tests/word-spacing.html", fullPage: true }, + { label: "Letter spacing", url: "/tests/letter-spacing.html", fullPage: true }, + { label: "Letter spacing CJK", url: "/tests/letter-spacing-cjk.html", fullPage: true }, + { label: "Ligatures", url: "/tests/arabic-ligatures.html", fullPage: true }, + { label: "Accessibility normalize", url: "/tests/a11y-normalize.html", fullPage: true }, + { label: "Accessibility custom", url: "/tests/a11y-custom.html", fullPage: true }, + { label: "No ruby", url: "/tests/no-ruby.html", fullPage: true }, + { label: "Font optical sizing", url: "/tests/font-optical-sizing.html", fullPage: true }, + { label: "Font weight", url: "/tests/font-weight.html", fullPage: true }, + { label: "Font width keyword", url: "/tests/font-width-keyword.html", fullPage: true }, + { label: "Font width percentage", url: "/tests/font-width-percentage.html", fullPage: true }, + { label: "Blend filter", url: "/tests/blend-filter.html", fullPage: true }, + { label: "Darken filter", url: "/tests/darken-filter.html", fullPage: true }, + { label: "Invert filter", url: "/tests/invert-filter.html", fullPage: true }, +]; + +for (const { label, url, fullPage = false } of scenarios) { + test(label, async ({ page }) => { + await page.goto(url, { waitUntil: "networkidle" }); + await page.evaluate(() => document.fonts.ready); + const name = url.split("/").pop().replace(".html", ""); + + if (fullPage) { + // ReadiumCSS scroll mode sets overflow:auto on :root (html) and + // overflow:clip on body, making html the scroll container rather than + // the window. Playwright's fullPage scrolls the window, so it captures + // only the viewport. We expand the viewport to the full content size instead. + const { scrollWidth, scrollHeight } = await page.evaluate(() => ({ + scrollWidth: document.documentElement.scrollWidth, + scrollHeight: document.documentElement.scrollHeight, + })); + await page.setViewportSize({ width: scrollWidth, height: scrollHeight }); + } + + await expect(page).toHaveScreenshot(`${name}.png`, { + fullPage: false, + maxDiffPixelRatio: 0.001, + }); + }); +} From 42b0ebfcc8a85e3e8ad5faa5053e4a1565b4f384 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 1 May 2026 08:52:30 +0200 Subject: [PATCH 02/14] Fix RTL For some reason Playwright will completely refuse to capture a single column in Paged RTL and return a blank image so we need to check 2. --- tests/base-rtl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/base-rtl.html b/tests/base-rtl.html index 3b0532ba..7330ae00 100644 --- a/tests/base-rtl.html +++ b/tests/base-rtl.html @@ -1,5 +1,5 @@ - + Test From 3eda2f139a32f589b8493a1b5227c13f74d1092e Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 1 May 2026 09:24:47 +0200 Subject: [PATCH 03/14] =?UTF-8?q?Upgrade=20to=20node=20=E2=80=93=20esm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/node.js.yml | 2 +- .nvmrc | 2 +- css/postcss.config.js | 49 +++++++++++++++++++++-------------- package.json | 1 + playwright.config.js | 4 +-- server.js | 10 ++++--- tests/visual.spec.js | 2 +- 7 files changed, 42 insertions(+), 28 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index b7477d65..7ab56102 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -24,7 +24,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '24.x' cache: 'npm' - run: npm ci - run: npm run build --if-present diff --git a/.nvmrc b/.nvmrc index 85aee5a5..18c92ea9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 \ No newline at end of file +v24 \ No newline at end of file diff --git a/css/postcss.config.js b/css/postcss.config.js index 174b186f..ba102239 100644 --- a/css/postcss.config.js +++ b/css/postcss.config.js @@ -1,21 +1,30 @@ -const version = require("../package.json").version; +import { execSync } from 'child_process'; +import pkg from '../package.json' with { type: 'json' }; +import postcssImport from 'postcss-import'; +import postcssCustomSelectors from 'postcss-custom-selectors'; +import postcssImportJson from '@daltontan/postcss-import-json'; +import postcssDiscardComments from 'postcss-discard-comments'; +import stylelint from 'stylelint'; +import postcssSorting from 'postcss-sorting'; +import postcssHeader from 'postcss-header'; + +const { version } = pkg; // Get contributors from git function getContributors() { try { - const log = require("child_process") - .execSync("git log --format='%aN <%aE>' | sort -u") + const log = execSync("git log --format='%aN <%aE>' | sort -u") .toString() .split("\n") .filter(Boolean); - + // Process contributors: filter bots and specific names, extract names, deduplicate, and sort return [ ...new Set( log .filter(contributor => { const name = contributor.toLowerCase(); - return !name.includes("dependabot") && + return !name.includes("dependabot") && !name.includes("[bot]") && !name.includes("bot@") && !name.includes("jaypanoz") && @@ -40,20 +49,20 @@ const header = `/*! * Copyright (c) 2017–${new Date().getFullYear()}. Readium Foundation. All rights reserved. * Use of this source code is governed by a BSD-style license which is detailed in the * LICENSE file present in the project repository where this source code is maintained. - * Core maintainer: Jiminy Panoz + * Core maintainer: Jiminy Panoz ${contributorsSection} */\n`; -module.exports = (ctx) => ({ +export default (ctx) => ({ map: false, plugins: [ - require("postcss-import")({ + postcssImport({ root: ctx.file.dirname }), - require("postcss-custom-selectors")({}), - require("@daltontan/postcss-import-json")({}), - require("postcss-discard-comments")({}), - require("stylelint")({ + postcssCustomSelectors({}), + postcssImportJson({}), + postcssDiscardComments({}), + stylelint({ "fix": true, "config": { "defaultSeverity": "warning", @@ -68,18 +77,18 @@ module.exports = (ctx) => ({ , "severity": "error" }] , "custom-property-pattern": [ "(RS|USER)__.+", { - "message": "It looks like you’re using a CSS variable prefix which is not supported. It should either start with “--RS__” or “--USER__”." + "message": "It looks like you're using a CSS variable prefix which is not supported. It should either start with '--RS__' or '--USER__'." , "severity": "error" }] , "color-hex-length": [ "long", { "message": "We recommend using long color HEX to prevent unexpected issues." }] , "font-family-name-quotes": [ "always-where-recommended", { - "message": "If looks like there are spaces or digits in your “font-family”, please use quotes." + "message": "If looks like there are spaces or digits in your 'font-family', please use quotes." }] , "function-url-quotes": "always" , "length-zero-no-unit": [ true, { - "message": "The value of this property being 0, you don’t need an unit. Please remove it." + "message": "The value of this property being 0, you don't need an unit. Please remove it." }] , "selector-type-case": "lower" , "function-name-case": "lower" @@ -91,17 +100,17 @@ module.exports = (ctx) => ({ , "rule-empty-line-before": "always" , "no-duplicate-at-import-rules": true , "no-invalid-double-slash-comments": [ true, { - "message": "It looks like you’re using single-line JS comments. This is CSS, you can’t use that." + "message": "It looks like you're using single-line JS comments. This is CSS, you can't use that." , "severity": "error" }] , "max-nesting-depth": [ 0, { - "message": "We’re using Vanilla CSS with PostCSS and our current configuration doesn’t allow nesting selectors as in LESS or SASS." + "message": "We're using Vanilla CSS with PostCSS and our current configuration doesn't allow nesting selectors as in LESS or SASS." , "severity": "error" }] } } }), - require("postcss-sorting")({ + postcssSorting({ "properties-order": [ "object-fit" , "position" @@ -268,9 +277,9 @@ module.exports = (ctx) => ({ ], "unspecified-properties-position": "bottomAlphabetical" }), - require("postcss-header")({ + postcssHeader({ header: header, headerLength: 0 }) ] -}) \ No newline at end of file +}) diff --git a/package.json b/package.json index 091a8e07..3099fe25 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "ebook-reader", "css" ], + "type": "module", "author": { "name": "readium", "email": "readium-css@edrlab.org", diff --git a/playwright.config.js b/playwright.config.js index c218d42a..eb9704ea 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,6 +1,6 @@ -const { defineConfig } = require("@playwright/test"); +import { defineConfig } from '@playwright/test'; -module.exports = defineConfig({ +export default defineConfig({ testDir: "./tests", snapshotPathTemplate: "tests/snapshots/{arg}{ext}", reporter: [["html", { open: "always" }]], diff --git a/server.js b/server.js index 4c29095e..08d9b47a 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,9 @@ -const http = require("http"); -const express = require("express"); +import http from 'http'; +import express from 'express'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); const app = express(); const httpPort = 8000; @@ -16,4 +20,4 @@ httpServer.listen(httpPort, (err) => { app.use("/tests", express.static(__dirname + "/tests")); app.use("/css/demo", express.static(__dirname + "/css/demo")); app.use("/css/dist", express.static(__dirname + "/css/dist")); -app.use("/docs/utils", express.static(__dirname + "/docs/utils")); \ No newline at end of file +app.use("/docs/utils", express.static(__dirname + "/docs/utils")); diff --git a/tests/visual.spec.js b/tests/visual.spec.js index 15d6a345..176d9e5d 100644 --- a/tests/visual.spec.js +++ b/tests/visual.spec.js @@ -1,4 +1,4 @@ -const { test, expect } = require("@playwright/test"); +import { test, expect } from '@playwright/test'; const scenarios = [ // viewport screenshots (paged mode — content is clipped to columns) From b593b69a81ec1860d0a29a1ab32663cd30b9e271 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 1 May 2026 09:40:20 +0200 Subject: [PATCH 04/14] Update ligatures test Setting is now global --- css/postcss.config.js | 2 +- tests/arabic-ligatures.html | 31 ------------------------------- tests/ligatures.html | 34 ++++++++++++++++++++++++++++++++++ tests/visual.spec.js | 2 +- 4 files changed, 36 insertions(+), 33 deletions(-) delete mode 100644 tests/arabic-ligatures.html create mode 100644 tests/ligatures.html diff --git a/css/postcss.config.js b/css/postcss.config.js index ba102239..51ace0a4 100644 --- a/css/postcss.config.js +++ b/css/postcss.config.js @@ -49,7 +49,7 @@ const header = `/*! * Copyright (c) 2017–${new Date().getFullYear()}. Readium Foundation. All rights reserved. * Use of this source code is governed by a BSD-style license which is detailed in the * LICENSE file present in the project repository where this source code is maintained. - * Core maintainer: Jiminy Panoz + * Core maintainer: Jiminy Panoz ${contributorsSection} */\n`; diff --git a/tests/arabic-ligatures.html b/tests/arabic-ligatures.html deleted file mode 100644 index eb15635e..00000000 --- a/tests/arabic-ligatures.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - Test - - - - - - - -

لغة عربية - ويكيبيديا، الموسوعة الحرة

- -

اللُّغَة العَرَبِيّة هي أكثر اللغات تحدثاً ونطقاً ضمن مجموعة اللغات السامية، وإحدى أكثر اللغات انتشاراً في العالم، يتحدثها أكثر من مليون نسمة، ويتوزع متحدثوها في الوطن العربي، بالإضافة إلى العديد من المناطق الأخرى المجاورة كالأحواز وتركيا وتشاد ومالي والسنغال وإرتيريا و إثيوبيا و جنوب السودان و إيران. اللغة العربية ذات أهمية قصوى لدى المسلمين، فهي لغة مقدسة (لغة القرآن)، ولا تتم الصلاة (وعبادات أخرى) في الإسلام إلا بإتقان بعض من كلماتها. العربية هي أيضاً لغة شعائرية رئيسية لدى عدد من الكنائس المسيحية في الوطن العربي، كما كتبت بها كثير من أهم الأعمال الدينية والفكرية اليهودية في العصور الوسطى. وأثّر انتشار الإسلام، وتأسيسه دولاً، في ارتفاع مكانة اللغة العربية، وأصبحت لغة السياسة والعلم والأدب لقرون طويلة في الأراضي التي حكمها المسلمون، وأثرت العربية تأثيراً مباشراً أو غير مباشر على كثير من اللغات الأخرى في العالم الإسلامي، كالتركية والفارسية والأمازيغية والكردية والأردوية والماليزية والإندونيسية والألبانية وبعض اللغات الإفريقية الأخرى مثل الهاوسا والسواحيلية والتجرية والأمهرية و الصومالية، وبعض اللغات الأوروبية وخاصةً المتوسطية كالإسبانية والبرتغالية والمالطية والصقلية. كما أنها تُدرَّس بشكل رسمي أو غير رسمي في الدول الإسلامية والدول الإفريقية المحاذية للوطن العربي.

- -

العربية لغة رسمية في كل دول الوطن العربي إضافة إلى كونها لغة رسمية في تشاد وإريتريا وإسرائيل. وهي إحدى اللغات الرسمية الست في منظمة الأمم المتحدة، ويُحتفل باليوم العالمي للغة العربية في ديسمبر كذكرى اعتماد العربية بين لغات العمل في الأمم المتحدة.

- -

واللغة العربية من أغزر اللغات من حيث المادة اللغوية، فعلى سبيل المثال يحوي معجم لسان العرب لابن منظور من القرن الثالث عشر أكثر من ألف مادة، بينما في اللغة الإنجليزية فإن قاموس صموئيل جونسون - وهو من أوائل من وضع قاموساً إنجليزياً من القرن الثامن عشر يحتوي على ألف كلمة.

-

تحتوي العربية على حرفاً مكتوباً. ويرى بعض اللغويين أنه يجب إضافة حرف الهمزة إلى حروف العربية، ليصبح عدد الحروف تُكتب العربية من اليمين إلى اليسار - ومثلها اللغة الفارسية والعبرية على عكس كثير من اللغات العالمية - ومن أعلى الصفحة إلى أسفلها.

- -

الأسماء

- -

حيث ذهب به إلى أنها للعرب خاصة. غير أن الضاد المقصودة هنا ليست الضاد المعروفة والمستخدمة اليوم في دول مثل جمهورية مصر العربية، والتي هي عبارة عن دال مفخمة، وهي التي لاتُستحسن قراءة القرآن أو الشعر العربي بها، أما الضاد العربية القديمة فهي صوتٌ آخر مزيجٌ بين الظاء واللام، واندمج هذا الصوت مع الظاء في الجزيرة العربية. ولأن الظاء هي ذال مفخمة، أي أنها حرف ما - بين - أسناني، فقد تحولت بدورها في الحواضر إلى دال مفخمة كتحول الثاء إلى تاء والذال إلى دال، وصارت هذه الدال المفخمة هي الضاد الحديثة. فالدال المفخمة ليست خاصة بالعربية، بل هي في الواقع موجودة في لغات كثيرة. وهي ليست الضاد الأصلية التي كان يعنيها المتنبي وابن منظور صاحب لسان العرب وغيرهم.

- -

تصنيفها

- -

تنتمي اللغة العربية إلى أسرة اللغات السامية المتفرعة من مجموعة اللغات الإفريقية الآسيوية. وتضم مجموعة اللغات السامية لغات حضارة الهلال الخصيب القديمة، مثل الأكادية والكنعانية والآرامية واللغة الصيهدية (جنوب الجزيرة العربية) واللغات العربية الشمالية القديمة وبعض لغات القرن الإفريقي كالأمهرية. وعلى وجه التحديد، يضع اللغويون اللغة العربية في المجموعة السامية الوسطى من اللغات السامية الغربية.

- -

والعربية من أحدث هذه اللغات نشأة وتاريخاً، ولكن يعتقد البعض أنها الأقرب إلى اللغة السامية الأم التي انبثقت منها اللغات السامية الأخرى، وذلك لاحتباس العرب في جزيرة العرب فلم تتعرض لما تعرضت له باقي اللغات السامية من اختلاط. ولكن هناك من يخالف هذا الرأي بين علماء اللسانيات، حيث أن تغير اللغة هو عملية مستمرة عبر الزمن والانعزال الجغرافي قد يزيد من حدة هذا التغير حيث يبدأ نشوء أيّة لغة جديدة بنشوء لهجة جديدة في منطقة منعزلة جغرافياً. بالإضافة لافتراض وجود لغة سامية أم لا يعني وجودها بالمعنى المفهوم للغة الواحدة بل هي تعبير مجازي قصد به الإفصاح عن تقارب مجموعة من اللغات فقد كان علماء اللسانيات يعتمدون على قرب لغة وعقلية من يرونه مرشحاً لعضوية عائلة اللغات السامية وبُنيت دراساتهم على أسس جغرافية وسياسية وليس على أُسس عرقية ولا علاقة لها بنظرة التوراة لأبناء سام وكثرة قواعد اللغة العربية ترجح أنها طرأت عليها في فترات لاحقة وأنها مرت بأطوار عديدة مما يضعف فرضية أن هذه اللغة أقرب لما عُرف اصطلاحاً باللغة السامية الأم هذه، ولا توجد لغة في العالم تستطيع الادعاء أنها نقية وصافية من عوامل ومؤثرات خارجية

- - \ No newline at end of file diff --git a/tests/ligatures.html b/tests/ligatures.html new file mode 100644 index 00000000..f47cdf72 --- /dev/null +++ b/tests/ligatures.html @@ -0,0 +1,34 @@ + + + + Test + + + + + + + +

CHAPTER 1. Loomings.

+ +

Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular + to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have + of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever + it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and + bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it + requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking + people’s hats off—then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. + With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising + in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings + towards the ocean with me.

+ +

Offerings finally flashing efficiently offtrack

+ +

But look! here come more crowds, pacing straight for the water, and seemingly bound for a dive. Strange! Nothing will content + them but the extremest limit of the land; loitering under the shady lee of yonder warehouses will not suffice. No. They + must get just as nigh the water as they possibly can without falling in. And there they stand—miles of them—leagues. + Inlanders all, they come from lanes and alleys, streets and avenues—north, east, south, and west. Yet here they all unite. + Tell me, does the magnetic virtue of the needles of the compasses of all those ships attract them thither? +

+ + \ No newline at end of file diff --git a/tests/visual.spec.js b/tests/visual.spec.js index 176d9e5d..c494a122 100644 --- a/tests/visual.spec.js +++ b/tests/visual.spec.js @@ -28,7 +28,7 @@ const scenarios = [ { label: "Word spacing", url: "/tests/word-spacing.html", fullPage: true }, { label: "Letter spacing", url: "/tests/letter-spacing.html", fullPage: true }, { label: "Letter spacing CJK", url: "/tests/letter-spacing-cjk.html", fullPage: true }, - { label: "Ligatures", url: "/tests/arabic-ligatures.html", fullPage: true }, + { label: "Ligatures", url: "/tests/ligatures.html", fullPage: true }, { label: "Accessibility normalize", url: "/tests/a11y-normalize.html", fullPage: true }, { label: "Accessibility custom", url: "/tests/a11y-custom.html", fullPage: true }, { label: "No ruby", url: "/tests/no-ruby.html", fullPage: true }, From 2a5eb33e22006ff245e985e50a741592ec99ce11 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 1 May 2026 09:44:58 +0200 Subject: [PATCH 05/14] Update Playwright config --- playwright.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/playwright.config.js b/playwright.config.js index eb9704ea..fe37f863 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -2,8 +2,12 @@ import { defineConfig } from '@playwright/test'; export default defineConfig({ testDir: "./tests", + outputDir: "./tests/test-results", snapshotPathTemplate: "tests/snapshots/{arg}{ext}", - reporter: [["html", { open: "always" }]], + reporter: [ + ["json", { outputFile: "tests/test-results/results.json" }], + ["html", { open: process.argv.includes("--update-snapshots") ? "never" : "always", outputFolder: "tests/playwright-report" }] + ], use: { baseURL: "http://localhost:8000", viewport: { width: 1024, height: 768 }, From 3a3ff16c8f34b7cad2ae7328ffc1f346c1accc5f Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 1 May 2026 09:54:17 +0200 Subject: [PATCH 06/14] Update EPUB doc --- docs/ReadiumCSS_docs.epub | Bin 3689618 -> 3689404 bytes docs/ReadiumCSS_docs/OEBPS/content.opf | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ReadiumCSS_docs.epub b/docs/ReadiumCSS_docs.epub index 8be2d0de136fa121d29203c69977864d471f7b28..1525faa872e9d86a5bdc5a306466b16546e13454 100644 GIT binary patch delta 5703 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 delta 5944 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 TARfbtK&XNkFoQv$ht~fKD)AfB diff --git a/docs/ReadiumCSS_docs/OEBPS/content.opf b/docs/ReadiumCSS_docs/OEBPS/content.opf index ff8b62e0..939c9e0f 100644 --- a/docs/ReadiumCSS_docs/OEBPS/content.opf +++ b/docs/ReadiumCSS_docs/OEBPS/content.opf @@ -8,7 +8,7 @@ en urn:uuid:527D093B-9C0A-4C83-8AF6-0A40E91D30FC - 2026-02-19T10:52:18Z + 2026-05-01T09:53:00Z displayTransformability readingOrder From 191c92d126c32ed866ed1a9bb309ef2d7dbdb8dc Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 1 May 2026 09:58:10 +0200 Subject: [PATCH 07/14] Update npm in docs --- docs/CSS22-npm.md | 19 ++++++---- docs/ReadiumCSS_docs.epub | Bin 3689404 -> 3689458 bytes .../OEBPS/Text/Section-022.xhtml | 33 ++++++++++-------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/docs/CSS22-npm.md b/docs/CSS22-npm.md index 15c25e11..732bedcd 100644 --- a/docs/CSS22-npm.md +++ b/docs/CSS22-npm.md @@ -85,17 +85,24 @@ Then you must customize the selectors in `ReadiumCSS-config.js` and replace them Finally you will have to enable the `postcss-css-variables` and `postcss-alter-property-value` in the `postcss.config.js` file to be found at the `src` folder’s root. -The following must be added to `plugins`: +First, add the following imports at the top of the file: ``` -require("postcss-css-variables")({ - "preserve": true +import postcssCssVariables from 'postcss-css-variables'; +import postcssAlterPropertyValue from 'postcss-alter-property-value'; +``` + +Then add the following to `plugins`: + +``` +postcssCssVariables({ + preserve: true }), -require("postcss-alter-property-value")({ +postcssAlterPropertyValue({ declarations: { "*": { - task: "remove" - , whenValueEquals: "undefined" + task: "remove", + whenValueEquals: "undefined" } } }) diff --git a/docs/ReadiumCSS_docs.epub b/docs/ReadiumCSS_docs.epub index 1525faa872e9d86a5bdc5a306466b16546e13454..19ddf7ef3672e8532755b59fc342b11ac13506a9 100644 GIT binary patch delta 3530 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 E07>YtP5=M^ delta 3485 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 LAO@>9H~;_uoeHA8 diff --git a/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml b/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml index d51aaee2..332965b7 100644 --- a/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml +++ b/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml @@ -119,20 +119,25 @@ npm run test:update

Then you must customize the selectors in ReadiumCSS-config.js and replace them with either CSS classes or custom attributes so that flags can work as expected.

-

Finally you will have to enable the postcss-css-variables and postcss-alter-property-value in the postcss.config.js file to be found at the src folder’s root.

- -

The following must be added to plugins:

- -
require("postcss-css-variables")({ 
-  "preserve": true 
-}), 
-require("postcss-alter-property-value")({ 
-  declarations: { 
-    "*": { 
-      task: "remove" 
-    , whenValueEquals: "undefined" 
-    } 
-  } 
+          

Finally you will have to enable the postcss-css-variables and postcss-alter-property-value in the postcss.config.js file to be found at the src folder's root.

+ +

First, add the following imports at the top of the file:

+ +
import postcssCssVariables from 'postcss-css-variables';
+import postcssAlterPropertyValue from 'postcss-alter-property-value';
+ +

Then add the following to plugins:

+ +
postcssCssVariables({
+  preserve: true
+}),
+postcssAlterPropertyValue({
+  declarations: {
+    "*": {
+      task: "remove",
+      whenValueEquals: "undefined"
+    }
+  }
 })

This will:

From 674229359c3521935619f82af32140d9fea02a88 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 10:55:48 +0200 Subject: [PATCH 08/14] Visual regression CI/CD --- .github/workflows/playwright.yml | 27 ++++++++++++++++++++++++++ .github/workflows/update-snapshots.yml | 27 ++++++++++++++++++++++++++ .gitignore | 6 ++++-- playwright.config.js | 4 +++- 4 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 .github/workflows/update-snapshots.yml diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 00000000..c2062eb9 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Visual Regression + +on: + push: + branches: ["develop"] + pull_request: + branches: ["develop"] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: "24.x" + cache: npm + - run: npm ci + - run: npx playwright install --with-deps chromium + - run: npm test + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: playwright-report + path: tests/playwright-report/ + retention-days: 14 diff --git a/.github/workflows/update-snapshots.yml b/.github/workflows/update-snapshots.yml new file mode 100644 index 00000000..3b45f85a --- /dev/null +++ b/.github/workflows/update-snapshots.yml @@ -0,0 +1,27 @@ +name: Update Playwright Snapshots + +on: + workflow_dispatch: + +jobs: + update: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + fetch-depth: 0 + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: "24.x" + cache: npm + - run: npm ci + - run: npx playwright install --with-deps chromium + - run: npm run build && npx playwright test --update-snapshots + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "chore: update playwright snapshots" + file_pattern: "tests/snapshots/*.png" diff --git a/.gitignore b/.gitignore index 3dc5e736..8b060e68 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ node_modules/ *.css.map tests/backstop_data/ -tests/snapshots/ +tests/snapshots/local/ test-results/ -playwright-report/ \ No newline at end of file +playwright-report/ +blob-report/ +playwright/.cache/ \ No newline at end of file diff --git a/playwright.config.js b/playwright.config.js index fe37f863..a3a96502 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -3,7 +3,9 @@ import { defineConfig } from '@playwright/test'; export default defineConfig({ testDir: "./tests", outputDir: "./tests/test-results", - snapshotPathTemplate: "tests/snapshots/{arg}{ext}", + snapshotPathTemplate: process.env.CI + ? "tests/snapshots/{arg}{ext}" + : "tests/snapshots/local/{arg}{ext}", reporter: [ ["json", { outputFile: "tests/test-results/results.json" }], ["html", { open: process.argv.includes("--update-snapshots") ? "never" : "always", outputFolder: "tests/playwright-report" }] From 2198567e7aeef1e3decae5cd53af4f79747fb6d1 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 15:17:21 +0200 Subject: [PATCH 09/14] Complete update to esm --- css/postcss.config.js | 4 ++-- docs/ReadiumCSS_docs.epub | Bin 3690001 -> 3689840 bytes scripts/generate-vars-doc.js | 19 ++++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/css/postcss.config.js b/css/postcss.config.js index ccc71a3b..e8319cdb 100644 --- a/css/postcss.config.js +++ b/css/postcss.config.js @@ -59,10 +59,10 @@ export default (ctx) => ({ postcssImport({ root: ctx.file.dirname }), - postcssCustomSelectors({ + postcssCustomSelectors({}), + postcssImportJson({ prefix: "--RS__" }), - postcssImportJson({}), postcssDiscardComments({}), stylelint({ "fix": true, diff --git a/docs/ReadiumCSS_docs.epub b/docs/ReadiumCSS_docs.epub index 405709fa59c7dbf0aa2aea1c679a0d8ef3e48dfd..87261b178a9c6c92644a80122446bf3442e7522a 100644 GIT binary patch delta 3607 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 delta 3763 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 diff --git a/scripts/generate-vars-doc.js b/scripts/generate-vars-doc.js index 5a2a3c34..2ebc8d78 100644 --- a/scripts/generate-vars-doc.js +++ b/scripts/generate-vars-doc.js @@ -1,12 +1,13 @@ #!/usr/bin/env node -"use strict"; +import { readFileSync, writeFileSync } from "fs"; +import { join, relative } from "path"; +import { fileURLToPath } from "url"; -const fs = require("fs"); -const path = require("path"); +const __dirname = fileURLToPath(new URL(".", import.meta.url)); -const VARS_DIR = path.join(__dirname, "../css/vars"); -const OUTPUT = path.join(VARS_DIR, "CSS-Variables.md"); +const VARS_DIR = join(__dirname, "../css/vars"); +const OUTPUT = join(VARS_DIR, "CSS-Variables.md"); const FILES = [ { file: "pagination.json", heading: "Pagination", type: "flat" }, @@ -92,8 +93,8 @@ function generate() { const parts = ["# CSS Variables Reference\n"]; for (const { file, heading, type } of FILES) { - const src = path.join(VARS_DIR, file); - const data = JSON.parse(fs.readFileSync(src, "utf8")); + const src = join(VARS_DIR, file); + const data = JSON.parse(readFileSync(src, "utf8")); if (type === "flat") { parts.push(flatSection(heading, data)); @@ -106,8 +107,8 @@ function generate() { } } - fs.writeFileSync(OUTPUT, parts.join("\n")); - console.log(`Generated ${path.relative(process.cwd(), OUTPUT)}`); + writeFileSync(OUTPUT, parts.join("\n")); + console.log(`Generated ${relative(process.cwd(), OUTPUT)}`); } generate(); From dc8c10ad66ef689c23470b001bbe934efe9b5032 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 15:21:46 +0200 Subject: [PATCH 10/14] Update playwright config for CI --- playwright.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.js b/playwright.config.js index a3a96502..9a3df28e 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -8,7 +8,7 @@ export default defineConfig({ : "tests/snapshots/local/{arg}{ext}", reporter: [ ["json", { outputFile: "tests/test-results/results.json" }], - ["html", { open: process.argv.includes("--update-snapshots") ? "never" : "always", outputFolder: "tests/playwright-report" }] + ["html", { open: process.env.CI || process.argv.includes("--update-snapshots") ? "never" : "always", outputFolder: "tests/playwright-report" }] ], use: { baseURL: "http://localhost:8000", From 5aa0bdb3fb37c68917547331669c147faabbab3b Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 15:25:39 +0200 Subject: [PATCH 11/14] Fix fontReady --- tests/visual.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/visual.spec.js b/tests/visual.spec.js index c494a122..4b94c420 100644 --- a/tests/visual.spec.js +++ b/tests/visual.spec.js @@ -44,7 +44,7 @@ const scenarios = [ for (const { label, url, fullPage = false } of scenarios) { test(label, async ({ page }) => { await page.goto(url, { waitUntil: "networkidle" }); - await page.evaluate(() => document.fonts.ready); + await page.evaluate(async () => { await document.fonts.ready; }); const name = url.split("/").pop().replace(".html", ""); if (fullPage) { From f7f302d1e65b7ba52793a58ffffe7a7acc85f57f Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 15:32:16 +0200 Subject: [PATCH 12/14] Fix typing errors --- css/postcss.config.js | 4 ++-- docs/ReadiumCSS_docs.epub | Bin 3689840 -> 3689811 bytes .../OEBPS/Text/Section-022.xhtml | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/css/postcss.config.js b/css/postcss.config.js index e8319cdb..994a8f8b 100644 --- a/css/postcss.config.js +++ b/css/postcss.config.js @@ -86,11 +86,11 @@ export default (ctx) => ({ "message": "We recommend using long color HEX to prevent unexpected issues." }] , "font-family-name-quotes": [ "always-where-recommended", { - "message": "If looks like there are spaces or digits in your 'font-family', please use quotes." + "message": "It looks like there are spaces or digits in your 'font-family', please use quotes." }] , "function-url-quotes": "always" , "length-zero-no-unit": [ true, { - "message": "The value of this property being 0, you don't need an unit. Please remove it." + "message": "The value of this property being 0, you don't need a unit. Please remove it." }] , "selector-type-case": "lower" , "function-name-case": "lower" diff --git a/docs/ReadiumCSS_docs.epub b/docs/ReadiumCSS_docs.epub index 87261b178a9c6c92644a80122446bf3442e7522a..9248b8c6fa0a4a70d90f42f42c63912e52ab8d31 100644 GIT binary patch delta 3493 zcmV;W4O;T>n&AP{n&AO}gaL#Cgad>Ggaw2Kga?EOgb9QSgbRcWgbjoagb#!egb{=i zgcF1mgcXDqgcpPugc*bygd2n$gdKz)gdc<;gdv0?gd>C`ge8O~geQb3gein7ge!zB zge`)D`u@1ki^<8SpME;IqBW6U zbSBDbwzE>E<=m}3y?5{7q$rJBd8RlWEb<74E(K4gM~t0k!g7`@xi-SqTurvWu$j5dtR*veIe!5sZbv!&X+Q%%pHIqq#Smk}lgyDUS=$4utT8X|IJbwwwBOoiO#Y)9DYb_T`+w4!4y2zl&BjTD4Crh4HWeOe+ z*9&oUu_Zp!#oEBAGgwk@oMsXj3=YtE5NSw=+$;<0ory>g1azIs>%pBo3En>x3@)xd z$iwe{98I6nuCCku03&I^Dg(%67lpB4Ys5ILQz*}>=6|`thl~~w&ueLy>?_#%wKMye zy|941Oc?(QXDd$OpA}VZSutmpo6ES+lENG=t*QkS>C^;eLUoK+c3Egc4pG5pGMGW< z%#Eiw9UHtz*#-!=WBp3i8gSq_J?8-&1MHU&4go}{A5DX#;BPJy$rW3R znUUlL9Dgo=-AC8cGL%EaEEUjjKDL!L5Xy|9g9*MsQm)LzDKrjeI)qAeflt9(Vys4V z%b8TtZsIt}Onmy_Zy!J0vR2bNm?fmOTE>!VKwv|vR=SeLZpj5&6H;9LrR`-k^X>TG zb-MdeOXbV^^>5zuV6b;GCkNaz@_CCCJn?>8rhl?djt9!*KIyrSp2OxAP*J94M)D@={M4%Qh$C~q%C>d1X{GFFj@k9(FK@7oqu;xsdB^?s0UHM z3!99OyG*s!-xRrVD0_D`{~+4I@#TZ-b^oL(mjflJ{lTtpmeZ#jq>VYR6nG<<&_SSR zBCKnwZX}$BsZLtyC6-V-I0MamJ%1RC<#U`u#iTW|qqjILK9-`+j1$~R;ebQvC+{y0q5o_tb78~?RWMq7_le5cuM3p@ zIW>1EXXUR&ZmF)+(q$&9Y7b#y1>legSGVND^Wgb;iMT10^eokMcNpq`P=8Yle)Lgj zeW((u{me0fn9)SR_hoZQNDb=rC3LOGKkahNcf8(r+x$1ZAeH=eKg`Q=+W`$jVJ8|Z z!x!S#5%`vN4@I48=IdU*>EykH{bsyr>pe)OGR+|ydLTt>H%@pw`FAficN=tSNZT

ns}PWV&OA*1> zRRr%lT$GCYu}-F^XO=I z;}g=-MNrcBuAbiAKBUGwj|PWvZHMfO3PlEe`(Z~Qu}{VU;eYP_hNW1609lDMW_2Zw zem@=^T`P{;kP3LN=7hxNjQ!?Li~btbADNqhow3M=U^EI(*O0^!dHzeq6?R7O0x?HY zPb0VF_aplI{dm7R!hEtXX)#dxNgB471x;OdF&9n?6>>l-S&j#aph9)E`~%I2d`C-z@0>442fH}BlDst+^&lV#si-g$G|!X{inwXg zj=L$TQ=lv9+9ny%(o|3ZHWO)sDtvqC^M>w$Ui%s#zJGV`;n?4LO^M7lU`s7Cp{WDC zwz@i~^MttbO2xZFrrUO&Zyhn#8Bz8-&w8N7n=u+p6Imx_@eF1($#cN#ryZSRG~saQqR?N!b;LbklUuxu$* z8A5g`lFNRXpCmFRn4;hgS3ewBDEK8YkSuwQ%72rrb|gG=Gi=SM}{W`cWsIsA!NV7m#7`j3P_s3Z+8` zP`ZEG(xdcRlM_ChG?j;UKU!Oly_`txoO^@9d$Yy(}qOndo)6S6o)bFo&N_<)SRj}US`_gUZD5{yDIOJ0^6pIZFQ zv~kfH{MkRMUrIVV$jJL%Zt1+<;>wTqElc~Qm0;|ab?Vnxamr6}IAO=D?H~;_uw=tMY delta 3533 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 HH~;_uLol+- diff --git a/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml b/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml index 332965b7..6f89ce6e 100644 --- a/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml +++ b/docs/ReadiumCSS_docs/OEBPS/Text/Section-022.xhtml @@ -168,12 +168,12 @@ postcssAlterPropertyValue({

Test

-

Once you have built dist stylesheets, you can run visual regression tests using Playwright.

+

Once you have built dist stylesheets, you can run visual regression tests using Playwright.

It helps you check if you didn’t accidentally create a breaking change when customizing stylesheets, and make sure pagination and user settings work as expected.

-
-

Config

+
+

Config

The test configuration lives in playwright.config.js at the root of the project. By default, it runs all tests at a 1024×768 tablet viewport using Chromium. You can adjust the viewport or add browsers there.

@@ -182,14 +182,14 @@ postcssAlterPropertyValue({
npx playwright install webkit
-
-

Test files

+
+

Test files

If you customize flags in ReadiumCSS-config.css, you must modify HTML files in the tests folder; user settings are indeed set as inline styles on the html element and are using the default flags.

-
-

Available scripts

+
+

Available scripts

By default, the following scripts are available:

@@ -200,8 +200,8 @@ postcssAlterPropertyValue({
-
-

Usage

+
+

Usage

First navigate to the readium-css folder if you didn’t already, then…

From f7198fbfd5c78d1014b7f60ec91bc509fc2f064c Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 15:45:18 +0200 Subject: [PATCH 13/14] Fix tests discrepancies --- package.json | 2 +- tests/ligatures.html | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 013a504a..c6d1c109 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,6 @@ "copyPatches": "copyfiles -u 2 css/src/ReadiumCSS-ebpaj_fonts_patch.css css/dist", "start": "node \"./server.js\"", "test": "npm run build && playwright test", - "test:update": "playwright test --update-snapshots" + "test:update": "npm run build && playwright test --update-snapshots" } } diff --git a/tests/ligatures.html b/tests/ligatures.html index f47cdf72..2cf54b88 100644 --- a/tests/ligatures.html +++ b/tests/ligatures.html @@ -4,9 +4,9 @@ Test - - - + + +

CHAPTER 1. Loomings.

From d203e253fd72b6c7a681c08c1bbef336f30c2945 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Mon, 4 May 2026 15:48:52 +0200 Subject: [PATCH 14/14] Align gitignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8b060e68..5fbf63ae 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ node_modules/ *.css.map tests/backstop_data/ tests/snapshots/local/ -test-results/ -playwright-report/ +tests/test-results/ +tests/playwright-report/ blob-report/ playwright/.cache/ \ No newline at end of file