diff --git a/.github/scripts/publish-dev-build b/.github/scripts/publish-dev-build index e3d8d367..85de28bd 100755 --- a/.github/scripts/publish-dev-build +++ b/.github/scripts/publish-dev-build @@ -1,78 +1,39 @@ #!/usr/bin/env bash set -eux -package-name() { - node -e " - const package = JSON.parse(fs.readFileSync('package.json')) - console.log(package.name) - " -} - -rewrite-package-json() { - ARCHIVE_URL="https://github.com/${DEV_BUILD_REPO_NAME}/archive" \ - PACKAGE_LIST="$package_list" node -e " - const url = process.env.ARCHIVE_URL - const sha = process.env.GITHUB_SHA.slice(0, 7) - const package = JSON.parse(fs.readFileSync('package.json')) - if (package.dependencies) { - const packageNames = JSON.parse(process.env.PACKAGE_LIST).map(_ => _.name) - for (const name in package.dependencies) - if (packageNames.indexOf(name) != -1) - package.dependencies[name] = url + '/' + name + '/' + sha + '.tar.gz' - fs.writeFileSync('package.json', JSON.stringify(package)) - } - " -} - DEV_BUILD_REPO_NAME="hotwired/dev-builds" DEV_BUILD_ORIGIN_URL="https://${1}@github.com/${DEV_BUILD_REPO_NAME}.git" BUILD_PATH="$HOME/publish-dev-build" -cd "$GITHUB_WORKSPACE" +mkdir "$BUILD_PATH" -_IFS="$IFS" -IFS=$'\n' -package_list="$(yarn -s lerna list --no-private --json 2>/dev/null)" -package_paths=( $(yarn -s lerna exec --no-private pwd 2>/dev/null) ) -IFS="$_IFS" +cd "$GITHUB_WORKSPACE" +package_name="$(jq -r .name package.json)" +package_files=( dist package.json ) +tag="${package_name}/${GITHUB_SHA:0:7}" name="$(git log -n 1 --format=format:%cn)" email="$(git log -n 1 --format=format:%ce)" subject="$(git log -n 1 --format=format:%s)" date="$(git log -n 1 --format=format:%ai)" url="https://github.com/${GITHUB_REPOSITORY}/tree/${GITHUB_SHA}" +message="$tag $subject"$'\n\n'"$url" -for package_path in "${package_paths[@]}"; do - pushd "$package_path" - package_name="$(package-name)" - tag="${package_name}/${GITHUB_SHA:0:7}" - message="$tag $subject"$'\n'$'\n'"$url" - popd - - mkdir -p "$BUILD_PATH" - - pushd "$BUILD_PATH" - git init . - git remote add origin "$DEV_BUILD_ORIGIN_URL" - git symbolic-ref HEAD refs/heads/publish-dev-build - - shopt -s nullglob - cp -R "$package_path"/{*.json,*.js,dist} . || true - shopt -u nullglob - rewrite-package-json - git add . +cp -R "${package_files[@]}" "$BUILD_PATH" - GIT_AUTHOR_DATE="$date" GIT_COMMITTER_DATE="$date" \ - GIT_AUTHOR_NAME="$name" GIT_COMMITTER_NAME="$name" \ - GIT_AUTHOR_EMAIL="$email" GIT_COMMITTER_EMAIL="$email" \ - git commit -m "$message" +cd "$BUILD_PATH" +git init . +git remote add origin "$DEV_BUILD_ORIGIN_URL" +git symbolic-ref HEAD refs/heads/publish-dev-build +git add "${package_files[@]}" - git tag "$tag" - [ "$GITHUB_REF" != "refs/heads/main" ] || git tag -f "${package_name}/latest" - git push -f --tags - popd +GIT_AUTHOR_DATE="$date" GIT_COMMITTER_DATE="$date" \ +GIT_AUTHOR_NAME="$name" GIT_COMMITTER_NAME="$name" \ +GIT_AUTHOR_EMAIL="$email" GIT_COMMITTER_EMAIL="$email" \ + git commit -m "$message" - rm -fr "$BUILD_PATH" -done +git tag "$tag" +[ "$GITHUB_REF" != "refs/heads/main" ] || git tag -f "${package_name}/latest" +git push -f --tags echo done diff --git a/.github/workflows/dev-builds.yml b/.github/workflows/dev-builds.yml new file mode 100644 index 00000000..889306f8 --- /dev/null +++ b/.github/workflows/dev-builds.yml @@ -0,0 +1,24 @@ +name: dev-builds + +on: + workflow_dispatch: + push: + branches: + - main + - 'builds/**' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '16' + cache: 'yarn' + + - run: yarn install + - run: yarn build + + - name: Publish dev build + run: .github/scripts/publish-dev-build '${{ secrets.DEV_BUILD_GITHUB_TOKEN }}' diff --git a/README.md b/README.md index 13d4a761..0aafa3d1 100644 --- a/README.md +++ b/README.md @@ -67,10 +67,10 @@ We expect all Stimulus contributors to abide by the terms of our [Code of Conduc ## Acknowledgments -Stimulus is [MIT-licensed](LICENSE.md) open-source software from [Basecamp](https://basecamp.com/), the creators of [Ruby on Rails](http://rubyonrails.org). +Stimulus is [MIT-licensed](LICENSE.md) open-source software from [Basecamp](https://basecamp.com/), the creators of [Ruby on Rails](https://rubyonrails.org). Continuous integration VMs generously provided by [Sauce Labs](https://opensource.saucelabs.com/). --- -© 2021 Basecamp, LLC. +© 2023 Basecamp, LLC. diff --git a/docs/reference/actions.md b/docs/reference/actions.md index aebae6ab..5c7e909b 100644 --- a/docs/reference/actions.md +++ b/docs/reference/actions.md @@ -82,20 +82,22 @@ This will only work if the event being fired is a keyboard event. The correspondence between these filter and keys is shown below. -Filter | Key Name --------- | -------- -enter | Enter -tab | Tab -esc | Escape -space | " " -up | ArrowUp -down | ArrowDown -left | ArrowLeft -right | ArrowRight -home | Home -end | End -[a-z] | [a-z] -[0-9] | [0-9] +Filter | Key Name +-------- | -------- +enter | Enter +tab | Tab +esc | Escape +space | " " +up | ArrowUp +down | ArrowDown +left | ArrowLeft +right | ArrowRight +home | Home +end | End +page_up | PageUp +page_down | PageDown +[a-z] | [a-z] +[0-9] | [0-9] If you need to support other keys, you can customize the modifiers using a custom schema. @@ -129,7 +131,7 @@ The list of supported modifier keys is shown below. Sometimes a controller needs to listen for events dispatched on the global `window` or `document` objects. -You can append `@window` or `@document` to the event name (along with any filter modifer) in an action descriptor to install the event listener on `window` or `document`, respectively, as in the following example: +You can append `@window` or `@document` to the event name (along with any filter modifier) in an action descriptor to install the event listener on `window` or `document`, respectively, as in the following example: @@ -213,12 +215,13 @@ route the event to the controller action, return `true`. The callback accepts a single object argument with the following keys: -Name | Description ---------|------------ -name | String: The option's name (`"open"` in the example above) -value | Boolean: The value of the option (`:open` would yield `true`, `:!open` would yield `false`) -event | [Event][]: The event instance -element | [Element]: The element where the action descriptor is declared +| Name | Description | +| ---------- | ----------------------------------------------------------------------------------------------------- | +| name | String: The option's name (`"open"` in the example above) | +| value | Boolean: The value of the option (`:open` would yield `true`, `:!open` would yield `false`) | +| event | [Event][]: The event instance, including with the `params` action parameters on the submitter element | +| element | [Element]: The element where the action descriptor is declared | +| controller | The `Controller` instance which would receive the method call | [toggle]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLDetailsElement/toggle_event [Event]: https://developer.mozilla.org/en-US/docs/web/api/event diff --git a/docs/reference/controllers.md b/docs/reference/controllers.md index 9fd572af..97023e23 100644 --- a/docs/reference/controllers.md +++ b/docs/reference/controllers.md @@ -169,13 +169,15 @@ If you want to trigger some behaviour once a controller has been registered you ```js class SpinnerButton extends Controller { + static legacySelector = ".legacy-spinner-button" + static afterLoad(identifier, application) { // use the application instance to read the configured 'data-controller' attribute const { controllerAttribute } = application.schema // update any legacy buttons with the controller's registered identifier const updateLegacySpinners = () => { - document.querySelector(".legacy-spinner-button").forEach((element) => { + document.querySelector(this.legacySelector).forEach((element) => { element.setAttribute(controllerAttribute, identifier) }) } @@ -193,7 +195,7 @@ class SpinnerButton extends Controller { application.register("spinner-button", SpinnerButton) ``` -The `afterLoad` method will get called as soon as the controller has been registered, even if no controlled elements exist in the DOM. It gets called with the `identifier` that was used when registering the controller and the Stimulus application instance. +The `afterLoad` method will get called as soon as the controller has been registered, even if no controlled elements exist in the DOM. The function will be called bound to the original controller constructor along with two arguments; the `identifier` that was used when registering the controller and the Stimulus application instance. ## Cross-Controller Coordination With Events @@ -229,6 +231,15 @@ class EffectsController extends Controller { } ``` +If the two controllers don't belong to the same HTML element, the `data-action` attribute +needs to be added to the *receiving* controller's element. And if the receiving controller's +element is not a parent (or same) of the emitting controller's element, you need to add +`@window` to the event: + +```html +
+``` + `dispatch` accepts additional options as the second parameter as follows: option | default | notes diff --git a/docs/reference/outlets.md b/docs/reference/outlets.md index 8f19ad21..a7c959a2 100644 --- a/docs/reference/outlets.md +++ b/docs/reference/outlets.md @@ -11,20 +11,20 @@ The use of Outlets helps with cross-controller communication and coordination as They are conceptually similar to [Stimulus Targets](https://stimulus.hotwired.dev/reference/targets) but with the difference that they reference a Stimulus controller instance plus its associated controller element. - - + + ```html -
+
+
...
+
...
...
... -
-
...
-
...
+
...
``` @@ -33,17 +33,17 @@ While a **target** is a specifically marked element **within the scope** of its ## Attributes and Names -The `data-search-result-outlet` attribute is called an _outlet attribute_, and its value is a [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) which you can use to refer to other controller elements which should be available as outlets on the _host controller_. +The `data-chat-user-status-outlet` attribute is called an _outlet attribute_, and its value is a [CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors) which you can use to refer to other controller elements which should be available as outlets on the _host controller_. The outlet identifier in the host controller must be the same as the target controller's identifier. ```html data-[identifier]-[outlet]-outlet="[selector]" ``` - + ```html -
+
``` ## Definitions @@ -51,17 +51,18 @@ data-[identifier]-[outlet]-outlet="[selector]" Define controller identifiers in your controller class using the `static outlets` array. This array declares which other controller identifiers can be used as outlets on this controller: - + + ```js -// search_controller.js +// chat_controller.js export default class extends Controller { - static outlets = [ "result" ] + static outlets = [ "user-status" ] connect () { - this.resultOutlets.forEach(result => ...) + this.userStatusOutlets.forEach(status => ...) } } ``` @@ -78,20 +79,38 @@ For each outlet defined in the `static outlets` array, Stimulus adds five proper | Singular | `[name]OutletElement` | `Element` | Returns the Controller `Element` of the first `[name]` outlet or throws an exception if none is present | Plural | `[name]OutletElements` | `Array` | Returns the Controller `Element`'s of all `[name]` outlets +**Note:** For nested Stimulus controller properties, make sure to omit namespace delimiters in order to correctly access the referenced outlet: + +```js +// chat_controller.js + +export default class extends Controller { + static outlets = [ "admin--user-status" ] + + selectAll(event) { + // returns undefined + this.admin__UserStatusOutlets + + // returns controller reference + this.adminUserStatusOutlets + } +} +``` + ## Accessing Controllers and Elements Since you get back a `Controller` instance from the `[name]Outlet` and `[name]Outlets` properties you are also able to access the Values, Classes, Targets and all of the other properties and functions that controller instance defines: ```js -this.resultOutlet.idValue -this.resultOutlet.imageTarget -this.resultOutlet.activeClasses +this.userStatusOutlet.idValue +this.userStatusOutlet.imageTarget +this.userStatusOutlet.activeClasses ``` You are also able to invoke any function the outlet controller may define: ```js -// result_controller.js +// user_status_controller.js export default class extends Controller { markAsSelected(event) { @@ -99,13 +118,13 @@ export default class extends Controller { } } -// search_controller.js +// chat_controller.js export default class extends Controller { - static outlets = [ "result" ] + static outlets = [ "user-status" ] selectAll(event) { - this.resultOutlets.forEach(result => result.markAsSelected(event)) + this.userStatusOutlets.forEach(status => status.markAsSelected(event)) } } ``` @@ -113,9 +132,9 @@ export default class extends Controller { Similarly with the Outlet Element, it allows you to call any function or property on [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element): ```js -this.resultOutletElement.dataset.value -this.resultOutletElement.getAttribute("id") -this.resultOutletElements.map(result => result.hasAttribute("selected")) +this.userStatusOutletElement.dataset.value +this.userStatusOutletElement.getAttribute("id") +this.userStatusOutletElements.map(status => status.hasAttribute("selected")) ``` ## Outlet Callbacks @@ -125,16 +144,16 @@ Outlet callbacks are specially named functions called by Stimulus to let you res To observe outlet changes, define a function named `[name]OutletConnected()` or `[name]OutletDisconnected()`. ```js -// search_controller.js +// chat_controller.js export default class extends Controller { - static outlets = [ "result" ] + static outlets = [ "user-status" ] - resultOutletConnected(outlet, element) { + userStatusOutletConnected(outlet, element) { // ... } - resultOutletDisconnected(outlet, element) { + userStatusOutletDisconnected(outlet, element) { // ... } } @@ -145,7 +164,7 @@ export default class extends Controller { When you access an Outlet property in a Controller, you assert that at least one corresponding Outlet is present. If the declaration is missing and no matching outlet is found Stimulus will throw an exception: ```html -Missing outlet element "result" for "search" controller +Missing outlet element "user-status" for "chat" controller ``` ### Optional outlets @@ -153,8 +172,8 @@ Missing outlet element "result" for "search" controller If an Outlet is optional or you want to assert that at least Outlet is present, you must first check the presence of the Outlet using the existential property: ```js -if (this.hasResultOutlet) { - this.resultOutlet.safelyCallSomethingOnTheOutlet() +if (this.hasUserStatusOutlet) { + this.userStatusOutlet.safelyCallSomethingOnTheOutlet() } ``` @@ -162,18 +181,18 @@ if (this.hasResultOutlet) { Stimulus will throw an exception if you try to declare an element as an outlet which doesn't have a corresponding `data-controller` and identifier on it: - - + + ```html -
+
-
+
``` Would result in: ```html -Missing "data-controller=result" attribute on outlet element for -"search" controller` +Missing "data-controller=user-status" attribute on outlet element for +"chat" controller` ``` diff --git a/docs/reference/values.md b/docs/reference/values.md index 0a67a09c..8a1aa5de 100644 --- a/docs/reference/values.md +++ b/docs/reference/values.md @@ -10,11 +10,12 @@ You can read and write [HTML data attributes](https://developer.mozilla.org/en-U ```html -
+
``` +As per the given HTML snippet, remember to place the data attributes for values on the same element as the `data-controller` attribute. + @@ -53,13 +54,13 @@ export default class extends Controller { A value's type is one of `Array`, `Boolean`, `Number`, `Object`, or `String`. The type determines how the value is transcoded between JavaScript and HTML. -Type | Encoded as… | Decoded as… ----- | ----------- | ----------- -Array | `JSON.stringify(array)` | `JSON.parse(value)` -Boolean | `boolean.toString()` | `!(value == "0" \|\| value == "false")` -Number | `number.toString()` | `Number(value)` -Object | `JSON.stringify(object)` | `JSON.parse(value)` -String | Itself | Itself +| Type | Encoded as… | Decoded as… | +| ------- | ------------------------ | --------------------------------------- | +| Array | `JSON.stringify(array)` | `JSON.parse(value)` | +| Boolean | `boolean.toString()` | `!(value == "0" \|\| value == "false")` | +| Number | `number.toString()` | `Number(value.replace(/_/g, ""))` | +| Object | `JSON.stringify(object)` | `JSON.parse(value)` | +| String | Itself | Itself | ## Properties and Attributes diff --git a/examples/package.json b/examples/package.json index ad465189..a7f40ff6 100644 --- a/examples/package.json +++ b/examples/package.json @@ -10,7 +10,7 @@ "@hotwired/turbo": "^7.2.4", "babel-loader": "^8.0.6", "ejs": "^3.1.7", - "express": "^4.16.3", + "express": "^4.17.3", "webpack": "^4.39.1", "webpack-dev-middleware": "^3.7.0" }, diff --git a/examples/yarn.lock b/examples/yarn.lock index dda0899f..3736b274 100644 --- a/examples/yarn.lock +++ b/examples/yarn.lock @@ -1045,13 +1045,13 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn@^6.4.1: version "6.4.2" @@ -1282,21 +1282,21 @@ bn.js@^5.0.0, bn.js@^5.1.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== +body-parser@1.19.2: + version "1.19.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" + integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== dependencies: - bytes "3.1.0" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" - http-errors "1.7.2" + http-errors "1.8.1" iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + qs "6.9.7" + raw-body "2.4.3" + type-is "~1.6.18" brace-expansion@^1.1.7: version "1.1.11" @@ -1437,10 +1437,10 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^12.0.2: version "12.0.4" @@ -1647,12 +1647,12 @@ constants-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" content-type@~1.0.4: version "1.0.4" @@ -1671,10 +1671,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== copy-concurrently@^1.0.0: version "1.0.5" @@ -1774,9 +1774,9 @@ debug@^4.1.0, debug@^4.1.1: ms "2.1.2" decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== define-properties@^1.1.3: version "1.1.3" @@ -1988,17 +1988,17 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -express@^4.16.3: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== +express@^4.17.3: + version "4.17.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" + integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" + body-parser "1.19.2" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.4.2" cookie-signature "1.0.6" debug "2.6.9" depd "~1.1.2" @@ -2012,13 +2012,13 @@ express@^4.16.3: on-finished "~2.3.0" parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + proxy-addr "~2.0.7" + qs "6.9.7" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" + safe-buffer "5.2.1" + send "0.17.2" + serve-static "1.14.2" + setprototypeof "1.2.0" statuses "~1.5.0" type-is "~1.6.18" utils-merge "1.0.1" @@ -2349,27 +2349,16 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== dependencies: depd "~1.1.2" inherits "2.0.4" - setprototypeof "1.1.1" + setprototypeof "1.2.0" statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + toidentifier "1.0.1" https-browserify@^1.0.0: version "1.0.0" @@ -2616,9 +2605,9 @@ json-schema-traverse@^0.4.1: integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -2793,6 +2782,11 @@ mime-db@1.48.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + mime-types@~2.1.24: version "2.1.31" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" @@ -2800,6 +2794,13 @@ mime-types@~2.1.24: dependencies: mime-db "1.48.0" +mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -2835,9 +2836,9 @@ minimatch@^5.0.1: brace-expansion "^2.0.1" minimist@^1.2.0, minimist@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== mississippi@^3.0.0: version "3.0.0" @@ -2887,16 +2888,16 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + nan@^2.12.1: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" @@ -2919,10 +2920,10 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.5.0, neo-async@^2.6.1: version "2.6.2" @@ -3188,7 +3189,7 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -proxy-addr@~2.0.5: +proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -3253,10 +3254,10 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@6.9.7: + version "6.9.7" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" + integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== querystring-es3@^0.2.0: version "0.2.1" @@ -3288,13 +3289,13 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" + integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== dependencies: - bytes "3.1.0" - http-errors "1.7.2" + bytes "3.1.2" + http-errors "1.8.1" iconv-lite "0.4.24" unpipe "1.0.0" @@ -3447,16 +3448,16 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -3493,19 +3494,19 @@ semver@7.0.0: integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" + integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== dependencies: debug "2.6.9" depd "~1.1.2" @@ -3514,9 +3515,9 @@ send@0.17.1: escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "1.8.1" mime "1.6.0" - ms "2.1.1" + ms "2.1.3" on-finished "~2.3.0" range-parser "~1.2.1" statuses "~1.5.0" @@ -3528,15 +3529,15 @@ serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.14.2: + version "1.14.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" + integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" + send "0.17.2" set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" @@ -3553,10 +3554,10 @@ setimmediate@^1.0.4: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" @@ -3808,17 +3809,17 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= -type-is@~1.6.17, type-is@~1.6.18: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== diff --git a/package.json b/package.json index 686cfad7..4db96b08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hotwired/stimulus", - "version": "3.2.1", + "version": "3.2.2", "license": "MIT", "description": "A modest JavaScript framework for the HTML you already have.", "author": "Basecamp, LLC", @@ -31,10 +31,11 @@ "scripts": { "clean": "rm -fr dist", "types": "tsc --noEmit false --declaration true --emitDeclarationOnly true --outDir dist/types", + "prebuild": "yarn build:test", "build": "yarn types && rollup -c", "build:test": "tsc -b tsconfig.test.json", "watch": "rollup -wc", - "prerelease": "yarn build && git --no-pager diff && echo && npm pack --dry-run", + "prerelease": "yarn clean && yarn build && yarn build:test && git --no-pager diff && echo && npm pack --dry-run", "release": "npm publish", "start": "concurrently \"npm:watch\" \"npm:start:examples\"", "start:examples": "cd examples && yarn install && node server.js", @@ -45,28 +46,28 @@ }, "devDependencies": { "@rollup/plugin-node-resolve": "^13.0.0", - "@rollup/plugin-typescript": "^8.5.0", + "@rollup/plugin-typescript": "^11.1.1", "@types/qunit": "^2.9.0", "@types/webpack-env": "^1.14.0", - "@typescript-eslint/eslint-plugin": "^5.36.2", - "@typescript-eslint/parser": "^5.36.2", + "@typescript-eslint/eslint-plugin": "^5.59.11", + "@typescript-eslint/parser": "^5.59.11", "concurrently": "^6.2.1", - "eslint": "^8.23.0", - "eslint-config-prettier": "^8.5.0", + "eslint": "^8.43.0", + "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^4.2.1", "karma": "^6.4.1", "karma-chrome-launcher": "^3.1.1", "karma-qunit": "^4.1.2", "karma-sauce-launcher": "^4.3.6", "karma-webpack": "^4.0.2", - "prettier": "^2.7.1", + "prettier": "^2.8.8", "qunit": "^2.9.2", "rimraf": "^3.0.2", "rollup": "^2.53", "rollup-plugin-terser": "^7.0.2", - "ts-loader": "^6.0.4", - "tslib": "^2.4.0", - "typescript": "^4.8.2", + "ts-loader": "^9.4.3", + "tslib": "^2.5.3", + "typescript": "^5.1.3", "webpack": "^4.39.1" }, "resolutions": { diff --git a/packages/stimulus/package.json b/packages/stimulus/package.json index b8676752..a0b1d90a 100644 --- a/packages/stimulus/package.json +++ b/packages/stimulus/package.json @@ -1,6 +1,6 @@ { "name": "stimulus", - "version": "3.2.1", + "version": "3.2.2", "description": "Stimulus JavaScript framework", "repository": "https://stimulus.hotwired.dev", "author": "Basecamp, LLC", @@ -42,7 +42,7 @@ ], "license": "MIT", "dependencies": { - "@hotwired/stimulus": "^3.2.1", + "@hotwired/stimulus": "^3.2.2", "@hotwired/stimulus-webpack-helpers": "^1.0.0" }, "devDependencies": { diff --git a/packages/stimulus/yarn.lock b/packages/stimulus/yarn.lock index 6ccf538b..7f97d8d0 100644 --- a/packages/stimulus/yarn.lock +++ b/packages/stimulus/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.0.tgz#6bd7906a4a2b6e1cd8732203b60264f987bd1084" integrity sha512-6oKDmJDSsV+zdlHnF485nneuekY/Zbl669wei4HIiwxUWHhVSU1XIVji4aj+Ws9AXghjTYBS8H5ralB97BVMDw== -"@hotwired/stimulus@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.2.0.tgz#257272f1348b1f7beb1a8510be88b80aec6c4c5b" - integrity sha512-uAIIdg049qId0lBhyjuMBfcC5uV8JwbhNLoxEyi9vxM3MW6h+mM97G9rNT4ZZMiqnKK9XUHp9SQUrd9rSLEmpQ== +"@hotwired/stimulus@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.2.2.tgz#071aab59c600fed95b97939e605ff261a4251608" + integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A== "@rollup/plugin-node-resolve@^13.0.0": version "13.0.5" diff --git a/src/core/action.ts b/src/core/action.ts index 8fba7a10..e009399b 100644 --- a/src/core/action.ts +++ b/src/core/action.ts @@ -2,6 +2,10 @@ import { ActionDescriptor, parseActionDescriptorString, stringifyEventTarget } f import { Token } from "../mutation-observers" import { Schema } from "./schema" import { camelize } from "./string_helpers" +import { hasProperty } from "./utils" + +const allModifiers = ["meta", "ctrl", "alt", "shift"] + export class Action { readonly element: Element readonly index: number @@ -35,32 +39,42 @@ export class Action { return `${this.eventName}${eventFilter}${eventTarget}->${this.identifier}#${this.methodName}` } - isFilterTarget(event: KeyboardEvent): boolean { + shouldIgnoreKeyboardEvent(event: KeyboardEvent): boolean { if (!this.keyFilter) { return false } - const filteres = this.keyFilter.split("+") - const modifiers = ["meta", "ctrl", "alt", "shift"] - const [meta, ctrl, alt, shift] = modifiers.map((modifier) => filteres.includes(modifier)) - - if (event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift) { + const filters = this.keyFilter.split("+") + if (this.keyFilterDissatisfied(event, filters)) { return true } - const standardFilter = filteres.filter((key) => !modifiers.includes(key))[0] + const standardFilter = filters.filter((key) => !allModifiers.includes(key))[0] if (!standardFilter) { // missing non modifier key return false } - if (!Object.prototype.hasOwnProperty.call(this.keyMappings, standardFilter)) { + if (!hasProperty(this.keyMappings, standardFilter)) { error(`contains unknown key filter: ${this.keyFilter}`) } return this.keyMappings[standardFilter].toLowerCase() !== event.key.toLowerCase() } + shouldIgnoreMouseEvent(event: MouseEvent): boolean { + if (!this.keyFilter) { + return false + } + + const filters = [this.keyFilter] + if (this.keyFilterDissatisfied(event, filters)) { + return true + } + + return false + } + get params() { const params: { [key: string]: any } = {} const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, "i") @@ -82,6 +96,12 @@ export class Action { private get keyMappings() { return this.schema.keyMappings } + + private keyFilterDissatisfied(event: KeyboardEvent | MouseEvent, filters: Array): boolean { + const [meta, ctrl, alt, shift] = allModifiers.map((modifier) => filters.includes(modifier)) + + return event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift + } } const defaultEventNames: { [tagName: string]: (element: Element) => string } = { diff --git a/src/core/action_descriptor.ts b/src/core/action_descriptor.ts index fe051981..35a4a211 100644 --- a/src/core/action_descriptor.ts +++ b/src/core/action_descriptor.ts @@ -1,3 +1,5 @@ +import type { Controller } from "./controller" + export type ActionDescriptorFilters = Record export type ActionDescriptorFilter = (options: ActionDescriptorFilterOptions) => boolean type ActionDescriptorFilterOptions = { @@ -5,6 +7,7 @@ type ActionDescriptorFilterOptions = { value: boolean event: Event element: Element + controller: Controller } export const defaultActionDescriptorFilters: ActionDescriptorFilters = { @@ -38,14 +41,14 @@ export interface ActionDescriptor { keyFilter: string } -// capture nos.: 1 1 2 2 3 3 4 4 5 5 6 6 -const descriptorPattern = /^(?:(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/ +// capture nos.: 1 1 2 2 3 3 4 4 5 5 6 6 7 7 +const descriptorPattern = /^(?:(?:([^.]+?)\+)?(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/ export function parseActionDescriptorString(descriptorString: string): Partial { const source = descriptorString.trim() const matches = source.match(descriptorPattern) || [] - let eventName = matches[1] - let keyFilter = matches[2] + let eventName = matches[2] + let keyFilter = matches[3] if (keyFilter && !["keydown", "keyup", "keypress"].includes(eventName)) { eventName += `.${keyFilter}` @@ -53,12 +56,12 @@ export function parseActionDescriptorString(descriptorString: string): Partial +type DispatchOptions = Partial<{ + target: Element | Window | Document + detail: Object + prefix: string + bubbles: boolean + cancelable: boolean +}> + export class Controller { static blessings = [ ClassPropertiesBlessing, @@ -79,7 +87,13 @@ export class Controller { dispatch( eventName: string, - { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {} + { + target = this.element, + detail = {}, + prefix = this.identifier, + bubbles = true, + cancelable = true, + }: DispatchOptions = {} ) { const type = prefix ? `${prefix}:${eventName}` : eventName const event = new CustomEvent(type, { detail, bubbles, cancelable }) diff --git a/src/core/outlet_observer.ts b/src/core/outlet_observer.ts index 0208129f..b0956f47 100644 --- a/src/core/outlet_observer.ts +++ b/src/core/outlet_observer.ts @@ -1,64 +1,79 @@ import { Multimap } from "../multimap" +import { AttributeObserver, AttributeObserverDelegate } from "../mutation-observers" import { SelectorObserver, SelectorObserverDelegate } from "../mutation-observers" import { Context } from "./context" import { Controller } from "./controller" import { readInheritableStaticArrayValues } from "./inheritable_statics" -type SelectorObserverDetails = { outletName: string } +type OutletObserverDetails = { outletName: string } export interface OutletObserverDelegate { outletConnected(outlet: Controller, element: Element, outletName: string): void outletDisconnected(outlet: Controller, element: Element, outletName: string): void } -export class OutletObserver implements SelectorObserverDelegate { +export class OutletObserver implements AttributeObserverDelegate, SelectorObserverDelegate { + started: boolean readonly context: Context readonly delegate: OutletObserverDelegate readonly outletsByName: Multimap readonly outletElementsByName: Multimap private selectorObserverMap: Map + private attributeObserverMap: Map constructor(context: Context, delegate: OutletObserverDelegate) { + this.started = false this.context = context this.delegate = delegate this.outletsByName = new Multimap() this.outletElementsByName = new Multimap() this.selectorObserverMap = new Map() + this.attributeObserverMap = new Map() } start() { - if (this.selectorObserverMap.size === 0) { + if (!this.started) { this.outletDefinitions.forEach((outletName) => { - const selector = this.selector(outletName) - const details: SelectorObserverDetails = { outletName } - - if (selector) { - this.selectorObserverMap.set(outletName, new SelectorObserver(document.body, selector, this, details)) - } + this.setupSelectorObserverForOutlet(outletName) + this.setupAttributeObserverForOutlet(outletName) }) - - this.selectorObserverMap.forEach((observer) => observer.start()) + this.started = true + this.dependentContexts.forEach((context) => context.refresh()) } + } - this.dependentContexts.forEach((context) => context.refresh()) + refresh() { + this.selectorObserverMap.forEach((observer) => observer.refresh()) + this.attributeObserverMap.forEach((observer) => observer.refresh()) } stop() { - if (this.selectorObserverMap.size > 0) { + if (this.started) { + this.started = false this.disconnectAllOutlets() + this.stopSelectorObservers() + this.stopAttributeObservers() + } + } + + stopSelectorObservers() { + if (this.selectorObserverMap.size > 0) { this.selectorObserverMap.forEach((observer) => observer.stop()) this.selectorObserverMap.clear() } } - refresh() { - this.selectorObserverMap.forEach((observer) => observer.refresh()) + stopAttributeObservers() { + if (this.attributeObserverMap.size > 0) { + this.attributeObserverMap.forEach((observer) => observer.stop()) + this.attributeObserverMap.clear() + } } // Selector observer delegate - selectorMatched(element: Element, _selector: string, { outletName }: SelectorObserverDetails) { + selectorMatched(element: Element, _selector: string, { outletName }: OutletObserverDetails) { const outlet = this.getOutlet(element, outletName) if (outlet) { @@ -66,7 +81,7 @@ export class OutletObserver implements SelectorObserverDelegate { } } - selectorUnmatched(element: Element, _selector: string, { outletName }: SelectorObserverDetails) { + selectorUnmatched(element: Element, _selector: string, { outletName }: OutletObserverDetails) { const outlet = this.getOutletFromMap(element, outletName) if (outlet) { @@ -74,11 +89,42 @@ export class OutletObserver implements SelectorObserverDelegate { } } - selectorMatchElement(element: Element, { outletName }: SelectorObserverDetails) { - return ( - this.hasOutlet(element, outletName) && - element.matches(`[${this.context.application.schema.controllerAttribute}~=${outletName}]`) - ) + selectorMatchElement(element: Element, { outletName }: OutletObserverDetails) { + const selector = this.selector(outletName) + const hasOutlet = this.hasOutlet(element, outletName) + const hasOutletController = element.matches(`[${this.schema.controllerAttribute}~=${outletName}]`) + + if (selector) { + return hasOutlet && hasOutletController && element.matches(selector) + } else { + return false + } + } + + // Attribute observer delegate + + elementMatchedAttribute(_element: Element, attributeName: string) { + const outletName = this.getOutletNameFromOutletAttributeName(attributeName) + + if (outletName) { + this.updateSelectorObserverForOutlet(outletName) + } + } + + elementAttributeValueChanged(_element: Element, attributeName: string) { + const outletName = this.getOutletNameFromOutletAttributeName(attributeName) + + if (outletName) { + this.updateSelectorObserverForOutlet(outletName) + } + } + + elementUnmatchedAttribute(_element: Element, attributeName: string) { + const outletName = this.getOutletNameFromOutletAttributeName(attributeName) + + if (outletName) { + this.updateSelectorObserverForOutlet(outletName) + } } // Outlet management @@ -111,12 +157,48 @@ export class OutletObserver implements SelectorObserverDelegate { } } + // Observer management + + private updateSelectorObserverForOutlet(outletName: string) { + const observer = this.selectorObserverMap.get(outletName) + + if (observer) { + observer.selector = this.selector(outletName) + } + } + + private setupSelectorObserverForOutlet(outletName: string) { + const selector = this.selector(outletName) + const selectorObserver = new SelectorObserver(document.body, selector!, this, { outletName }) + + this.selectorObserverMap.set(outletName, selectorObserver) + + selectorObserver.start() + } + + private setupAttributeObserverForOutlet(outletName: string) { + const attributeName = this.attributeNameForOutletName(outletName) + const attributeObserver = new AttributeObserver(this.scope.element, attributeName, this) + + this.attributeObserverMap.set(outletName, attributeObserver) + + attributeObserver.start() + } + // Private private selector(outletName: string) { return this.scope.outlets.getSelectorForOutletName(outletName) } + private attributeNameForOutletName(outletName: string) { + return this.scope.schema.outletAttributeForScope(this.identifier, outletName) + } + + private getOutletNameFromOutletAttributeName(attributeName: string) { + return this.outletDefinitions.find((outletName) => this.attributeNameForOutletName(outletName) === attributeName) + } + private get outletDependencies() { const dependencies = new Multimap() @@ -159,6 +241,10 @@ export class OutletObserver implements SelectorObserverDelegate { return this.context.scope } + private get schema() { + return this.context.schema + } + private get identifier() { return this.context.identifier } diff --git a/src/core/outlet_properties.ts b/src/core/outlet_properties.ts index 3fe7928d..4af436a4 100644 --- a/src/core/outlet_properties.ts +++ b/src/core/outlet_properties.ts @@ -10,26 +10,42 @@ export function OutletPropertiesBlessing(constructor: Constructor) { }, {} as PropertyDescriptorMap) } +function getOutletController(controller: Controller, element: Element, identifier: string) { + return controller.application.getControllerForElementAndIdentifier(element, identifier) +} + +function getControllerAndEnsureConnectedScope(controller: Controller, element: Element, outletName: string) { + let outletController = getOutletController(controller, element, outletName) + if (outletController) return outletController + + controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName) + + outletController = getOutletController(controller, element, outletName) + if (outletController) return outletController +} + function propertiesForOutletDefinition(name: string) { const camelizedName = namespaceCamelize(name) return { [`${camelizedName}Outlet`]: { get(this: Controller) { - const outlet = this.outlets.find(name) - - if (outlet) { - const outletController = this.application.getControllerForElementAndIdentifier(outlet, name) - if (outletController) { - return outletController - } else { - throw new Error( - `Missing "data-controller=${name}" attribute on outlet element for "${this.identifier}" controller` - ) - } + const outletElement = this.outlets.find(name) + const selector = this.outlets.getSelectorForOutletName(name) + + if (outletElement) { + const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name) + + if (outletController) return outletController + + throw new Error( + `The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"` + ) } - throw new Error(`Missing outlet element "${name}" for "${this.identifier}" controller`) + throw new Error( + `Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".` + ) }, }, @@ -39,16 +55,15 @@ function propertiesForOutletDefinition(name: string) { if (outlets.length > 0) { return outlets - .map((outlet: Element) => { - const controller = this.application.getControllerForElementAndIdentifier(outlet, name) - if (controller) { - return controller - } else { - console.warn( - `The provided outlet element is missing the outlet controller "${name}" for "${this.identifier}"`, - outlet - ) - } + .map((outletElement: Element) => { + const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name) + + if (outletController) return outletController + + console.warn( + `The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, + outletElement + ) }) .filter((controller) => controller) as Controller[] } @@ -59,11 +74,15 @@ function propertiesForOutletDefinition(name: string) { [`${camelizedName}OutletElement`]: { get(this: Controller) { - const outlet = this.outlets.find(name) - if (outlet) { - return outlet + const outletElement = this.outlets.find(name) + const selector = this.outlets.getSelectorForOutletName(name) + + if (outletElement) { + return outletElement } else { - throw new Error(`Missing outlet element "${name}" for "${this.identifier}" controller`) + throw new Error( + `Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".` + ) } }, }, diff --git a/src/core/router.ts b/src/core/router.ts index c06e5e57..d0d40a84 100644 --- a/src/core/router.ts +++ b/src/core/router.ts @@ -57,7 +57,7 @@ export class Router implements ScopeObserverDelegate { this.connectModule(module) const afterLoad = (definition.controllerConstructor as any).afterLoad if (afterLoad) { - afterLoad(definition.identifier, this.application) + afterLoad.call(definition.controllerConstructor, definition.identifier, this.application) } } @@ -75,6 +75,16 @@ export class Router implements ScopeObserverDelegate { } } + proposeToConnectScopeForElementAndIdentifier(element: Element, identifier: string) { + const scope = this.scopeObserver.parseValueForElementAndIdentifier(element, identifier) + + if (scope) { + this.scopeObserver.elementMatchedValue(scope.element, scope) + } else { + console.error(`Couldn't find or create scope for identifier: "${identifier}" and element:`, element) + } + } + // Error handler delegate handleError(error: Error, message: string, detail: any) { diff --git a/src/core/schema.ts b/src/core/schema.ts index 20845d20..bbc5b24a 100644 --- a/src/core/schema.ts +++ b/src/core/schema.ts @@ -24,6 +24,8 @@ export const defaultSchema: Schema = { right: "ArrowRight", home: "Home", end: "End", + page_up: "PageUp", + page_down: "PageDown", // [a-z] ...objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c])), // [0-9] diff --git a/src/core/scope_observer.ts b/src/core/scope_observer.ts index 6ddcd0ef..0349a24b 100644 --- a/src/core/scope_observer.ts +++ b/src/core/scope_observer.ts @@ -42,6 +42,10 @@ export class ScopeObserver implements ValueListObserverDelegate { parseValueForToken(token: Token): Scope | undefined { const { element, content: identifier } = token + return this.parseValueForElementAndIdentifier(element, identifier) + } + + parseValueForElementAndIdentifier(element: Element, identifier: string): Scope | undefined { const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element) let scope = scopesByIdentifier.get(identifier) diff --git a/src/core/utils.ts b/src/core/utils.ts new file mode 100644 index 00000000..ae3a262f --- /dev/null +++ b/src/core/utils.ts @@ -0,0 +1,7 @@ +export function isSomething(object: any): boolean { + return object !== null && object !== undefined +} + +export function hasProperty(object: any, property: string): boolean { + return Object.prototype.hasOwnProperty.call(object, property) +} diff --git a/src/core/value_properties.ts b/src/core/value_properties.ts index 6a431314..c15e2d9a 100644 --- a/src/core/value_properties.ts +++ b/src/core/value_properties.ts @@ -2,6 +2,7 @@ import { Constructor } from "./constructor" import { Controller } from "./controller" import { readInheritableStaticObjectPairs } from "./inheritable_statics" import { camelize, capitalize, dasherize } from "./string_helpers" +import { isSomething, hasProperty } from "./utils" export function ValuePropertiesBlessing(constructor: Constructor) { const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values") @@ -77,7 +78,7 @@ export type ValueTypeConstant = typeof Array | typeof Boolean | typeof Number | export type ValueTypeDefault = Array | boolean | number | Object | string -export type ValueTypeObject = { type: ValueTypeConstant; default: ValueTypeDefault } +export type ValueTypeObject = Partial<{ type: ValueTypeConstant; default: ValueTypeDefault }> export type ValueTypeDefinition = ValueTypeConstant | ValueTypeDefault | ValueTypeObject @@ -91,7 +92,7 @@ function parseValueDefinitionPair([token, typeDefinition]: ValueDefinitionPair, }) } -function parseValueTypeConstant(constant: ValueTypeConstant) { +export function parseValueTypeConstant(constant?: ValueTypeConstant) { switch (constant) { case Array: return "array" @@ -106,7 +107,7 @@ function parseValueTypeConstant(constant: ValueTypeConstant) { } } -function parseValueTypeDefault(defaultValue: ValueTypeDefault) { +export function parseValueTypeDefault(defaultValue?: ValueTypeDefault) { switch (typeof defaultValue) { case "boolean": return "boolean" @@ -120,73 +121,97 @@ function parseValueTypeDefault(defaultValue: ValueTypeDefault) { if (Object.prototype.toString.call(defaultValue) === "[object Object]") return "object" } -function parseValueTypeObject(payload: { controller?: string; token: string; typeObject: ValueTypeObject }) { - const typeFromObject = parseValueTypeConstant(payload.typeObject.type) +type ValueTypeObjectPayload = { + controller?: string + token: string + typeObject: ValueTypeObject +} + +export function parseValueTypeObject(payload: ValueTypeObjectPayload) { + const { controller, token, typeObject } = payload + + const hasType = isSomething(typeObject.type) + const hasDefault = isSomething(typeObject.default) - if (!typeFromObject) return + const fullObject = hasType && hasDefault + const onlyType = hasType && !hasDefault + const onlyDefault = !hasType && hasDefault - const defaultValueType = parseValueTypeDefault(payload.typeObject.default) + const typeFromObject = parseValueTypeConstant(typeObject.type) + const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default) - if (typeFromObject !== defaultValueType) { - const propertyPath = payload.controller ? `${payload.controller}.${payload.token}` : payload.token + if (onlyType) return typeFromObject + if (onlyDefault) return typeFromDefaultValue + + if (typeFromObject !== typeFromDefaultValue) { + const propertyPath = controller ? `${controller}.${token}` : token throw new Error( - `The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${payload.typeObject.default}" is of type "${defaultValueType}".` + `The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".` ) } - return typeFromObject + if (fullObject) return typeFromObject } -function parseValueTypeDefinition(payload: { +type ValueTypeDefinitionPayload = { controller?: string token: string typeDefinition: ValueTypeDefinition -}): ValueType { - const typeFromObject = parseValueTypeObject({ - controller: payload.controller, - token: payload.token, - typeObject: payload.typeDefinition as ValueTypeObject, - }) - const typeFromDefaultValue = parseValueTypeDefault(payload.typeDefinition as ValueTypeDefault) - const typeFromConstant = parseValueTypeConstant(payload.typeDefinition as ValueTypeConstant) +} + +export function parseValueTypeDefinition(payload: ValueTypeDefinitionPayload): ValueType { + const { controller, token, typeDefinition } = payload + + const typeObject = { controller, token, typeObject: typeDefinition as ValueTypeObject } + + const typeFromObject = parseValueTypeObject(typeObject as ValueTypeObjectPayload) + const typeFromDefaultValue = parseValueTypeDefault(typeDefinition as ValueTypeDefault) + const typeFromConstant = parseValueTypeConstant(typeDefinition as ValueTypeConstant) const type = typeFromObject || typeFromDefaultValue || typeFromConstant if (type) return type - const propertyPath = payload.controller ? `${payload.controller}.${payload.typeDefinition}` : payload.token + const propertyPath = controller ? `${controller}.${typeDefinition}` : token - throw new Error(`Unknown value type "${propertyPath}" for "${payload.token}" value`) + throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`) } -function defaultValueForDefinition(typeDefinition: ValueTypeDefinition): ValueTypeDefault { +export function defaultValueForDefinition(typeDefinition: ValueTypeDefinition): ValueTypeDefault { const constant = parseValueTypeConstant(typeDefinition as ValueTypeConstant) - if (constant) return defaultValuesByType[constant] - const defaultValue = (typeDefinition as ValueTypeObject).default - if (defaultValue !== undefined) return defaultValue + const hasDefault = hasProperty(typeDefinition, "default") + const hasType = hasProperty(typeDefinition, "type") + const typeObject = typeDefinition as ValueTypeObject + + if (hasDefault) return typeObject.default! + + if (hasType) { + const { type } = typeObject + const constantFromType = parseValueTypeConstant(type) + + if (constantFromType) return defaultValuesByType[constantFromType] + } return typeDefinition } -function valueDescriptorForTokenAndTypeDefinition(payload: { - token: string - typeDefinition: ValueTypeDefinition - controller?: string -}) { - const key = `${dasherize(payload.token)}-value` +function valueDescriptorForTokenAndTypeDefinition(payload: ValueTypeDefinitionPayload) { + const { token, typeDefinition } = payload + + const key = `${dasherize(token)}-value` const type = parseValueTypeDefinition(payload) return { type, key, name: camelize(key), get defaultValue() { - return defaultValueForDefinition(payload.typeDefinition) + return defaultValueForDefinition(typeDefinition) }, get hasCustomDefaultValue() { - return parseValueTypeDefault(payload.typeDefinition) !== undefined + return parseValueTypeDefault(typeDefinition) !== undefined }, reader: readers[type], writer: writers[type] || writers.default, @@ -223,7 +248,7 @@ const readers: { [type: string]: Reader } = { }, number(value: string): number { - return Number(value) + return Number(value.replace(/_/g, "")) }, object(value: string): object { diff --git a/src/mutation-observers/element_observer.ts b/src/mutation-observers/element_observer.ts index 2902cd00..544de6e4 100644 --- a/src/mutation-observers/element_observer.ts +++ b/src/mutation-observers/element_observer.ts @@ -14,7 +14,7 @@ export class ElementObserver { private elements: Set private mutationObserver: MutationObserver - private mutationObserverInit = { attributes: true, childList: true, subtree: true } + private mutationObserverInit: MutationObserverInit = { attributes: true, childList: true, subtree: true } constructor(element: Element, delegate: ElementObserverDelegate) { this.element = element @@ -83,15 +83,14 @@ export class ElementObserver { private processMutation(mutation: MutationRecord) { if (mutation.type == "attributes") { - this.processAttributeChange(mutation.target, mutation.attributeName!) + this.processAttributeChange(mutation.target as Element, mutation.attributeName!) } else if (mutation.type == "childList") { this.processRemovedNodes(mutation.removedNodes) this.processAddedNodes(mutation.addedNodes) } } - private processAttributeChange(node: Node, attributeName: string) { - const element = node as Element + private processAttributeChange(element: Element, attributeName: string) { if (this.elements.has(element)) { if (this.delegate.elementAttributeChanged && this.matchElement(element)) { this.delegate.elementAttributeChanged(element, attributeName) diff --git a/src/mutation-observers/selector_observer.ts b/src/mutation-observers/selector_observer.ts index d18d09ec..6321de64 100644 --- a/src/mutation-observers/selector_observer.ts +++ b/src/mutation-observers/selector_observer.ts @@ -8,14 +8,14 @@ export interface SelectorObserverDelegate { } export class SelectorObserver implements ElementObserverDelegate { - private selector: string - private elementObserver: ElementObserver - private delegate: SelectorObserverDelegate - private matchesByElement: Multimap - private details: object - - constructor(element: Element, selector: string, delegate: SelectorObserverDelegate, details: object = {}) { - this.selector = selector + private readonly elementObserver: ElementObserver + private readonly delegate: SelectorObserverDelegate + private readonly matchesByElement: Multimap + private readonly details: object + _selector: string | null + + constructor(element: Element, selector: string, delegate: SelectorObserverDelegate, details: object) { + this._selector = selector this.details = details this.elementObserver = new ElementObserver(element, this) this.delegate = delegate @@ -26,6 +26,15 @@ export class SelectorObserver implements ElementObserverDelegate { return this.elementObserver.started } + get selector() { + return this._selector + } + + set selector(selector: string | null) { + this._selector = selector + this.refresh() + } + start() { this.elementObserver.start() } @@ -49,47 +58,73 @@ export class SelectorObserver implements ElementObserverDelegate { // Element observer delegate matchElement(element: Element): boolean { - const matches = element.matches(this.selector) + const { selector } = this - if (this.delegate.selectorMatchElement) { - return matches && this.delegate.selectorMatchElement(element, this.details) - } + if (selector) { + const matches = element.matches(selector) + + if (this.delegate.selectorMatchElement) { + return matches && this.delegate.selectorMatchElement(element, this.details) + } - return matches + return matches + } else { + return false + } } matchElementsInTree(tree: Element): Element[] { - const match = this.matchElement(tree) ? [tree] : [] - const matches = Array.from(tree.querySelectorAll(this.selector)).filter((match) => this.matchElement(match)) - return match.concat(matches) + const { selector } = this + + if (selector) { + const match = this.matchElement(tree) ? [tree] : [] + const matches = Array.from(tree.querySelectorAll(selector)).filter((match) => this.matchElement(match)) + return match.concat(matches) + } else { + return [] + } } elementMatched(element: Element) { - this.selectorMatched(element) + const { selector } = this + + if (selector) { + this.selectorMatched(element, selector) + } } elementUnmatched(element: Element) { - this.selectorUnmatched(element) + const selectors = this.matchesByElement.getKeysForValue(element) + + for (const selector of selectors) { + this.selectorUnmatched(element, selector) + } } elementAttributeChanged(element: Element, _attributeName: string) { - const matches = this.matchElement(element) - const matchedBefore = this.matchesByElement.has(this.selector, element) + const { selector } = this - if (!matches && matchedBefore) { - this.selectorUnmatched(element) + if (selector) { + const matches = this.matchElement(element) + const matchedBefore = this.matchesByElement.has(selector, element) + + if (matches && !matchedBefore) { + this.selectorMatched(element, selector) + } else if (!matches && matchedBefore) { + this.selectorUnmatched(element, selector) + } } } - private selectorMatched(element: Element) { - if (this.delegate.selectorMatched) { - this.delegate.selectorMatched(element, this.selector, this.details) - this.matchesByElement.add(this.selector, element) - } + // Selector management + + private selectorMatched(element: Element, selector: string) { + this.delegate.selectorMatched(element, selector, this.details) + this.matchesByElement.add(selector, element) } - private selectorUnmatched(element: Element) { - this.delegate.selectorUnmatched(element, this.selector, this.details) - this.matchesByElement.delete(this.selector, element) + private selectorUnmatched(element: Element, selector: string) { + this.delegate.selectorUnmatched(element, selector, this.details) + this.matchesByElement.delete(selector, element) } } diff --git a/src/tests/cases/dom_test_case.ts b/src/tests/cases/dom_test_case.ts index 438239ef..fe39ac39 100644 --- a/src/tests/cases/dom_test_case.ts +++ b/src/tests/cases/dom_test_case.ts @@ -51,6 +51,15 @@ export class DOMTestCase extends TestCase { return event } + async triggerMouseEvent(selectorOrTarget: string | EventTarget, type: string, options: MouseEventInit = {}) { + const eventTarget = typeof selectorOrTarget == "string" ? this.findElement(selectorOrTarget) : selectorOrTarget + const event = new MouseEvent(type, options) + + eventTarget.dispatchEvent(event) + await this.nextFrame + return event + } + async triggerKeyboardEvent(selectorOrTarget: string | EventTarget, type: string, options: KeyboardEventInit = {}) { const eventTarget = typeof selectorOrTarget == "string" ? this.findElement(selectorOrTarget) : selectorOrTarget const event = new KeyboardEvent(type, options) @@ -60,6 +69,34 @@ export class DOMTestCase extends TestCase { return event } + async setAttribute(selectorOrElement: string | Element, name: string, value: string) { + const element = typeof selectorOrElement == "string" ? this.findElement(selectorOrElement) : selectorOrElement + + element.setAttribute(name, value) + await this.nextFrame + } + + async removeAttribute(selectorOrElement: string | Element, name: string) { + const element = typeof selectorOrElement == "string" ? this.findElement(selectorOrElement) : selectorOrElement + + element.removeAttribute(name) + await this.nextFrame + } + + async appendChild(selectorOrElement: T | string, child: T) { + const parent = typeof selectorOrElement == "string" ? this.findElement(selectorOrElement) : selectorOrElement + + parent.appendChild(child) + await this.nextFrame + } + + async remove(selectorOrElement: Element | string) { + const element = typeof selectorOrElement == "string" ? this.findElement(selectorOrElement) : selectorOrElement + + element.remove() + await this.nextFrame + } + findElement(selector: string) { const element = this.fixtureElement.querySelector(selector) if (element) { diff --git a/src/tests/controllers/outlet_controller.ts b/src/tests/controllers/outlet_controller.ts index c3a5b840..b382f80c 100644 --- a/src/tests/controllers/outlet_controller.ts +++ b/src/tests/controllers/outlet_controller.ts @@ -19,6 +19,9 @@ export class OutletController extends BaseOutletController { alphaOutletDisconnectedCallCount: Number, betaOutletConnectedCallCount: Number, betaOutletDisconnectedCallCount: Number, + betaOutletsInConnect: Number, + gammaOutletConnectedCallCount: Number, + gammaOutletDisconnectedCallCount: Number, namespacedEpsilonOutletConnectedCallCount: Number, namespacedEpsilonOutletDisconnectedCallCount: Number, } @@ -44,9 +47,16 @@ export class OutletController extends BaseOutletController { alphaOutletDisconnectedCallCountValue = 0 betaOutletConnectedCallCountValue = 0 betaOutletDisconnectedCallCountValue = 0 + betaOutletsInConnectValue = 0 + gammaOutletConnectedCallCountValue = 0 + gammaOutletDisconnectedCallCountValue = 0 namespacedEpsilonOutletConnectedCallCountValue = 0 namespacedEpsilonOutletDisconnectedCallCountValue = 0 + connect() { + this.betaOutletsInConnectValue = this.betaOutlets.length + } + alphaOutletConnected(_outlet: Controller, element: Element) { if (this.hasConnectedClass) element.classList.add(this.connectedClass) this.alphaOutletConnectedCallCountValue++ @@ -67,6 +77,11 @@ export class OutletController extends BaseOutletController { this.betaOutletDisconnectedCallCountValue++ } + gammaOutletConnected(_outlet: Controller, element: Element) { + if (this.hasConnectedClass) element.classList.add(this.connectedClass) + this.gammaOutletConnectedCallCountValue++ + } + namespacedEpsilonOutletConnected(_outlet: Controller, element: Element) { if (this.hasConnectedClass) element.classList.add(this.connectedClass) this.namespacedEpsilonOutletConnectedCallCountValue++ diff --git a/src/tests/modules/core/action_click_filter_tests.ts b/src/tests/modules/core/action_click_filter_tests.ts new file mode 100644 index 00000000..accec9ac --- /dev/null +++ b/src/tests/modules/core/action_click_filter_tests.ts @@ -0,0 +1,21 @@ +import { LogControllerTestCase } from "../../cases/log_controller_test_case" + +export default class ActionClickFilterTests extends LogControllerTestCase { + identifier = ["a"] + + fixtureHTML = ` +
+ +
+ ` + + async "test ignoring clicks with unmatched modifier"() { + const button = this.findElement("#ctrl") + await this.triggerMouseEvent(button, "click", { ctrlKey: true }) + await this.nextFrame + this.assertActions( + { name: "log", identifier: "a", eventType: "click", currentTarget: button }, + { name: "log2", identifier: "a", eventType: "click", currentTarget: button } + ) + } +} diff --git a/src/tests/modules/core/event_options_tests.ts b/src/tests/modules/core/event_options_tests.ts index 403cb10a..45027cd3 100644 --- a/src/tests/modules/core/event_options_tests.ts +++ b/src/tests/modules/core/event_options_tests.ts @@ -1,3 +1,4 @@ +import type { Controller } from "src/core" import { LogControllerTestCase } from "../../cases/log_controller_test_case" export default class EventOptionsTests extends LogControllerTestCase { @@ -177,6 +178,47 @@ export default class EventOptionsTests extends LogControllerTestCase { this.assertNoActions() } + async "test custom action option callback params contain the controller instance"() { + let lastActionOptions: { controller?: Controller } = {} + + const mockCallback = (options: Object) => { + lastActionOptions = options + } + + this.application.registerActionOption("all", (options: Object) => { + mockCallback(options) + return true + }) + + await this.setAction(this.buttonElement, "click->c#log:all") + + await this.triggerEvent(this.buttonElement, "click") + + this.assertActions({ name: "log", identifier: "c", eventType: "click", currentTarget: this.buttonElement }) + + this.assert.deepEqual(["name", "value", "event", "element", "controller"], Object.keys(lastActionOptions)) + + this.assert.equal( + lastActionOptions.controller, + this.application.getControllerForElementAndIdentifier(this.element, "c") + ) + + this.controllerConstructor.actionLog = [] // clear actions + + await this.setAction(this.buttonElement, "click->d#log:all") + + await this.triggerEvent(this.buttonElement, "click") + + this.assertActions({ name: "log", identifier: "d", eventType: "click", currentTarget: this.buttonElement }) + + this.assert.deepEqual(["name", "value", "event", "element", "controller"], Object.keys(lastActionOptions)) + + this.assert.equal( + lastActionOptions.controller, + this.application.getControllerForElementAndIdentifier(this.element, "d") + ) + } + async "test custom option"() { this.application.registerActionOption("open", ({ value, event: { type, target } }) => { switch (type) { @@ -213,6 +255,43 @@ export default class EventOptionsTests extends LogControllerTestCase { this.assertActions({ name: "log", eventType: "toggle" }) } + async "test custom action option callback event contains params"() { + let lastActionEventParams: Object = {} + + // clone the params to ensure we check the value as the callback receives it + // not the event after all actions have resolved + + const mockCallback = ({ event: { params = {} } = {} }) => { + lastActionEventParams = { ...params } + } + + this.application.registerActionOption("all", (options: Object) => { + mockCallback(options) + return true + }) + + this.buttonElement.setAttribute("data-c-custom-number-param", "41") + this.buttonElement.setAttribute("data-c-custom-string-param", "validation") + this.buttonElement.setAttribute("data-c-custom-boolean-param", "true") + this.buttonElement.setAttribute("data-d-should-ignore-param", "_IGNORED_") + + await this.setAction(this.buttonElement, "click->c#log:all") + + await this.triggerEvent(this.buttonElement, "click") + + this.assertActions({ name: "log", identifier: "c", eventType: "click", currentTarget: this.buttonElement }) + + const expectedEventParams = { + customBoolean: true, + customNumber: 41, + customString: "validation", + } + + this.assert.deepEqual(this.controllerConstructor.actionLog[0].params, expectedEventParams) + + this.assert.deepEqual(lastActionEventParams, expectedEventParams) + } + setAction(element: Element, value: string) { element.setAttribute("data-action", value) return this.nextFrame diff --git a/src/tests/modules/core/loading_tests.ts b/src/tests/modules/core/loading_tests.ts index 1190dcdb..20ed5c92 100644 --- a/src/tests/modules/core/loading_tests.ts +++ b/src/tests/modules/core/loading_tests.ts @@ -13,12 +13,20 @@ class LoadableController extends LogController { } class AfterLoadController extends LogController { + static values = { + example: { default: "demo", type: String }, + } + static afterLoad(identifier: string, application: any) { const newElement = document.createElement("div") newElement.classList.add("after-load-test") newElement.setAttribute(application.schema.controllerAttribute, identifier) application.element.append(newElement) - document.dispatchEvent(new CustomEvent("test", { detail: { identifier, application } })) + document.dispatchEvent( + new CustomEvent("test", { + detail: { identifier, application, exampleDefault: this.values.example.default, controller: this }, + }) + ) } } @@ -37,13 +45,15 @@ export default class ApplicationTests extends ApplicationTestCase { "test module with afterLoad method should be triggered when registered"() { // set up an event listener to track the params passed into the AfterLoadController - let data: { application?: any; identifier?: string } = {} + let data: { application?: any; identifier?: string; exampleDefault?: string; controller?: any } = {} document.addEventListener("test", (({ detail }: CustomEvent) => { data = detail }) as EventListener) - this.assert.equal(data.identifier, undefined) this.assert.equal(data.application, undefined) + this.assert.equal(data.controller, undefined) + this.assert.equal(data.exampleDefault, undefined) + this.assert.equal(data.identifier, undefined) this.application.register("after-load", AfterLoadController) @@ -51,8 +61,10 @@ export default class ApplicationTests extends ApplicationTestCase { this.assert.equal(this.findElements('[data-controller="after-load"]').length, 1) // check that static method was correctly called with the params - this.assert.equal(data.identifier, "after-load") this.assert.equal(data.application, this.application) + this.assert.equal(data.controller, AfterLoadController) + this.assert.equal(data.exampleDefault, "demo") + this.assert.equal(data.identifier, "after-load") } get controllers() { diff --git a/src/tests/modules/core/outlet_order_tests.ts b/src/tests/modules/core/outlet_order_tests.ts new file mode 100644 index 00000000..5d8bfcf4 --- /dev/null +++ b/src/tests/modules/core/outlet_order_tests.ts @@ -0,0 +1,45 @@ +import { ControllerTestCase } from "../../cases/controller_test_case" +import { OutletController } from "../../controllers/outlet_controller" + +const connectOrder: string[] = [] + +class OutletOrderController extends OutletController { + connect() { + connectOrder.push(`${this.identifier}-${this.element.id}-start`) + super.connect() + connectOrder.push(`${this.identifier}-${this.element.id}-end`) + } +} + +export default class OutletOrderTests extends ControllerTestCase(OutletOrderController) { + fixtureHTML = ` +
Search
+
Beta
+
Beta
+
Beta
+ ` + + get identifiers() { + return ["alpha", "beta"] + } + + async "test can access outlets in connect() even if they are referenced before they are connected"() { + this.assert.equal(this.controller.betaOutletsInConnectValue, 3) + + this.controller.betaOutlets.forEach((outlet) => { + this.assert.equal(outlet.identifier, "beta") + this.assert.equal(Array.from(outlet.element.classList.values()), "beta") + }) + + this.assert.deepEqual(connectOrder, [ + "alpha-alpha1-start", + "beta-beta-1-start", + "beta-beta-1-end", + "beta-beta-2-start", + "beta-beta-2-end", + "beta-beta-3-start", + "beta-beta-3-end", + "alpha-alpha1-end", + ]) + } +} diff --git a/src/tests/modules/core/outlet_tests.ts b/src/tests/modules/core/outlet_tests.ts index 0ff686d8..fb87ba12 100644 --- a/src/tests/modules/core/outlet_tests.ts +++ b/src/tests/modules/core/outlet_tests.ts @@ -132,7 +132,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { this.assert.throws(() => this.controller.alphaOutletElement) } - "test outlet connected callback fires"() { + async "test outlet connected callback fires"() { const alphaOutlets = this.controller.alphaOutletElements.filter((outlet) => outlet.classList.contains("connected")) this.assert.equal(alphaOutlets.length, 2) @@ -149,13 +149,12 @@ export default class OutletTests extends ControllerTestCase(OutletController) { async "test outlet connected callback when element is inserted"() { const betaOutletElement = document.createElement("div") - betaOutletElement.setAttribute("class", "beta") - betaOutletElement.setAttribute("data-controller", "beta") + await this.setAttribute(betaOutletElement, "class", "beta") + await this.setAttribute(betaOutletElement, "data-controller", "beta") this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 2) - this.controller.element.appendChild(betaOutletElement) - await this.nextFrame + await this.appendChild(this.controller.element, betaOutletElement) this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 3) this.assert.ok( @@ -164,8 +163,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { ) this.assert.ok(betaOutletElement.isConnected, "element is present in document") - this.findElement("#container").appendChild(betaOutletElement.cloneNode(true)) - await this.nextFrame + await this.appendChild("#container", betaOutletElement.cloneNode(true)) this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 4) } @@ -175,9 +173,8 @@ export default class OutletTests extends ControllerTestCase(OutletController) { this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 2) - element.setAttribute("data-controller", "beta") - element.classList.add("beta") - await this.nextFrame + await this.setAttribute(element, "data-controller", "beta") + await this.setAttribute(element, "class", "beta") this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 3) this.assert.ok(element.classList.contains("connected"), `expected "${element.className}" to contain "connected"`) @@ -189,8 +186,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 2) - element.classList.add("beta") - await this.nextFrame + await this.setAttribute(element, "class", "beta") this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 3) this.assert.ok(element.classList.contains("connected"), `expected "${element.className}" to contain "connected"`) @@ -202,8 +198,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 2) - element.setAttribute(`data-controller`, "beta") - await this.nextFrame + await this.setAttribute(element, "data-controller", "beta") this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 3) this.assert.ok(element.classList.contains("connected"), `expected "${element.className}" to contain "connected"`) @@ -236,8 +231,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { `expected "${disconnectedAlpha.className}" not to contain "disconnected"` ) - disconnectedAlpha.parentElement?.removeChild(disconnectedAlpha) - await this.nextFrame + await this.remove(disconnectedAlpha) this.assert.equal(this.controller.alphaOutletDisconnectedCallCountValue, 1) this.assert.ok( @@ -256,8 +250,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { `expected "${disconnectedEpsilon.className}" not to contain "disconnected"` ) - disconnectedEpsilon.parentElement?.removeChild(disconnectedEpsilon) - await this.nextFrame + await this.remove(disconnectedEpsilon) this.assert.equal(this.controller.namespacedEpsilonOutletDisconnectedCallCountValue, 1) this.assert.ok( @@ -276,8 +269,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { `expected "${element.className}" not to contain "disconnected"` ) - element.removeAttribute(`id`) - await this.nextFrame + await this.removeAttribute(element, "id") this.assert.equal(this.controller.alphaOutletDisconnectedCallCountValue, 1) this.assert.ok( @@ -296,8 +288,7 @@ export default class OutletTests extends ControllerTestCase(OutletController) { `expected "${element.className}" not to contain "disconnected"` ) - element.removeAttribute(`data-controller`) - await this.nextFrame + await this.removeAttribute(element, "data-controller") this.assert.equal(this.controller.alphaOutletDisconnectedCallCountValue, 1) this.assert.ok( @@ -306,4 +297,73 @@ export default class OutletTests extends ControllerTestCase(OutletController) { ) this.assert.ok(element.isConnected, "element is still present in document") } + + async "test outlet connect callback when the controlled element's outlet attribute is added"() { + const gamma2 = this.findElement("#gamma2") + + await this.setAttribute(this.controller.element, `data-${this.identifier}-gamma-outlet`, "#gamma2") + + this.assert.equal(this.controller.gammaOutletConnectedCallCountValue, 1) + this.assert.ok(gamma2.isConnected, "#gamma2 is still present in document") + this.assert.ok(gamma2.classList.contains("connected"), `expected "${gamma2.className}" to contain "connected"`) + } + + async "test outlet connect callback doesn't get trigged when any attribute gets added to the controller element"() { + this.assert.equal(this.controller.alphaOutletConnectedCallCountValue, 2) + this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 2) + this.assert.equal(this.controller.gammaOutletConnectedCallCountValue, 0) + this.assert.equal(this.controller.namespacedEpsilonOutletConnectedCallCountValue, 2) + + await this.setAttribute(this.controller.element, "data-some-random-attribute", "#alpha1") + + this.assert.equal(this.controller.alphaOutletConnectedCallCountValue, 2) + this.assert.equal(this.controller.betaOutletConnectedCallCountValue, 2) + this.assert.equal(this.controller.gammaOutletConnectedCallCountValue, 0) + this.assert.equal(this.controller.namespacedEpsilonOutletConnectedCallCountValue, 2) + + this.assert.equal(this.controller.alphaOutletDisconnectedCallCountValue, 0) + this.assert.equal(this.controller.betaOutletDisconnectedCallCountValue, 0) + this.assert.equal(this.controller.gammaOutletDisconnectedCallCountValue, 0) + this.assert.equal(this.controller.namespacedEpsilonOutletDisconnectedCallCountValue, 0) + } + + async "test outlet connect callback when the controlled element's outlet attribute is changed"() { + const alpha1 = this.findElement("#alpha1") + const alpha2 = this.findElement("#alpha2") + + await this.setAttribute(this.controller.element, `data-${this.identifier}-alpha-outlet`, "#alpha1") + + this.assert.equal(this.controller.alphaOutletConnectedCallCountValue, 2) + this.assert.equal(this.controller.alphaOutletDisconnectedCallCountValue, 1) + this.assert.ok(alpha1.isConnected, "alpha1 is still present in document") + this.assert.ok(alpha2.isConnected, "alpha2 is still present in document") + this.assert.ok(alpha1.classList.contains("connected"), `expected "${alpha1.className}" to contain "connected"`) + this.assert.notOk( + alpha1.classList.contains("disconnected"), + `expected "${alpha1.className}" to contain "disconnected"` + ) + this.assert.ok( + alpha2.classList.contains("disconnected"), + `expected "${alpha2.className}" to contain "disconnected"` + ) + } + + async "test outlet disconnected callback when the controlled element's outlet attribute is removed"() { + const alpha1 = this.findElement("#alpha1") + const alpha2 = this.findElement("#alpha2") + + await this.removeAttribute(this.controller.element, `data-${this.identifier}-alpha-outlet`) + + this.assert.equal(this.controller.alphaOutletDisconnectedCallCountValue, 2) + this.assert.ok(alpha1.isConnected, "#alpha1 is still present in document") + this.assert.ok(alpha2.isConnected, "#alpha2 is still present in document") + this.assert.ok( + alpha1.classList.contains("disconnected"), + `expected "${alpha1.className}" to contain "disconnected"` + ) + this.assert.ok( + alpha2.classList.contains("disconnected"), + `expected "${alpha2.className}" to contain "disconnected"` + ) + } } diff --git a/src/tests/modules/core/value_properties_tests.ts b/src/tests/modules/core/value_properties_tests.ts new file mode 100644 index 00000000..0c8a583d --- /dev/null +++ b/src/tests/modules/core/value_properties_tests.ts @@ -0,0 +1,176 @@ +import { ValueController } from "../../controllers/value_controller" +import { ControllerTestCase } from "../../cases/controller_test_case" + +import { + parseValueTypeDefault, + parseValueTypeConstant, + parseValueTypeObject, + parseValueTypeDefinition, + defaultValueForDefinition, +} from "../../../core/value_properties" + +export default class ValuePropertiesTests extends ControllerTestCase(ValueController) { + "test parseValueTypeConstant"() { + this.assert.equal(parseValueTypeConstant(String), "string") + this.assert.equal(parseValueTypeConstant(Boolean), "boolean") + this.assert.equal(parseValueTypeConstant(Array), "array") + this.assert.equal(parseValueTypeConstant(Object), "object") + this.assert.equal(parseValueTypeConstant(Number), "number") + + this.assert.equal(parseValueTypeConstant("" as any), undefined) + this.assert.equal(parseValueTypeConstant({} as any), undefined) + this.assert.equal(parseValueTypeConstant([] as any), undefined) + this.assert.equal(parseValueTypeConstant(true as any), undefined) + this.assert.equal(parseValueTypeConstant(false as any), undefined) + this.assert.equal(parseValueTypeConstant(0 as any), undefined) + this.assert.equal(parseValueTypeConstant(1 as any), undefined) + this.assert.equal(parseValueTypeConstant(null!), undefined) + this.assert.equal(parseValueTypeConstant(undefined), undefined) + } + + "test parseValueTypeDefault"() { + this.assert.equal(parseValueTypeDefault(""), "string") + this.assert.equal(parseValueTypeDefault("Some string"), "string") + + this.assert.equal(parseValueTypeDefault(true), "boolean") + this.assert.equal(parseValueTypeDefault(false), "boolean") + + this.assert.equal(parseValueTypeDefault([]), "array") + this.assert.equal(parseValueTypeDefault([1, 2, 3]), "array") + this.assert.equal(parseValueTypeDefault([true, false, true]), "array") + this.assert.equal(parseValueTypeDefault([{}, {}, {}]), "array") + + this.assert.equal(parseValueTypeDefault({}), "object") + this.assert.equal(parseValueTypeDefault({ one: "key" }), "object") + + this.assert.equal(parseValueTypeDefault(-1), "number") + this.assert.equal(parseValueTypeDefault(0), "number") + this.assert.equal(parseValueTypeDefault(1), "number") + this.assert.equal(parseValueTypeDefault(-0.1), "number") + this.assert.equal(parseValueTypeDefault(0.0), "number") + this.assert.equal(parseValueTypeDefault(0.1), "number") + + this.assert.equal(parseValueTypeDefault(null!), undefined) + this.assert.equal(parseValueTypeDefault(undefined!), undefined) + } + + "test parseValueTypeObject"() { + const typeObject = (object: any) => { + return parseValueTypeObject({ + controller: this.controller.identifier, + token: "url", + typeObject: object, + }) + } + + this.assert.equal(typeObject({ type: String, default: "" }), "string") + this.assert.equal(typeObject({ type: String, default: "123" }), "string") + this.assert.equal(typeObject({ type: String }), "string") + this.assert.equal(typeObject({ default: "" }), "string") + this.assert.equal(typeObject({ default: "123" }), "string") + + this.assert.equal(typeObject({ type: Number, default: 0 }), "number") + this.assert.equal(typeObject({ type: Number, default: 1 }), "number") + this.assert.equal(typeObject({ type: Number, default: -1 }), "number") + this.assert.equal(typeObject({ type: Number }), "number") + this.assert.equal(typeObject({ default: 0 }), "number") + this.assert.equal(typeObject({ default: 1 }), "number") + this.assert.equal(typeObject({ default: -1 }), "number") + + this.assert.equal(typeObject({ type: Array, default: [] }), "array") + this.assert.equal(typeObject({ type: Array, default: [1] }), "array") + this.assert.equal(typeObject({ type: Array }), "array") + this.assert.equal(typeObject({ default: [] }), "array") + this.assert.equal(typeObject({ default: [1] }), "array") + + this.assert.equal(typeObject({ type: Object, default: {} }), "object") + this.assert.equal(typeObject({ type: Object, default: { some: "key" } }), "object") + this.assert.equal(typeObject({ type: Object }), "object") + this.assert.equal(typeObject({ default: {} }), "object") + this.assert.equal(typeObject({ default: { some: "key" } }), "object") + + this.assert.equal(typeObject({ type: Boolean, default: true }), "boolean") + this.assert.equal(typeObject({ type: Boolean, default: false }), "boolean") + this.assert.equal(typeObject({ type: Boolean }), "boolean") + this.assert.equal(typeObject({ default: false }), "boolean") + + this.assert.throws(() => typeObject({ type: Boolean, default: "something else" }), { + name: "Error", + message: `The specified default value for the Stimulus Value "test.url" must match the defined type "boolean". The provided default value of "something else" is of type "string".`, + }) + + this.assert.throws(() => typeObject({ type: Boolean, default: "true" }), { + name: "Error", + message: `The specified default value for the Stimulus Value "test.url" must match the defined type "boolean". The provided default value of "true" is of type "string".`, + }) + } + + "test parseValueTypeDefinition booleans"() { + const typeDefinition = (definition: any) => { + return parseValueTypeDefinition({ + controller: this.controller.identifier, + token: "url", + typeDefinition: definition, + }) + } + + this.assert.equal(typeDefinition(Boolean), "boolean") + this.assert.equal(typeDefinition(true), "boolean") + this.assert.equal(typeDefinition(false), "boolean") + this.assert.equal(typeDefinition({ type: Boolean, default: false }), "boolean") + this.assert.equal(typeDefinition({ type: Boolean }), "boolean") + this.assert.equal(typeDefinition({ default: true }), "boolean") + + // since the provided value is actually an object, it's going to be of type "object" + this.assert.equal(typeDefinition({ default: null }), "object") + this.assert.equal(typeDefinition({ default: undefined }), "object") + + this.assert.equal(typeDefinition({}), "object") + this.assert.equal(typeDefinition(""), "string") + this.assert.equal(typeDefinition([]), "array") + + this.assert.throws(() => typeDefinition(null)) + this.assert.throws(() => typeDefinition(undefined)) + } + + "test defaultValueForDefinition"() { + this.assert.deepEqual(defaultValueForDefinition(String), "") + this.assert.deepEqual(defaultValueForDefinition(Boolean), false) + this.assert.deepEqual(defaultValueForDefinition(Object), {}) + this.assert.deepEqual(defaultValueForDefinition(Array), []) + this.assert.deepEqual(defaultValueForDefinition(Number), 0) + + this.assert.deepEqual(defaultValueForDefinition({ type: String }), "") + this.assert.deepEqual(defaultValueForDefinition({ type: Boolean }), false) + this.assert.deepEqual(defaultValueForDefinition({ type: Object }), {}) + this.assert.deepEqual(defaultValueForDefinition({ type: Array }), []) + this.assert.deepEqual(defaultValueForDefinition({ type: Number }), 0) + + this.assert.deepEqual(defaultValueForDefinition({ type: String, default: null }), null) + this.assert.deepEqual(defaultValueForDefinition({ type: Boolean, default: null }), null) + this.assert.deepEqual(defaultValueForDefinition({ type: Object, default: null }), null) + this.assert.deepEqual(defaultValueForDefinition({ type: Array, default: null }), null) + this.assert.deepEqual(defaultValueForDefinition({ type: Number, default: null }), null) + + this.assert.deepEqual(defaultValueForDefinition({ type: String, default: "some string" }), "some string") + this.assert.deepEqual(defaultValueForDefinition({ type: Boolean, default: true }), true) + this.assert.deepEqual(defaultValueForDefinition({ type: Object, default: { some: "key" } }), { some: "key" }) + this.assert.deepEqual(defaultValueForDefinition({ type: Array, default: [1, 2, 3] }), [1, 2, 3]) + this.assert.deepEqual(defaultValueForDefinition({ type: Number, default: 99 }), 99) + + this.assert.deepEqual(defaultValueForDefinition("some string"), "some string") + this.assert.deepEqual(defaultValueForDefinition(true), true) + this.assert.deepEqual(defaultValueForDefinition({ some: "key" }), { some: "key" }) + this.assert.deepEqual(defaultValueForDefinition([1, 2, 3]), [1, 2, 3]) + this.assert.deepEqual(defaultValueForDefinition(99), 99) + + this.assert.deepEqual(defaultValueForDefinition({ default: "some string" }), "some string") + this.assert.deepEqual(defaultValueForDefinition({ default: true }), true) + this.assert.deepEqual(defaultValueForDefinition({ default: { some: "key" } }), { some: "key" }) + this.assert.deepEqual(defaultValueForDefinition({ default: [1, 2, 3] }), [1, 2, 3]) + this.assert.deepEqual(defaultValueForDefinition({ default: 99 }), 99) + + this.assert.deepEqual(defaultValueForDefinition({ default: null }), null) + this.assert.deepEqual(defaultValueForDefinition({ default: undefined }), undefined) + } +} diff --git a/src/tests/modules/core/value_tests.ts b/src/tests/modules/core/value_tests.ts index 1bcb0377..fd60ee1a 100644 --- a/src/tests/modules/core/value_tests.ts +++ b/src/tests/modules/core/value_tests.ts @@ -46,6 +46,14 @@ export default class ValueTests extends ControllerTestCase(ValueController) { this.controller.numericValue = "" as any this.assert.equal(this.controller.numericValue, 0) this.assert.equal(this.get("numeric-value"), "") + + // Number values should support Numeric separators + this.set("numeric-value", "7_150") + this.assert.equal(this.controller.numericValue, 7150) + + // Number values should be written simply, without Numeric separators + this.controller.numericValue = 10500 + this.assert.deepEqual(this.get("numeric-value"), "10500") } "test boolean values"() { diff --git a/yarn.lock b/yarn.lock index a54c7735..547fd21f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,34 +28,46 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@eslint/eslintrc@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356" - integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.4.0" - globals "^13.15.0" + espree "^9.5.2" + 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" -"@humanwhocodes/config-array@^0.10.5": - version "0.10.7" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.7.tgz#6d53769fd0c222767e6452e8ebda825c22e9f0dc" - integrity sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w== +"@eslint/js@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0" + integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg== + +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/gitignore-to-minimatch@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d" - integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA== + minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" @@ -80,7 +92,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -100,13 +112,13 @@ is-module "^1.0.0" resolve "^1.19.0" -"@rollup/plugin-typescript@^8.5.0": - version "8.5.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz#7ea11599a15b0a30fa7ea69ce3b791d41b862515" - integrity sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ== +"@rollup/plugin-typescript@^11.1.1": + version "11.1.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.1.tgz#258663a7aa6b51390dd39ae6e5502f2c4b2807cb" + integrity sha512-Ioir+x5Bejv72Lx2Zbz3/qGg7tvGbxQZALCLoJaGrkNXak/19+vKgKYJYM3i/fJxvsb23I9FuFQ8CUBEfsmBRg== dependencies: - "@rollup/pluginutils" "^3.1.0" - resolve "^1.17.0" + "@rollup/pluginutils" "^5.0.1" + resolve "^1.22.1" "@rollup/pluginutils@^3.1.0": version "3.1.0" @@ -117,6 +129,15 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^5.0.1": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" + integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + "@sindresorhus/is@^0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" @@ -169,6 +190,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/estree@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== + "@types/http-cache-semantics@*": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" @@ -215,6 +241,11 @@ dependencies: "@types/node" "*" +"@types/semver@^7.3.12": + version "7.3.13" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + "@types/ua-parser-js@^0.7.33": version "0.7.36" resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz#9bd0b47f26b5a3151be21ba4ce9f5fa457c5f190" @@ -237,84 +268,88 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.36.2": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz#9f05d42fa8fb9f62304cc2f5c2805e03c01c2620" - integrity sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ== +"@typescript-eslint/eslint-plugin@^5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.11.tgz#8d466aa21abea4c3f37129997b198d141f09e76f" + integrity sha512-XxuOfTkCUiOSyBWIvHlUraLw/JT/6Io1365RO6ZuI88STKMavJZPNMU0lFcUTeQXEhHiv64CbxYxBNoDVSmghg== dependencies: - "@typescript-eslint/scope-manager" "5.38.1" - "@typescript-eslint/type-utils" "5.38.1" - "@typescript-eslint/utils" "5.38.1" + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.11" + "@typescript-eslint/type-utils" "5.59.11" + "@typescript-eslint/utils" "5.59.11" debug "^4.3.4" + grapheme-splitter "^1.0.4" ignore "^5.2.0" - regexpp "^3.2.0" + natural-compare-lite "^1.4.0" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.36.2": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.38.1.tgz#c577f429f2c32071b92dff4af4f5fbbbd2414bd0" - integrity sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw== +"@typescript-eslint/parser@^5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.11.tgz#af7d4b7110e3068ce0b97550736de455e4250103" + integrity sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA== dependencies: - "@typescript-eslint/scope-manager" "5.38.1" - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/typescript-estree" "5.38.1" + "@typescript-eslint/scope-manager" "5.59.11" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/typescript-estree" "5.59.11" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz#f87b289ef8819b47189351814ad183e8801d5764" - integrity sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ== +"@typescript-eslint/scope-manager@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.11.tgz#5d131a67a19189c42598af9fb2ea1165252001ce" + integrity sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q== dependencies: - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/visitor-keys" "5.38.1" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/visitor-keys" "5.59.11" -"@typescript-eslint/type-utils@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz#7f038fcfcc4ade4ea76c7c69b2aa25e6b261f4c1" - integrity sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw== +"@typescript-eslint/type-utils@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.11.tgz#5eb67121808a84cb57d65a15f48f5bdda25f2346" + integrity sha512-LZqVY8hMiVRF2a7/swmkStMYSoXMFlzL6sXV6U/2gL5cwnLWQgLEG8tjWPpaE4rMIdZ6VKWwcffPlo1jPfk43g== dependencies: - "@typescript-eslint/typescript-estree" "5.38.1" - "@typescript-eslint/utils" "5.38.1" + "@typescript-eslint/typescript-estree" "5.59.11" + "@typescript-eslint/utils" "5.59.11" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.38.1.tgz#74f9d6dcb8dc7c58c51e9fbc6653ded39e2e225c" - integrity sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg== +"@typescript-eslint/types@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.11.tgz#1a9018fe3c565ba6969561f2a49f330cf1fe8db1" + integrity sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA== -"@typescript-eslint/typescript-estree@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz#657d858d5d6087f96b638ee383ee1cff52605a1e" - integrity sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g== +"@typescript-eslint/typescript-estree@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.11.tgz#b2caaa31725e17c33970c1197bcd54e3c5f42b9f" + integrity sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA== dependencies: - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/visitor-keys" "5.38.1" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/visitor-keys" "5.59.11" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.38.1.tgz#e3ac37d7b33d1362bb5adf4acdbe00372fb813ef" - integrity sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA== +"@typescript-eslint/utils@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.11.tgz#9dbff49dc80bfdd9289f9f33548f2e8db3c59ba1" + integrity sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.38.1" - "@typescript-eslint/types" "5.38.1" - "@typescript-eslint/typescript-estree" "5.38.1" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.11" + "@typescript-eslint/types" "5.59.11" + "@typescript-eslint/typescript-estree" "5.59.11" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" + semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.38.1": - version "5.38.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz#508071bfc6b96d194c0afe6a65ad47029059edbc" - integrity sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA== +"@typescript-eslint/visitor-keys@5.59.11": + version "5.59.11" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.11.tgz#dca561ddad169dc27d62396d64f45b2d2c3ecc56" + integrity sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA== dependencies: - "@typescript-eslint/types" "5.38.1" + "@typescript-eslint/types" "5.59.11" eslint-visitor-keys "^3.3.0" "@wdio/config@7.26.0": @@ -1161,7 +1196,7 @@ caw@^2.0.1: tunnel-agent "^0.6.0" url-to-options "^1.0.1" -chalk@^2.0.0, chalk@^2.3.0: +chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1649,9 +1684,9 @@ debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, de ms "2.1.2" decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.3.0: version "3.3.0" @@ -2003,7 +2038,7 @@ engine.io@~6.2.0: engine.io-parser "~5.0.3" ws "~8.2.3" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.5.0: +enhanced-resolve@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== @@ -2012,6 +2047,14 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.5.0: memory-fs "^0.5.0" tapable "^1.0.0" +enhanced-resolve@^5.0.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + ent@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" @@ -2070,10 +2113,10 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-config-prettier@^8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== +eslint-config-prettier@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== eslint-plugin-prettier@^4.2.1: version "4.2.1" @@ -2098,64 +2141,58 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.23.0: - version "8.24.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.24.0.tgz#489516c927a5da11b3979dbfb2679394523383c8" - integrity sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ== - dependencies: - "@eslint/eslintrc" "^1.3.2" - "@humanwhocodes/config-array" "^0.10.5" - "@humanwhocodes/gitignore-to-minimatch" "^1.0.2" +eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@^8.43.0: + version "8.43.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094" + integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.43.0" + "@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" 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.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + 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.1" - globals "^13.15.0" - globby "^11.1.0" - grapheme-splitter "^1.0.4" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - js-sdsl "^4.1.4" + is-path-inside "^3.0.3" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" @@ -2163,24 +2200,23 @@ eslint@^8.23.0: minimatch "^3.1.2" natural-compare "^1.4.0" optionator "^0.9.1" - regexpp "^3.2.0" strip-ansi "^6.0.1" strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" - integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== dependencies: acorn "^8.8.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.1" -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -2211,6 +2247,11 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2711,7 +2752,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.1: +glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -2766,10 +2807,10 @@ global-agent@^2.1.12: semver "^7.3.2" serialize-error "^7.0.1" -globals@^13.15.0: - version "13.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== +globals@^13.19.0: + version "13.19.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" + integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== dependencies: type-fest "^0.20.2" @@ -2876,11 +2917,21 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + grapheme-splitter@^1.0.2, grapheme-splitter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + has-bigints@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -3202,6 +3253,13 @@ is-callable@^1.1.3: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + is-core-module@^2.2.0: version "2.4.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" @@ -3209,13 +3267,6 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" -is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -3342,6 +3393,11 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -3481,11 +3537,6 @@ jest-worker@^26.2.1: merge-stream "^2.0.0" supports-color "^7.0.0" -js-sdsl@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6" - integrity sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3534,9 +3585,9 @@ json-stringify-safe@^5.0.1: integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -3695,7 +3746,7 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: +loader-utils@^1.1.0, loader-utils@^1.2.3: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -4017,7 +4068,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -4031,12 +4082,7 @@ minimatch@^5.0.0, minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== @@ -4128,6 +4174,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -4638,10 +4689,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== +prettier@^2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== printj@~1.1.0: version "1.1.2" @@ -4915,11 +4966,6 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -4968,12 +5014,12 @@ resolve@^1.10.0, resolve@^1.19.0: is-core-module "^2.2.0" path-parse "^1.0.6" -resolve@^1.17.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== +resolve@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.11.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -5159,26 +5205,14 @@ semver-truncate@^1.1.2: semver "^5.3.0" "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^7.3.7: - version "7.3.7" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== +semver@^7.3.2, semver@^7.3.4, semver@^7.3.7: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" @@ -5334,9 +5368,9 @@ socket.io-adapter@~2.4.0: integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== socket.io-parser@~4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5" - integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g== + version "4.2.3" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.3.tgz#926bcc6658e2ae0883dc9dee69acbdc76e4e3667" + integrity sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" @@ -5617,6 +5651,11 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + tar-fs@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" @@ -5793,16 +5832,15 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -ts-loader@^6.0.4: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" - integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== +ts-loader@^9.4.3: + version "9.4.3" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.3.tgz#55cfa7c28dd82a2de968ae45c3adb75fb888b27e" + integrity sha512-n3hBnm6ozJYzwiwt5YRiJZkzktftRpMiBApHaJPoWLA+qetQBAXkHqCLM6nwSdRDimqVtA5ocIkcTRLMTt7yzA== dependencies: - chalk "^2.3.0" - enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" + chalk "^4.1.0" + enhanced-resolve "^5.0.0" micromatch "^4.0.0" - semver "^6.0.0" + semver "^7.3.4" tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" @@ -5814,10 +5852,10 @@ tslib@^2.0.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== -tslib@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== tsutils@^3.21.0: version "3.21.0" @@ -5878,15 +5916,15 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.2.tgz#e3b33d5ccfb5914e4eeab6699cf208adee3fd790" - integrity sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw== +typescript@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" + integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== ua-parser-js@^0.7.30: - version "0.7.32" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" - integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== + version "0.7.33" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" + integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== ua-parser-js@^1.0.1: version "1.0.32" @@ -6244,9 +6282,9 @@ which@^2.0.1, which@^2.0.2: isexe "^2.0.0" word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" + integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA== worker-farm@^1.7.0: version "1.7.0"