Compare commits

..

17 Commits

Author SHA1 Message Date
Bart van Andel
4290ea7539
fix: use js-yaml for both JSON to YAML and YAML to JSON (#2710) 2026-08-06 10:52:18 +01:00
dependabot[bot]
e2b0558c9c
chore (deps): bump the patch-updates group across 1 directory with 6 updates (#2712)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 08:32:40 +01:00
dependabot[bot]
bb941dd2b6
chore (deps): bump the minor-updates group across 1 directory with 3 updates (#2705)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 07:58:04 +01:00
dependabot[bot]
1d39e75dac
chore (deps): bump the actions-dependencies group with 2 updates (#2703)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 07:49:01 +01:00
Bart van Andel
396c6c8e93
fix: replace shasum / sha256sum / sed calls with node built-ins (#2019) 2026-08-06 07:39:30 +01:00
dependabot[bot]
b435acc6b4
chore (deps): bump fast-uri from 3.1.4 to 3.1.5 (#2709)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 08:31:29 +00:00
dependabot[bot]
f161086705
chore (deps): bump ip-address from 10.2.0 to 10.4.0 (#2708)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 08:06:47 +00:00
Sanjay Santhanam
c56dd23358
fix: stop Parse QR Code from participating in Magic (#2610) (#2613) 2026-07-25 09:08:18 +01:00
Kirill
be42a3b9c8
Restrict A1Z26 Magic checks to valid ranges (#2644) 2026-07-25 08:39:11 +01:00
MAN$I VERMA
8e19b7e402
feat: Extend automated ingredient validation to include argSelector ingredients (#2641) (#2643) 2026-07-25 08:17:08 +01:00
p-leriche
f6a4631130
Add Modular Exponentiation operation (#2149) 2026-07-25 08:00:06 +01:00
Zain Nadeem
c7d20d8601
Add npm allowScripts policy for npm v12 (#2682) 2026-07-24 15:47:02 +01:00
dependabot[bot]
536ee84034
chore (deps): bump assorted vulnerable dependencies (#2689)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com>
2026-07-24 10:54:29 +01:00
dependabot[bot]
08b2b7b3dd
chore (deps): bump shell-quote from 1.8.4 to 1.10.0 (#2690)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 10:05:16 +01:00
dependabot[bot]
ed21930260
chore (deps): bump the patch-updates group across 1 directory with 9 updates (#2686)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 09:04:47 +01:00
dependabot[bot]
51600c4a4f
chore (deps): bump the actions-dependencies group across 1 directory with 2 updates (#2685)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 08:49:31 +01:00
dependabot[bot]
4b43f89eb8
chore (deps): bump nginxinc/nginx-unprivileged from fd3314e to 44e3633 in the docker-dependencies group (#2684)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 08:38:40 +01:00
22 changed files with 869 additions and 249 deletions

View File

@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Close stale unsigned-CLA PRs
uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 #v10.4.0
uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 #v11.0.0
with:
# ---- Guards: only act on PRs carrying the CLA label ----
only-labels: 'awaiting cla'

View File

@ -16,10 +16,10 @@ jobs:
pages: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set node version
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
registry-url: "https://registry.npmjs.org"

View File

@ -12,10 +12,10 @@ jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set node version
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
registry-url: "https://registry.npmjs.org"

View File

@ -22,10 +22,10 @@ jobs:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set node version
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
@ -77,7 +77,7 @@ jobs:
type=semver,pattern={{version}}
- name: Log in to GHCR
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
uses: docker/login-action@371161bbe7024a29a25c5e19bfcbc0804fe9ad2c # v4.5.2
with:
registry: ${{ env.REGISTRY }}
username: ${{ env.REGISTRY_USER }}
@ -110,10 +110,10 @@ jobs:
needs: main
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set node version
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
registry-url: "https://registry.npmjs.org"

View File

@ -27,7 +27,7 @@ RUN npm run build
#########################################
# Package static build files into nginx #
#########################################
FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:fd3314e343bad2de4e1127ef58be122abbfa7e09572fa46ae62fcddb6b3f21c5 AS cyberchef
FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:44e36330f74d4f3a1d4e222acca9e23b401fb87811a7597024502bb759c4dd49 AS cyberchef
LABEL maintainer="GCHQ <oss@gchq.gov.uk>"

View File

@ -1,10 +1,13 @@
"use strict";
const crypto = require("node:crypto");
const fs = require("node:fs");
const path = require("node:path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const glob = require("glob");
const path = require("path");
const nodeFlags = "--no-warnings --no-deprecation";
@ -29,7 +32,7 @@ module.exports = function (grunt) {
"Creates a production-ready build. Use the --msg flag to add a compile message.",
[
"eslint", "clean:prod", "clean:config", "exec:generateConfig", "findModules", "webpack:web",
"copy:standalone", "zip:standalone", "clean:standalone", "exec:calcDownloadHash", "chmod"
"copy:standalone", "zip:standalone", "clean:standalone", "calcDownloadHash", "chmod"
]);
grunt.registerTask("node",
@ -60,7 +63,7 @@ module.exports = function (grunt) {
grunt.registerTask("findModules",
"Finds all generated modules and updates the entry point list for Webpack",
function(arg1, arg2) {
function (arg1, arg2) {
const moduleEntryPoints = listEntryModules();
grunt.log.writeln(`Found ${Object.keys(moduleEntryPoints).length} modules.`);
@ -71,6 +74,26 @@ module.exports = function (grunt) {
}, moduleEntryPoints));
});
grunt.registerTask("calcDownloadHash", "Compute download hash", function () {
const done = this.async();
const hash = crypto.createHash("sha256");
// Use online algorithm to calculate hash, prevents reading the entire 75+ MB zip file into memory
fs.createReadStream(`build/prod/${downloadZipFilename}`)
.on("data", (chunk) => hash.update(chunk))
.on("end", () => {
const digest = hash.digest("hex");
fs.writeFileSync("build/prod/sha256digest.txt", `${digest}\n`, { encoding: "utf8" });
const index = fs.readFileSync("build/prod/index.html", { encoding: "utf8" });
fs.writeFileSync("build/prod/index.html", index.replace(/DOWNLOAD_HASH_PLACEHOLDER/g, digest), { encoding: "utf8" });
done(true);
})
.on("error", (err) => done(false));
});
// Load tasks provided by each plugin
grunt.loadNpmTasks("grunt-eslint");
@ -114,7 +137,7 @@ module.exports = function (grunt) {
output: {
path: __dirname + "/build/prod",
filename: chunkData => {
return chunkData.chunk.name === "main" ? "assets/[name].js": "[name].js";
return chunkData.chunk.name === "main" ? "assets/[name].js" : "[name].js";
},
globalObject: "this"
},
@ -333,22 +356,6 @@ module.exports = function (grunt) {
}
},
exec: {
calcDownloadHash: {
command: function () {
switch (process.platform) {
case "darwin":
return chainCommands([
`shasum -a 256 build/prod/${downloadZipFilename} | awk '{print $1;}' > build/prod/sha256digest.txt`,
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
]);
default:
return chainCommands([
`sha256sum build/prod/${downloadZipFilename} | awk '{print $1;}' > build/prod/sha256digest.txt`,
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
]);
}
},
},
repoSize: {
command: chainCommands([
"git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'",

563
package-lock.json generated
View File

@ -39,7 +39,7 @@
"d3": "7.9.0",
"d3-hexbin": "^0.2.2",
"diff": "^9.0.0",
"dompurify": "^3.4.11",
"dompurify": "^3.4.13",
"es6-promisify": "^7.0.0",
"escodegen": "^2.1.0",
"esprima": "^4.0.1",
@ -56,10 +56,11 @@
"jq-web": "^0.5.1",
"jquery": "3.7.1",
"js-ascon": "^1.3.0",
"js-sha3": "^0.9.3",
"js-sha3": "^0.12.0",
"js-yaml": "^5.2.3",
"jsesc": "^3.1.0",
"json5": "^2.2.3",
"jsonata": "^2.2.1",
"jsonata": "^2.2.2",
"jsonpath-plus": "^10.4.0",
"jsonwebtoken": "9.0.3",
"jsqr": "^1.4.0",
@ -74,8 +75,8 @@
"lz4js": "^0.2.0",
"markdown-it": "^14.3.0",
"moment": "^2.30.1",
"moment-timezone": "^0.6.2",
"ngeohash": "^0.6.3",
"moment-timezone": "^0.6.3",
"ngeohash": "^0.6.4",
"node-forge": "^1.4.0",
"node-md6": "^0.1.0",
"nodom": "^2.4.0",
@ -86,7 +87,7 @@
"path": "^0.12.7",
"popper.js": "^1.16.1",
"process": "^0.11.10",
"protobufjs": "^8.7.0",
"protobufjs": "^8.7.1",
"punycode.js": "^2.3.1",
"qr-image": "^3.2.0",
"reflect-metadata": "^0.2.2",
@ -119,12 +120,12 @@
"@codemirror/language": "^6.12.4",
"@codemirror/search": "^6.7.1",
"@codemirror/state": "^6.7.1",
"@codemirror/view": "^6.43.6",
"@codemirror/view": "^6.43.7",
"@puppeteer/browsers": "3.0.6",
"autoprefixer": "^10.5.2",
"autoprefixer": "^10.5.4",
"babel-loader": "^10.1.1",
"base64-loader": "^1.0.0",
"chromedriver": "^150.0.3",
"chromedriver": "^150.0.4",
"cli-progress": "^3.12.0",
"colors": "^1.4.0",
"compression-webpack-plugin": "^12.0.0",
@ -132,10 +133,11 @@
"core-js": "^3.49.0",
"cspell": "^10.0.1",
"css-loader": "^7.1.4",
"eslint": "^9.39.4",
"eslint": "^9.39.5",
"eslint-plugin-jsdoc": "^50.8.0",
"globals": "^17.7.0",
"grunt": "^1.6.2",
"glob": "^13.0.6",
"globals": "^17.9.0",
"grunt": "^1.6.3",
"grunt-chmod": "~1.1.1",
"grunt-concurrent": "^3.0.0",
"grunt-contrib-clean": "~2.0.1",
@ -146,20 +148,20 @@
"grunt-exec": "~3.0.0",
"grunt-webpack": "^8.0.0",
"grunt-zip": "^1.0.0",
"html-webpack-plugin": "^5.6.7",
"html-webpack-plugin": "^5.6.8",
"imports-loader": "^5.0.0",
"mini-css-extract-plugin": "2.10.2",
"modify-source-webpack-plugin": "^4.1.0",
"nightwatch": "^3.16.0",
"postcss": "^8.5.16",
"postcss": "^8.5.25",
"postcss-css-variables": "^0.19.0",
"postcss-import": "^16.1.1",
"postcss-loader": "^8.2.1",
"prompt": "^1.3.0",
"sitemap": "^9.0.1",
"terser": "^5.49.0",
"webpack": "^5.108.4",
"webpack-bundle-analyzer": "^5.3.0",
"webpack": "^5.109.2",
"webpack-bundle-analyzer": "^5.3.1",
"webpack-dev-server": "^5.2.6",
"webpack-node-externals": "^3.0.0",
"worker-loader": "^3.0.8"
@ -1899,9 +1901,9 @@
}
},
"node_modules/@codemirror/view": {
"version": "6.43.6",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.6.tgz",
"integrity": "sha512-EVunGSYN1wz1p75WY1s3Xg7t3i8Yol0kGZGizNdX9BUFgMFILYVe8/u6EVpo7Ff5PwbZuILb4QAq7IZoKzIEQA==",
"version": "6.43.7",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.7.tgz",
"integrity": "sha512-FZsExxkoxnAN+d9TgqXLg5g4A1oQwzX9WlkOT5i2PKkcW7xx3Bmu0vs90g6fo9Mpdsb/l96dnAraQ8932aO4/g==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2776,9 +2778,9 @@
}
},
"node_modules/@eslint/eslintrc": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
"integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz",
"integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2788,7 +2790,7 @@
"globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.1",
"js-yaml": "^4.3.0",
"minimatch": "^3.1.5",
"strip-json-comments": "^3.1.1"
},
@ -2812,10 +2814,33 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
"integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/@eslint/js": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
"integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"version": "9.39.5",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz",
"integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==",
"dev": true,
"license": "MIT",
"engines": {
@ -5092,19 +5117,6 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-phases": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
"integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10.13.0"
},
"peerDependencies": {
"acorn": "^8.14.0"
}
},
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
@ -5376,6 +5388,28 @@
"node": ">= 6"
}
},
"node_modules/archiver-utils/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/archiver/node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -5620,9 +5654,9 @@
"license": "MIT"
},
"node_modules/autoprefixer": {
"version": "10.5.2",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.2.tgz",
"integrity": "sha512-rD5t5DwOjJdmSORcTq64j8MawTC+tbQ+HHqjR4NDumamy/ambn1UJrlKL+KdwujWxMkFjPM3pPHOEA9tl4767Q==",
"version": "10.5.4",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz",
"integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==",
"dev": true,
"funding": [
{
@ -5640,8 +5674,8 @@
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.28.4",
"caniuse-lite": "^1.0.30001799",
"browserslist": "^4.28.6",
"caniuse-lite": "^1.0.30001806",
"fraction.js": "^5.3.4",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
@ -5842,9 +5876,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.40",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz",
"integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==",
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.1.tgz",
"integrity": "sha512-HYXq73DDpCtNzOmrFsm9eSwCvWCql0RzqjpDzXN9EadiLJ4DNat0nsZ/Bzmy+Ud12mb4/zKDY0cQ805ZzN+i0A==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@ -6024,9 +6058,9 @@
}
},
"node_modules/body-parser": {
"version": "1.20.5",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
"integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"version": "1.20.6",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz",
"integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -6259,9 +6293,9 @@
}
},
"node_modules/brace-expansion": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
"integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz",
"integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -6376,9 +6410,9 @@
}
},
"node_modules/browserslist": {
"version": "4.28.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
"integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
"version": "4.28.7",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz",
"integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==",
"dev": true,
"funding": [
{
@ -6396,10 +6430,10 @@
],
"license": "MIT",
"dependencies": {
"baseline-browser-mapping": "^2.10.38",
"caniuse-lite": "^1.0.30001799",
"electron-to-chromium": "^1.5.376",
"node-releases": "^2.0.48",
"baseline-browser-mapping": "^2.10.44",
"caniuse-lite": "^1.0.30001806",
"electron-to-chromium": "^1.5.393",
"node-releases": "^2.0.51",
"update-browserslist-db": "^1.2.3"
},
"bin": {
@ -6591,9 +6625,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001799",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz",
"integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==",
"version": "1.0.30001806",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz",
"integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==",
"dev": true,
"funding": [
{
@ -6733,9 +6767,9 @@
}
},
"node_modules/chromedriver": {
"version": "150.0.3",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-150.0.3.tgz",
"integrity": "sha512-i2L979d6YDTVVUDUPWXz75HGKKVhjNXo74gLiy/f8Adb5zHLU+h3ABdg8RRoiegtjJB0m9vUEiPTdecD0ifa3w==",
"version": "150.0.4",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-150.0.4.tgz",
"integrity": "sha512-Yg2oXBONi1mqAMOG2ybwUneSvxIn04NF4qNAJ+yGO2H7WwX1WYLGQRHVHsbySEjIuqIyDmS1ZfAw6p0wtl43zQ==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
@ -7353,6 +7387,29 @@
"node": ">=6"
}
},
"node_modules/cosmiconfig/node_modules/js-yaml": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
"integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
@ -8702,9 +8759,9 @@
}
},
"node_modules/dompurify": {
"version": "3.4.11",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz",
"integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==",
"version": "3.4.13",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz",
"integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
@ -8809,9 +8866,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.379",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.379.tgz",
"integrity": "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA==",
"version": "1.5.396",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.396.tgz",
"integrity": "sha512-yHiw2Y3C3H9U6TMbOfoWK/BPreiOPXRfTWPBwQBoZG6/8TB6eOPnsy5oaRYuatR7Fw2SJ4kKforgufeo7fq0EQ==",
"dev": true,
"license": "ISC"
},
@ -8874,9 +8931,9 @@
}
},
"node_modules/enhanced-resolve": {
"version": "5.24.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.1.tgz",
"integrity": "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==",
"version": "5.24.5",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz",
"integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -9112,9 +9169,9 @@
}
},
"node_modules/eslint": {
"version": "9.39.4",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"version": "9.39.5",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz",
"integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -9123,8 +9180,8 @@
"@eslint/config-array": "^0.21.2",
"@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.5",
"@eslint/js": "9.39.4",
"@eslint/eslintrc": "^3.3.6",
"@eslint/js": "9.39.5",
"@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@ -9692,9 +9749,9 @@
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
"integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
"integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
"dev": true,
"funding": [
{
@ -9772,9 +9829,9 @@
}
},
"node_modules/filelist/node_modules/brace-expansion": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz",
"integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -10239,22 +10296,18 @@
}
},
"node_modules/glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"version": "13.0.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz",
"integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==",
"dev": true,
"license": "ISC",
"license": "BlueOak-1.0.0",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
"minimatch": "^10.2.2",
"minipass": "^7.1.3",
"path-scurry": "^2.0.2"
},
"engines": {
"node": "*"
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@ -10290,6 +10343,45 @@
"tslib": "2"
}
},
"node_modules/glob/node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/glob/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/glob/node_modules/minimatch": {
"version": "10.2.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
"integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.8"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/global-directory": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz",
@ -10359,9 +10451,9 @@
}
},
"node_modules/globals": {
"version": "17.7.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.7.0.tgz",
"integrity": "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==",
"version": "17.9.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.9.0.tgz",
"integrity": "sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg==",
"dev": true,
"license": "MIT",
"engines": {
@ -10386,6 +10478,28 @@
"node": ">= 0.10"
}
},
"node_modules/globule/node_modules/glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/globule/node_modules/minimatch": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz",
@ -10419,9 +10533,9 @@
"license": "ISC"
},
"node_modules/grunt": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.2.tgz",
"integrity": "sha512-bUzh5nA/P5L66ihXTDP6J5BGnMB/8lXJXejYWSbH4Y4TvWM9t2S39sggQDYYQlx06cYcCsmu63HMYHGCIzUVfg==",
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.3.tgz",
"integrity": "sha512-ng0CbpyNp/ox5e5CBY9TkZgVdAL4wK+nBHO6rNE8cXGa5kM++Lxlp0MpFBVZbpgOR2oCp/91V+T3CZVSWWLqMA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -10435,7 +10549,7 @@
"grunt-legacy-log": "~3.0.0",
"grunt-legacy-util": "~2.0.1",
"iconv-lite": "~0.6.3",
"js-yaml": "~3.14.0",
"js-yaml": "^3.15.0",
"minimatch": "^3.1.5",
"nopt": "^5.0.0"
},
@ -10872,10 +10986,32 @@
"sprintf-js": "~1.0.2"
}
},
"node_modules/grunt/node_modules/glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/grunt/node_modules/js-yaml": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz",
"integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -11159,9 +11295,9 @@
}
},
"node_modules/html-webpack-plugin": {
"version": "5.6.7",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz",
"integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==",
"version": "5.6.8",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.8.tgz",
"integrity": "sha512-MZmKQcTnhEh1SPSyMiEytIeDZDUoBZVorNHivQGXMASHf/BSGGOrKa2xQ5bGx3TCe1n109ecCt+cpww7wwWhKA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -11179,7 +11315,7 @@
"url": "https://opencollective.com/html-webpack-plugin"
},
"peerDependencies": {
"@rspack/core": "0.x || 1.x",
"@rspack/core": "0.x || 1.x || 2.x",
"webpack": "^5.20.0"
},
"peerDependenciesMeta": {
@ -11607,9 +11743,9 @@
"license": "MIT"
},
"node_modules/ip-address": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
"integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
"dev": true,
"license": "MIT",
"engines": {
@ -12387,9 +12523,9 @@
}
},
"node_modules/js-sha3": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz",
"integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==",
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.12.0.tgz",
"integrity": "sha512-DGaUQKtsHeqChRD6ndGcESOBXUBQs5/ji4xyyoAgdqBsAu5yHsVTrzuF7MZ0VQTAa/IQFXOq0WmV2I1HNuzPtA==",
"license": "MIT"
},
"node_modules/js-tokens": {
@ -12400,10 +12536,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
"integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
"dev": true,
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.3.tgz",
"integrity": "sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==",
"funding": [
{
"type": "github",
@ -12419,7 +12554,7 @@
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
"js-yaml": "bin/js-yaml.mjs"
}
},
"node_modules/jsdoc-type-pratt-parser": {
@ -12535,9 +12670,9 @@
}
},
"node_modules/jsonata": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.2.1.tgz",
"integrity": "sha512-xd1uwUrKeIcJbsWhaoS3qAX4Ea8m0Mw0G5nlnAQvPT7TbZ5qaPdzBVTQia9KfyuyQm+nenfyjvzUDTRYHsC2sw==",
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.2.2.tgz",
"integrity": "sha512-XDFH2PuaAXv0AXJEWwElXbqADmKFGKMLMkFb+qOz0EhjQW2EIJ6pgtordLU+4u3IVERyBfqy6bi6kZKEncvRqA==",
"license": "MIT",
"engines": {
"node": ">= 8"
@ -12830,20 +12965,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/loader-runner": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
"integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.11.5"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
@ -13460,6 +13581,16 @@
}
}
},
"node_modules/minipass": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
"integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mocha": {
"version": "10.8.2",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
@ -13497,9 +13628,9 @@
}
},
"node_modules/mocha/node_modules/brace-expansion": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz",
"integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -13537,6 +13668,29 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mocha/node_modules/js-yaml": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
"integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/mocha/node_modules/minimatch": {
"version": "5.1.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
@ -13584,9 +13738,9 @@
}
},
"node_modules/moment-timezone": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.2.tgz",
"integrity": "sha512-lDsQv8FoGdBUdf0+TjGsq2orxKuXdwFlQ6Zw6TX3xIcTwTfEpCLyKqvEauvCHJ8iu3KBV8+uPhlv70YsNGdUBQ==",
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.3.tgz",
"integrity": "sha512-pVEPA/HCFHHbwJ130ywnzYuZpkEGcP6Daa/OwNebpA18MybeFHmQilAGGovXgWijQ8vQtmud9jZrziUBgsykfg==",
"license": "MIT",
"dependencies": {
"moment": "^2.29.4"
@ -13698,9 +13852,9 @@
"license": "ISC"
},
"node_modules/nanoid": {
"version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"version": "3.3.16",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
"integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
"dev": true,
"funding": [
{
@ -13778,9 +13932,9 @@
}
},
"node_modules/ngeohash": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/ngeohash/-/ngeohash-0.6.3.tgz",
"integrity": "sha512-kltF0cOxgx1AbmVzKxYZaoB0aj7mOxZeHaerEtQV0YaqnkXNq26WWqMmJ6lTqShYxVRWZ/mwvvTrNeOwdslWiw==",
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/ngeohash/-/ngeohash-0.6.4.tgz",
"integrity": "sha512-+dEKu+Be7xkK6gVQ2wZSGLbr+iWO+0ZGaLi98iE7F0/1WCSqQDRmS8LAlZBNLD2z/3zFKE9v9BvUfCrhyDhXbg==",
"license": "MIT",
"engines": {
"node": ">=v0.2.0"
@ -14033,9 +14187,9 @@
"license": "CC0-1.0"
},
"node_modules/node-releases": {
"version": "2.0.50",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
"integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
"version": "2.0.51",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz",
"integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==",
"dev": true,
"license": "MIT",
"engines": {
@ -14823,6 +14977,33 @@
"node": ">=0.10.0"
}
},
"node_modules/path-scurry": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
"integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "11.5.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz",
"integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
@ -15041,9 +15222,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.16",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz",
"integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==",
"version": "8.5.25",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
"integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"dev": true,
"funding": [
{
@ -15061,7 +15242,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.12",
"nanoid": "^3.3.16",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@ -15310,9 +15491,9 @@
"license": "MIT"
},
"node_modules/protobufjs": {
"version": "8.7.0",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.7.0.tgz",
"integrity": "sha512-uu52JNxLh3vsL7tXU/h0gDaywufvuUCTbGSi0NKQKBZ2ZopkmrWQJSQO/EFqzu/5YhiwgVM8rq/a/iVpx4eZ0g==",
"version": "8.7.1",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.7.1.tgz",
"integrity": "sha512-agdGHrXNTv0IrYscJPDou/PlEJk1c/hBZ9o/B5NH2i/nSPtPqacNxzgwf1CebXxFMjMrZH5sqv9uQuw96aGt/A==",
"license": "BSD-3-Clause",
"dependencies": {
"long": "^5.3.2"
@ -15760,9 +15941,9 @@
}
},
"node_modules/readdir-glob/node_modules/brace-expansion": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
"integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz",
"integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -16071,6 +16252,28 @@
"rimraf": "bin.js"
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/ripemd160": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz",
@ -16616,9 +16819,9 @@
}
},
"node_modules/shell-quote": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz",
"integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz",
"integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==",
"dev": true,
"license": "MIT",
"engines": {
@ -18166,9 +18369,9 @@
}
},
"node_modules/webpack": {
"version": "5.108.4",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.108.4.tgz",
"integrity": "sha512-yur8LyJoeiWh47dErD+Ok7vlbmDsJ3UbbRPAoxbGJ54WpE2y5yVo5G/inUzujnYgw3tPmBRdn+G7PoxXaYC33w==",
"version": "5.109.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.109.2.tgz",
"integrity": "sha512-U9/cvLzxObKNEZ9+TtdqrHM5/9z3lgl2c+c4BzbqGxFQvQvBAq87yql5A8pQ+rrMbS496MZJeF5enVBndIy2hw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -18178,22 +18381,20 @@
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
"acorn": "^8.16.0",
"acorn-import-phases": "^1.0.3",
"browserslist": "^4.28.1",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.22.2",
"enhanced-resolve": "^5.24.4",
"es-module-lexer": "^2.1.0",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"graceful-fs": "^4.2.11",
"loader-runner": "^4.3.2",
"mime-db": "^1.54.0",
"minimizer-webpack-plugin": "^5.6.1",
"neo-async": "^2.6.2",
"schema-utils": "^4.3.3",
"tapable": "^2.3.0",
"watchpack": "^2.5.2",
"webpack-sources": "^3.5.0"
"webpack-sources": "^3.5.1"
},
"bin": {
"webpack": "bin/webpack.js"
@ -18212,9 +18413,9 @@
}
},
"node_modules/webpack-bundle-analyzer": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.3.0.tgz",
"integrity": "sha512-PEhAoqiJ+47d0uLMx/+zo5XOvaU+Vk6N2ZLht7H3n09QLy/fhyvqGNwjdRUHJDgMN8crBR2ZwVHkIswT3Xuawg==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.3.1.tgz",
"integrity": "sha512-wP2EusncRGL1tZyMHC/umLkjPdYMkTL9nPEKh8G8dkYCJ9TyF6xnXFqjhdqmv5J900irN/g0P5jMvLT22krEXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -18431,9 +18632,9 @@
}
},
"node_modules/webpack-sources": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz",
"integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==",
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.1.tgz",
"integrity": "sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==",
"dev": true,
"license": "MIT",
"engines": {

View File

@ -48,12 +48,12 @@
"@codemirror/language": "^6.12.4",
"@codemirror/search": "^6.7.1",
"@codemirror/state": "^6.7.1",
"@codemirror/view": "^6.43.6",
"@codemirror/view": "^6.43.7",
"@puppeteer/browsers": "3.0.6",
"autoprefixer": "^10.5.2",
"autoprefixer": "^10.5.4",
"babel-loader": "^10.1.1",
"base64-loader": "^1.0.0",
"chromedriver": "^150.0.3",
"chromedriver": "^150.0.4",
"cli-progress": "^3.12.0",
"colors": "^1.4.0",
"compression-webpack-plugin": "^12.0.0",
@ -61,10 +61,11 @@
"core-js": "^3.49.0",
"cspell": "^10.0.1",
"css-loader": "^7.1.4",
"eslint": "^9.39.4",
"eslint": "^9.39.5",
"eslint-plugin-jsdoc": "^50.8.0",
"globals": "^17.7.0",
"grunt": "^1.6.2",
"glob": "^13.0.6",
"globals": "^17.9.0",
"grunt": "^1.6.3",
"grunt-chmod": "~1.1.1",
"grunt-concurrent": "^3.0.0",
"grunt-contrib-clean": "~2.0.1",
@ -75,20 +76,20 @@
"grunt-exec": "~3.0.0",
"grunt-webpack": "^8.0.0",
"grunt-zip": "^1.0.0",
"html-webpack-plugin": "^5.6.7",
"html-webpack-plugin": "^5.6.8",
"imports-loader": "^5.0.0",
"mini-css-extract-plugin": "2.10.2",
"modify-source-webpack-plugin": "^4.1.0",
"nightwatch": "^3.16.0",
"postcss": "^8.5.16",
"postcss": "^8.5.25",
"postcss-css-variables": "^0.19.0",
"postcss-import": "^16.1.1",
"postcss-loader": "^8.2.1",
"prompt": "^1.3.0",
"sitemap": "^9.0.1",
"terser": "^5.49.0",
"webpack": "^5.108.4",
"webpack-bundle-analyzer": "^5.3.0",
"webpack": "^5.109.2",
"webpack-bundle-analyzer": "^5.3.1",
"webpack-dev-server": "^5.2.6",
"webpack-node-externals": "^3.0.0",
"worker-loader": "^3.0.8"
@ -123,7 +124,7 @@
"d3": "7.9.0",
"d3-hexbin": "^0.2.2",
"diff": "^9.0.0",
"dompurify": "^3.4.11",
"dompurify": "^3.4.13",
"es6-promisify": "^7.0.0",
"escodegen": "^2.1.0",
"esprima": "^4.0.1",
@ -140,10 +141,11 @@
"jq-web": "^0.5.1",
"jquery": "3.7.1",
"js-ascon": "^1.3.0",
"js-sha3": "^0.9.3",
"js-sha3": "^0.12.0",
"js-yaml": "^5.2.3",
"jsesc": "^3.1.0",
"json5": "^2.2.3",
"jsonata": "^2.2.1",
"jsonata": "^2.2.2",
"jsonpath-plus": "^10.4.0",
"jsonwebtoken": "9.0.3",
"jsqr": "^1.4.0",
@ -158,8 +160,8 @@
"lz4js": "^0.2.0",
"markdown-it": "^14.3.0",
"moment": "^2.30.1",
"moment-timezone": "^0.6.2",
"ngeohash": "^0.6.3",
"moment-timezone": "^0.6.3",
"ngeohash": "^0.6.4",
"node-forge": "^1.4.0",
"node-md6": "^0.1.0",
"nodom": "^2.4.0",
@ -170,7 +172,7 @@
"path": "^0.12.7",
"popper.js": "^1.16.1",
"process": "^0.11.10",
"protobufjs": "^8.7.0",
"protobufjs": "^8.7.1",
"punycode.js": "^2.3.1",
"qr-image": "^3.2.0",
"reflect-metadata": "^0.2.2",
@ -193,6 +195,14 @@
"xregexp": "^5.1.2",
"zlibjs": "^0.3.1"
},
"allowScripts": {
"@nightwatch/nightwatch-inspector@1.0.1": true,
"chromedriver@150.0.3": true,
"core-js": false,
"core-js-pure": false,
"fsevents": false,
"tesseract.js": false
},
"scripts": {
"start": "npx grunt dev",
"build": "npx grunt prod",

View File

@ -86,6 +86,9 @@ class Ingredient {
if (this.type === "option" && Array.isArray(checkVal)) {
checkVal = checkVal[this.defaultIndex ?? 0];
}
if (this.type === "argSelector" && Array.isArray(checkVal)) {
checkVal = checkVal[this.defaultIndex ?? 0]?.name || "";
}
// 1. check if empty
let isEmpty = false;
@ -99,8 +102,10 @@ class Ingredient {
let isAllowedOptionEmpty = false;
if (this.type === "option" && Array.isArray(this.defaultValue)) {
isAllowedOptionEmpty = this.defaultValue.includes("");
} else if (this.type === "argSelector" && Array.isArray(this.defaultValue)) {
isAllowedOptionEmpty = this.defaultValue.some(opt => opt.name === "");
}
if (this.allowEmpty === false || (this.type === "option" && !isAllowedOptionEmpty)) {
if (this.allowEmpty === false || ((this.type === "option" || this.type === "argSelector") && !isAllowedOptionEmpty)) {
throw new OperationError(`${this.name} cannot be empty.`);
}
return true;
@ -150,6 +155,23 @@ class Ingredient {
}
}
// 5. argSelector checks
if (this.type === "argSelector") {
if (Array.isArray(this.defaultValue)) {
const permittedOptions = this.defaultValue
.map(opt => opt.name)
.filter(optName => {
if (typeof optName !== "string") return false;
return !optName.match(/^\[\/?[a-z0-9 -()^]+\]$/i);
});
const valStr = (checkVal !== null && checkVal !== undefined) ? String(checkVal).toLowerCase() : "";
const matchedOption = permittedOptions.find(opt => opt.toLowerCase() === valStr);
if (!matchedOption) {
throw new OperationError(`${this.name} must be one of the following: ${permittedOptions.join(", ")}.`);
}
}
}
return true;
}

View File

@ -246,6 +246,7 @@
"Divide",
"MOD",
"Extended GCD",
"Modular Exponentiation",
"Modular Inverse",
"Mean",
"Median",

View File

@ -35,32 +35,32 @@ class A1Z26CipherDecode extends Operation {
];
this.checks = [
{
pattern: "^\\s*([12]?[0-9] )+[12]?[0-9]\\s*$",
pattern: "^\\s*((?:0?[1-9]|1[0-9]|2[0-6]) )+(?:0?[1-9]|1[0-9]|2[0-6])\\s*$",
flags: "",
args: ["Space"]
},
{
pattern: "^\\s*([12]?[0-9],)+[12]?[0-9]\\s*$",
pattern: "^\\s*((?:0?[1-9]|1[0-9]|2[0-6]),)+(?:0?[1-9]|1[0-9]|2[0-6])\\s*$",
flags: "",
args: ["Comma"]
},
{
pattern: "^\\s*([12]?[0-9];)+[12]?[0-9]\\s*$",
pattern: "^\\s*((?:0?[1-9]|1[0-9]|2[0-6]);)+(?:0?[1-9]|1[0-9]|2[0-6])\\s*$",
flags: "",
args: ["Semi-colon"]
},
{
pattern: "^\\s*([12]?[0-9]:)+[12]?[0-9]\\s*$",
pattern: "^\\s*((?:0?[1-9]|1[0-9]|2[0-6]):)+(?:0?[1-9]|1[0-9]|2[0-6])\\s*$",
flags: "",
args: ["Colon"]
},
{
pattern: "^\\s*([12]?[0-9]\\n)+[12]?[0-9]\\s*$",
pattern: "^\\s*((?:0?[1-9]|1[0-9]|2[0-6])\\n)+(?:0?[1-9]|1[0-9]|2[0-6])\\s*$",
flags: "",
args: ["Line feed"]
},
{
pattern: "^\\s*([12]?[0-9]\\r\\n)+[12]?[0-9]\\s*$",
pattern: "^\\s*((?:0?[1-9]|1[0-9]|2[0-6])\\r\\n)+(?:0?[1-9]|1[0-9]|2[0-6])\\s*$",
flags: "",
args: ["CRLF"]
}

View File

@ -66,6 +66,23 @@ class AutomatedValidationTestOp extends Operation {
"type": "option",
"value": ["[Group 1]", "Option 1", "Option 2", "[/Group 1]", "[Group 2]", "Option 3", "[/Group 2]"],
"allowEmpty": false
},
{
"name": "Arg Selector Ingredient",
"type": "argSelector",
"value": [
{
name: "Option 1",
on: [0],
off: [1]
},
{
name: "Option 2",
on: [1],
off: [0]
}
],
"allowEmpty": false
}
];
}

View File

@ -6,7 +6,7 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import YAML from "yaml";
import { dump } from "js-yaml";
/**
* JSON to YAML operation
@ -35,9 +35,9 @@ class JSONtoYAML extends Operation {
*/
run(input, args) {
try {
return YAML.stringify(input);
return dump(input);
} catch (err) {
throw new OperationError("Test");
throw new OperationError("Unable to stringify YAML: " + err);
}
}

View File

@ -0,0 +1,111 @@
/**
* @author p-leriche [philip.leriche@cantab.net]
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { parseBigInt, modPow } from "../lib/BigIntUtils.mjs";
/* ---------- operation class ---------- */
/**
* Modular Exponentiation operation
*/
class ModularExponentiation extends Operation {
/**
* ModularExponentiation constructor
*/
constructor() {
super();
this.name = "Modular Exponentiation";
this.module = "Crypto";
this.description = "Performs modular exponentiation, as used in Diffie-Hellman and RSA.<br><br>" +
"Computes Base ^ Exponent mod Modulus.<br><br>" +
"<b>Input handling:</b> If <i>either</i> Base <i>or</i> Exponent is left blank, " +
"its value is taken from the Input field.";
this.infoURL = "https://wikipedia.org/wiki/Modular_exponentiation";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Base",
type: "string",
value: ""
},
{
name: "Modulus",
type: "string",
value: "1"
},
{
name: "Exponent",
type: "string",
value: ""
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [baseStr, modStr, expStr] = args;
// Trim everything so "" and " " count as empty
const baseParam = baseStr?.trim();
const expParam = expStr?.trim();
const modParam = modStr?.trim();
const inputVal = input?.trim();
const mod = modParam;
if (!mod) {
throw new OperationError("Modulus must be defined");
}
// Base *or* Exponent (but not both) are taken from the Input
// if their boxes are empty.
let base, exp;
if (baseParam && expParam) {
// Case 1: base and exponent both given as parameters
base = baseParam;
exp = expParam;
} else if (!baseParam && expParam) {
// Case 2: base missing - take from input
base = inputVal;
exp = expParam;
if (!base) {
throw new OperationError("Base must be defined");
}
} else if (baseParam && !expParam) {
// Case 3: exponent missing - take from input
base = baseParam;
exp = inputVal;
if (!exp) {
throw new OperationError("Exponent must be defined");
}
} else if (!inputVal) {
// Case 4: base and exponent both missing
throw new OperationError("Base and Exponent must be defined");
} else throw new OperationError("Ambiguous input: specify either Base or Exponent when using Input");
// Parse numbers
const baseBI = parseBigInt(base, "Base");
const expBI = parseBigInt(exp, "Exponent");
const modBI = parseBigInt(mod, "Modulus");
// Check for invalid modulus (parseBigInt eliminates negatives)
if (modBI === 0n) {
throw new OperationError("Modulus must be greater than zero");
}
return modPow(baseBI, expBI, modBI).toString();
}
}
export default ModularExponentiation;

View File

@ -33,15 +33,11 @@ class ParseQRCode extends Operation {
value: false,
},
];
this.checks = [
{
pattern:
"^(?:\\xff\\xd8\\xff|\\x89\\x50\\x4e\\x47|\\x47\\x49\\x46|.{8}\\x57\\x45\\x42\\x50|\\x42\\x4d)",
flags: "",
args: [false],
useful: true,
},
];
// No Magic checks: detecting a QR code in arbitrary image data requires
// actually attempting to parse one, which is expensive and produces
// spurious "Could not read a QR code from the image" log messages for
// any image input via Magic. Users can add Parse QR Code manually when
// they know the image contains a QR code. See issue #2610.
}
/**

View File

@ -6,7 +6,8 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import jsYaml from "js-yaml";
import { load } from "js-yaml";
/**
* YAML to JSON operation
*/
@ -34,7 +35,7 @@ class YAMLToJSON extends Operation {
*/
run(input, args) {
try {
return jsYaml.load(input);
return load(input);
} catch (err) {
throw new OperationError("Unable to parse YAML: " + err);
}

View File

@ -77,6 +77,10 @@ function transformArgs(opArgsList, newArgs) {
return !Array.isArray(arg.value) ? arg.value : arg.value[arg.defaultIndex ?? 0];
}
if (arg.type === "argSelector") {
return !Array.isArray(arg.value) ? arg.value : (arg.value[arg.defaultIndex ?? 0]?.name || "");
}
if (arg.type === "editableOption") {
return typeof arg.value === "string" ? arg.value : arg.value[arg.defaultIndex ?? 0].value;
}

View File

@ -27,6 +27,7 @@ import "./tests/Categories.mjs";
import "./tests/ToHTMLEntity.mjs";
import "./tests/lib/BigIntUtils.mjs";
import "./tests/lib/ChartsProtocolPrototypePollution.mjs";
import "./tests/ParseQRCode.mjs";
const testStatus = {
allTestsPassing: true,

View File

@ -0,0 +1,35 @@
/**
* ParseQRCode API tests.
*
* @author Sanjays2402
* @copyright Crown Copyright 2026
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
import OperationConfig from "../../../src/core/config/OperationConfig.json" with { type: "json" };
import it from "../assertionHandler.mjs";
import assert from "assert";
TestRegister.addApiTests([
/*
* Regression test for #2610.
*
* Parse QR Code used to declare a `checks` regex that matched any JPEG,
* PNG, GIF, WEBP or BMP magic bytes. Magic aggregates every operation
* with a `checks` property, so any image input ran through a full QR
* parse attempt, which in turn emitted a "Could not read a QR code from
* the image" warning to the browser console for every image. There is
* no cheap way to detect a QR code without attempting a full parse, so
* Parse QR Code must not participate in Magic; users can add it
* manually when they know an image contains a QR code.
*/
it("Parse QR Code: must not participate in Magic (#2610)", () => {
const op = OperationConfig["Parse QR Code"];
assert(op, "Parse QR Code operation is missing from OperationConfig");
assert(
!op.checks || op.checks.length === 0,
"Parse QR Code must not declare `checks`; otherwise Magic will run a " +
"QR parse on every image and spam the console (see issue #2610)."
);
}),
]);

View File

@ -150,5 +150,38 @@ TestRegister.addTests([
args: [5, 1.5, "hello", "", { "option": "Option A", "string": "test" }, ""]
}
]
},
{
name: "Automated Validation: Valid Arg Selector value",
input: "test",
expectedOutput: "Success",
recipeConfig: [
{
op: "Automated Validation Test Op",
args: [5, 1.5, "hello", "", { "option": "Option A", "string": "test" }, "Option 1", "Option 2"]
}
]
},
{
name: "Automated Validation: Invalid Arg Selector value",
input: "test",
expectedOutput: "Arg Selector Ingredient must be one of the following: Option 1, Option 2.",
recipeConfig: [
{
op: "Automated Validation Test Op",
args: [5, 1.5, "hello", "", { "option": "Option A", "string": "test" }, "Option 1", "Option 3"]
}
]
},
{
name: "Automated Validation: Arg Selector value empty (invalid)",
input: "test",
expectedOutput: "Arg Selector Ingredient cannot be empty.",
recipeConfig: [
{
op: "Automated Validation Test Op",
args: [5, 1.5, "hello", "", { "option": "Option A", "string": "test" }, "Option 1", ""]
}
]
}
]);

