From 9ce4fa6f987a15cd3dc8c8aa228a1bab994ed977 Mon Sep 17 00:00:00 2001 From: Robin Windey Date: Mon, 21 Nov 2022 07:14:44 +0100 Subject: [PATCH] Implement configurable OCR skip options (closing #129) (#164) * Implement configurable OCR skip options (closing #129) * Minor naming and code improvements --- .vscode/launch.json | 6 - README.md | 70 +- doc/img/per_workflow_settings.jpg | Bin 0 -> 50790 bytes doc/img/per_workflow_settings.png | Bin 25233 -> 0 bytes lib/Model/WorkflowSettings.php | 16 + lib/OcrProcessors/OcrMyPdfBasedProcessor.php | 22 +- package-lock.json | 698 +++++++++--------- src/components/WorkflowOcr.vue | 120 ++- src/test/components/WorkflowOcr.spec.js | 71 +- .../OcrProcessors/PdfOcrProcessorTest.php | 58 ++ 10 files changed, 627 insertions(+), 434 deletions(-) create mode 100644 doc/img/per_workflow_settings.jpg delete mode 100644 doc/img/per_workflow_settings.png diff --git a/.vscode/launch.json b/.vscode/launch.json index ed736e6..4692077 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,12 +10,6 @@ "request": "launch", "port": 9003 }, - { - "name": "Listen for XDebug (CLI)", - "type": "php", - "request": "launch", - "port": 9003 - }, { "name": "Run cron.php", "type": "php", diff --git a/README.md b/README.md index 87c105f..699913a 100644 --- a/README.md +++ b/README.md @@ -9,33 +9,33 @@ ## Table of contents - [Nextcloud Workflow OCR app](#nextcloud-workflow-ocr-app) - - [Table of contents](#table-of-contents) - - [Setup](#setup) - - [App installation](#app-installation) - - [Nextcloud background jobs](#nextcloud-background-jobs) - - [Backend](#backend) - - [Usage](#usage) - - [Useful triggers](#useful-triggers) - - [Trigger OCR if file was created or updated](#trigger-ocr-if-file-was-created-or-updated) - - [Trigger OCR on tag assigning](#trigger-ocr-on-tag-assigning) - - [Settings](#settings) - - [Per workflow settings](#per-workflow-settings) - - [Global settings](#global-settings) - - [Testing your configuration](#testing-your-configuration) - - [How it works](#how-it-works) - - [General](#general) - - [PDF](#pdf) - - [Images](#images) - - [Development](#development) - - [Dev setup](#dev-setup) - - [Debugging](#debugging) - - [`docker`-based setup](#docker-based-setup) - - [Executing tests](#executing-tests) - - [Adding a new `OcrProcessor`](#adding-a-new-ocrprocessor) - - [Events emitted by the app](#events-emitted-by-the-app) - - [`TextRecognizedEvent`](#textrecognizedevent) - - [Limitations](#limitations) - - [Used libraries & components](#used-libraries--components) + - [Table of contents](#table-of-contents) + - [Setup](#setup) + - [App installation](#app-installation) + - [Nextcloud background jobs](#nextcloud-background-jobs) + - [Backend](#backend) + - [Usage](#usage) + - [Useful triggers](#useful-triggers) + - [Trigger OCR if file was created or updated](#trigger-ocr-if-file-was-created-or-updated) + - [Trigger OCR on tag assigning](#trigger-ocr-on-tag-assigning) + - [Settings](#settings) + - [Per workflow settings](#per-workflow-settings) + - [Global settings](#global-settings) + - [Testing your configuration](#testing-your-configuration) + - [How it works](#how-it-works) + - [General](#general) + - [PDF](#pdf) + - [Images](#images) + - [Development](#development) + - [Dev setup](#dev-setup) + - [Debugging](#debugging) + - [`docker`-based setup](#docker-based-setup) + - [Executing tests](#executing-tests) + - [Adding a new `OcrProcessor`](#adding-a-new-ocrprocessor) + - [Events emitted by the app](#events-emitted-by-the-app) + - [`TextRecognizedEvent`](#textrecognizedevent) + - [Limitations](#limitations) + - [Used libraries & components](#used-libraries--components) ## Setup ### App installation @@ -118,21 +118,21 @@ After that you should be able to add a file to the OCR processing queue by assig Anyone who can create new workflows (admin or regular user) can configure settings for the OCR processing for a specific workflow. These settings are only applied to the specific workflow and do not affect other workflows.

- Per workflow settings + Per workflow settings

Currently the following settings are available per workflow: Name | Description --- | --- -Languages | The languages to be used for OCR processing. The languages can be choosen from a dropdown list. For PDF files this setting corresponds to the `-l` parameter of `ocrmypdf`. **Please note** that you'll have to install the appropriate languages like described in the [`ocrmypdf` documentation](https://ocrmypdf.readthedocs.io/en/latest/languages.html). -Remove background | If the switch is set, the OCR processor will try to remove the background of the document before processing and instead set a white background. For PDF files this setting corresponds to the [`--remove-background`](https://ocrmypdf.readthedocs.io/en/latest/cookbook.html?highlight=remove-background#image-processing) parameter of `ocrmypdf`. - +\* *For `ocrmypdf` the parameter `--remove-background` is [incompatible with `--redo-ocr`](https://github.com/ocrmypdf/OCRmyPDF/blob/110c75cba25121dcca7e2b91644206cce29e8430/src/ocrmypdf/_validation.py#L104).* #### Global settings As a Nextcloud administrator you're able to configure global settings which apply to all configured OCR-workflows on the current system. @@ -395,4 +395,4 @@ This event will be emitted when a OCR process has finished successfully. It cont | OCRmyPDF (commandline) | >= 9.6.0 | https://github.com/jbarlow83/OCRmyPDF On Debian, you might need to manually install a more recent version as described in https://ocrmypdf.readthedocs.io/en/latest/installation.html#ubuntu-18-04-lts; see https://github.com/R0Wi/workflow_ocr/issues/46 | | php-shellcommand | >= 1.6 | https://github.com/mikehaertl/php-shellcommand | | chain | >= 0.9.0 | https://packagist.org/packages/cocur/chain | -| PHPUnit | >= 8.0 | https://phpunit.de/ | \ No newline at end of file +| PHPUnit | >= 8.0 | https://phpunit.de/ | diff --git a/doc/img/per_workflow_settings.jpg b/doc/img/per_workflow_settings.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9117b25ed4c438a4c6ba1e87412650d5982f1723 GIT binary patch literal 50790 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 am%07wK0uCDF8K8KViEq2pNIW@;{O4X=@Wba literal 0 HcmV?d00001 diff --git a/doc/img/per_workflow_settings.png b/doc/img/per_workflow_settings.png deleted file mode 100644 index 3d28231dc9263d332c351b6475533a4d1e4f4aa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25233 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 QK6|gGqODx^#5(-H067d&YXATM diff --git a/lib/Model/WorkflowSettings.php b/lib/Model/WorkflowSettings.php index 1f2c8bd..71dbd34 100644 --- a/lib/Model/WorkflowSettings.php +++ b/lib/Model/WorkflowSettings.php @@ -29,6 +29,9 @@ use InvalidArgumentException; class WorkflowSettings { + public const OCR_MODE_SKIP_TEXT = 0; + public const OCR_MODE_REDO_OCR = 1; + public const OCR_MODE_FORCE_OCR = 2; /** @var array */ private $languages = []; @@ -36,6 +39,9 @@ class WorkflowSettings { /** @var bool */ private $removeBackground = false; + /** @var int */ + private $ocrMode = self::OCR_MODE_SKIP_TEXT; + /** @var array string */ private $tagsToRemoveAfterOcr = []; @@ -63,6 +69,13 @@ public function getRemoveBackground(): bool { return $this->removeBackground; } + /** + * @return int + */ + public function getOcrMode(): int { + return $this->ocrMode; + } + /** * @return array */ @@ -109,6 +122,9 @@ private function setJson(string $json = null) { if (array_key_exists('removeBackground', $data) && is_bool($data['removeBackground'])) { $this->removeBackground = $data['removeBackground']; } + if (array_key_exists('ocrMode', $data) && is_int($data['ocrMode'])) { + $this->ocrMode = $data['ocrMode']; + } if (array_key_exists('tagsToRemoveAfterOcr', $data) && is_array($data['tagsToRemoveAfterOcr'])) { $this->tagsToRemoveAfterOcr = $data['tagsToRemoveAfterOcr']; } diff --git a/lib/OcrProcessors/OcrMyPdfBasedProcessor.php b/lib/OcrProcessors/OcrMyPdfBasedProcessor.php index 83a8416..9fbae61 100644 --- a/lib/OcrProcessors/OcrMyPdfBasedProcessor.php +++ b/lib/OcrProcessors/OcrMyPdfBasedProcessor.php @@ -33,6 +33,11 @@ use Psr\Log\LoggerInterface; abstract class OcrMyPdfBasedProcessor implements IOcrProcessor { + private static $ocrModeToCmdParameterMapping = [ + WorkflowSettings::OCR_MODE_SKIP_TEXT => '--skip-text', + WorkflowSettings::OCR_MODE_REDO_OCR => '--redo-ocr', + WorkflowSettings::OCR_MODE_FORCE_OCR => '--force-ocr' + ]; /** @var ICommand */ private $command; @@ -106,8 +111,11 @@ protected function getAdditionalCommandlineArgs(WorkflowSettings $settings, Glob private function getCommandlineArgs(WorkflowSettings $settings, GlobalSettings $globalSettings): string { - // Default setting is quiet with skip-text - $args = ['-q', '--skip-text']; + // Default setting is quiet + $args = ['-q']; + + // OCR mode ('--skip-text', '--redo-ocr' or '--force-ocr') + $args[] = self::$ocrModeToCmdParameterMapping[$settings->getOcrMode()]; // Language settings if ($settings->getLanguages()) { @@ -115,10 +123,14 @@ private function getCommandlineArgs(WorkflowSettings $settings, GlobalSettings $ $args[] = "-l $langStr"; } - // Remove background option (NOTE :: this is incompatible with redo-ocr, so if we - // decide to make this configurable, make it exclusive against each other!) + // Remove background option (NOTE :: this is incompatible with redo-ocr, so + // we have to make it exclusive against each other!) if ($settings->getRemoveBackground()) { - $args[] = '--remove-background'; + if ($settings->getOcrMode() === WorkflowSettings::OCR_MODE_REDO_OCR) { + $this->logger->warning('--remove-background is incompatible with --redo-ocr, ignoring'); + } else { + $args[] = '--remove-background'; + } } // Number of CPU's to be used diff --git a/package-lock.json b/package-lock.json index 2b7f007..a335055 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2718,13 +2718,13 @@ "peer": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "peer": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "node_modules/@mrmlnc/readdir-enhanced": { @@ -3476,9 +3476,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", "peer": true, "dependencies": { "@types/eslint": "*", @@ -3486,9 +3486,9 @@ } }, "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "peer": true }, "node_modules/@types/express": { @@ -4559,6 +4559,13 @@ "dev": true, "peer": true }, + "node_modules/@vue/cli-service/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, "node_modules/@vue/cli-service/node_modules/css-loader": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", @@ -5070,7 +5077,7 @@ "node_modules/@vue/cli-service/node_modules/is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", "dev": true, "peer": true, "engines": { @@ -5087,16 +5094,6 @@ "json5": "lib/cli.js" } }, - "node_modules/@vue/cli-service/node_modules/loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, "node_modules/@vue/cli-service/node_modules/locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -5501,16 +5498,6 @@ "rimraf": "bin.js" } }, - "node_modules/@vue/cli-service/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/@vue/cli-service/node_modules/sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -5557,14 +5544,22 @@ "node": ">=6" } }, - "node_modules/@vue/cli-service/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "node_modules/@vue/cli-service/node_modules/terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "peer": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, "node_modules/@vue/cli-service/node_modules/terser-webpack-plugin": { @@ -5891,17 +5886,6 @@ "lodash": "^4.17.15" } }, - "node_modules/@vue/cli-service/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "peer": true, - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, "node_modules/@vue/cli-service/node_modules/webpack/node_modules/acorn": { "version": "6.4.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", @@ -7238,9 +7222,9 @@ } }, "node_modules/@webpack-cli/configtest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", - "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", "dev": true, "peer": true, "peerDependencies": { @@ -7249,9 +7233,9 @@ } }, "node_modules/@webpack-cli/info": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", - "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", "dev": true, "peer": true, "dependencies": { @@ -7262,9 +7246,9 @@ } }, "node_modules/@webpack-cli/serve": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", - "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", "dev": true, "peer": true, "peerDependencies": { @@ -10864,16 +10848,6 @@ "node": ">= 4" } }, - "node_modules/copy-webpack-plugin/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/copy-webpack-plugin/node_modules/slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -12628,9 +12602,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", "peer": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -12640,6 +12614,15 @@ "node": ">=10.13.0" } }, + "node_modules/enhanced-resolve/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -15151,9 +15134,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/graphql": { "version": "14.7.0", @@ -19047,9 +19030,9 @@ } }, "node_modules/jest-worker": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz", - "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "peer": true, "dependencies": { "@types/node": "*", @@ -19814,12 +19797,13 @@ } }, "node_modules/loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, "peer": true, "engines": { - "node": ">=6.11.5" + "node": ">=4.3.0 <5.0.0 || >=5.10" } }, "node_modules/loader-utils": { @@ -21027,14 +21011,14 @@ "node_modules/node-libs-browser/node_modules/assert/node_modules/inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", "dev": true, "peer": true }, "node_modules/node-libs-browser/node_modules/assert/node_modules/util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", "dev": true, "peer": true, "dependencies": { @@ -21067,7 +21051,7 @@ "node_modules/node-libs-browser/node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true, "peer": true }, @@ -21081,7 +21065,7 @@ "node_modules/node-libs-browser/node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, "peer": true }, @@ -21139,7 +21123,7 @@ "node_modules/node-libs-browser/node_modules/tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", "dev": true, "peer": true }, @@ -26451,9 +26435,10 @@ "dev": true }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, "peer": true, "dependencies": { "randombytes": "^2.1.0" @@ -28259,9 +28244,10 @@ "peer": true }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, "peer": true, "engines": { "node": ">=6" @@ -28445,34 +28431,34 @@ } }, "node_modules/terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", - "dev": true, + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", + "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", "peer": true, "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" } }, "node_modules/terser-webpack-plugin": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz", - "integrity": "sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", "peer": true, "dependencies": { - "jest-worker": "^27.0.6", + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "engines": { "node": ">= 10.13.0" @@ -28496,24 +28482,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/terser-webpack-plugin/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "peer": true - }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -28532,50 +28500,33 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser-webpack-plugin/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==", + "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "peer": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/terser-webpack-plugin/node_modules/terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "node_modules/terser/node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, "bin": { - "terser": "bin/terser" + "acorn": "bin/acorn" }, "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "peer": true }, - "node_modules/terser/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, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -28868,7 +28819,7 @@ "node_modules/to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", "dev": true, "peer": true }, @@ -30057,9 +30008,9 @@ } }, "node_modules/vue-loader": { - "version": "15.9.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", - "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", + "version": "15.10.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.1.tgz", + "integrity": "sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==", "dev": true, "peer": true, "dependencies": { @@ -30363,9 +30314,9 @@ } }, "node_modules/watchpack": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.0.tgz", - "integrity": "sha512-MnN0Q1OsvB/GGHETrFeZPQaOelWh/7O+EiFlj8sM9GPjtQkis7k01aAxrg/18kTfoIVcLL+haEVFlXDaSRwKRw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -30401,7 +30352,7 @@ "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "dev": true, "optional": true, "peer": true, @@ -30450,7 +30401,7 @@ "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", "dev": true, "optional": true, "peer": true, @@ -30474,7 +30425,7 @@ "node_modules/watchpack-chokidar2/node_modules/fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "dev": true, "optional": true, "peer": true, @@ -30511,7 +30462,7 @@ "node_modules/watchpack-chokidar2/node_modules/glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dev": true, "optional": true, "peer": true, @@ -30523,7 +30474,7 @@ "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "dev": true, "optional": true, "peer": true, @@ -30537,7 +30488,7 @@ "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", "dev": true, "optional": true, "peer": true, @@ -30565,7 +30516,7 @@ "node_modules/watchpack-chokidar2/node_modules/is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "dev": true, "optional": true, "peer": true, @@ -30579,7 +30530,7 @@ "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dev": true, "optional": true, "peer": true, @@ -30619,7 +30570,7 @@ "node_modules/watchpack-chokidar2/node_modules/micromatch/node_modules/extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "optional": true, "peer": true, @@ -30678,7 +30629,7 @@ "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "dev": true, "optional": true, "peer": true, @@ -30838,19 +30789,19 @@ "peer": true }, "node_modules/webpack-cli": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", - "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.0", - "@webpack-cli/info": "^1.4.0", - "@webpack-cli/serve": "^1.6.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", "colorette": "^2.0.14", "commander": "^7.0.0", - "execa": "^5.0.0", + "cross-spawn": "^7.0.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^2.2.0", @@ -30863,6 +30814,10 @@ "engines": { "node": ">=10.13.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, "peerDependencies": { "webpack": "4.x.x || 5.x.x" }, @@ -31156,31 +31111,36 @@ } }, "node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, "peer": true, "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" } }, "node_modules/webpack-sources/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, "peer": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/webpack/node_modules/@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "peer": true + }, "node_modules/webpack/node_modules/acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "peer": true, "bin": { "acorn": "bin/acorn" @@ -31189,6 +31149,15 @@ "node": ">=0.4.0" } }, + "node_modules/webpack/node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -31207,6 +31176,37 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webpack/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==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "peer": true, + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -33591,13 +33591,13 @@ "peer": true }, "@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "peer": true, "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "@mrmlnc/readdir-enhanced": { @@ -34216,9 +34216,9 @@ } }, "@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", "peer": true, "requires": { "@types/eslint": "*", @@ -34226,9 +34226,9 @@ } }, "@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "peer": true }, "@types/express": { @@ -35413,6 +35413,13 @@ "dev": true, "peer": true }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "peer": true + }, "css-loader": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", @@ -35821,7 +35828,7 @@ "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", "dev": true, "peer": true }, @@ -35832,13 +35839,6 @@ "dev": true, "peer": true }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true, - "peer": true - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -36155,16 +36155,6 @@ "glob": "^7.1.3" } }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -36202,12 +36192,17 @@ "has-flag": "^3.0.0" } }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, - "peer": true + "peer": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } }, "terser-webpack-plugin": { "version": "1.4.5", @@ -36476,17 +36471,6 @@ "lodash": "^4.17.15" } }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "peer": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -37426,17 +37410,17 @@ } }, "@webpack-cli/configtest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.0.tgz", - "integrity": "sha512-ttOkEkoalEHa7RaFYpM0ErK1xc4twg3Am9hfHhL7MVqlHebnkYd2wuI/ZqTDj0cVzZho6PdinY0phFZV3O0Mzg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", + "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", "dev": true, "peer": true, "requires": {} }, "@webpack-cli/info": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.0.tgz", - "integrity": "sha512-F6b+Man0rwE4n0409FyAJHStYA5OIZERxmnUfLVwv0mc0V1wLad3V7jqRlMkgKBeAq07jUvglacNaa6g9lOpuw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", + "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", "dev": true, "peer": true, "requires": { @@ -37444,9 +37428,9 @@ } }, "@webpack-cli/serve": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.0.tgz", - "integrity": "sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", + "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", "dev": true, "peer": true, "requires": {} @@ -40352,16 +40336,6 @@ "ajv-keywords": "^3.1.0" } }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -41825,13 +41799,21 @@ } }, "enhanced-resolve": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz", - "integrity": "sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", "peer": true, "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" + }, + "dependencies": { + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true + } } }, "enquirer": { @@ -43812,9 +43794,9 @@ } }, "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "graphql": { "version": "14.7.0", @@ -46935,9 +46917,9 @@ } }, "jest-worker": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz", - "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "peer": true, "requires": { "@types/node": "*", @@ -47485,9 +47467,10 @@ } }, "loader-runner": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", - "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, "peer": true }, "loader-utils": { @@ -48483,14 +48466,14 @@ "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", "dev": true, "peer": true }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", "dev": true, "peer": true, "requires": { @@ -48521,7 +48504,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true, "peer": true }, @@ -48535,7 +48518,7 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, "peer": true }, @@ -48593,7 +48576,7 @@ "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", "dev": true, "peer": true }, @@ -52778,9 +52761,10 @@ } }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, "peer": true, "requires": { "randombytes": "^2.1.0" @@ -54249,9 +54233,10 @@ } }, "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, "peer": true }, "tar-stream": { @@ -54398,58 +54383,44 @@ "dev": true }, "terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", - "dev": true, + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", + "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==", "peer": true, "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "source-map-support": "~0.5.20" }, "dependencies": { + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "peer": true + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true - }, - "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, "peer": true } } }, "terser-webpack-plugin": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz", - "integrity": "sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g==", + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", "peer": true, "requires": { - "jest-worker": "^27.0.6", + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" + "terser": "^5.14.1" }, "dependencies": { - "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "peer": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "peer": true - }, "schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", @@ -54461,22 +54432,13 @@ "ajv-keywords": "^3.5.2" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "peer": true - }, - "terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "peer": true, "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" + "randombytes": "^2.1.0" } } } @@ -54726,7 +54688,7 @@ "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", "dev": true, "peer": true }, @@ -55673,9 +55635,9 @@ } }, "vue-loader": { - "version": "15.9.8", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", - "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", + "version": "15.10.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.1.tgz", + "integrity": "sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==", "dev": true, "peer": true, "requires": { @@ -55923,9 +55885,9 @@ } }, "watchpack": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.0.tgz", - "integrity": "sha512-MnN0Q1OsvB/GGHETrFeZPQaOelWh/7O+EiFlj8sM9GPjtQkis7k01aAxrg/18kTfoIVcLL+haEVFlXDaSRwKRw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "peer": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -55958,7 +55920,7 @@ "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "dev": true, "optional": true, "peer": true, @@ -56021,7 +55983,7 @@ "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "dev": true, "optional": true, "peer": true, @@ -56047,7 +56009,7 @@ "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "dev": true, "optional": true, "peer": true, @@ -56059,7 +56021,7 @@ "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "dev": true, "optional": true, "peer": true, @@ -56072,7 +56034,7 @@ "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", "dev": true, "optional": true, "peer": true, @@ -56094,7 +56056,7 @@ "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "dev": true, "optional": true, "peer": true, @@ -56105,7 +56067,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "dev": true, "optional": true, "peer": true, @@ -56141,7 +56103,7 @@ "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "optional": true, "peer": true, @@ -56196,7 +56158,7 @@ "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "dev": true, "optional": true, "peer": true, @@ -56263,10 +56225,22 @@ "webpack-sources": "^2.3.1" }, "dependencies": { + "@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "peer": true + }, "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "peer": true + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "peer": true }, "schema-utils": { @@ -56279,6 +56253,28 @@ "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "peer": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "peer": true + }, + "webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "peer": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } } } }, @@ -56351,19 +56347,19 @@ } }, "webpack-cli": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", - "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", + "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, "peer": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.0", - "@webpack-cli/info": "^1.4.0", - "@webpack-cli/serve": "^1.6.0", + "@webpack-cli/configtest": "^1.2.0", + "@webpack-cli/info": "^1.5.0", + "@webpack-cli/serve": "^1.7.0", "colorette": "^2.0.14", "commander": "^7.0.0", - "execa": "^5.0.0", + "cross-spawn": "^7.0.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^2.2.0", @@ -56574,19 +56570,21 @@ } }, "webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, "peer": true, "requires": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" }, "dependencies": { "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, "peer": true } } diff --git a/src/components/WorkflowOcr.vue b/src/components/WorkflowOcr.vue index 818cda2..60c1c5f 100644 --- a/src/components/WorkflowOcr.vue +++ b/src/components/WorkflowOcr.vue @@ -46,10 +46,42 @@ {{ tagsToRemoveAfterOcr }} - - {{ translate('Remove background') }} - + +
+ + {{ translate('Skip text') }} + + + {{ translate('Redo OCR') }} + + + {{ translate('Force OCR') }} + +
+
+ +
+ + {{ translate('Remove background') }} + +
+
@@ -80,77 +112,93 @@ export default { data: function() { return { availableLanguages: [], + /* + * This is our JS data object model as single source of truth. + * Model structure which is captured by NC parent as JSON string: + * { + * languages: [ 'de', 'en' ], + * assignTagsAfterOcr: [1, 2, 3], + * removeTagsAfterOcr: [42, 43], + * removeBackground: true, + * ocrMode: 0, + * } + * It's initially set after component creation by 'created'-hook. + */ + model: {}, } }, computed: { selectedLanguages: { get: function() { - const model = this.getModel() - return model.languages - ? model.languages + return this.model.languages + ? this.model.languages .map(langCode => tesseractLanguageMapping.find(lang => lang.langCode === langCode)) .filter(entry => !!entry) : [] }, set: function(langArray) { - const model = this.getModel() - model.languages = langArray.map(lang => lang.langCode).filter(lang => lang !== null) - this.$emit('input', JSON.stringify(model)) + this.$set(this.model, 'languages', langArray.map(lang => lang.langCode).filter(lang => lang !== null)) + this.modelChanged() }, }, tagsToAddAfterOcr: { get: function() { - const model = this.getModel() - return model.tagsToAddAfterOcr ?? [] + return this.model.tagsToAddAfterOcr ?? [] }, set: function(tagIdArray) { - const model = this.getModel() - model.tagsToAddAfterOcr = tagIdArray - this.$emit('input', JSON.stringify(model)) + this.$set(this.model, 'tagsToAddAfterOcr', tagIdArray) + this.modelChanged() }, }, tagsToRemoveAfterOcr: { get: function() { - const model = this.getModel() - return model.tagsToRemoveAfterOcr ?? [] + return this.model.tagsToRemoveAfterOcr ?? [] }, set: function(tagIdArray) { - const model = this.getModel() - model.tagsToRemoveAfterOcr = tagIdArray - this.$emit('input', JSON.stringify(model)) + this.$set(this.model, 'tagsToRemoveAfterOcr', tagIdArray) + this.modelChanged() }, }, removeBackground: { get: function() { - const model = this.getModel() - return !!model.removeBackground + return !!this.model.removeBackground }, set: function(checked) { - const model = this.getModel() - model.removeBackground = !!checked - this.$emit('input', JSON.stringify(model)) + this.$set(this.model, 'removeBackground', !!checked) + this.modelChanged() + }, + }, + ocrMode: { + get: function() { + return '' + (this.model.ocrMode ?? 0) + }, + set: function(mode) { + this.$set(this.model, 'ocrMode', parseInt(mode)) + // --redo-ocr is incompatible with --remove-background + if (this.model.ocrMode === 1) { + this.$set(this.model, 'removeBackground', false) + } + this.modelChanged() }, }, selectedLanguagesPlaceholder: function() { return this.translate('Select language(s)') }, + removeBackgroundDisabled: function() { + return this.model.ocrMode === 1 + }, }, beforeMount: async function() { const installedLanguagesCodes = await getInstalledLanguages() this.availableLanguages = tesseractLanguageMapping.filter(lang => installedLanguagesCodes.includes(lang.langCode)) }, + created: function() { + // Set the initial model by applying the JSON value set by parent after initial mount + this.model = this.value ? JSON.parse(this.value) : {} + }, methods: { - getModel: function() { - /* - * Model structure which is captured by NC parent as JSON string: - * { - * languages: [ 'de', 'en' ], - * assignTagsAfterOcr: [1, 2, 3], - * removeTagsAfterOcr: [42, 43], - * removeBackground: true, - * } - */ - return this.value ? JSON.parse(this.value) : {} + modelChanged: function() { + this.$emit('input', JSON.stringify(this.model)) }, translate: function(str) { return t(appId, str) diff --git a/src/test/components/WorkflowOcr.spec.js b/src/test/components/WorkflowOcr.spec.js index 5677ba7..597f828 100644 --- a/src/test/components/WorkflowOcr.spec.js +++ b/src/test/components/WorkflowOcr.spec.js @@ -4,7 +4,6 @@ import WorkflowOcr from '../../components/WorkflowOcr.vue' import SettingsItem from '../../components/SettingsItem.vue' import Multiselect from '@nextcloud/vue/dist/Components/Multiselect' import MultiselectTags from '@nextcloud/vue/dist/Components/MultiselectTags' -import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/CheckboxRadioSwitch' let installedLanguages = [] @@ -175,7 +174,7 @@ describe('Remove background tests', () => { }, }) - const radioSwitch = wrapper.findComponent(CheckboxRadioSwitch) + const radioSwitch = wrapper.findComponent({ ref: 'removeBackgroundSwitch' }) expect(radioSwitch.vm.checked).toBe(true) @@ -187,3 +186,71 @@ describe('Remove background tests', () => { expect(inputEvent[0][0]).toBe('{"languages":["de"],"removeBackground":false}') }) }) + +describe('OCR mode tests', () => { + test('Default OCR mode is 0 (skip-text)', () => { + const wrapper = mount(WorkflowOcr) + expect(wrapper.vm.ocrMode).toBe("0") + }) + + test.each([0, 1, 2])(`Should set OCR mode to %i`, (mode) => { + const wrapper = mount(WorkflowOcr) + const radioButton = wrapper.findComponent({ ref: `ocrMode${mode}` }) + + // Simulate user click on radiobutton + radioButton.vm.$emit('update:checked', mode) + + const inputEvent = wrapper.emitted().input + expect(inputEvent).toBeTruthy() + expect(inputEvent[0][0]).toContain(`"ocrMode":${mode}`) + }) + + test('Setting OCR mode to --redo-ocr (1) should set removeBackground to false and disable the control', async() => { + const wrapper = mount(WorkflowOcr, { + propsData: { + value: '{ "languages": [ "de" ], "removeBackground": true, "ocrMode": 0 }', + }, + }) + + const radioButton = wrapper.findComponent({ ref: 'ocrMode1' }) + + // Simulate user click on radiobutton 'Redo OCR' + radioButton.vm.$emit('update:checked', 1) + + await wrapper.vm.$nextTick() + + const inputEvent = wrapper.emitted().input + expect(inputEvent).toBeTruthy() + expect(inputEvent[0][0]).toContain('"ocrMode":1') + expect(inputEvent[0][0]).toContain('"removeBackground":false') + + const removeBackgroundSwitch = wrapper.findComponent({ ref: 'removeBackgroundSwitch' }) + expect(removeBackgroundSwitch.vm.disabled).toBe(true) + }) + + test.each([0, 2])(`Should enable remove background switch when setting OCR mode from 1 (--redo-ocr) to %i`, async(mode) => { + const wrapper = mount(WorkflowOcr, { + propsData: { + value: '{ "removeBackground": false, "ocrMode": 1 }', + }, + }) + + await wrapper.vm.$nextTick() + const removeBackgroundSwitchPre = wrapper.findComponent({ ref: 'removeBackgroundSwitch' }) + expect(removeBackgroundSwitchPre.vm.disabled).toBe(true) + + const radioButton = wrapper.findComponent({ ref: `ocrMode${mode}` }) + + // Simulate user click on radiobutton + radioButton.vm.$emit('update:checked', mode) + + await wrapper.vm.$nextTick() + + const inputEvent = wrapper.emitted().input + expect(inputEvent).toBeTruthy() + expect(inputEvent[0][0]).toContain(`"ocrMode":${mode}`) + + const removeBackgroundSwitchPost = wrapper.findComponent({ ref: 'removeBackgroundSwitch' }) + expect(removeBackgroundSwitchPost.vm.disabled).toBe(false) + }) +}) diff --git a/tests/Unit/OcrProcessors/PdfOcrProcessorTest.php b/tests/Unit/OcrProcessors/PdfOcrProcessorTest.php index 7620425..b7ae663 100644 --- a/tests/Unit/OcrProcessors/PdfOcrProcessorTest.php +++ b/tests/Unit/OcrProcessors/PdfOcrProcessorTest.php @@ -301,4 +301,62 @@ public function testAppliesSidecarParameterIfSidecarFileCanBeCreated() { $processor = new PdfOcrProcessor($this->command, $this->logger, $this->sidecarFileAccessor); $processor->ocrFile($this->fileBefore, $this->defaultSettings, $this->defaultGlobalSettings); } + + /** + * @dataProvider dataProvider_testAppliesOcrModeParameter + */ + public function testAppliesOcrModeParameter(int $simulatedOcrMode, string $expectedOcrMyPdfFlag) { + $this->command->expects($this->once()) + ->method('setCommand') + ->with('ocrmypdf -q ' . $expectedOcrMyPdfFlag . ' --sidecar /tmp/sidecar.txt - - | cat'); + $this->command->expects($this->once()) + ->method('execute') + ->willReturn(true); + $this->command->expects($this->once()) + ->method('getOutput') + ->willReturn('someOcrContent'); + $this->sidecarFileAccessor->expects($this->once()) + ->method('getSidecarFileContent') + ->willReturn('someOcrContent'); + $this->sidecarFileAccessor->expects($this->once()) + ->method('getOrCreateSidecarFile') + ->willReturn('/tmp/sidecar.txt'); + + $processor = new PdfOcrProcessor($this->command, $this->logger, $this->sidecarFileAccessor); + $processor->ocrFile($this->fileBefore, new WorkflowSettings('{"ocrMode": ' . $simulatedOcrMode . '}'), $this->defaultGlobalSettings); + } + + public function testRemoveBackgroundIsNotAppliedIfOcrModeIsRedoOcr() { + $this->command->expects($this->once()) + ->method('setCommand') + ->with('ocrmypdf -q --redo-ocr --sidecar /tmp/sidecar.txt - - | cat'); + $this->command->expects($this->once()) + ->method('execute') + ->willReturn(true); + $this->command->expects($this->once()) + ->method('getOutput') + ->willReturn('someOcrContent'); + $this->sidecarFileAccessor->expects($this->once()) + ->method('getSidecarFileContent') + ->willReturn('someOcrContent'); + $this->sidecarFileAccessor->expects($this->once()) + ->method('getOrCreateSidecarFile') + ->willReturn('/tmp/sidecar.txt'); + $this->logger->expects($this->once()) + ->method('warning') + ->with($this->callback(function ($message) { + return strpos($message, '--remove-background is incompatible with --redo-ocr') !== false; + })); + + $processor = new PdfOcrProcessor($this->command, $this->logger, $this->sidecarFileAccessor); + $processor->ocrFile($this->fileBefore, new WorkflowSettings('{"ocrMode": ' . WorkflowSettings::OCR_MODE_REDO_OCR .', "removeBackground": true}'), $this->defaultGlobalSettings); + } + + public function dataProvider_testAppliesOcrModeParameter() { + return [ + [WorkflowSettings::OCR_MODE_SKIP_TEXT, '--skip-text'], + [WorkflowSettings::OCR_MODE_REDO_OCR, '--redo-ocr'], + [WorkflowSettings::OCR_MODE_FORCE_OCR, '--force-ocr'], + ]; + } }