diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..f2d44b7 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,44 @@ + +module.exports = { + "root": true, + "ignorePatterns": [ + "/node_modules/*", + "/vendor/*", + ], + "env": { + "browser": true, + "es6": true, + "jquery": true, + }, + "extends": "eslint:recommended", + "globals": { + "CFG_GLPI": true, + "GLPI_PLUGINS_PATH": true, + "__": true, + "_n": true, + "_x": true, + "_nx": true + }, + "parserOptions": { + "ecmaVersion": 8, + }, + "plugins": [ + "@stylistic/js", + ], + "rules": { + "no-console": ["error", {"allow": ["warn", "error"]}], + "no-unused-vars": ["error", {"vars": "local"}], + "@stylistic/js/eol-last": ["error", "always"], + "@stylistic/js/indent": ["error", 4], + "@stylistic/js/linebreak-style": ["error", "unix"], + "@stylistic/js/semi": ["error", "always"], + }, + "overrides": [ + { + "files": [".eslintrc.js", ".stylelintrc.js"], + "env": { + "node": true + } + }, + ], +}; diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 0000000..77f0f86 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,31 @@ +name: "Continuous integration" + +on: + push: + branches: + - "master" + tags: + - "*" + pull_request: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + ci: + name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}" + strategy: + fail-fast: false + matrix: + include: + - {glpi-version: "10.0.x", php-version: "7.4", db-image: "mysql:5.7"} + - {glpi-version: "10.0.x", php-version: "8.0", db-image: "mysql:8.0"} + - {glpi-version: "10.0.x", php-version: "8.1", db-image: "mariadb:10.2"} + - {glpi-version: "10.0.x", php-version: "8.2", db-image: "mariadb:11.0"} + - {glpi-version: "10.0.x", php-version: "8.3-rc", db-image: "mysql:8.0"} + uses: "glpi-project/plugin-ci-workflows/.github/workflows/continuous-integration.yml@v1" + with: + plugin-key: "tag" + glpi-version: "${{ matrix.glpi-version }}" + php-version: "${{ matrix.php-version }}" + db-image: "${{ matrix.db-image }}" diff --git a/.gitignore b/.gitignore index f033123..f5446d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ -dist/ -vendor/ +/dist/ +/node_modules/ +/vendor/ .gh_token -*.min.* - diff --git a/.phpcs.xml b/.phpcs.xml new file mode 100644 index 0000000..7cc76ed --- /dev/null +++ b/.phpcs.xml @@ -0,0 +1,18 @@ + + + . + /.git/ + ^node_modules/ + ^vendor/ + + + + + + + + + + + + diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..80ff93d --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,11 @@ + +module.exports = { + "extends": "stylelint-config-standard", + "ignoreFiles": [ + "node_modules/**/*", + "vendor/**/*" + ], + "rules": { + "selector-class-pattern": null, // DISABLE: Expected class selector to be kebab-case + }, +}; diff --git a/ajax/get_entity_tags.php b/ajax/get_entity_tags.php index 48f2e0d..619a824 100644 --- a/ajax/get_entity_tags.php +++ b/ajax/get_entity_tags.php @@ -28,14 +28,14 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); Session::checkLoginUser(); if (!isset($_REQUEST['name'])) { - exit; + exit; } echo PluginTagTag::getTagForEntityName($_REQUEST['name']); diff --git a/composer.json b/composer.json index 4d0e2db..e511074 100644 --- a/composer.json +++ b/composer.json @@ -3,13 +3,21 @@ "php": ">=7.4" }, "require-dev": { - "glpi-project/tools": "^0.6" + "glpi-project/tools": "^0.7.1", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "squizlabs/php_codesniffer": "^3.7" }, "config": { "optimize-autoloader": true, "platform": { "php": "7.4.0" }, - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "phpstan/extension-installer": true + } } } diff --git a/composer.lock b/composer.lock index ff4864b..4853b57 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,31 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "49ff730c8068667841d45903c3c04259", + "content-hash": "53b0dda4208b78e493a979e2ed492618", "packages": [], "packages-dev": [ { "name": "glpi-project/tools", - "version": "0.6.4", + "version": "0.7.1", "source": { "type": "git", "url": "https://github.com/glpi-project/tools.git", - "reference": "8ef917fa2967e716eaed198bb803f418a80cd621" + "reference": "4bc5a725d9f4da0ee946ad3cbdd54a782d2f40fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/glpi-project/tools/zipball/8ef917fa2967e716eaed198bb803f418a80cd621", - "reference": "8ef917fa2967e716eaed198bb803f418a80cd621", + "url": "https://api.github.com/repos/glpi-project/tools/zipball/4bc5a725d9f4da0ee946ad3cbdd54a782d2f40fb", + "reference": "4bc5a725d9f4da0ee946ad3cbdd54a782d2f40fb", "shasum": "" }, "require": { "symfony/console": "^5.4 || ^6.0", "twig/twig": "^3.3" }, + "require-dev": { + "nikic/php-parser": "^4.13", + "phpstan/phpstan-src": "^1.10" + }, "bin": [ "bin/extract-locales", "bin/licence-headers-check", @@ -33,7 +37,7 @@ "type": "library", "autoload": { "psr-4": { - "Glpi\\": "src/" + "GlpiProject\\Tools\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -57,7 +61,218 @@ "issues": "https://github.com/glpi-project/tools/issues", "source": "https://github.com/glpi-project/tools" }, - "time": "2023-07-27T12:32:25+00:00" + "time": "2023-10-16T11:40:35+00:00" + }, + { + "name": "php-parallel-lint/php-parallel-lint", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git", + "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6483c9832e71973ed29cf71bd6b3f4fde438a9de", + "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.3.0" + }, + "replace": { + "grogy/php-parallel-lint": "*", + "jakub-onderka/php-parallel-lint": "*" + }, + "require-dev": { + "nette/tester": "^1.3 || ^2.0", + "php-parallel-lint/php-console-highlighter": "0.* || ^1.0", + "squizlabs/php_codesniffer": "^3.6" + }, + "suggest": { + "php-parallel-lint/php-console-highlighter": "Highlight syntax in code snippet" + }, + "bin": [ + "parallel-lint" + ], + "type": "library", + "autoload": { + "classmap": [ + "./src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "ahoj@jakubonderka.cz" + } + ], + "description": "This tool check syntax of PHP files about 20x faster than serial check.", + "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", + "support": { + "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", + "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.3.2" + }, + "time": "2022-02-21T12:50:22+00:00" + }, + { + "name": "phpstan/extension-installer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "f45734bfb9984c6c56c4486b71230355f066a58a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a", + "reference": "f45734bfb9984c6c56c4486b71230355f066a58a", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", + "support": { + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.3.1" + }, + "time": "2023-05-24T08:59:17+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.10.41", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "c6174523c2a69231df55bdc65b61655e72876d76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6174523c2a69231df55bdc65b61655e72876d76", + "reference": "c6174523c2a69231df55bdc65b61655e72876d76", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-11-05T12:57:57+00:00" + }, + { + "name": "phpstan/phpstan-deprecation-rules", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", + "reference": "089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa", + "reference": "089d8a8258ed0aeefdc7b68b6c3d25572ebfdbaa", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.10.3" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-php-parser": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", + "support": { + "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.1.4" + }, + "time": "2023-08-05T09:02:04+00:00" }, { "name": "psr/container", @@ -107,6 +322,63 @@ }, "time": "2021-11-05T16:50:12+00:00" }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2023-02-22T23:07:41+00:00" + }, { "name": "symfony/console", "version": "v5.4.26", @@ -1018,5 +1290,5 @@ "platform-overrides": { "php": "7.4.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/front/tag.form.php b/front/tag.form.php index 3a76b74..8a32c90 100644 --- a/front/tag.form.php +++ b/front/tag.form.php @@ -28,30 +28,32 @@ * ------------------------------------------------------------------------- */ -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkRight(PluginTagTag::$rightname, UPDATE); if (!Plugin::isPluginActive("tag")) { - Html::displayNotFoundError(); + Html::displayNotFoundError(); } if (isset($_POST['add'])) { - $item = new PluginTagTagItem(); - - // Check unicity : - if (isset($_REQUEST['plugin_tag_tags_id'])) { - $found = $item->find(['plugin_tag_tags_id' => $_REQUEST['plugin_tag_tags_id'], - 'items_id' => $_REQUEST['items_id'], - 'itemtype' => $_REQUEST['itemtype']]); - - if (count($found) == 0) { - $item->add($_REQUEST); - } - } else { - $item->add($_REQUEST); - } + $item = new PluginTagTagItem(); + + // Check unicity : + if (isset($_REQUEST['plugin_tag_tags_id'])) { + $found = $item->find([ + 'plugin_tag_tags_id' => $_REQUEST['plugin_tag_tags_id'], + 'items_id' => $_REQUEST['items_id'], + 'itemtype' => $_REQUEST['itemtype'] + ]); + + if (count($found) == 0) { + $item->add($_REQUEST); + } + } else { + $item->add($_REQUEST); + } } $dropdown = new PluginTagTag(); -include (GLPI_ROOT . "/front/dropdown.common.form.php"); +include(GLPI_ROOT . "/front/dropdown.common.form.php"); diff --git a/front/tag.php b/front/tag.php index c1c2305..36ce012 100644 --- a/front/tag.php +++ b/front/tag.php @@ -28,10 +28,9 @@ * ------------------------------------------------------------------------- */ -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); if (Plugin::isPluginActive("tag")) { - - $dropdown = new PluginTagTag(); - include (GLPI_ROOT . "/front/dropdown.common.php"); + $dropdown = new PluginTagTag(); + include(GLPI_ROOT . "/front/dropdown.common.php"); } diff --git a/hook.php b/hook.php index f8eb8a9..0822246 100644 --- a/hook.php +++ b/hook.php @@ -29,134 +29,141 @@ */ // Plugin hook after *Uninstall* -function plugin_uninstall_after_tag($item) { - $tagitem = new PluginTagTagItem(); - $tagitem->deleteByCriteria([ - 'itemtype' => $item->getType(), - 'items_id' => $item->getID() - ]); +function plugin_uninstall_after_tag($item) +{ + $tagitem = new PluginTagTagItem(); + $tagitem->deleteByCriteria([ + 'itemtype' => $item->getType(), + 'items_id' => $item->getID() + ]); } -function plugin_datainjection_populate_tag() { - global $INJECTABLE_TYPES; +function plugin_datainjection_populate_tag() +{ + /** @var array $INJECTABLE_TYPES */ + global $INJECTABLE_TYPES; - $INJECTABLE_TYPES['PluginTagTagInjection'] = 'tag'; + $INJECTABLE_TYPES['PluginTagTagInjection'] = 'tag'; } -function plugin_tag_getAddSearchOptionsNew($itemtype) { - if (!PluginTagTag::canView() || !PluginTagTag::canItemtype($itemtype)) { - return []; - } - - $options = [ - [ - 'id' => PluginTagTag::S_OPTION, - 'table' => PluginTagTag::getTable(), - 'field' => 'name', - 'name' => PluginTagTag::getTypeName(2), - 'datatype' => 'dropdown', - 'searchtype' => ['equals','notequals','contains'], - 'massiveaction' => false, - 'forcegroupby' => true, - 'joinparams' => [ - 'beforejoin' => [ - 'table' => 'glpi_plugin_tag_tagitems', - 'joinparams' => [ - 'jointype' => 'itemtype_item' - ] - ] - ] - ] - ]; - - if ($itemtype != 'AllAssets') { - $item = new $itemtype; - if ($item->isEntityAssign()) { - $options [] = [ - 'id' => (PluginTagTag::S_OPTION + 1), +function plugin_tag_getAddSearchOptionsNew($itemtype) +{ + if (!PluginTagTag::canView() || !PluginTagTag::canItemtype($itemtype)) { + return []; + } + + $options = [ + [ + 'id' => PluginTagTag::S_OPTION, 'table' => PluginTagTag::getTable(), 'field' => 'name', - 'name' => PluginTagTag::getTypeName(2)." - ".__("Entity"), - 'datatype' => 'string', - 'searchtype' => 'contains', + 'name' => PluginTagTag::getTypeName(2), + 'datatype' => 'dropdown', + 'searchtype' => ['equals','notequals','contains'], 'massiveaction' => false, 'forcegroupby' => true, - 'usehaving' => true, 'joinparams' => [ - 'condition' => "AND 1=1", // to force distinct complex id than the previous option - 'beforejoin' => [ - 'table' => 'glpi_plugin_tag_tagitems', - 'joinparams' => [ - 'jointype' => 'itemtype_item', - 'specific_itemtype' => 'Entity', - 'beforejoin' => [ - 'table' => 'glpi_entities', - ] - ] - ] + 'beforejoin' => [ + 'table' => 'glpi_plugin_tag_tagitems', + 'joinparams' => [ + 'jointype' => 'itemtype_item' + ] + ] ] - ]; - } - } - - return $options; + ] + ]; + + if ($itemtype != 'AllAssets') { + $item = new $itemtype(); + if ($item->isEntityAssign()) { + $options [] = [ + 'id' => (PluginTagTag::S_OPTION + 1), + 'table' => PluginTagTag::getTable(), + 'field' => 'name', + 'name' => PluginTagTag::getTypeName(2) . " - " . __("Entity"), + 'datatype' => 'string', + 'searchtype' => 'contains', + 'massiveaction' => false, + 'forcegroupby' => true, + 'usehaving' => true, + 'joinparams' => [ + 'condition' => "AND 1=1", // to force distinct complex id than the previous option + 'beforejoin' => [ + 'table' => 'glpi_plugin_tag_tagitems', + 'joinparams' => [ + 'jointype' => 'itemtype_item', + 'specific_itemtype' => 'Entity', + 'beforejoin' => [ + 'table' => 'glpi_entities', + ] + ] + ] + ] + ]; + } + } + + return $options; } -function plugin_tag_giveItem($type, $field, $data, $num, $linkfield = "") { - switch ($field) { - case PluginTagTag::S_OPTION: - case PluginTagTag::S_OPTION+1: - $out = '
+function plugin_tag_giveItem($type, $field, $data, $num, $linkfield = "") +{ + switch ($field) { + case PluginTagTag::S_OPTION: + case PluginTagTag::S_OPTION + 1: + $out = '
'; - $separator = ''; - foreach ($data[$num] as $tag) { - if (isset($tag['id']) && isset($tag['name'])) { - $out .= PluginTagTag::getSingleTag($tag['id'], $separator); - //For export (CSV, PDF) of GLPI core - $separator = ', '; + $separator = ''; + foreach ($data[$num] as $tag) { + if (isset($tag['id']) && isset($tag['name'])) { + $out .= PluginTagTag::getSingleTag($tag['id'], $separator); + //For export (CSV, PDF) of GLPI core + $separator = ', '; + } } - } - $out .= '
'; - return $out; - } + $out .= '
'; + return $out; + } - return ""; + return ""; } -function plugin_tag_addHaving($link, $nott, $itemtype, $id, $val, $num) { - $searchopt = &Search::getOptions($itemtype); - $table = $searchopt[$id]["table"]; - $field = $searchopt[$id]["field"]; - - if ($table.".".$field == "glpi_plugin_tag_tags.type_menu") { - $values = explode(",", $val); - $where = "$link `ITEM_$num` LIKE '%".$values[0]."%'"; - array_shift($values); - foreach ($values as $value) { - $value = trim($value); - $where .= " OR `ITEM_$num` LIKE '%$value%'"; - } - return $where; - } +function plugin_tag_addHaving($link, $nott, $itemtype, $id, $val, $num) +{ + $searchopt = &Search::getOptions($itemtype); + $table = $searchopt[$id]["table"]; + $field = $searchopt[$id]["field"]; + + if ($table . "." . $field == "glpi_plugin_tag_tags.type_menu") { + $values = explode(",", $val); + $where = "$link `ITEM_$num` LIKE '%" . $values[0] . "%'"; + array_shift($values); + foreach ($values as $value) { + $value = trim($value); + $where .= " OR `ITEM_$num` LIKE '%$value%'"; + } + return $where; + } } -function plugin_tag_addWhere($link, $nott, $itemtype, $id, $val, $searchtype) { - $searchopt = &Search::getOptions($itemtype); - $table = $searchopt[$id]["table"]; - $field = $searchopt[$id]["field"]; +function plugin_tag_addWhere($link, $nott, $itemtype, $id, $val, $searchtype) +{ + $searchopt = &Search::getOptions($itemtype); + $table = $searchopt[$id]["table"]; + $field = $searchopt[$id]["field"]; - if ($table.".".$field == "glpi_plugin_tag_tags.type_menu") { - switch ($searchtype) { - case 'equals': - return "`glpi_plugin_tag_tags`.`type_menu` LIKE '%\"$val\"%'"; + if ($table . "." . $field == "glpi_plugin_tag_tags.type_menu") { + switch ($searchtype) { + case 'equals': + return "`glpi_plugin_tag_tags`.`type_menu` LIKE '%\"$val\"%'"; - case 'notequals': - return "`glpi_plugin_tag_tags`.`type_menu` NOT LIKE '%\"$val\"%'"; - } - } + case 'notequals': + return "`glpi_plugin_tag_tags`.`type_menu` NOT LIKE '%\"$val\"%'"; + } + } - return ""; + return ""; } @@ -165,8 +172,9 @@ function plugin_tag_addWhere($link, $nott, $itemtype, $id, $val, $searchtype) { * * @return array the list of dropdowns (label => class) */ -function plugin_tag_getDropdown() { - return ['PluginTagTag' => PluginTagTag::getTypeName(2)]; +function plugin_tag_getDropdown() +{ + return ['PluginTagTag' => PluginTagTag::getTypeName(2)]; } /** @@ -175,17 +183,18 @@ function plugin_tag_getDropdown() { * @param string $itemtype * @return array the massive action list */ -function plugin_tag_MassiveActions($itemtype = '') { - if (PluginTagTag::canItemtype($itemtype) && is_a($itemtype, CommonDBTM::class, true) && $itemtype::canUpdate()) { - return [ - 'PluginTagTagItem'.MassiveAction::CLASS_ACTION_SEPARATOR.'addTag' +function plugin_tag_MassiveActions($itemtype = '') +{ + if (PluginTagTag::canItemtype($itemtype) && is_a($itemtype, CommonDBTM::class, true) && $itemtype::canUpdate()) { + return [ + 'PluginTagTagItem' . MassiveAction::CLASS_ACTION_SEPARATOR . 'addTag' => __("Add tags", 'tag'), - 'PluginTagTagItem'.MassiveAction::CLASS_ACTION_SEPARATOR.'removeTag' + 'PluginTagTagItem' . MassiveAction::CLASS_ACTION_SEPARATOR . 'removeTag' => __("Remove tags", 'tag'), - ]; - } + ]; + } - return []; + return []; } /** @@ -193,29 +202,30 @@ function plugin_tag_MassiveActions($itemtype = '') { * * @return boolean */ -function plugin_tag_install() { - $version = plugin_version_tag(); - $migration = new Migration($version['version']); - - // Parse inc directory - foreach (glob(dirname(__FILE__).'/inc/*') as $filepath) { - // Load *.class.php files and get the class name - if (preg_match("/inc.(.+)\.class.php/", $filepath, $matches)) { - $classname = 'PluginTag' . ucfirst($matches[1]); - - // Don't load Datainjection mapping lass (no install + bug if datainjection is not installed and activated) - if ($classname == 'PluginTagTaginjection') { - continue; - } - - include_once($filepath); - // If the install method exists, load it - if (method_exists($classname, 'install')) { - $classname::install($migration); - } - } - } - return true; +function plugin_tag_install() +{ + $version = plugin_version_tag(); + $migration = new Migration($version['version']); + + // Parse inc directory + foreach (glob(dirname(__FILE__) . '/inc/*') as $filepath) { + // Load *.class.php files and get the class name + if (preg_match("/inc.(.+)\.class.php/", $filepath, $matches)) { + $classname = 'PluginTag' . ucfirst($matches[1]); + + // Don't load Datainjection mapping lass (no install + bug if datainjection is not installed and activated) + if ($classname == 'PluginTagTaginjection') { + continue; + } + + include_once($filepath); + // If the install method exists, load it + if (method_exists($classname, 'install')) { + $classname::install($migration); + } + } + } + return true; } /** @@ -223,63 +233,66 @@ function plugin_tag_install() { * * @return boolean */ -function plugin_tag_uninstall() { - // Parse inc directory - foreach (glob(dirname(__FILE__).'/inc/*') as $filepath) { - // Load *.class.php files and get the class name - if (preg_match("/inc.(.+)\.class.php/", $filepath, $matches)) { - $classname = 'PluginTag' . ucfirst($matches[1]); - - // Don't load Datainjection mapping lass (no uninstall + bug if datainjection is not installed and activated) - if ($classname == 'PluginTagTaginjection') { - continue; - } - - include_once($filepath); - // If the uninstall method exists, load it - if (method_exists($classname, 'uninstall')) { - $classname::uninstall(); - } - } - } - return true; +function plugin_tag_uninstall() +{ + // Parse inc directory + foreach (glob(dirname(__FILE__) . '/inc/*') as $filepath) { + // Load *.class.php files and get the class name + if (preg_match("/inc.(.+)\.class.php/", $filepath, $matches)) { + $classname = 'PluginTag' . ucfirst($matches[1]); + + // Don't load Datainjection mapping lass (no uninstall + bug if datainjection is not installed and activated) + if ($classname == 'PluginTagTaginjection') { + continue; + } + + include_once($filepath); + // If the uninstall method exists, load it + if (method_exists($classname, 'uninstall')) { + $classname::uninstall(); + } + } + } + return true; } -function plugin_tag_post_init() { - global $PLUGIN_HOOKS; - - // hook on object changes - if ($itemtype = PluginTagTag::getCurrentItemtype()) { - if (PluginTagTag::canItemtype($itemtype)) { - $PLUGIN_HOOKS['item_add']['tag'][$itemtype] = ['PluginTagTagItem', 'updateItem']; - $PLUGIN_HOOKS['pre_item_update']['tag'][$itemtype] = ['PluginTagTagItem', 'updateItem']; - $PLUGIN_HOOKS['pre_item_purge']['tag'][$itemtype] = ['PluginTagTagItem', 'purgeItem']; - } - } - - // Always define hook for tickets - // Needed for rules to function properly when a ticket is created from a mail - // collector - $PLUGIN_HOOKS['item_add']['tag'][Ticket::getType()] = ['PluginTagTagItem', 'updateItem']; - $PLUGIN_HOOKS['pre_item_update']['tag'][Ticket::getType()] = ['PluginTagTagItem', 'updateItem']; - $PLUGIN_HOOKS['pre_item_purge']['tag'][Ticket::getType()] = ['PluginTagTagItem', 'purgeItem']; +function plugin_tag_post_init() +{ + /** @var array $PLUGIN_HOOKS */ + global $PLUGIN_HOOKS; + + // hook on object changes + if ($itemtype = PluginTagTag::getCurrentItemtype()) { + if (PluginTagTag::canItemtype($itemtype)) { + $PLUGIN_HOOKS['item_add']['tag'][$itemtype] = ['PluginTagTagItem', 'updateItem']; + $PLUGIN_HOOKS['pre_item_update']['tag'][$itemtype] = ['PluginTagTagItem', 'updateItem']; + $PLUGIN_HOOKS['pre_item_purge']['tag'][$itemtype] = ['PluginTagTagItem', 'purgeItem']; + } + } + + // Always define hook for tickets + // Needed for rules to function properly when a ticket is created from a mail + // collector + $PLUGIN_HOOKS['item_add']['tag'][Ticket::getType()] = ['PluginTagTagItem', 'updateItem']; + $PLUGIN_HOOKS['pre_item_update']['tag'][Ticket::getType()] = ['PluginTagTagItem', 'updateItem']; + $PLUGIN_HOOKS['pre_item_purge']['tag'][Ticket::getType()] = ['PluginTagTagItem', 'purgeItem']; } function plugin_tag_getRuleActions($params = []) { - $actions = []; + $actions = []; - switch ($params['rule_itemtype']) { - case "RuleTicket": - $actions['_plugin_tag_tag_values'] = [ - 'name' => __("Add tags", 'tag'), - 'type' => 'dropdown', - 'table' => PluginTagTag::getTable(), - 'condition' => ['type_menu' => ['LIKE', '%\"Ticket\"%']], - ]; + switch ($params['rule_itemtype']) { + case "RuleTicket": + $actions['_plugin_tag_tag_values'] = [ + 'name' => __("Add tags", 'tag'), + 'type' => 'dropdown', + 'table' => PluginTagTag::getTable(), + 'condition' => ['type_menu' => ['LIKE', '%\"Ticket\"%']], + ]; - break; - } + break; + } - return $actions; + return $actions; } diff --git a/inc/config.class.php b/inc/config.class.php index 26de661..95467e9 100644 --- a/inc/config.class.php +++ b/inc/config.class.php @@ -28,64 +28,69 @@ * ------------------------------------------------------------------------- */ -class PluginTagConfig extends CommonDBTM { +class PluginTagConfig extends CommonDBTM +{ + protected static $notable = true; - static protected $notable = true; + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + if (!$withtemplate && $item->getType() === 'Config') { + return __('Tag Management', 'tag'); + } + return ''; + } - if (!$withtemplate && $item->getType() === 'Config') { - return __('Tag Management', 'tag'); - } - return ''; - } + public function showConfigForm() + { + if (!Session::haveRight('config', UPDATE)) { + return false; + } + $config = Config::getConfigurationValues('plugin:Tag'); - public function showConfigForm() { - global $CFG_GLPI; - if (!Session::haveRight('config', UPDATE)) { - return false; - } - $config = Config::getConfigurationValues('plugin:Tag'); + echo "
"; + echo ""; + echo ""; + echo "
"; + echo ""; + echo "'; + echo ''; + echo '
" . __('Tag Management', 'tag') . '
' . __('Tags location', 'tag') . ''; + Dropdown::showFromArray( + 'tags_location', + [ + __('Top'), + __('Bottom') + ], + [ + 'value' => $config['tags_location'] ?? 0 + ] + ); + echo '
'; - echo ""; - echo ""; - echo ""; - echo "
"; - echo ""; - echo "'; - echo ''; - echo '
" . __('Tag Management', 'tag') . '
' . __('Tags location', 'tag') . ''; - Dropdown::showFromArray('tags_location', [ - __('Top'), - __('Bottom') - ], - [ - 'value' => $config['tags_location'] ?? 0 - ]); - echo '
'; + echo ""; + echo ""; + echo "'; + echo '
"; + echo "'; + echo '
'; + echo '
'; + Html::closeForm(); + } - echo ""; - echo ""; - echo "'; - echo '
"; - echo "'; - echo '
'; - echo '
'; - Html::closeForm(); - } + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + if ($item->getType() == 'Config') { + $config = new self(); + $config->showConfigForm(); + } + return true; + } - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - - if ($item->getType() == 'Config') { - $config = new self(); - $config->showConfigForm(); - } - } - - public static function uninstall() { - $config = Config::getConfigurationValues('plugin:Tag'); - Config::deleteConfigurationValues('plugin:Tag', array_keys($config)); - return true; - } - -} \ No newline at end of file + public static function uninstall() + { + $config = Config::getConfigurationValues('plugin:Tag'); + Config::deleteConfigurationValues('plugin:Tag', array_keys($config)); + return true; + } +} diff --git a/inc/profile.class.php b/inc/profile.class.php index c49449e..c23bc37 100644 --- a/inc/profile.class.php +++ b/inc/profile.class.php @@ -28,43 +28,52 @@ * ------------------------------------------------------------------------- */ -class PluginTagProfile extends Profile { +class PluginTagProfile extends Profile +{ + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + return self::createTabEntry(__('Tag management', 'tag')); + } - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - return self::createTabEntry(__('Tag management', 'tag')); - } + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + $tagprofile = new self(); + $tagprofile->showForm($item->getID()); + return true; + } - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - $tagprofile = new self(); - $tagprofile->showForm($item->getID()); - return true; - } + public function showForm($ID, array $options = []) + { + if (!self::canView()) { + return false; + } - function showForm($ID, array $options = []) { - if (!self::canView()) { - return false; - } + echo "
"; + $profile = new Profile(); + $profile->getFromDB($ID); + if ($canedit = Session::haveRightsOr(self::$rightname, [CREATE, UPDATE, PURGE])) { + echo ""; + } - echo "
"; - $profile = new Profile(); - $profile->getFromDB($ID); - if ($canedit = Session::haveRightsOr(self::$rightname, [CREATE, UPDATE, PURGE])) { - echo ""; - } + $rights = [ + [ + 'itemtype' => 'PluginTagTag', + 'label' => PluginTagTag::getTypeName(Session::getPluralNumber()), + 'field' => 'plugin_tag_tag' + ] + ]; + $matrix_options['title'] = __('Tag management', 'tag'); + $profile->displayRightsChoiceMatrix($rights, $matrix_options); - $rights = [['itemtype' => 'PluginTagTag', - 'label' => PluginTagTag::getTypeName(Session::getPluralNumber()), - 'field' => 'plugin_tag_tag']]; - $matrix_options['title'] = __('Tag management', 'tag'); - $profile->displayRightsChoiceMatrix($rights, $matrix_options); + if ($canedit) { + echo "
"; + echo Html::hidden('id', ['value' => $ID]); + echo Html::submit(_sx('button', 'Save'), ['name' => 'update']); + echo "
\n"; + Html::closeForm(); + } + echo "
"; - if ($canedit) { - echo "
"; - echo Html::hidden('id', ['value' => $ID]); - echo Html::submit(_sx('button', 'Save'), ['name' => 'update']); - echo "
\n"; - Html::closeForm(); - } - echo "
"; - } -} \ No newline at end of file + return true; + } +} diff --git a/inc/tag.class.php b/inc/tag.class.php index bd9d018..9260952 100644 --- a/inc/tag.class.php +++ b/inc/tag.class.php @@ -28,809 +28,869 @@ * ------------------------------------------------------------------------- */ -class PluginTagTag extends CommonDropdown { - - // From CommonDBTM - public $dohistory = true; - - const S_OPTION = 10500; - static $rightname = 'plugin_tag_tag'; - - public static function getTypeName($nb = 1) { - return _n('Tag', 'Tags', $nb, 'tag'); - } - - /** - * Return the list of blackisted itemtype - * We don't want tag system on theses - * - * @return array of string itemtypes - */ - public static function getBlacklistItemtype() { - return [ - 'PluginTagTag', - 'PluginTagTagItem', - 'Itil_Project', - 'Item_Project', - 'Notification', - 'Crontask', - 'PluginFormcreatorFormanswer', - 'QueuedNotification', - 'PluginPrintercountersRecord', - 'ITILSolution', - 'ITILFollowup', - ]; - } - - /** - * Check if the passed itemtype is in the blacklist - * - * @param string $itemtype - * - * @return bool - */ - public static function canItemtype($itemtype = '') { - return !empty($itemtype) && class_exists($itemtype) && !in_array($itemtype, self::getBlacklistItemtype()); - } - - public function showForm($ID, $options = []) { - global $CFG_GLPI; - - if (!$this->canViewItem()) { - return false; - } - - $this->initForm($ID, $options); - $this->showFormHeader($options); - - echo ''; - echo ""; - echo ""; - echo ""; - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - - $this->showFormButtons($options); - - return true; - } - - public static function install(Migration $migration) { - global $DB, $CFG_GLPI; - - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - - $table = getTableForItemType(__CLASS__); - - if (!$DB->tableExists($table)) { - $DB->query("CREATE TABLE IF NOT EXISTS `$table` ( - `id` int {$default_key_sign} NOT NULL auto_increment, - `entities_id` int {$default_key_sign} NOT NULL DEFAULT '0', - `is_recursive` tinyint NOT NULL DEFAULT '1', - `name` varchar(255) NOT NULL DEFAULT '', - `comment` text, - `color` varchar(50) NOT NULL DEFAULT '', - `type_menu` text, - PRIMARY KEY (`id`), - KEY `name` (`name`) - ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;") - or die($DB->error()); - } - - if (!$DB->fieldExists($table, 'type_menu')) { - $migration->addField($table, 'type_menu', "text"); - $migration->migrationOneTable($table); - } - - // Version 0.90-1.1 - // Disable cache on field list as cache wes not pruned after adding field - $fields = $DB->listFields($table, false); - if (stristr($fields['type_menu']["Type"], 'varchar') !== false) { - $migration->changeField($table, 'type_menu', 'type_menu', 'text'); - $migration->dropKey($table, 'type_menu'); - $migration->migrationOneTable($table); - - $datas = getAllDataFromTable($table, ['NOT' => ['type_menu' => null]]); - if (!empty($datas)) { - foreach ($datas as $data) { - $itemtypes = $CFG_GLPI['plugin_tag_itemtypes'][$data['type_menu']] ?? []; - $DB->update($table, ['type_menu' => json_encode($itemtypes)], ['id' => $data['id']]); +class PluginTagTag extends CommonDropdown +{ + // From CommonDBTM + public $dohistory = true; + + const S_OPTION = 10500; + public static $rightname = 'plugin_tag_tag'; + + public static function getTypeName($nb = 1) + { + return _n('Tag', 'Tags', $nb, 'tag'); + } + + /** + * Return the list of blackisted itemtype + * We don't want tag system on theses + * + * @return array of string itemtypes + */ + public static function getBlacklistItemtype() + { + return [ + 'PluginTagTag', + 'PluginTagTagItem', + 'Itil_Project', + 'Item_Project', + 'Notification', + 'Crontask', + 'PluginFormcreatorFormanswer', + 'QueuedNotification', + 'PluginPrintercountersRecord', + 'ITILSolution', + 'ITILFollowup', + ]; + } + + /** + * Check if the passed itemtype is in the blacklist + * + * @param string $itemtype + * + * @return bool + */ + public static function canItemtype($itemtype = '') + { + return !empty($itemtype) && class_exists($itemtype) && !in_array($itemtype, self::getBlacklistItemtype()); + } + + public function showForm($ID, $options = []) + { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + + if (!$this->canViewItem()) { + return false; + } + + $this->initForm($ID, $options); + $this->showFormHeader($options); + + echo '
"; - echo ''; - echo "
"; - echo ""; - echo "
"; - Html::showColorField('color', ['value' => $this->fields['color'] ?: '#DDDDDD']); - echo "
"; - // show an hidden input to permist deletion of all values - echo Html::hidden("type_menu"); - - // retrieve tags elements and existing values - $type_menu_elements = []; - foreach ($CFG_GLPI['plugin_tag_itemtypes'] as $group_label => $group_values) { - foreach ($group_values as $itemtype) { - $type_menu_elements[$group_label][$itemtype] = $itemtype::getTypeName(); - } - } - $type_menu_values = !empty($this->fields['type_menu']) ? json_decode($this->fields['type_menu']) : []; - - // show the multiple dropdown - Dropdown::showFromArray("type_menu", - $type_menu_elements, - ['values' => $type_menu_values, - 'multiple' => 'multiples']); - - echo "
'; + echo ""; + echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + + $this->showFormButtons($options); + + return true; + } + + public static function install(Migration $migration) + { + /** + * @var DBmysql $DB + * @var array $CFG_GLPI + */ + global $DB, $CFG_GLPI; + + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + + $table = getTableForItemType(__CLASS__); + + if (!$DB->tableExists($table)) { + $query = <<doQueryOrDie($query); + } else { + /** @phpstan-ignore-next-line */ + $DB->queryOrDie($query); + } + } + + if (!$DB->fieldExists($table, 'type_menu')) { + $migration->addField($table, 'type_menu', "text"); + $migration->migrationOneTable($table); + } + + // Version 0.90-1.1 + // Disable cache on field list as cache wes not pruned after adding field + $fields = $DB->listFields($table, false); + if (stristr($fields['type_menu']["Type"], 'varchar') !== false) { + $migration->changeField($table, 'type_menu', 'type_menu', 'text'); + $migration->dropKey($table, 'type_menu'); + $migration->migrationOneTable($table); + + $datas = getAllDataFromTable($table, ['NOT' => ['type_menu' => null]]); + if (!empty($datas)) { + foreach ($datas as $data) { + $itemtypes = $CFG_GLPI['plugin_tag_itemtypes'][$data['type_menu']] ?? []; + $DB->update($table, ['type_menu' => json_encode($itemtypes)], ['id' => $data['id']]); + } + } + } - // Add full rights to profiles that have READ or UPDATE config right - $migration->addRight(self::$rightname); - $migration->displayWarning("Tags now have rights. Please review all profiles to set the required level of rights."); + // Add full rights to profiles that have READ or UPDATE config right + $migration->addRight(self::$rightname); + $migration->displayWarning("Tags now have rights. Please review all profiles to set the required level of rights."); - if (Session::haveRight(Config::$rightname, READ | UPDATE)) { - // Update active profile to give access without having to logout/login - $_SESSION['glpiactiveprofile'][self::$rightname] = ALLSTANDARDRIGHT; - } + if (Session::haveRight(Config::$rightname, READ | UPDATE)) { + // Update active profile to give access without having to logout/login + $_SESSION['glpiactiveprofile'][self::$rightname] = ALLSTANDARDRIGHT; + } - return true; - } + return true; + } - public static function uninstall() { - global $DB; + public static function uninstall() + { + /** @var DBmysql $DB */ + global $DB; - $DB->deleteOrDie('glpi_logs', [ - 'OR' => [ - 'itemtype_link' => __CLASS__, + $DB->deleteOrDie('glpi_logs', [ + 'OR' => [ + 'itemtype_link' => __CLASS__, + 'itemtype' => __CLASS__ + ] + ]); + $DB->deleteOrDie('glpi_savedsearches', [ 'itemtype' => __CLASS__ - ] - ]); - $DB->deleteOrDie('glpi_savedsearches', [ - 'itemtype' => __CLASS__ - ]); - $DB->deleteOrDie('glpi_savedsearches_users', [ - 'itemtype' => __CLASS__ - ]); - $DB->deleteOrDie('glpi_displaypreferences', [ - 'OR' => [ - 'itemtype' => __CLASS__, - 'num' => self::S_OPTION - ] - ]); - - $migration = new Migration(PLUGIN_TAG_VERSION); - $migration->dropTable(getTableForItemType(__CLASS__)); - - return true; - } - - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - $tab = []; - $tab[2] = _n('Associated item', 'Associated items', 2); //Note : can add nb_element here - return $tab; - } - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - switch ($item->getType()) { - case __CLASS__ : - switch ($tabnum) { - case 2 : - $tagitem = new PluginTagTagItem(); - $tagitem->showForTag($item); - break; - - } - } - return true; - } - - function defineTabs($options = []) { - $ong = []; - $this->addDefaultFormTab($ong); - $this->addStandardTab(__CLASS__, $ong, $options); - $this->addStandardTab('PluginTagTagItem', $ong, $options); - $this->addStandardTab('Log', $ong, $options); - return $ong; - } - - public function cleanDBonPurge() { - $tagitem = new PluginTagTagItem(); - $tagitem->deleteByCriteria([ - 'plugin_tag_tags_id' => $this->getID() - ]); - } - - function getLinkedItems() { - global $DB; - - $query = "SELECT `itemtype`, `items_id` + ]); + $DB->deleteOrDie('glpi_savedsearches_users', [ + 'itemtype' => __CLASS__ + ]); + $DB->deleteOrDie('glpi_displaypreferences', [ + 'OR' => [ + 'itemtype' => __CLASS__, + 'num' => self::S_OPTION + ] + ]); + + $migration = new Migration(PLUGIN_TAG_VERSION); + $migration->dropTable(getTableForItemType(__CLASS__)); + + return true; + } + + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + $tab = []; + $tab[2] = _n('Associated item', 'Associated items', 2); //Note : can add nb_element here + return $tab; + } + + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + switch ($item->getType()) { + case __CLASS__: + switch ($tabnum) { + case 2: + $tagitem = new PluginTagTagItem(); + $tagitem->showForTag($item); + break; + } + } + return true; + } + + public function defineTabs($options = []) + { + $ong = []; + $this->addDefaultFormTab($ong); + $this->addStandardTab(__CLASS__, $ong, $options); + $this->addStandardTab('PluginTagTagItem', $ong, $options); + $this->addStandardTab('Log', $ong, $options); + return $ong; + } + + public function cleanDBonPurge() + { + $tagitem = new PluginTagTagItem(); + $tagitem->deleteByCriteria([ + 'plugin_tag_tags_id' => $this->getID() + ]); + } + + public function getLinkedItems() + { + /** @var DBmysql $DB */ + global $DB; + + $query = "SELECT `itemtype`, `items_id` FROM `glpi_computers_items` - WHERE `computers_id` = '".$this->getID()."'"; - $tab = []; - foreach ($DB->request($query) as $data) { - $tab[$data['itemtype']][$data['items_id']] = $data['items_id']; - } - return $tab; - } - - // for massive actions - function haveChildren() { - $tagitems = new PluginTagTagItem(); - $data = $tagitems->find(['plugin_tag_tags_id' => $this->getID()]); - if (count($data) == 0) { - return false; - } - return true; - } - - function rawSearchOptions() { - - $tab = []; - - $tab[] = [ - 'id' => 'common', - 'name' => __('Characteristics'), - ]; - - $tab[] = [ - 'id' => 1, - 'table' => $this->getTable(), - 'field' => 'name', - 'name' => __('Name'), - 'datatype' => 'itemlink', - 'massiveaction' => true, - ]; - - $tab[] = [ - 'id' => 2, - 'table' => $this->getTable(), - 'field' => 'comment', - 'name' => __('Description'), - 'datatype' => 'string', - 'massiveaction' => true, - ]; - - $tab[] = [ - 'id' => 3, - 'table' => $this->getTable(), - 'field' => 'id', - 'name' => __('ID'), - 'datatype' => 'number', - 'massiveaction' => false, - ]; - - $tab[] = [ - 'id' => 4, - 'table' => 'glpi_entities', - 'field' => 'completename', - 'linkfield' => 'entities_id', - 'name' => __('Entity'), - 'datatype' => 'dropdown', - ]; - - $tab[] = [ - 'id' => 5, - 'table' => $this->getTable(), - 'field' => 'is_recursive', - 'name' => __('Child entities'), - 'datatype' => 'bool', - ]; - - $tab[] = [ - 'id' => 6, - 'table' => $this->getTable(), - 'field' => 'type_menu', - 'name' => _n('Associated item type', 'Associated item types', 2), - 'searchtype' => ['equals', 'notequals'], - 'datatype' => 'specific', - ]; - - $tab[] = [ - 'id' => 7, - 'table' => $this->getTable(), - 'field' => 'color', - 'name' => __('HTML color', 'tag'), - 'searchtype' => 'contains', - 'datatype' => 'specific', - ]; - - return $tab; - } - - static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) { - global $CFG_GLPI; - if (!is_array($values)) { - $values = [$field => $values]; - } - switch ($field) { - case 'type_menu': - $elements = ['' => Dropdown::EMPTY_VALUE]; - $supported_itemtypes = $CFG_GLPI['plugin_tag_itemtypes'] ?? []; - foreach ($supported_itemtypes as $itemtypes) { + WHERE `computers_id` = '" . $this->getID() . "'"; + $tab = []; + foreach ($DB->request($query) as $data) { + $tab[$data['itemtype']][$data['items_id']] = $data['items_id']; + } + return $tab; + } + + // for massive actions + public function haveChildren() + { + $tagitems = new PluginTagTagItem(); + $data = $tagitems->find(['plugin_tag_tags_id' => $this->getID()]); + if (count($data) == 0) { + return false; + } + return true; + } + + public function rawSearchOptions() + { + + $tab = []; + + $tab[] = [ + 'id' => 'common', + 'name' => __('Characteristics'), + ]; + + $tab[] = [ + 'id' => 1, + 'table' => $this->getTable(), + 'field' => 'name', + 'name' => __('Name'), + 'datatype' => 'itemlink', + 'massiveaction' => true, + ]; + + $tab[] = [ + 'id' => 2, + 'table' => $this->getTable(), + 'field' => 'comment', + 'name' => __('Description'), + 'datatype' => 'string', + 'massiveaction' => true, + ]; + + $tab[] = [ + 'id' => 3, + 'table' => $this->getTable(), + 'field' => 'id', + 'name' => __('ID'), + 'datatype' => 'number', + 'massiveaction' => false, + ]; + + $tab[] = [ + 'id' => 4, + 'table' => 'glpi_entities', + 'field' => 'completename', + 'linkfield' => 'entities_id', + 'name' => __('Entity'), + 'datatype' => 'dropdown', + ]; + + $tab[] = [ + 'id' => 5, + 'table' => $this->getTable(), + 'field' => 'is_recursive', + 'name' => __('Child entities'), + 'datatype' => 'bool', + ]; + + $tab[] = [ + 'id' => 6, + 'table' => $this->getTable(), + 'field' => 'type_menu', + 'name' => _n('Associated item type', 'Associated item types', 2), + 'searchtype' => ['equals', 'notequals'], + 'datatype' => 'specific', + ]; + + $tab[] = [ + 'id' => 7, + 'table' => $this->getTable(), + 'field' => 'color', + 'name' => __('HTML color', 'tag'), + 'searchtype' => 'contains', + 'datatype' => 'specific', + ]; + + return $tab; + } + + public static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) + { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + if (!is_array($values)) { + $values = [$field => $values]; + } + switch ($field) { + case 'type_menu': + $elements = ['' => Dropdown::EMPTY_VALUE]; + $supported_itemtypes = $CFG_GLPI['plugin_tag_itemtypes'] ?? []; + foreach ($supported_itemtypes as $itemtypes) { + foreach ($itemtypes as $itemtype) { + $item = getItemForItemtype($itemtype); + $elements[$itemtype] = $item::getTypeName(); + } + } + + return Dropdown::showFromArray( + $name, + $elements, + ['display' => false, + 'value' => $values[$field] + ] + ); + break; + } + + return parent::getSpecificValueToSelect($field, $name, $values, $options); + } + public static function getSpecificValueToDisplay($field, $values, array $options = []) + { + switch ($field) { + case 'type_menu': + $itemtypes = json_decode($values[$field]); + if (!is_array($itemtypes)) { + return " "; + } + $itemtype_names = []; foreach ($itemtypes as $itemtype) { $item = getItemForItemtype($itemtype); - $elements[$itemtype] = $item::getTypeName(); + $itemtype_names[] = $item->getTypeName(); + } + $out = implode(", ", $itemtype_names); + return $out; + case 'color': + $color = $values[$field] ?: '#DDDDDD'; + return "
 
"; + } + + return parent::getSpecificValueToDisplay($field, $values, $options); + } + + /** + * @see https://github.com/pluginsGLPI/tag/issues/1 + */ + public static function parseItemtype($itemtype, $id = 0) + { + if ($itemtype == 'rule.generic') { + $rule = new Rule(); + $rule->getFromDB($id); + return $rule->fields["sub_type"]; + } + return $itemtype; + } + + /** + * Display the current tag dropdown in form of items. + * + * Depending on the config settings, this will either show at the top or bottom of the forms. + * + * @param array $params should contains theses keys: + * - item the CommonDBTM object + * @return bool|void False if the form was not shown. Otherwise nothing is returned and the form is displayed. + */ + public static function showForItem($params = []) + { + if (!self::canView()) { + return false; + } + + if ( + isset($params['item']) + && $params['item'] instanceof CommonDBTM + ) { + $item = $params['item']; + $itemtype = get_class($item); + + if (self::canItemtype($itemtype)) { + // manage values after a redirect (ex ticket creation, after a cat change) + $value = ''; + if (isset($item->input['_plugin_tag_tag_values'])) { + $value = $item->input['_plugin_tag_tag_values']; } - } - return Dropdown::showFromArray($name, $elements, - ['display' => false, - 'value' => $values[$field]]); - break; - } - - return parent::getSpecificValueToSelect($field, $name, $values, $options); - } - - static function getSpecificValueToDisplay($field, $values, array $options = []) { - switch ($field) { - case 'type_menu': - $itemtypes = json_decode($values[$field]); - if (!is_array($itemtypes)) { - return " "; - } - $itemtype_names = []; - foreach ($itemtypes as $itemtype) { - $item = getItemForItemtype($itemtype); - $itemtype_names[] = $item->getTypeName(); - } - $out = implode(", ", $itemtype_names); - return $out; - case 'color' : - $color = $values[$field] ?: '#DDDDDD'; - return "
 
"; - } - - return parent::getSpecificValueToDisplay($field, $values, $options); - } - - /** - * @see https://github.com/pluginsGLPI/tag/issues/1 - */ - static function parseItemtype($itemtype, $id = 0) { - if ($itemtype == 'rule.generic') { - $rule = new Rule(); - $rule->getFromDB($id); - return $rule->fields["sub_type"]; - } - return $itemtype; - } - - /** - * Display the current tag dropdown in form of items. - * - * Depending on the config settings, this will either show at the top or bottom of the forms. - * - * @param array $params should contains theses keys: - * - item the CommonDBTM object - * @return bool|void False if the form was not shown. Otherwise nothing is returned and the form is displayed. - */ - static function showForItem($params = []) { - if (!self::canView()) { - return false; - } - - if (isset($params['item']) - && $params['item'] instanceof CommonDBTM) { - $item = $params['item']; - $itemtype = get_class($item); - - if (self::canItemtype($itemtype)) { - // manage values after a redirect (ex ticket creation, after a cat change) - $value = ''; - if (isset($item->input['_plugin_tag_tag_values'])) { - $value = $item->input['_plugin_tag_tag_values']; - } + $field_class = "form-field row col-12 col-sm-6 px-3 mt-2 mb-n2"; + $label_class = "col-form-label col-xxl-5 text-xxl-end"; + $input_class = "col-xxl-7 field-container"; - $field_class = "form-field row col-12 col-sm-6 px-3 mt-2 mb-n2"; - $label_class = "col-form-label col-xxl-5 text-xxl-end"; - $input_class = "col-xxl-7 field-container"; + if ($item instanceof CommonITILObject) { + $field_class = "form-field row col-12 mb-2"; + $label_class = "col-form-label col-xxl-4 text-xxl-end"; + $input_class = "col-xxl-8 field-container"; + } - if ($item instanceof CommonITILObject) { - $field_class = "form-field row col-12 mb-2"; - $label_class = "col-form-label col-xxl-4 text-xxl-end"; - $input_class = "col-xxl-8 field-container"; + echo "
"; + echo "
" . _n('Tag', 'Tags', 2, 'tag') . "
"; + echo "
"; + self::showTagDropdown([ + 'itemtype' => $itemtype, + 'id' => $item->getId(), + 'value' => $value, + ]); + echo "
"; + echo "
"; } + } + } + + /** + * Display the current tags before the Kanban item content. + * + * @param array $params should contains theses keys: + * - itemtype The item type + * - items_id The item's id + * - content postKanbanContent content + * @return array Array of params passed in in addition to the new content. + */ + public static function preKanbanContent($params = []) + { + /** @var DBmysql $DB */ + global $DB; + + if (!Session::haveRight(PluginTagTag::$rightname, READ)) { + return null; + } + + if (isset($params['itemtype']) && isset($params['items_id'])) { + if (!isset($params['content'])) { + $params['content'] = ""; + } + $iterator = $DB->request([ + 'SELECT' => [ + 'name', + 'comment', + 'color' + ], + 'FROM' => PluginTagTagItem::getTable(), + 'LEFT JOIN' => [ + PluginTagTag::getTable() => [ + 'FKEY' => [ + PluginTagTag::getTable() => 'id', + PluginTagTagItem::getTable() => 'plugin_tag_tags_id' + ] + ] + ], + 'WHERE' => [ + 'itemtype' => $params['itemtype'], + 'items_id' => $params['items_id'] + ] + ]); - echo "
"; - echo "
". - _n('Tag', 'Tags', 2, 'tag'). - "
"; - echo "
"; - self::showTagDropdown([ - 'itemtype' => $itemtype, - 'id' => $item->getId(), - 'value' => $value, + $content = "
"; + foreach ($iterator as $data) { + $title = $data['comment']; + $name = $data['name']; + $color = $data['color'] ?: '#DDDDDD'; + $textcolor = idealTextColor($color); + $style = "background-color: {$color}; color: {$textcolor};"; + $content .= "{$name}  "; + } + $content .= "
"; + $params['content'] .= $content; + return $params; + } + return null; + } + + public static function kanbanItemMetadata($params) + { + /** @var DBmysql $DB */ + global $DB; + + if (!Session::haveRight(PluginTagTag::$rightname, READ)) { + return $params; + } + + if (isset($params['itemtype']) && isset($params['items_id'])) { + $iterator = $DB->request([ + 'SELECT' => [ + 'name', + ], + 'FROM' => PluginTagTagItem::getTable(), + 'LEFT JOIN' => [ + PluginTagTag::getTable() => [ + 'FKEY' => [ + PluginTagTag::getTable() => 'id', + PluginTagTagItem::getTable() => 'plugin_tag_tags_id' + ] + ] + ], + 'WHERE' => [ + 'itemtype' => $params['itemtype'], + 'items_id' => $params['items_id'] + ] ]); - echo "
"; - echo "
"; - } - } - } - - /** - * Display the current tags before the Kanban item content. - * - * @param array $params should contains theses keys: - * - itemtype The item type - * - items_id The item's id - * - content postKanbanContent content - * @return array Array of params passed in in addition to the new content. - */ - static function preKanbanContent($params = []) { - global $DB; - - if (!Session::haveRight(PluginTagTag::$rightname, READ)) { - return null; - } - - if (isset($params['itemtype']) && isset($params['items_id'])) { - if (!isset($params['content'])) { - $params['content'] = ""; - } - $iterator = $DB->request([ - 'SELECT' => [ - 'name', - 'comment', - 'color' - ], - 'FROM' => PluginTagTagItem::getTable(), - 'LEFT JOIN' => [ - PluginTagTag::getTable() => [ - 'FKEY' => [ - PluginTagTag::getTable() => 'id', - PluginTagTagItem::getTable() => 'plugin_tag_tags_id' - ] - ] - ], - 'WHERE' => [ - 'itemtype' => $params['itemtype'], - 'items_id' => $params['items_id'] + + $params['metadata']['tags'] = $params['metadata']['tags'] ?? []; + foreach ($iterator as $data) { + $params['metadata']['tags'][] = $data['name']; + } + } + return $params; + } + + /** + * Display the tag dropdowns + * @param array $params could contains theses keys: + * - itemtype (mandatory) + * - id (optionnal) + * @return void + */ + public static function showTagDropdown($params = []) + { + // compute default params + $default_params = [ + 'id' => 0, + 'itemtype' => '', + 'value' => '', + ]; + $params = array_merge($default_params, $params); + + // check itemtype + $itemtype = self::parseItemtype($params['itemtype'], $params['id']); + $obj = new $itemtype(); + + // Object must be an instance of CommonDBTM (or inherint of this) + if (!$obj instanceof CommonDBTM) { + return; + } + + // instanciate needed objects + $tag = new self(); + $tag_item = new PluginTagTagItem(); + + // retrieve current item + if (isset($params['id'])) { + $obj->getFromDB($params['id']); + } + if ($obj->isNewItem()) { + $obj->getEmpty(); + } + + // find values for this items + $values = []; + if (!$obj->isNewItem()) { + foreach ( + $tag_item->find(['items_id' => $params['id'], + 'itemtype' => $itemtype + ]) as $found_item + ) { + $values[] = $found_item['plugin_tag_tags_id']; + } + } elseif (is_string($params['value'])) { + $values = !empty($params['value']) ? explode(',', $params['value']) : []; + } elseif (is_array($params['value'])) { + $values = $params['value']; + } + + // Restrict tags finding by itemtype and entity + $where = [ + 'OR' => [ + ['type_menu' => null], + ['type_menu' => ''], + ['type_menu' => 0], + ['type_menu' => ['LIKE', '%"' . $itemtype . '"%']], ] - ]); - - $content = "
"; - foreach ($iterator as $data) { - $title = $data['comment']; - $name = $data['name']; - $color = $data['color'] ?: '#DDDDDD'; - $textcolor = idealTextColor($color); - $style = "background-color: {$color}; color: {$textcolor};"; - $content .= "{$name}  "; - } - $content .= "
"; - $params['content'] .= $content; - return $params; - } - return null; - } - - public static function kanbanItemMetadata($params) { - global $DB; - - if (!Session::haveRight(PluginTagTag::$rightname, READ)) { - return $params; - } - - if (isset($params['itemtype']) && isset($params['items_id'])) { - $iterator = $DB->request([ - 'SELECT' => [ - 'name', - ], - 'FROM' => PluginTagTagItem::getTable(), - 'LEFT JOIN' => [ - PluginTagTag::getTable() => [ - 'FKEY' => [ - PluginTagTag::getTable() => 'id', - PluginTagTagItem::getTable() => 'plugin_tag_tags_id' - ] - ] - ], - 'WHERE' => [ - 'itemtype' => $params['itemtype'], - 'items_id' => $params['items_id'] + ]; + if ($obj->isEntityAssign()) { + $where += getEntitiesRestrictCriteria('', '', '', true); + } + + // found existing tags + $existing_tags = $tag->find($where, 'name'); + $select2_tags = []; + foreach ($existing_tags as $existing_tag) { + $select2_tags[] = [ + 'id' => $existing_tag['id'], + 'text' => $existing_tag['name'], + 'color' => $existing_tag['color'], + 'selected' => in_array($existing_tag['id'], $values), + ]; + } + // new tags restored from saved input + $new_tags = array_diff($values, array_column($existing_tags, 'id')); + foreach ($new_tags as $new_tag) { + $select2_tags[] = [ + 'id' => $new_tag, + 'text' => preg_replace('/^newtag_(.+)/', '$1', $new_tag), + 'selected' => true, + ]; + } + + // create an input receiving the tag tokens + $extra_class = ""; + if ($obj instanceof CommonITILTask) { + $extra_class = "mb-3"; + } + + echo "
"; + + $rand = mt_rand(); + echo Html::hidden('_plugin_tag_tag_process_form', ['value' => '1',]); + echo Html::select( + '_plugin_tag_tag_values[]', + [], + [ + 'id' => "tag_select_$rand", + 'class' => 'tag_select', + 'multiple' => 'multiple', ] - ]); - - $params['metadata']['tags'] = $params['metadata']['tags'] ?? []; - foreach ($iterator as $data) { - $params['metadata']['tags'][] = $data['name']; - } - } - return $params; - } - - /** - * Display the tag dropdowns - * @param array $params could contains theses keys: - * - itemtype (mandatory) - * - id (optionnal) - * @return nothing - */ - static function showTagDropdown($params = []) { - // compute default params - $default_params = [ - 'id' => 0, - 'itemtype' => '', - 'value' => '', - ]; - $params = array_merge($default_params, $params); - - // check itemtype - $itemtype = self::parseItemtype($params['itemtype'], $params['id']); - $obj = new $itemtype(); - - // Object must be an instance of CommonDBTM (or inherint of this) - if (!$obj instanceof CommonDBTM) { - return; - } - - // instanciate needed objects - $tag = new self(); - $tag_item = new PluginTagTagItem(); - - // retrieve current item - if (isset($params['id'])) { - $obj->getFromDB($params['id']); - } - if ($obj->isNewItem()) { - $obj->getEmpty(); - } - - // find values for this items - $values = []; - if (!$obj->isNewItem()) { - foreach ($tag_item->find(['items_id' => $params['id'], - 'itemtype' => $itemtype]) as $found_item) { - $values[] = $found_item['plugin_tag_tags_id']; - } - } elseif (is_string($params['value'])) { - $values = !empty($params['value']) ? explode(',', $params['value']) : []; - } elseif (is_array($params['value'])) { - $values = $params['value']; - } - - // Restrict tags finding by itemtype and entity - $where = [ - 'OR' => [ - ['type_menu' => null], - ['type_menu' => ''], - ['type_menu' => 0], - ['type_menu' => ['LIKE', '%"'.$itemtype.'"%']], - ] - ]; - if ($obj->isEntityAssign()) { - $where += getEntitiesRestrictCriteria('', '', '', true); - } - - // found existing tags - $existing_tags = $tag->find($where, 'name'); - $select2_tags = []; - foreach ($existing_tags as $existing_tag) { - $select2_tags[] = [ - 'id' => $existing_tag['id'], - 'text' => $existing_tag['name'], - 'color' => $existing_tag['color'], - 'selected' => in_array($existing_tag['id'], $values), - ]; - } - // new tags restored from saved input - $new_tags = array_diff($values, array_column($existing_tags, 'id')); - foreach ($new_tags as $new_tag) { - $select2_tags[] = [ - 'id' => $new_tag, - 'text' => preg_replace('/^newtag_(.+)/', '$1', $new_tag), - 'selected' => true, - ]; - } - - // create an input receiving the tag tokens - $extra_class = ""; - if ($obj instanceof CommonITILTask) { - $extra_class = "mb-3"; - } - - echo "
"; - - $rand = mt_rand(); - echo Html::hidden('_plugin_tag_tag_process_form', ['value' => '1',]); - echo Html::select( - '_plugin_tag_tag_values[]', - [], - [ - 'id' => "tag_select_$rand", - 'class' => 'tag_select', - 'multiple' => 'multiple', - ] - ); - - $token_creation = " - // prefix value by 'newtag_' to differenciate created tag from existing ones - return { id: 'newtag_'+ params.term, text: params.term };"; - if (!self::canCreate()) { - $token_creation = "return null;"; - } - - $readOnly = !$tag::canUpdate() - || ($obj->isNewItem() && !$obj->canCreateItem()) - || (!$obj->isNewItem() && !$obj->canUpdateItem()) - ; - - // call select2 lib for this input - echo Html::scriptBlock("$(function() { - $('#tag_select_$rand').select2({ - width: 'calc(100% - 20px)', - templateResult: formatOptionResult, - templateSelection: formatOptionSelection, - formatSearching: '".__("Loading...")."', - dropdownCssClass: 'tag_select_results', - data: ".json_encode($select2_tags).", - tags: true, - tokenSeparators: [',', ';'], - disabled: ".($readOnly ? 'true': 'false').", - createTag: function (params) { - var term = $.trim(params.term); - if (term === '') { - return null; - } - $token_creation + ); + + // prefix value by 'newtag_' to differenciate created tag from existing ones + $token_creation = "return { id: 'newtag_'+ params.term, text: params.term };"; + if (!self::canCreate()) { + $token_creation = "return null;"; + } + + $readOnly = !$tag::canUpdate() + || ($obj->isNewItem() && !$obj->canCreateItem()) + || (!$obj->isNewItem() && !$obj->canUpdateItem()) + ; + + // call select2 lib for this input + echo Html::scriptBlock(" + $(function() { + $('#tag_select_$rand').select2({ + width: 'calc(100% - 20px)', + templateResult: formatOptionResult, + templateSelection: formatOptionSelection, + formatSearching: '" . __("Loading...") . "', + dropdownCssClass: 'tag_select_results', + data: " . json_encode($select2_tags) . ", + tags: true, + tokenSeparators: [',', ';'], + disabled: " . ($readOnly ? 'true' : 'false') . ", + createTag: function (params) { + var term = $.trim(params.term); + if (term === '') { + return null; + } + $token_creation + } + }); + }); + "); + + // Show tooltip + if (self::canCreate()) { + echo "
"; + echo Html::showToolTip( + __("View all tags", 'tag'), + ['link' => self::getSearchURL()] + ); + echo "
"; + } + + echo "
"; + } + + public static function getTagForEntityName($completename = "") + { + $plus_rootentity = sprintf(__('%1$s + %2$s'), '', __('Child entities')); + $completename = Html::entity_decode_deep($completename); + $completename = trim(str_replace($plus_rootentity, '', $completename)); + $entities_id = Entity::getEntityIDByCompletename($completename); + + $out = ""; + if ($entities_id >= 0) { + $tag_item = new PluginTagTagItem(); + foreach ($tag_item->find(['items_id' => $entities_id, 'itemtype' => 'Entity']) as $found_item) { + $out .= PluginTagTag::getSingleTag($found_item['plugin_tag_tags_id']); } - }); - });"); - - // Show tooltip - if (self::canCreate()) { - echo "
"; - echo Html::showToolTip(__("View all tags", 'tag'), - ['link' => self::getSearchURL()]); - echo "
"; - } - - echo "
"; - } - - static function getTagForEntityName($completename = "") { - $plus_rootentity = sprintf(__('%1$s + %2$s'), '', __('Child entities')); - $completename = Html::entity_decode_deep($completename); - $completename = trim(str_replace($plus_rootentity, '', $completename)); - $entities_id = Entity::getEntityIDByCompletename($completename); - - $out = ""; - if ($entities_id >= 0) { - $tag_item = new PluginTagTagItem(); - foreach ($tag_item->find(['items_id' => $entities_id, - 'itemtype' => 'Entity']) as $found_item) { - $out .= PluginTagTag::getSingleTag($found_item['plugin_tag_tags_id']); - } - } - - return $out; - } - - static function getSingleTag($tag_id, $separator = '') { - $plugintagtag = new self(); - $plugintagtag->getFromDB($tag_id); - $color = $plugintagtag->fields["color"] ?: '#DDDDDD'; - $inv_color = idealTextColor($color); - $style = "background-color: $color; border: 1px solid $inv_color; color: $inv_color"; - - return "". - $separator.$plugintagtag->fields['name'].''; - } - - function prepareInputForAdd($input) { - if (!$this->checkMandatoryFields($input)) { - return false; - } - - return $this->encodeSubtypes($input); - } - - function prepareInputForUpdate($input) { - if (!$this->checkMandatoryFields($input)) { - return false; - } - - return $this->encodeSubtypes($input); - } - - /** - * Encode sub types - * - * @param type $input - */ - function encodeSubtypes($input) { - if (!empty($input['type_menu'])) { - $input['type_menu'] = json_encode(array_values($input['type_menu'])); - } - - return $input; - } - - /** - * Check all mandatory field are filled - * - * @param array $input - * @return boolean - */ - function checkMandatoryFields($input = []) { - $msg = []; - $checkKo = false; - $mandatory_fields = ['name' => __('Name')]; - - foreach ($input as $key => $value) { - if (isset($mandatory_fields[$key])) { - if (empty($value)) { - $msg[] = $mandatory_fields[$key]; - $checkKo = true; + } + + return $out; + } + + public static function getSingleTag($tag_id, $separator = '') + { + $plugintagtag = new self(); + $plugintagtag->getFromDB($tag_id); + $color = $plugintagtag->fields["color"] ?: '#DDDDDD'; + $inv_color = idealTextColor($color); + $style = "background-color: $color; border: 1px solid $inv_color; color: $inv_color"; + + return "" . + $separator . $plugintagtag->fields['name'] . ''; + } + + public function prepareInputForAdd($input) + { + if (!$this->checkMandatoryFields($input)) { + return false; + } + + return $this->encodeSubtypes($input); + } + + public function prepareInputForUpdate($input) + { + if (!$this->checkMandatoryFields($input)) { + return false; + } + + return $this->encodeSubtypes($input); + } + + /** + * Encode sub types + * + * @param type $input + */ + public function encodeSubtypes($input) + { + if (!empty($input['type_menu'])) { + $input['type_menu'] = json_encode(array_values($input['type_menu'])); + } + + return $input; + } + + /** + * Check all mandatory field are filled + * + * @param array $input + * @return boolean + */ + public function checkMandatoryFields($input = []) + { + $msg = []; + $checkKo = false; + $mandatory_fields = ['name' => __('Name')]; + + foreach ($input as $key => $value) { + if (isset($mandatory_fields[$key])) { + if (empty($value)) { + $msg[] = $mandatory_fields[$key]; + $checkKo = true; + } } - } - } - - if ($checkKo) { - Session::addMessageAfterRedirect(sprintf(__("Mandatory fields are not filled. Please correct: %s"), implode(', ', $msg)), true, ERROR); - return false; - } - return true; - } - - /** - * Retrieve the current itemtype from the current page url - * - * @return mixed(string/boolean) false if not itemtype found, the string itemtype if found - */ - public static function getCurrentItemtype() { - $itemtype = ''; - if ( - preg_match('/\/(?:marketplace|plugins)\/genericobject\/front\/object\.form.php/', $_SERVER['PHP_SELF']) - && array_key_exists('itemtype', $_GET) - ) { - $itemtype = $_GET['itemtype']; - } else if (preg_match('/\/(?:marketplace|plugins)\/([a-zA-Z]+)\/front\/([a-zA-Z]+).form.php/', - $_SERVER['PHP_SELF'], $matches)) { - $itemtype = 'Plugin'.ucfirst($matches[1]).ucfirst($matches[2]); - - } else if (preg_match('/([a-zA-Z]+).form.php/', $_SERVER['PHP_SELF'], $matches)) { - $itemtype = $matches[1]; - - } else if (preg_match('/\/(?:marketplace|plugins)\/([a-zA-Z]+)\/front\/([a-zA-Z]+).php/', - $_SERVER['PHP_SELF'], $matches)) { - $itemtype = 'Plugin'.ucfirst($matches[1]).ucfirst($matches[2]); - - } else if (preg_match('/([a-zA-Z]+).php/', $_SERVER['PHP_SELF'], $matches)) { - $itemtype = $matches[1]; - } - - $item = getItemForItemtype($itemtype); - if ($item instanceof CommonDBTM) { - return $item->getType(); - } - - return false; - } - - static function getIcon() { - return "fas fa-tags"; - } + } + + if ($checkKo) { + Session::addMessageAfterRedirect(sprintf(__("Mandatory fields are not filled. Please correct: %s"), implode(', ', $msg)), true, ERROR); + return false; + } + return true; + } + + /** + * Retrieve the current itemtype from the current page url + * + * @return mixed(string/boolean) false if not itemtype found, the string itemtype if found + */ + public static function getCurrentItemtype() + { + $itemtype = ''; + if ( + preg_match('/\/(?:marketplace|plugins)\/genericobject\/front\/object\.form.php/', $_SERVER['PHP_SELF']) + && array_key_exists('itemtype', $_GET) + ) { + $itemtype = $_GET['itemtype']; + } else if ( + preg_match( + '/\/(?:marketplace|plugins)\/([a-zA-Z]+)\/front\/([a-zA-Z]+).form.php/', + $_SERVER['PHP_SELF'], + $matches + ) + ) { + $itemtype = 'Plugin' . ucfirst($matches[1]) . ucfirst($matches[2]); + } else if (preg_match('/([a-zA-Z]+).form.php/', $_SERVER['PHP_SELF'], $matches)) { + $itemtype = $matches[1]; + } else if ( + preg_match( + '/\/(?:marketplace|plugins)\/([a-zA-Z]+)\/front\/([a-zA-Z]+).php/', + $_SERVER['PHP_SELF'], + $matches + ) + ) { + $itemtype = 'Plugin' . ucfirst($matches[1]) . ucfirst($matches[2]); + } else if (preg_match('/([a-zA-Z]+).php/', $_SERVER['PHP_SELF'], $matches)) { + $itemtype = $matches[1]; + } + + $item = getItemForItemtype($itemtype); + if ($item instanceof CommonDBTM) { + return $item->getType(); + } + + return false; + } + + public static function getIcon() + { + return "fas fa-tags"; + } } diff --git a/inc/taginjection.class.php b/inc/taginjection.class.php index fdce3ff..c8d7abb 100644 --- a/inc/taginjection.class.php +++ b/inc/taginjection.class.php @@ -28,57 +28,65 @@ * ------------------------------------------------------------------------- */ -class PluginTagTagInjection extends PluginTagTag - implements PluginDatainjectionInjectionInterface { +class PluginTagTagInjection extends PluginTagTag implements PluginDatainjectionInjectionInterface +{ + public static function getTable($classname = null) + { + $parenttype = get_parent_class(); + return $parenttype::getTable(); + } - static function getTable($classname = null) { - $parenttype = get_parent_class(); - return $parenttype::getTable(); - } + public static function getTypeName($nb = 0) + { + return parent::getTypeName(1); + } - static function getTypeName($nb = 0) { - return parent::getTypeName(1); - } + public function isPrimaryType() + { + return true; + } - function isPrimaryType() { - return true; - } + public function connectedTo() + { + //Note : Interesting to have GLPI core object (who can have a tag) here + return []; + } - function connectedTo() { - //Note : Interesting to have GLPI core object (who can have a tag) here - return []; - } + /** + * @see plugins/datainjection/inc/PluginDatainjectionInjectionInterface::getOptions() + */ + public function getOptions($primary_type = '') + { - /** - * @see plugins/datainjection/inc/PluginDatainjectionInjectionInterface::getOptions() - **/ - function getOptions($primary_type = '') { + $tab = Search::getOptions(get_parent_class($this)); - $tab = Search::getOptions(get_parent_class($this)); + //Remove some options because some fields cannot be imported + $options['ignore_fields'] = [3, 4, 6]; //id, entity, type_menu; + $options['displaytype'] = ["dropdown" => [12]]; - //Remove some options because some fields cannot be imported - $options['ignore_fields'] = [3, 4, 6]; //id, entity, type_menu; - $options['displaytype'] = ["dropdown" => [12]]; + /** @phpstan-ignore-next-line */ + return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); + } - return PluginDatainjectionCommonInjectionLib::addToSearchOptions($tab, $options, $this); - } + /** + * @see plugins/datainjection/inc/PluginDatainjectionInjectionInterface::addOrUpdateObject() + */ + public function addOrUpdateObject($values = [], $options = []) + { + /** @phpstan-ignore-next-line */ + $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); + $lib->processAddOrUpdate(); + $results = $lib->getInjectionResults(); - /** - * @see plugins/datainjection/inc/PluginDatainjectionInjectionInterface::addOrUpdateObject() - **/ - function addOrUpdateObject($values = [], $options = []) { + // Update field for add a default value + /** @phpstan-ignore-next-line */ + if ($results['status'] == PluginDatainjectionCommonInjectionLib::SUCCESS) { + $item = new parent(); + $item->update(['id' => $results[get_parent_class()], + 'type_menu' => '0' + ]); //default value + } - $lib = new PluginDatainjectionCommonInjectionLib($this, $values, $options); - $lib->processAddOrUpdate(); - $results = $lib->getInjectionResults(); - - // Update field for add a default value - if ($results['status'] == PluginDatainjectionCommonInjectionLib::SUCCESS) { - $item = new parent(); - $item->update(['id' => $results[get_parent_class()], - 'type_menu' => '0']); //default value - } - - return $results; - } + return $results; + } } diff --git a/inc/tagitem.class.php b/inc/tagitem.class.php index 98d1112..e8d700b 100644 --- a/inc/tagitem.class.php +++ b/inc/tagitem.class.php @@ -28,489 +28,518 @@ * ------------------------------------------------------------------------- */ -class PluginTagTagItem extends CommonDBRelation { - - // From CommonDBRelation - static public $itemtype_1 = 'PluginTagTag'; - static public $items_id_1 = 'plugin_tag_tags_id'; - static public $take_entity_1 = true; - - static public $itemtype_2 = 'itemtype'; - static public $items_id_2 = 'items_id'; - static public $take_entity_2 = false; - - - public static function getTypeName($nb = 1) { - return PluginTagTag::getTypeName($nb); - } - - public static function install(Migration $migration) { - global $DB; - - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - - $table = getTableForItemType(__CLASS__); - - if (!$DB->tableExists($table)) { - $query = "CREATE TABLE IF NOT EXISTS `$table` ( - `id` INT {$default_key_sign} NOT NULL AUTO_INCREMENT, - `plugin_tag_tags_id` INT {$default_key_sign} NOT NULL DEFAULT '0', - `items_id` INT {$default_key_sign} NOT NULL DEFAULT '1', - `itemtype` VARCHAR(255) NOT NULL DEFAULT '', - PRIMARY KEY (`id`), - UNIQUE INDEX `unicity` (`itemtype`, `items_id`, `plugin_tag_tags_id`) - ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->queryOrDie($query); - } - - // fix indexes - $migration->dropKey($table, 'name'); - $migration->addKey($table, - ['items_id', 'itemtype', 'plugin_tag_tags_id'], - 'unicity', - 'UNIQUE INDEX'); - $migration->migrationOneTable($table); - - return true; - } - - public static function uninstall() { - global $DB; - - $migration = new Migration(PLUGIN_TAG_VERSION); - $migration->dropTable(getTableForItemType(__CLASS__)); - } - - /** - * Display the list of available itemtype - * - * @param PluginTagTag $tag - * @return boolean - */ - static function showForTag(PluginTagTag $tag) { - global $DB, $CFG_GLPI; - - $instID = $tag->fields['id']; - if (!$tag->can($instID, READ)) { - return false; - } - - $canedit = $tag->can($instID, UPDATE); - $table = getTableForItemType(__CLASS__); - - $it = $DB->request([ - 'SELECT' => ['itemtype'], - 'DISTINCT' => true, - 'FROM' => $table, - 'WHERE' => ['plugin_tag_tags_id' => $instID] - ]); - $result = []; - foreach ($it as $data) { - $result[] = $data; - } - - $it2 = $DB->request([ - 'SELECT' => ['itemtype', 'items_id'], - 'FROM' => $table, - 'WHERE' => ['plugin_tag_tags_id' => $instID] - ]); - $result = []; - foreach ($it2 as $data) { - $result2[] = $data; - } - - $number = count($result); - $rand = mt_rand(); - - if ($canedit) { - echo "
"; - echo ""; - - echo "
"; + echo ''; + echo "
"; + echo ""; + echo "
"; + Html::showColorField('color', ['value' => $this->fields['color'] ?: '#DDDDDD']); + echo "
"; + // show an hidden input to permist deletion of all values + echo Html::hidden("type_menu"); + + // retrieve tags elements and existing values + $type_menu_elements = []; + foreach ($CFG_GLPI['plugin_tag_itemtypes'] as $group_label => $group_values) { + foreach ($group_values as $itemtype) { + $type_menu_elements[$group_label][$itemtype] = $itemtype::getTypeName(); } - } - } + } + $type_menu_values = !empty($this->fields['type_menu']) ? json_decode($this->fields['type_menu']) : []; + + // show the multiple dropdown + Dropdown::showFromArray( + "type_menu", + $type_menu_elements, + [ + 'values' => $type_menu_values, + 'multiple' => 'multiples' + ] + ); + + echo "
"; - echo ""; - - if (!empty($tag->fields['type_menu'])) { - $itemtypes_to_show = json_decode($tag->fields['type_menu']); - } else { - $itemtypes_to_show = []; - foreach ($CFG_GLPI['plugin_tag_itemtypes'] as $menu_entry) { - foreach ($menu_entry as $default_itemtype) { - array_push($itemtypes_to_show, $default_itemtype); - } +class PluginTagTagItem extends CommonDBRelation +{ + // From CommonDBRelation + public static $itemtype_1 = 'PluginTagTag'; + public static $items_id_1 = 'plugin_tag_tags_id'; + public static $take_entity_1 = true; + + public static $itemtype_2 = 'itemtype'; + public static $items_id_2 = 'items_id'; + public static $take_entity_2 = false; + + + public static function getTypeName($nb = 1) + { + return PluginTagTag::getTypeName($nb); + } + + public static function install(Migration $migration) + { + /** @var DBmysql $DB */ + global $DB; + + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + + $table = getTableForItemType(__CLASS__); + + if (!$DB->tableExists($table)) { + $query = <<doQueryOrDie($query); + } else { + /** @phpstan-ignore-next-line */ + $DB->queryOrDie($query); } - } - echo ""; - - echo "
".__('Add an item')."
"; - Dropdown::showSelectItemFromItemtypes(['itemtypes' => $itemtypes_to_show, - 'entity_restrict' - => ($tag->fields['is_recursive'] - ?getSonsOf('glpi_entities', - $tag->fields['entities_id']) - :$tag->fields['entities_id']), - 'checkright' => true]); - echo ""; - echo ""; - echo ""; - echo "
"; - Html::closeForm(); - echo ""; - } - - echo "
"; - if ($canedit && $number) { - Html::openMassiveActionsForm('mass'.__CLASS__.$rand); - - $massiveactionparams['specific_actions'] - = [ 'MassiveAction:purge' - => _x('button', 'Delete permanently the relation with selected elements')]; - - Html::showMassiveActions($massiveactionparams); - } - echo ""; - echo ""; - - if ($canedit && $number) { - echo ""; - } - - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - - for ($i=0; $i < $number; $i++) { - $itemtype = $result[$i]['itemtype']; - if (!($item = getItemForItemtype($itemtype))) { - continue; - } - $item_id = $result2[$i]['items_id']; - - if ($item->canView()) { - $column = (strtolower(substr($itemtype, 0, 6)) == "device") ? "designation" : "name"; - - // For rules itemtypes (example : ruledictionnaryphonemodel) - if (strtolower(substr($itemtype, 0, 4)) == 'rule' || $itemtype == "PluginResourcesRulechecklist") { - $itemtable = getTableForItemType('Rule'); + } + + // fix indexes + $migration->dropKey($table, 'name'); + $migration->addKey( + $table, + ['items_id', 'itemtype', 'plugin_tag_tags_id'], + 'unicity', + 'UNIQUE INDEX' + ); + $migration->migrationOneTable($table); + + return true; + } + + public static function uninstall() + { + $migration = new Migration(PLUGIN_TAG_VERSION); + $migration->dropTable(getTableForItemType(__CLASS__)); + } + + /** + * Display the list of available itemtype + * + * @param PluginTagTag $tag + * @return boolean + */ + public static function showForTag(PluginTagTag $tag) + { + /** + * @var DBmysql $DB + * @var array $CFG_GLPI + */ + global $DB, $CFG_GLPI; + + $instID = $tag->fields['id']; + if (!$tag->can($instID, READ)) { + return false; + } + + $canedit = $tag->can($instID, UPDATE); + $table = getTableForItemType(__CLASS__); + + $it = $DB->request([ + 'SELECT' => ['itemtype'], + 'DISTINCT' => true, + 'FROM' => $table, + 'WHERE' => ['plugin_tag_tags_id' => $instID] + ]); + $result = []; + foreach ($it as $data) { + $result[] = $data; + } + + $it2 = $DB->request([ + 'SELECT' => ['itemtype', 'items_id'], + 'FROM' => $table, + 'WHERE' => ['plugin_tag_tags_id' => $instID] + ]); + $result2 = []; + foreach ($it2 as $data) { + $result2[] = $data; + } + + $number = count($result); + $rand = mt_rand(); + + if ($canedit) { + echo "
"; + echo ""; + + echo "
" . Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand) . "" . __('Type') . "" . __('Name') . "" . __('Entity') . "" . __('Serial number') . "" . __('Inventory number') . "
"; + echo ""; + + if (!empty($tag->fields['type_menu'])) { + $itemtypes_to_show = json_decode($tag->fields['type_menu']); } else { - $itemtable = getTableForItemType($itemtype); + $itemtypes_to_show = []; + foreach ($CFG_GLPI['plugin_tag_itemtypes'] as $menu_entry) { + foreach ($menu_entry as $default_itemtype) { + array_push($itemtypes_to_show, $default_itemtype); + } + } } - - $criteria = [ - 'SELECT' => [ - $itemtable . '.*', - 'glpi_plugin_tag_tagitems.id AS IDD', - ], - 'FROM' => 'glpi_plugin_tag_tagitems', - 'INNER JOIN' => [ - $itemtable => [ - 'ON' => [ - $itemtable => 'id', - 'glpi_plugin_tag_tagitems' => 'items_id', - [ - 'AND' => [ - 'glpi_plugin_tag_tagitems.itemtype' => $itemtype - ] - ] - ] - ], - ], - 'WHERE' => [ - 'glpi_plugin_tag_tagitems.plugin_tag_tags_id' => $instID, - ] + getEntitiesRestrictCriteria($itemtable, '', '', $item->maybeRecursive()), - 'ORDERBY' => [ - $itemtable . '.' . $column, - ], + echo ""; + + echo "
" . __('Add an item') . "
"; + Dropdown::showSelectItemFromItemtypes([ + 'itemtypes' => $itemtypes_to_show, + 'entity_restrict' => $tag->fields['is_recursive'] + ? getSonsOf('glpi_entities', $tag->fields['entities_id']) + : $tag->fields['entities_id'], + 'checkright' => true + ]); + echo ""; + echo ""; + echo ""; + echo "
"; + Html::closeForm(); + echo "
"; + } + + echo "
"; + if ($canedit && $number) { + Html::openMassiveActionsForm('mass' . __CLASS__ . $rand); + + $massiveactionparams['specific_actions'] = [ + 'MassiveAction:purge' => _x('button', 'Delete permanently the relation with selected elements') ]; - if ($item->maybeTemplate()) { - $criteria['WHERE'][$itemtable . '.is_template'] = 0; + Html::showMassiveActions($massiveactionparams); + } + echo ""; + echo ""; + + if ($canedit && $number) { + echo ""; + } + + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + + for ($i = 0; $i < $number; $i++) { + $itemtype = $result[$i]['itemtype']; + if (!($item = getItemForItemtype($itemtype))) { + continue; } - - switch ($itemtype) { - case 'KnowbaseItem': - $criteria['SELECT'][] = new QueryExpression('-1 AS ' . $DB::quoteName('entity')); - $visibility_crit = KnowbaseItem::getVisibilityCriteria(); - if (array_key_exists('LEFT JOIN', $visibility_crit) - && !empty($visibility_crit['LEFT JOIN'])) { - $criteria['LEFT JOIN'] = $visibility_crit['LEFT JOIN']; - } - break; - case 'Profile': - case 'RSSFeed': - case 'Reminder': - case 'Entity': - //Possible to add (in code) condition to visibility : - $criteria['SELECT'][] = new QueryExpression('-1 AS ' . $DB::quoteName('entity')); - break; - default: - $obj = new $itemtype(); - $obj->getFromDB($item_id); - - if (isset($obj->fields['entities_id'])) { - $criteria['SELECT'][] = 'glpi_entities.id AS entity'; - $criteria['LEFT JOIN'] = [ - 'glpi_entities' => [ - 'ON' => [ - 'glpi_entities' => 'id', - $itemtable => 'entities_id', - ] + $item_id = $result2[$i]['items_id']; + + if ($item->canView()) { + $column = (strtolower(substr($itemtype, 0, 6)) == "device") ? "designation" : "name"; + + // For rules itemtypes (example : ruledictionnaryphonemodel) + if (strtolower(substr($itemtype, 0, 4)) == 'rule' || $itemtype == "PluginResourcesRulechecklist") { + $itemtable = getTableForItemType('Rule'); + } else { + $itemtable = getTableForItemType($itemtype); + } + + $criteria = [ + 'SELECT' => [ + $itemtable . '.*', + 'glpi_plugin_tag_tagitems.id AS IDD', + ], + 'FROM' => 'glpi_plugin_tag_tagitems', + 'INNER JOIN' => [ + $itemtable => [ + 'ON' => [ + $itemtable => 'id', + 'glpi_plugin_tag_tagitems' => 'items_id', + [ + 'AND' => [ + 'glpi_plugin_tag_tagitems.itemtype' => $itemtype + ] + ] + ] ], - ]; - array_unshift($criteria['ORDERBY'], 'glpi_entities.completename'); - } else { - $criteria['SELECT'][] = new QueryExpression('-1 AS ' . $DB::quoteName('entity')); - } - break; - } - - $linked_iterator = $DB->request($criteria); - - foreach ($linked_iterator as $data) { - - if ($itemtype == 'Softwarelicense') { - $soft = new Software(); - $soft->getFromDB($data['softwares_id']); - $data["name"] .= ' - ' . $soft->getName(); //This add name of software - } else if ($itemtype == "PluginResourcesResource") { - $data["name"] = formatUserName($data["id"], "", $data["name"], - $data["firstname"]); - } - - $linkname = $data[$column]; - - if ($_SESSION["glpiis_ids_visible"] || empty($data[$column])) { - $linkname = sprintf(__('%1$s (%2$s)'), $linkname, $data["id"]); - } - - $name = "".$linkname.""; - - if ($itemtype == 'PluginProjetProjet' - || $itemtype == 'PluginResourcesResource') { - $pieces = preg_split('/(?=[A-Z])/', $itemtype); - $plugin_name = $pieces[2]; - - $datas = ["entities_id" => $data["entity"], + ], + 'WHERE' => [ + 'glpi_plugin_tag_tagitems.plugin_tag_tags_id' => $instID, + ] + getEntitiesRestrictCriteria($itemtable, '', '', $item->maybeRecursive()), + 'ORDERBY' => [ + $itemtable . '.' . $column, + ], + ]; + + if ($item->maybeTemplate()) { + $criteria['WHERE'][$itemtable . '.is_template'] = 0; + } + + switch ($itemtype) { + case 'KnowbaseItem': + $criteria['SELECT'][] = new QueryExpression('-1 AS ' . $DB::quoteName('entity')); + $visibility_crit = KnowbaseItem::getVisibilityCriteria(); + if ( + array_key_exists('LEFT JOIN', $visibility_crit) + && !empty($visibility_crit['LEFT JOIN']) + ) { + $criteria['LEFT JOIN'] = $visibility_crit['LEFT JOIN']; + } + break; + case 'Profile': + case 'RSSFeed': + case 'Reminder': + case 'Entity': + //Possible to add (in code) condition to visibility : + $criteria['SELECT'][] = new QueryExpression('-1 AS ' . $DB::quoteName('entity')); + break; + default: + $obj = new $itemtype(); + $obj->getFromDB($item_id); + + if (isset($obj->fields['entities_id'])) { + $criteria['SELECT'][] = 'glpi_entities.id AS entity'; + $criteria['LEFT JOIN'] = [ + 'glpi_entities' => [ + 'ON' => [ + 'glpi_entities' => 'id', + $itemtable => 'entities_id', + ] + ], + ]; + array_unshift($criteria['ORDERBY'], 'glpi_entities.completename'); + } else { + $criteria['SELECT'][] = new QueryExpression('-1 AS ' . $DB::quoteName('entity')); + } + break; + } + + $linked_iterator = $DB->request($criteria); + + foreach ($linked_iterator as $data) { + if ($itemtype == 'Softwarelicense') { + $soft = new Software(); + $soft->getFromDB($data['softwares_id']); + $data["name"] .= ' - ' . $soft->getName(); //This add name of software + } else if ($itemtype == "PluginResourcesResource") { + $data["name"] = formatUserName( + $data["id"], + "", + $data["name"], + $data["firstname"] + ); + } + + $linkname = $data[$column]; + + if ($_SESSION["glpiis_ids_visible"] || empty($data[$column])) { + $linkname = sprintf(__('%1$s (%2$s)'), $linkname, $data["id"]); + } + + $name = "" . $linkname . ""; + + if ( + $itemtype == 'PluginProjetProjet' + || $itemtype == 'PluginResourcesResource' + ) { + $pieces = preg_split('/(?=[A-Z])/', $itemtype); + $plugin_name = $pieces[2]; + + $datas = ["entities_id" => $data["entity"], "ITEM_0" => $data["name"], "ITEM_0_2" => $data["id"], "id" => $data["id"], - "META_0" => $data["name"]]; //for PluginResourcesResource - - if (isset($data["is_recursive"])) { - $datas["is_recursive"] = $data["is_recursive"]; - } - - Plugin::load(strtolower($plugin_name), true); - $function_giveitem = 'plugin_'.strtolower($plugin_name).'_giveItem'; - if (function_exists($function_giveitem)) { // For security - $name = call_user_func($function_giveitem, $itemtype, 1, $datas, 0); - } - - } - - echo ""; - - if ($canedit) { - echo ""; - } - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; + "META_0" => $data["name"] + ]; //for PluginResourcesResource + + if (isset($data["is_recursive"])) { + $datas["is_recursive"] = $data["is_recursive"]; + } + + Plugin::load(strtolower($plugin_name), true); + $function_giveitem = 'plugin_' . strtolower($plugin_name) . '_giveItem'; + if (function_exists($function_giveitem)) { // For security + $name = call_user_func($function_giveitem, $itemtype, 1, $datas, 0); + } + } + + echo ""; + + if ($canedit) { + echo ""; + } + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + } } - } - } - echo "
" . Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand) . "" . __('Type') . "" . __('Name') . "" . __('Entity') . "" . __('Serial number') . "" . __('Inventory number') . "
"; - if ($item->canUpdate()) { - Html::showMassiveActionCheckBox(__CLASS__, $data["IDD"]); - } - echo ""; - - // Show plugin name (is to delete remove any ambiguity) : - $pieces = preg_split('/(?=[A-Z])/', $itemtype); - if ($pieces[1] == 'Plugin') { - $plugin_name = $pieces[2]; - if (function_exists("plugin_version_".$plugin_name)) { // For security - $tab = call_user_func("plugin_version_".$plugin_name); - echo $tab["name"]." : "; - } - } - - echo $item->getTypeName(1)."".$name.""; - - $entity = $data['entity']; - - //for Plugins : - if ($data["entity"] == -1) { - $item->getFromDB($data['id']); - if (isset($item->fields["entities_id"])) { - $entity = $item->fields["entities_id"]; - } - } - echo Dropdown::getDropdownName("glpi_entities", $entity); - - echo "". - (isset($data["serial"]) ? "".$data["serial"]."" :"-")."". - (isset($data["otherserial"]) ? "".$data["otherserial"]."" :"-")."
"; + if ($item->canUpdate()) { + Html::showMassiveActionCheckBox(__CLASS__, $data["IDD"]); + } + echo ""; + + // Show plugin name (is to delete remove any ambiguity) : + $pieces = preg_split('/(?=[A-Z])/', $itemtype); + if ($pieces[1] == 'Plugin') { + $plugin_name = $pieces[2]; + if (function_exists("plugin_version_" . $plugin_name)) { // For security + $tab = call_user_func("plugin_version_" . $plugin_name); + echo $tab["name"] . " : "; + } + } + + echo $item->getTypeName(1) . "" . $name . ""; + + $entity = $data['entity']; + + //for Plugins : + if ($data["entity"] == -1) { + $item->getFromDB($data['id']); + if (isset($item->fields["entities_id"])) { + $entity = $item->fields["entities_id"]; + } + } + echo Dropdown::getDropdownName("glpi_entities", $entity); + + echo "" . (isset($data["serial"]) ? "" . $data["serial"] . "" : "-") . "" . (isset($data["otherserial"]) ? "" . $data["otherserial"] . "" : "-") . "
"; - if ($canedit && $number) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - echo "
"; - - } - - /** - * Add tags to an item - * - * @param CommonDBTM $item - * @param bool $delete_existing_tags - * - * @return boolean - */ - static function updateItem(CommonDBTM $item, bool $delete_existing_tags = true) { - - if ($item->getID() - && !isset($item->input["_plugin_tag_tag_process_form"]) - && !( - // Always trigger on newly created tickets, as they may come from - // the mail collector which wont set the _plugin_tag_tag_process_form - // flag - $item::getType() == Ticket::getType() - && $item->fields['date_creation'] == $_SESSION['glpi_currenttime'] - ) - ) { - return true; - } - - // instanciate needed objects - $tag = new PluginTagTag(); - $tag_item = new self(); - - if (!$tag::canUpdate()) { - return true; - } - - // create new values - $tag_values = !empty($item->input["_plugin_tag_tag_values"]) + } + echo ""; + if ($canedit && $number) { + $massiveactionparams['ontop'] = false; + Html::showMassiveActions($massiveactionparams); + Html::closeForm(); + } + echo ""; + + return true; + } + + /** + * Add tags to an item + * + * @param CommonDBTM $item + * @param bool $delete_existing_tags + * + * @return boolean + */ + public static function updateItem(CommonDBTM $item, bool $delete_existing_tags = true) + { + + if ( + $item->getID() + && !isset($item->input["_plugin_tag_tag_process_form"]) + && !( + // Always trigger on newly created tickets, as they may come from + // the mail collector which wont set the _plugin_tag_tag_process_form + // flag + $item::getType() == Ticket::getType() + && $item->fields['date_creation'] == $_SESSION['glpi_currenttime'] + ) + ) { + return true; + } + + // instanciate needed objects + $tag = new PluginTagTag(); + $tag_item = new self(); + + if (!$tag::canUpdate()) { + return true; + } + + // create new values + $tag_values = !empty($item->input["_plugin_tag_tag_values"]) ? $item->input["_plugin_tag_tag_values"] : []; - if (!is_array($tag_values)) { - // Business rule engine will add value as a unique string that must be converted to array. - $tag_values = [$tag_values]; - } - foreach ($tag_values as &$tag_value) { - if (strpos($tag_value, "newtag_") !== false) { - $tag_value = str_replace("newtag_", "", $tag_value); - $tag_value = $tag->add([ - 'name' => $tag_value, + if (!is_array($tag_values)) { + // Business rule engine will add value as a unique string that must be converted to array. + $tag_values = [$tag_values]; + } + foreach ($tag_values as &$tag_value) { + if (strpos($tag_value, "newtag_") !== false) { + $tag_value = str_replace("newtag_", "", $tag_value); + $tag_value = $tag->add([ + 'name' => $tag_value, + ]); + } + } + + // process actions + $existing_tags_ids = array_column( + $tag_item->find(['items_id' => $item->getID(), 'itemtype' => $item->getType()]), + 'plugin_tag_tags_id' + ); + $added_tags_ids = array_diff($tag_values, $existing_tags_ids); + $removed_tags_ids = $delete_existing_tags ? array_diff($existing_tags_ids, $tag_values) : []; + + // link tags with the current item + foreach ($added_tags_ids as $tag_id) { + $tag_item->add([ + 'plugin_tag_tags_id' => $tag_id, + 'items_id' => $item->getID(), + 'itemtype' => $item->getType() + ]); + } + foreach ($removed_tags_ids as $tag_id) { + $tag_item->deleteByCriteria([ + 'plugin_tag_tags_id' => $tag_id, + "items_id" => $item->getID(), + "itemtype" => $item->getType(), ]); - } - } - - // process actions - $existing_tags_ids = array_column( - $tag_item->find(['items_id' => $item->getID(), 'itemtype' => $item->getType()]), - 'plugin_tag_tags_id' - ); - $added_tags_ids = array_diff($tag_values, $existing_tags_ids); - $removed_tags_ids = $delete_existing_tags ? array_diff($existing_tags_ids, $tag_values) : []; - - // link tags with the current item - foreach ($added_tags_ids as $tag_id) { - $tag_item->add([ - 'plugin_tag_tags_id' => $tag_id, - 'items_id' => $item->getID(), - 'itemtype' => $item->getType() - ]); - } - foreach ($removed_tags_ids as $tag_id) { - $tag_item->deleteByCriteria([ - 'plugin_tag_tags_id' => $tag_id, + } + + return true; + } + + /** + * Delete all tags associated to an item + * + * @param CommonDBTM $item + * @return boolean + */ + public static function purgeItem(CommonDBTM $item) + { + $tagitem = new self(); + return $tagitem->deleteByCriteria([ "items_id" => $item->getID(), "itemtype" => $item->getType(), - ]); - } - - return true; - } - - /** - * Delete all tags associated to an item - * - * @param CommonDBTM $item - * @return boolean - */ - static function purgeItem(CommonDBTM $item) { - $tagitem = new self(); - return $tagitem->deleteByCriteria([ - "items_id" => $item->getID(), - "itemtype" => $item->getType(), - ]); - } - - static function showMassiveActionsSubForm(MassiveAction $ma) { - - $itemtypes = array_keys($ma->items); - $itemtype = array_shift($itemtypes); - - switch ($ma->getAction()) { - case 'addTag': - case 'removeTag': - PluginTagTag::showTagDropdown(['itemtype' => $itemtype]); - echo Html::submit(_sx('button', 'Save')); - return true; - } - return parent::showMassiveActionsSubForm($ma); - } - - static function processMassiveActionsForOneItemtype(MassiveAction $ma, - CommonDBTM $item, - array $ids) { - $input = $ma->getInput(); - switch ($ma->getAction()) { - case "addTag": - foreach ($ma->items as $itemtype => $items) { - $object = new $itemtype; - foreach ($items as $items_id) { - $object->fields['id'] = $items_id; - $object->input = $input; - if (self::updateItem($object, false)) { - $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_OK); - } else { - $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_KO); - $ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION)); - } - } - } - break; - case "removeTag": - $tagitem = new self; - foreach ($ma->items as $itemtype => $items) { - $object = new $itemtype; - foreach ($items as $items_id) { - if ($tagitem->deleteByCriteria([ - 'items_id' => $items_id, - 'itemtype' => $itemtype, - 'plugin_tag_tags_id' => $input['_plugin_tag_tag_values'], - ])) { - $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_OK); - } else { - $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_KO); - $ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION)); - } - } - } - break; - } - } - + ]); + } + + public static function showMassiveActionsSubForm(MassiveAction $ma) + { + + $itemtypes = array_keys($ma->items); + $itemtype = array_shift($itemtypes); + + switch ($ma->getAction()) { + case 'addTag': + case 'removeTag': + PluginTagTag::showTagDropdown(['itemtype' => $itemtype]); + echo Html::submit(_sx('button', 'Save')); + return true; + } + return parent::showMassiveActionsSubForm($ma); + } + + public static function processMassiveActionsForOneItemtype( + MassiveAction $ma, + CommonDBTM $item, + array $ids + ) { + $input = $ma->getInput(); + switch ($ma->getAction()) { + case "addTag": + foreach ($ma->items as $itemtype => $items) { + $object = new $itemtype(); + foreach ($items as $items_id) { + $object->fields['id'] = $items_id; + $object->input = $input; + if (self::updateItem($object, false)) { + $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_OK); + } else { + $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_KO); + $ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION)); + } + } + } + break; + case "removeTag": + $tagitem = new self(); + foreach ($ma->items as $itemtype => $items) { + $object = new $itemtype(); + foreach ($items as $items_id) { + if ( + $tagitem->deleteByCriteria([ + 'items_id' => $items_id, + 'itemtype' => $itemtype, + 'plugin_tag_tags_id' => $input['_plugin_tag_tag_values'], + ]) + ) { + $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_OK); + } else { + $ma->itemDone($item->getType(), $items_id, MassiveAction::ACTION_KO); + $ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION)); + } + } + } + break; + } + } } diff --git a/js/common.js b/js/common.js index 263a98a..95ba833 100644 --- a/js/common.js +++ b/js/common.js @@ -26,59 +26,63 @@ * ------------------------------------------------------------------------- */ +/* global escapeMarkupText */ + var rgb2hex = function(rgb){ - rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); - return (rgb && rgb.length === 4) ? "#" + - ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) + - ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) + - ("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : ''; + rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); + return (rgb && rgb.length === 4) + ? "#" + + ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) + + ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) + + ("0" + parseInt(rgb[3],10).toString(16)).slice(-2) + : ''; }; var idealTextColor = function(hexTripletColor) { - var nThreshold = 105; - if (hexTripletColor.indexOf('rgb') != -1) { - hexTripletColor = rgb2hex(hexTripletColor); - } - hexTripletColor = hexTripletColor.replace('#',''); - var components = { - R: parseInt(hexTripletColor.substring(0, 2), 16), - G: parseInt(hexTripletColor.substring(2, 4), 16), - B: parseInt(hexTripletColor.substring(4, 6), 16) - }; - var bgDelta = (components.R * 0.299) + (components.G * 0.587) + (components.B * 0.114); - return ((255 - bgDelta) < nThreshold) ? "#000000" : "#E6E6E6"; -} + var nThreshold = 105; + if (hexTripletColor.indexOf('rgb') != -1) { + hexTripletColor = rgb2hex(hexTripletColor); + } + hexTripletColor = hexTripletColor.replace('#',''); + var components = { + R: parseInt(hexTripletColor.substring(0, 2), 16), + G: parseInt(hexTripletColor.substring(2, 4), 16), + B: parseInt(hexTripletColor.substring(4, 6), 16) + }; + var bgDelta = (components.R * 0.299) + (components.G * 0.587) + (components.B * 0.114); + return ((255 - bgDelta) < nThreshold) ? "#000000" : "#E6E6E6"; +}; var formatOptionSelection = function(option, container) { - var color = (typeof option.color !== 'undefined' && option.color !== '') - ? option.color - : '#DDDDDD'; - var invertedcolor = idealTextColor(color); + var color = (typeof option.color !== 'undefined' && option.color !== '') + ? option.color + : '#DDDDDD'; + var invertedcolor = idealTextColor(color); - $(container) - .css("background-color", color) - .css("border-color", invertedcolor) - .css("color", invertedcolor) - .children('.select2-selection__choice__remove') - .css("color", invertedcolor); + $(container) + .css("background-color", color) + .css("border-color", invertedcolor) + .css("color", invertedcolor) + .children('.select2-selection__choice__remove') + .css("color", invertedcolor); - var _elt = $(''); - _elt.html(escapeMarkupText(option.text)); - return _elt; + var _elt = $(''); + _elt.html(escapeMarkupText(option.text)); + return _elt; }; var formatOptionResult = function(option) { - var color = (typeof option.color !== 'undefined' && option.color !== '') - ? option.color - : '#DDDDDD'; - var invertedcolor = idealTextColor(color); + var color = (typeof option.color !== 'undefined' && option.color !== '') + ? option.color + : '#DDDDDD'; + var invertedcolor = idealTextColor(color); - var template = ` - - ${option.text} - + var template = ` + + ${option.text} + `; - return $(template); + return $(template); }; diff --git a/js/entity.js b/js/entity.js index b476ab7..e5bcef3 100644 --- a/js/entity.js +++ b/js/entity.js @@ -40,29 +40,30 @@ $(function() { }); var setEntityTag = function() { - $('.entity-name, .entity-badge, .glpi-badge') - .each(function() { + $('.entity-name, .entity-badge, .glpi-badge').each( + function() { var entity_element = $(this); - entity_name = entity_element.attr('title'); + var entity_name = entity_element.attr('title'); if (entity_element.hasClass('tags_already_set')) { return; // consider this return as a continue in a jquery each } entity_element.addClass('tags_already_set'); - + $.ajax({ url: CFG_GLPI.root_doc + '/' + GLPI_PLUGINS_PATH.tag + '/ajax/get_entity_tags.php', data: { - 'name': entity_name, + 'name': entity_name, }, success: function(response) { - entity_element.html(function() { - if ($(this).html().indexOf(')') > 0) { - return $(this).html().replace(/\)$/, response + ')'); - } else { - return $(this).html() + response; - } - }); + entity_element.html(function() { + if ($(this).html().indexOf(')') > 0) { + return $(this).html().replace(/\)$/, response + ')'); + } else { + return $(this).html() + response; + } + }); } }); - }); + } + ); }; diff --git a/js/kanban.js b/js/kanban.js index c64d9db..6a285c3 100644 --- a/js/kanban.js +++ b/js/kanban.js @@ -30,61 +30,61 @@ * Kanban plugin for Tags */ $(document).on('kanban:refresh_tokenizer', (e, tokenizer) => { - // Refresh tokenizer - tokenizer.setAutocomplete('tagged', ["true", "false"]); + // Refresh tokenizer + tokenizer.setAutocomplete('tagged', ["true", "false"]); }); $(document).on('kanban:filter', (e, data) => { - const filters = data.filters; + const filters = data.filters; - $(data.kanban_element + ' .kanban-item').each(function(i, item) { - const card = $(item); + $(data.kanban_element + ' .kanban-item').each(function(i, item) { + const card = $(item); - let shown = true; - const tags = card.data('tags') ?? {}; - //lowercase tags - const tags_lower = Object.values(tags).map(tag => tag.toLowerCase()); - const tagged = tags_lower.length > 0; + let shown = true; + const tags = card.data('tags') || {}; + //lowercase tags + const tags_lower = Object.values(tags).map(tag => tag.toLowerCase()); + const tagged = tags_lower.length > 0; - if (filters.tagged !== undefined) { - const tagged_term = filters.tagged.term.toLowerCase() === 'false' ? false : true; - if ((tagged !== tagged_term) !== filters.tagged.exclusion) { - shown = false; - } - } + if (filters.tagged !== undefined) { + const tagged_term = filters.tagged.term.toLowerCase() === 'false' ? false : true; + if ((tagged !== tagged_term) !== filters.tagged.exclusion) { + shown = false; + } + } - if (filters.tag !== undefined) { - if (!tags_lower.includes(filters.tag.term.toLowerCase()) !== filters.tag.exclusion) { - shown = false; - } - } + if (filters.tag !== undefined) { + if (!tags_lower.includes(filters.tag.term.toLowerCase()) !== filters.tag.exclusion) { + shown = false; + } + } - if (!shown) { - card.addClass('filtered-out'); - } - }); + if (!shown) { + card.addClass('filtered-out'); + } + }); }); $(document).on('click', '.kanban .kanban-item .kanban-plugin-content .tag_choice', (e) => { - const clicked_tag = $(e.currentTarget); - const kanban_obj = clicked_tag.closest('.kanban').data('js_class'); - const tag_value = clicked_tag.text(); - // Quote tag_value if it contains spaces + const clicked_tag = $(e.currentTarget); + const kanban_obj = clicked_tag.closest('.kanban').data('js_class'); + const tag_value = clicked_tag.text(); + // Quote tag_value if it contains spaces const tag_value_quoted = tag_value.includes(' ') ? `"${tag_value}"` : tag_value; - /** @type {SearchInput} */ - const filter_input = kanban_obj.filter_input; - const token = { - term: tag_value_quoted, - tag: 'tag', - raw: 'tag:' + tag_value_quoted, - }; - // This param should be a SearchToken but we cannot import in this file - const new_filter_node = filter_input.tokenToTagHtml(token); - filter_input.displayed_input.find('.search-input-tag[data-tag="tag"]').remove(); - // Insert new filter node before the ".search-input-tag-input" node - const last_inserted = $(new_filter_node).insertBefore(filter_input.displayed_input.find('.search-input-tag-input')); - last_inserted.data('token', token); - // Refresh filters - filter_input.displayed_input.trigger('result_change'); - kanban_obj.filter(); + /** @type {SearchInput} */ + const filter_input = kanban_obj.filter_input; + const token = { + term: tag_value_quoted, + tag: 'tag', + raw: 'tag:' + tag_value_quoted, + }; + // This param should be a SearchToken but we cannot import in this file + const new_filter_node = filter_input.tokenToTagHtml(token); + filter_input.displayed_input.find('.search-input-tag[data-tag="tag"]').remove(); + // Insert new filter node before the ".search-input-tag-input" node + const last_inserted = $(new_filter_node).insertBefore(filter_input.displayed_input.find('.search-input-tag-input')); + last_inserted.data('token', token); + // Refresh filters + filter_input.displayed_input.trigger('result_change'); + kanban_obj.filter(); }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b9da687 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4576 @@ +{ + "name": "@glpi-plugins/tag", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@glpi-plugins/tag", + "license": "GPL-2.0", + "devDependencies": { + "@stylistic/eslint-plugin-js": "^1.0.1", + "eslint": "^8.53.0", + "stylelint": "^15.11.0", + "stylelint-config-standard": "^34.0.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.2.tgz", + "integrity": "sha512-sLYGdAdEY2x7TSw9FtmdaTrh2wFtRJO5VMbBrA8tEqEod7GEggFmxTSK9XqExib3yMuYNcvcTdCZIP6ukdjAIA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.2.1" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.1.tgz", + "integrity": "sha512-Zmsf2f/CaEPWEVgw29odOj+WEVoiJy9s9NOv5GgNY9mZ1CZ7394By6wONrONrTsnNDv6F9hR02nvFihrGVGHBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.5.tgz", + "integrity": "sha512-IxVBdYzR8pYe89JiyXQuYk4aVVoCPhMJkz6ElRwlVysjwURTsTk/bmY/z4FfeRE+CRBMlykPwXEVUg8lThv7AQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz", + "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@stylistic/eslint-plugin-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.0.1.tgz", + "integrity": "sha512-SfJlEnmBowaWx9GyN/7vQ/7jQP2wVQe5CcaoVL6V5nmCWl9Q+VSeJPSBOjB7XOYSYL1HoEQsvA+8Hy7Zt2XrnA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "acorn": "^8.11.2", + "escape-string-regexp": "^4.0.0", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esutils": "^2.0.3", + "graphemer": "^1.4.0" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", + "dev": true, + "engines": { + "node": ">=12 || >=16" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "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/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz", + "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0", + "@csstools/media-query-list-parser": "^2.1.4", + "@csstools/selector-specificity": "^3.0.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.2.0", + "css-functions-list": "^3.2.1", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.1", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^7.0.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.29.0", + "mathml-tag-names": "^2.1.3", + "meow": "^10.1.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.28", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", + "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", + "dev": true, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "stylelint": "^15.10.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "34.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", + "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^13.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "stylelint": "^15.10.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.1.tgz", + "integrity": "sha512-uLfFktPmRetVCbHe5UPuekWrQ6hENufnA46qEGbfACkK5drjTTdQYUragRgMjHldcbYG+nslUerqMPjbBSHXjQ==", + "dev": true, + "dependencies": { + "flat-cache": "^3.1.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@csstools/css-parser-algorithms": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.2.tgz", + "integrity": "sha512-sLYGdAdEY2x7TSw9FtmdaTrh2wFtRJO5VMbBrA8tEqEod7GEggFmxTSK9XqExib3yMuYNcvcTdCZIP6ukdjAIA==", + "dev": true, + "requires": {} + }, + "@csstools/css-tokenizer": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.1.tgz", + "integrity": "sha512-Zmsf2f/CaEPWEVgw29odOj+WEVoiJy9s9NOv5GgNY9mZ1CZ7394By6wONrONrTsnNDv6F9hR02nvFihrGVGHBg==", + "dev": true + }, + "@csstools/media-query-list-parser": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.5.tgz", + "integrity": "sha512-IxVBdYzR8pYe89JiyXQuYk4aVVoCPhMJkz6ElRwlVysjwURTsTk/bmY/z4FfeRE+CRBMlykPwXEVUg8lThv7AQ==", + "dev": true, + "requires": {} + }, + "@csstools/selector-specificity": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz", + "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", + "dev": true, + "requires": {} + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.53.0.tgz", + "integrity": "sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@stylistic/eslint-plugin-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.0.1.tgz", + "integrity": "sha512-SfJlEnmBowaWx9GyN/7vQ/7jQP2wVQe5CcaoVL6V5nmCWl9Q+VSeJPSBOjB7XOYSYL1HoEQsvA+8Hy7Zt2XrnA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "acorn": "^8.11.2", + "escape-string-regexp": "^4.0.0", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esutils": "^2.0.3", + "graphemer": "^1.4.0" + } + }, + "@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "requires": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "requires": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "css-functions-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", + "dev": true + }, + "css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "requires": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.53.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.53.0.tgz", + "integrity": "sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.53.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "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" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "known-css-properties": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true + }, + "mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true + }, + "mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "requires": {} + }, + "postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "requires": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + } + } + }, + "redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "requires": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + } + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "requires": { + "min-indent": "^1.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "stylelint": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz", + "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", + "dev": true, + "requires": { + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0", + "@csstools/media-query-list-parser": "^2.1.4", + "@csstools/selector-specificity": "^3.0.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.2.0", + "css-functions-list": "^3.2.1", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.1", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^7.0.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.29.0", + "mathml-tag-names": "^2.1.3", + "meow": "^10.1.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.28", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "file-entry-cache": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.1.tgz", + "integrity": "sha512-uLfFktPmRetVCbHe5UPuekWrQ6hENufnA46qEGbfACkK5drjTTdQYUragRgMjHldcbYG+nslUerqMPjbBSHXjQ==", + "dev": true, + "requires": { + "flat-cache": "^3.1.1" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "stylelint-config-recommended": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", + "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", + "dev": true, + "requires": {} + }, + "stylelint-config-standard": { + "version": "34.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", + "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", + "dev": true, + "requires": { + "stylelint-config-recommended": "^13.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + } + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6ef7e4a --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "@glpi-plugins/tag", + "description": "Tag GLPI plugin", + "private": true, + "license": "GPL-2.0", + "devDependencies": { + "@stylistic/eslint-plugin-js": "^1.0.1", + "eslint": "^8.53.0", + "stylelint": "^15.11.0", + "stylelint-config-standard": "^34.0.0" + }, + "scripts": {} +} diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..bb158ef --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,21 @@ +parameters: + parallel: + maximumNumberOfProcesses: 2 + level: 1 + bootstrapFiles: + - ../../inc/based_config.php + paths: + - ajax + - front + - inc + - hook.php + - setup.php + excludePaths: + - inc/taginjection.class.php + scanDirectories: + - ../../inc + - ../../src + stubFiles: + - ../../stubs/glpi_constants.php +rules: + - GlpiProject\Tools\PHPStan\Rules\GlobalVarTypeRule diff --git a/setup.php b/setup.php index 4a49d4e..b2eaba3 100644 --- a/setup.php +++ b/setup.php @@ -30,7 +30,7 @@ use Glpi\Plugin\Hooks; -define ('PLUGIN_TAG_VERSION', '2.11.6'); +define('PLUGIN_TAG_VERSION', '2.11.6'); // Minimal GLPI version, inclusive define("PLUGIN_TAG_MIN_GLPI", "10.0.0"); @@ -43,107 +43,118 @@ * * @return void */ -function plugin_init_tag() { - global $PLUGIN_HOOKS, $UNINSTALL_TYPES, $CFG_GLPI; - - $PLUGIN_HOOKS['csrf_compliant']['tag'] = true; - - if (Plugin::isPluginActive("tag")) { - - // define list of itemtype which can be associated with tags - $CFG_GLPI['plugin_tag_itemtypes'] = [ - __('Assets') => ['Computer', 'Monitor', 'Software', 'NetworkEquipment', - 'Peripheral', 'Printer', 'CartridgeItem', 'ConsumableItem', - 'Phone', 'Enclosure', 'PDU', 'PassiveDCEquipment'], - __('Assistance') => ['Ticket', 'Problem', 'Change', 'TicketRecurrent', - 'TicketTemplate'], - __('Management') => ['Budget', 'Supplier', 'Contact', 'Contract', 'Document', - 'Line', 'Certificate', 'Appliance', 'Cluster', 'Domain'], - __('Tools') => ['Project', 'Reminder', 'RSSFeed', 'KnowbaseItem', 'ProjectTask'], - __('Administration') => ['User', 'Group', 'Entity', 'Profile'], - __('Setup') => ['SLA', 'SlaLevel', 'Link'], - ]; - - if (class_exists('Webhook')) { - $CFG_GLPI['plugin_tag_itemtypes'][__('Setup')][] = 'Webhook'; - } - - if (Plugin::isPluginActive('appliances')) { - $CFG_GLPI['plugin_tag_itemtypes'][__('Assets')][] = 'PluginAppliancesAppliance'; - } - - // Plugin Webapplication - if (Plugin::isPluginActive('webapplications')) { - $CFG_GLPI['plugin_tag_itemtypes'][__('Assets')][] = 'PluginWebapplicationsWebapplication'; - } - - // Plugin fusioninventory - if (Plugin::isPluginActive('fusioninventory')) { - $CFG_GLPI['plugin_tag_itemtypes'][__('FusionInventory')][] = 'PluginFusioninventoryTask'; - } - - // add link on plugin name in Configuration > Plugin - $PLUGIN_HOOKS['config_page']['tag'] = "front/tag.php"; - - // Wait all plugins are loaded to find the itemtype matching the current URL - $PLUGIN_HOOKS['post_init']['tag'] = 'plugin_tag_post_init'; - - // Plugin use specific massive actions - $PLUGIN_HOOKS['use_massive_action']['tag'] = true; - - // Plugin uninstall : after uninstall action - if (Plugin::isPluginActive("uninstall")) { - //to prevent null global variable load plugin if needed - if ($UNINSTALL_TYPES == null) { - Plugin::load('uninstall'); - } - foreach ($UNINSTALL_TYPES as $u_itemtype) { - $PLUGIN_HOOKS['plugin_uninstall_after']['tag'][$u_itemtype] = 'plugin_uninstall_after_tag'; - } - } - - // insert tag dropdown into all possible itemtypes - $location = Config::getConfigurationValues('plugin:Tag')['tags_location'] ?? 0; - if ($location === '1') { - $PLUGIN_HOOKS['post_item_form']['tag'] = ['PluginTagTag', 'showForItem']; - } else { - $PLUGIN_HOOKS['pre_item_form']['tag'] = ['PluginTagTag', 'showForItem']; - } - $PLUGIN_HOOKS['pre_kanban_content']['tag'] = ['PluginTagTag', 'preKanbanContent']; - $common_kanban_filters = [ - 'tag' => [ - 'description' => _x('filters', 'If the item has a tag', 'tag'), - 'supported_prefixes' => ['!'] - ], - 'tagged' => [ - 'description' => _x('filters', 'If the item is tagged', 'tag'), - 'supported_prefixes' => ['!'] - ] - ]; - $PLUGIN_HOOKS[Hooks::KANBAN_FILTERS]['tag'] = [ - 'Project' => $common_kanban_filters, - 'Ticket' => $common_kanban_filters, - 'Problem' => $common_kanban_filters, - 'Change' => $common_kanban_filters, - ]; - $PLUGIN_HOOKS[Hooks::KANBAN_ITEM_METADATA]['tag'] = ['PluginTagTag', 'kanbanItemMetadata']; - - // plugin datainjection - $PLUGIN_HOOKS['plugin_datainjection_populate']['tag'] = "plugin_datainjection_populate_tag"; - - // add needed javascript & css files - $PLUGIN_HOOKS['add_javascript']['tag'][] = 'js/common.js'; - $PLUGIN_HOOKS['add_javascript']['tag'][] = 'js/kanban.js'; - $PLUGIN_HOOKS['add_css']['tag'][] = 'css/tag.css'; - if (Session::isMultiEntitiesMode()) { - $PLUGIN_HOOKS['add_javascript']['tag'][] = 'js/entity.js'; - } - - Plugin::registerClass('PluginTagProfile', ['addtabon' => ['Profile']]); - Plugin::registerClass('PluginTagConfig', ['addtabon' => 'Config']); - - $PLUGIN_HOOKS['use_rules']['tag'] = ['RuleTicket']; - } +function plugin_init_tag() +{ + /** + * @var array $PLUGIN_HOOKS + * @var array $UNINSTALL_TYPES + * @var array $CFG_GLPI + */ + global $PLUGIN_HOOKS, $UNINSTALL_TYPES, $CFG_GLPI; + + $PLUGIN_HOOKS['csrf_compliant']['tag'] = true; + + if (Plugin::isPluginActive("tag")) { + // define list of itemtype which can be associated with tags + $CFG_GLPI['plugin_tag_itemtypes'] = [ + __('Assets') => [ + 'Computer', 'Monitor', 'Software', 'NetworkEquipment', + 'Peripheral', 'Printer', 'CartridgeItem', 'ConsumableItem', + 'Phone', 'Enclosure', 'PDU', 'PassiveDCEquipment' + ], + __('Assistance') => [ + 'Ticket', 'Problem', 'Change', 'TicketRecurrent', + 'TicketTemplate' + ], + __('Management') => [ + 'Budget', 'Supplier', 'Contact', 'Contract', 'Document', + 'Line', 'Certificate', 'Appliance', 'Cluster', 'Domain' + ], + __('Tools') => ['Project', 'Reminder', 'RSSFeed', 'KnowbaseItem', 'ProjectTask'], + __('Administration') => ['User', 'Group', 'Entity', 'Profile'], + __('Setup') => ['SLA', 'SlaLevel', 'Link'], + ]; + + if (class_exists('Webhook')) { + $CFG_GLPI['plugin_tag_itemtypes'][__('Setup')][] = 'Webhook'; + } + + if (Plugin::isPluginActive('appliances')) { + $CFG_GLPI['plugin_tag_itemtypes'][__('Assets')][] = 'PluginAppliancesAppliance'; + } + + // Plugin Webapplication + if (Plugin::isPluginActive('webapplications')) { + $CFG_GLPI['plugin_tag_itemtypes'][__('Assets')][] = 'PluginWebapplicationsWebapplication'; + } + + // Plugin fusioninventory + if (Plugin::isPluginActive('fusioninventory')) { + $CFG_GLPI['plugin_tag_itemtypes'][__('FusionInventory')][] = 'PluginFusioninventoryTask'; + } + + // add link on plugin name in Configuration > Plugin + $PLUGIN_HOOKS['config_page']['tag'] = "front/tag.php"; + + // Wait all plugins are loaded to find the itemtype matching the current URL + $PLUGIN_HOOKS['post_init']['tag'] = 'plugin_tag_post_init'; + + // Plugin use specific massive actions + $PLUGIN_HOOKS['use_massive_action']['tag'] = true; + + // Plugin uninstall : after uninstall action + if (Plugin::isPluginActive("uninstall")) { + //to prevent null global variable load plugin if needed + if ($UNINSTALL_TYPES == null) { + Plugin::load('uninstall'); + } + foreach ($UNINSTALL_TYPES as $u_itemtype) { + $PLUGIN_HOOKS['plugin_uninstall_after']['tag'][$u_itemtype] = 'plugin_uninstall_after_tag'; + } + } + + // insert tag dropdown into all possible itemtypes + $location = Config::getConfigurationValues('plugin:Tag')['tags_location'] ?? 0; + if ($location === '1') { + $PLUGIN_HOOKS['post_item_form']['tag'] = ['PluginTagTag', 'showForItem']; + } else { + $PLUGIN_HOOKS['pre_item_form']['tag'] = ['PluginTagTag', 'showForItem']; + } + $PLUGIN_HOOKS['pre_kanban_content']['tag'] = ['PluginTagTag', 'preKanbanContent']; + $common_kanban_filters = [ + 'tag' => [ + 'description' => _x('filters', 'If the item has a tag', 'tag'), + 'supported_prefixes' => ['!'] + ], + 'tagged' => [ + 'description' => _x('filters', 'If the item is tagged', 'tag'), + 'supported_prefixes' => ['!'] + ] + ]; + $PLUGIN_HOOKS[Hooks::KANBAN_FILTERS]['tag'] = [ + 'Project' => $common_kanban_filters, + 'Ticket' => $common_kanban_filters, + 'Problem' => $common_kanban_filters, + 'Change' => $common_kanban_filters, + ]; + $PLUGIN_HOOKS[Hooks::KANBAN_ITEM_METADATA]['tag'] = ['PluginTagTag', 'kanbanItemMetadata']; + + // plugin datainjection + $PLUGIN_HOOKS['plugin_datainjection_populate']['tag'] = "plugin_datainjection_populate_tag"; + + // add needed javascript & css files + $PLUGIN_HOOKS['add_javascript']['tag'][] = 'js/common.js'; + $PLUGIN_HOOKS['add_javascript']['tag'][] = 'js/kanban.js'; + $PLUGIN_HOOKS['add_css']['tag'][] = 'css/tag.css'; + if (Session::isMultiEntitiesMode()) { + $PLUGIN_HOOKS['add_javascript']['tag'][] = 'js/entity.js'; + } + + Plugin::registerClass('PluginTagProfile', ['addtabon' => ['Profile']]); + Plugin::registerClass('PluginTagConfig', ['addtabon' => 'Config']); + + $PLUGIN_HOOKS['use_rules']['tag'] = ['RuleTicket']; + } } /** @@ -152,34 +163,36 @@ function plugin_init_tag() { * * @return array */ -function plugin_version_tag() { - return [ - 'name' => __('Tag Management', 'tag'), - 'version' => PLUGIN_TAG_VERSION, - 'author' => 'Teclib\' - Infotel conseil', - 'homepage' => 'https://github.com/pluginsGLPI/tag', - 'license' => 'GPLv2+', - 'requirements' => [ - 'glpi' => [ - 'min' => PLUGIN_TAG_MIN_GLPI, - 'max' => PLUGIN_TAG_MAX_GLPI, - 'dev' => true, //Required to allow 9.2-dev - ] - ] - ]; +function plugin_version_tag() +{ + return [ + 'name' => __('Tag Management', 'tag'), + 'version' => PLUGIN_TAG_VERSION, + 'author' => 'Teclib\' - Infotel conseil', + 'homepage' => 'https://github.com/pluginsGLPI/tag', + 'license' => 'GPLv2+', + 'requirements' => [ + 'glpi' => [ + 'min' => PLUGIN_TAG_MIN_GLPI, + 'max' => PLUGIN_TAG_MAX_GLPI, + 'dev' => true, //Required to allow 9.2-dev + ] + ] + ]; } -function idealTextColor($hexTripletColor) { - $nThreshold = 105; - $hexTripletColor = str_replace('#', '', $hexTripletColor); - $components = [ - 'R' => hexdec(substr($hexTripletColor, 0, 2)), - 'G' => hexdec(substr($hexTripletColor, 2, 2)), - 'B' => hexdec(substr($hexTripletColor, 4, 2)), - ]; - $bgDelta = ($components['R'] * 0.299) +function idealTextColor($hexTripletColor) +{ + $nThreshold = 105; + $hexTripletColor = str_replace('#', '', $hexTripletColor); + $components = [ + 'R' => hexdec(substr($hexTripletColor, 0, 2)), + 'G' => hexdec(substr($hexTripletColor, 2, 2)), + 'B' => hexdec(substr($hexTripletColor, 4, 2)), + ]; + $bgDelta = ($components['R'] * 0.299) + ($components['G'] * 0.587) + ($components['B'] * 0.114); - return (((255 - $bgDelta) < $nThreshold) ? "#000000" : "#ffffff"); + return (((255 - $bgDelta) < $nThreshold) ? "#000000" : "#ffffff"); }