View File

@ -152,5 +152,49 @@ TestRegister.addTests([
args: [1, false, false]
}
]
},
{
name: "Magic: invalid zero A1Z26 values do not match",
input: "0,0",
unexpectedMatch: /A1Z26 Cipher Decode/,
recipeConfig: [
{
op: "Magic",
args: [0, false, false]
}
]
},
{
name: "Magic: invalid high A1Z26 values do not match",
input: "27,1",
unexpectedMatch: /A1Z26 Cipher Decode/,
recipeConfig: [
{
op: "Magic",
args: [0, false, false]
}
]
},
{
name: "Magic: valid leading-zero A1Z26 values match",
input: "26,01",
expectedMatch: /A1Z26 Cipher Decode/,
recipeConfig: [
{
op: "Magic",
args: [0, false, false]
}
]
},
{
name: "Magic: valid leading-zero A1Z26 values match with two digits",
input: "09,10",
expectedMatch: /A1Z26 Cipher Decode/,
recipeConfig: [
{
op: "Magic",
args: [0, false, false]
}
]
}
]);

View File

@ -0,0 +1,137 @@
/**
* Modular Exponentiation tests.
*
* @author p-leriche [philip.leriche@cantab.net]
*
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Modular Exponentiation: basic example (2^10 mod 1000)",
input: "",
expectedOutput: "24",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["2", "1000", "10"],
},
],
},
{
name: "Modular Exponentiation: small values (3^5 mod 7)",
input: "",
expectedOutput: "5",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["3", "7", "5"],
},
],
},
{
name: "Modular Exponentiation: exponent zero",
input: "",
expectedOutput: "1",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["999", "100", "0"],
},
],
},
{
name: "Modular Exponentiation: base one",
input: "",
expectedOutput: "1",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["1", "1000", "999"],
},
],
},
{
name: "Modular Exponentiation: hexadecimal input",
input: "",
expectedOutput: "256",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["0x10", "1000", "0x2"],
},
],
},
{
name: "Modular Exponentiation: using input field for base",
input: "5",
expectedOutput: "6",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["", "7", "3"],
},
],
},
{
name: "Modular Exponentiation: using input field for exponent",
input: "4",
expectedOutput: "5",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["2", "11", ""],
},
],
},
{
name: "Modular Exponentiation: RSA-like example (small)",
input: "",
expectedOutput: "561",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["123", "1000", "456"],
},
],
},
{
name: "Modular Exponentiation: large base and exponent",
input: "",
expectedOutput: "560583526",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["123456789", "1000000007", "65537"],
},
],
},
{
name: "Modular Exponentiation: crypto-sized numbers (RSA-2048 simulation)",
input: "",
expectedOutput: "1",
recipeConfig: [
{
op: "Modular Exponentiation",
args: [
"12345678901234567890123456789012345678901234567890",
"99999999999999999999999999999999999999999999999999",
"0"
],
},
],
},
{
name: "Modular Exponentiation: Fermat's Little Theorem (a^(p-1) mod p = 1)",
input: "",
expectedOutput: "1",
recipeConfig: [
{
op: "Modular Exponentiation",
args: ["3", "11", "10"],
},
],
},
]);